Page MenuHomec4science

No OneTemporary

File Metadata

Created
Wed, Jul 31, 14:19
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/README b/README
index 7cda5f2b3..a258a335e 100644
--- a/README
+++ b/README
@@ -1,41 +1,42 @@
This is the LAMMPS software package.
LAMMPS stands for Large-scale Atomic/Molecular Massively Parallel
Simulator.
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.
----------------------------------------------------------------------
LAMMPS is a classical molecular dynamics simulation code designed to
run efficiently on parallel computers. It was developed at Sandia
National Laboratories, a US Department of Energy facility, with
funding from the DOE. It is an open-source code, distributed freely
under the terms of the GNU Public License (GPL).
The primary author of the code is Steve Plimpton, who can be emailed
at sjplimp@sandia.gov. The LAMMPS WWW Site at lammps.sandia.gov has
more information about the code and its uses.
The LAMMPS distribution includes the following files and directories:
README this file
LICENSE the GNU General Public License (GPL)
bench benchmark problems
couple code coupling examples using LAMMPS as a library
doc documentation
examples simple test problems
lib libraries LAMMPS can be linked with
potentials interatomic potential files
python Python wrapper on LAMMPS as a library
src source files
tools pre- and post-processing tools
Point your browser at any of these files to get started:
doc/Manual.html the LAMMPS manual
doc/Section_intro.html hi-level introduction to LAMMPS
doc/Section_start.html how to build and use LAMMPS
+doc/Developer.pdf LAMMPS developer guide
diff --git a/doc/Section_errors.html b/doc/Section_errors.html
index bd7722e92..4330576f5 100644
--- a/doc/Section_errors.html
+++ b/doc/Section_errors.html
@@ -1,6597 +1,6601 @@
<HTML>
<CENTER><A HREF = "Section_python.html">Previous Section</A> - <A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> -
<A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> - <A HREF = "Section_history.html">Next
Section</A>
</CENTER>
<HR>
<H3>12. Errors
</H3>
<P>This section describes the various kinds of errors you can encounter
when using LAMMPS.
</P>
12.1 <A HREF = "#err_1">Common problems</A><BR>
12.2 <A HREF = "#err_2">Reporting bugs</A><BR>
12.3 <A HREF = "#err_3">Error & warning messages</A> <BR>
<HR>
<A NAME = "err_1"></A><H4>12.1 Common problems
</H4>
<P>If two LAMMPS runs do not produce the same answer on different
machines or different numbers of processors, this is typically not a
bug. In theory you should get identical answers on any number of
processors and on any machine. In practice, numerical round-off can
cause slight differences and eventual divergence of molecular dynamics
phase space trajectories within a few 100s or few 1000s of timesteps.
However, the statistical properties of the two runs (e.g. average
energy or temperature) should still be the same.
</P>
<P>If the <A HREF = "velocity.html">velocity</A> command is used to set initial atom
velocities, a particular atom can be assigned a different velocity
when the problem is run on a different number of processors or on
different machines. If this happens, the phase space trajectories of
the two simulations will rapidly diverge. See the discussion of the
<I>loop</I> option in the <A HREF = "velocity.html">velocity</A> command for details and
options that avoid this issue.
</P>
<P>Similarly, the <A HREF = "create_atoms.html">create_atoms</A> command generates a
lattice of atoms. For the same physical system, the ordering and
numbering of atoms by atom ID may be different depending on the number
of processors.
</P>
<P>Some commands use random number generators which may be setup to
produce different random number streams on each processor and hence
will produce different effects when run on different numbers of
processors. A commonly-used example is the <A HREF = "fix_langevin.html">fix
langevin</A> command for thermostatting.
</P>
<P>A LAMMPS simulation typically has two stages, setup and run. Most
LAMMPS errors are detected at setup time; others like a bond
stretching too far may not occur until the middle of a run.
</P>
<P>LAMMPS tries to flag errors and print informative error messages so
you can fix the problem. Of course, LAMMPS cannot figure out your
physics or numerical mistakes, like choosing too big a timestep,
specifying erroneous force field coefficients, or putting 2 atoms on
top of each other! If you run into errors that LAMMPS doesn't catch
that you think it should flag, please send an email to the
<A HREF = "http://lammps.sandia.gov/authors.html">developers</A>.
</P>
<P>If you get an error message about an invalid command in your input
script, you can determine what command is causing the problem by
looking in the log.lammps file or using the <A HREF = "echo.html">echo command</A>
to see it on the screen. For a given command, LAMMPS expects certain
arguments in a specified order. If you mess this up, LAMMPS will
often flag the error, but it may read a bogus argument and assign a
value that is valid, but not what you wanted. E.g. trying to read the
string "abc" as an integer value and assigning the associated variable
a value of 0.
</P>
<P>Generally, LAMMPS will print a message to the screen and logfile and
exit gracefully when it encounters a fatal error. Sometimes it will
print a WARNING to the screen and logfile and continue on; you can
decide if the WARNING is important or not. A WARNING message that is
generated in the middle of a run is only printed to the screen, not to
the logfile, to avoid cluttering up thermodynamic output. If LAMMPS
crashes or hangs without spitting out an error message first then it
could be a bug (see <A HREF = "#err_2">this section</A>) or one of the following
cases:
</P>
<P>LAMMPS runs in the available memory a processor allows to be
allocated. Most reasonable MD runs are compute limited, not memory
limited, so this shouldn't be a bottleneck on most platforms. Almost
all large memory allocations in the code are done via C-style malloc's
which will generate an error message if you run out of memory.
Smaller chunks of memory are allocated via C++ "new" statements. If
you are unlucky you could run out of memory just when one of these
small requests is made, in which case the code will crash or hang (in
parallel), since LAMMPS doesn't trap on those errors.
</P>
<P>Illegal arithmetic can cause LAMMPS to run slow or crash. This is
typically due to invalid physics and numerics that your simulation is
computing. If you see wild thermodynamic values or NaN values in your
LAMMPS output, something is wrong with your simulation. If you
suspect this is happening, it is a good idea to print out
thermodynamic info frequently (e.g. every timestep) via the
<A HREF = "thermo.html">thermo</A> so you can monitor what is happening.
Visualizing the atom movement is also a good idea to insure your model
is behaving as you expect.
</P>
<P>In parallel, one way LAMMPS can hang is due to how different MPI
implementations handle buffering of messages. If the code hangs
without an error message, it may be that you need to specify an MPI
setting or two (usually via an environment variable) to enable
buffering or boost the sizes of messages that can be buffered.
</P>
<HR>
<A NAME = "err_2"></A><H4>12.2 Reporting bugs
</H4>
<P>If you are confident that you have found a bug in LAMMPS, follow these
steps.
</P>
<P>Check the <A HREF = "http://lammps.sandia.gov/bug.html">New features and bug
fixes</A> section of the <A HREF = "http://lammps.sandia.gov">LAMMPS WWW
site</A> to see if the bug has already been reported or fixed or the
<A HREF = "http://lammps.sandia.gov/unbug.html">Unfixed bug</A> to see if a fix is
pending.
</P>
<P>Check the <A HREF = "http://lammps.sandia.gov/mail.html">mailing list</A>
to see if it has been discussed before.
</P>
<P>If not, send an email to the mailing list describing the problem with
any ideas you have as to what is causing it or where in the code the
problem might be. The developers will ask for more info if needed,
such as an input script or data files.
</P>
<P>The most useful thing you can do to help us fix the bug is to isolate
the problem. Run it on the smallest number of atoms and fewest number
of processors and with the simplest input script that reproduces the
bug and try to identify what command or combination of commands is
causing the problem.
</P>
<P>As a last resort, you can send an email directly to the
<A HREF = "http://lammps.sandia.gov/authors.html">developers</A>.
</P>
<HR>
<H4><A NAME = "err_3"></A>12.3 Error & warning messages
</H4>
<P>These are two alphabetic lists of the <A HREF = "#error">ERROR</A> and
<A HREF = "#warn">WARNING</A> messages LAMMPS prints out and the reason why. If the
explanation here is not sufficient, the documentation for the
-offending command may help. Grepping the source files for the text of
-the error message and staring at the source code and comments is also
-not a bad idea! Note that sometimes the same message can be printed
-from multiple places in the code.
+offending command may help.
+Error and warning messages also list the source file and line number
+where the error was generated. For example, this message
</P>
-<P>Also note that error messages from <A HREF = "Section_start.html#start_3">user-contributed
-packages</A> are not listed here. Is such an
+<P>ERROR: Illegal velocity command (velocity.cpp:78)
+</P>
+<P>means that line #78 in the file src/velocity.cpp generated the error.
+Looking in the source code may help you figure out what went wrong.
+</P>
+<P>Note that error messages from <A HREF = "Section_start.html#start_3">user-contributed
+packages</A> are not listed here. If such an
error occurs and is not self-explanatory, you'll need to look in the
source code or contact the author of the package.
</P>
<H4><A NAME = "error"></A>Errors:
</H4>
<DL>
<DT><I>1-3 bond count is inconsistent</I>
<DD>An inconsistency was detected when computing the number of 1-3
neighbors for each atom. This likely means something is wrong with
the bond topologies you have defined.
<DT><I>1-4 bond count is inconsistent</I>
<DD>An inconsistency was detected when computing the number of 1-4
neighbors for each atom. This likely means something is wrong with
the bond topologies you have defined.
<DT><I>Accelerated style in input script but no fix gpu</I>
<DD>GPU acceleration requires fix gpu in the input script.
<DT><I>All angle coeffs are not set</I>
<DD>All angle coefficients must be set in the data file or by the
angle_coeff command before running a simulation.
<DT><I>All bond coeffs are not set</I>
<DD>All bond coefficients must be set in the data file or by the
bond_coeff command before running a simulation.
<DT><I>All dihedral coeffs are not set</I>
<DD>All dihedral coefficients must be set in the data file or by the
dihedral_coeff command before running a simulation.
<DT><I>All dipole moments are not set</I>
<DD>For atom styles that define dipole moments for each atom type, all
moments must be set in the data file or by the dipole command before
running a simulation.
<DT><I>All improper coeffs are not set</I>
<DD>All improper coefficients must be set in the data file or by the
improper_coeff command before running a simulation.
<DT><I>All masses are not set</I>
<DD>For atom styles that define masses for each atom type, all masses must
be set in the data file or by the mass command before running a
simulation. They must also be set before using the velocity
command.
<DT><I>All pair coeffs are not set</I>
<DD>All pair coefficients must be set in the data file or by the
pair_coeff command before running a simulation.
<DT><I>All shapes are not set</I>
<DD>All atom types must have a shape setting, even if the particles
are spherical.
<DT><I>All universe/uloop variables must have same # of values</I>
<DD>Self-explanatory.
<DT><I>All variables in next command must be same style</I>
<DD>Self-explanatory.
<DT><I>Angle atom missing in delete_bonds</I>
<DD>The delete_bonds command cannot find one or more atoms in a particular
angle on a particular processor. The pairwise cutoff is too short or
the atoms are too far apart to make a valid angle.
<DT><I>Angle atom missing in set command</I>
<DD>The set command cannot find one or more atoms in a particular angle on
a particular processor. The pairwise cutoff is too short or the atoms
are too far apart to make a valid angle.
<DT><I>Angle atoms %d %d %d missing on proc %d at step</I>
<DD>One or more of 3 atoms needed to compute a particular angle are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the angle has blown apart and an atom is
too far away.
<DT><I>Angle coeff for hybrid has invalid style</I>
<DD>Angle style hybrid uses another angle style as one of its
coefficients. The angle style used in the angle_coeff command or read
from a restart file is not recognized.
<DT><I>Angle coeffs are not set</I>
<DD>No angle coefficients have been assigned in the data file or via the
angle_coeff command.
<DT><I>Angle potential must be defined for SHAKE</I>
<DD>When shaking angles, an angle_style potential must be used.
<DT><I>Angle style hybrid cannot have hybrid as an argument</I>
<DD>Self-explanatory.
<DT><I>Angle style hybrid cannot have none as an argument</I>
<DD>Self-explanatory.
<DT><I>Angle style hybrid cannot use same pair style twice</I>
<DD>Self-explanatory.
<DT><I>Angle table must range from 0 to 180 degrees</I>
<DD>Self-explanatory.
<DT><I>Angle table parameters did not set N</I>
<DD>List of angle table parameters must include N setting.
<DT><I>Angle_coeff command before angle_style is defined</I>
<DD>Coefficients cannot be set in the data file or via the angle_coeff
command until an angle_style has been assigned.
<DT><I>Angle_coeff command before simulation box is defined</I>
<DD>The angle_coeff command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Angle_coeff command when no angles allowed</I>
<DD>The chosen atom style does not allow for angles to be defined.
<DT><I>Angle_style command when no angles allowed</I>
<DD>The chosen atom style does not allow for angles to be defined.
<DT><I>Angles assigned incorrectly</I>
<DD>Angles read in from the data file were not assigned correctly to
atoms. This means there is something invalid about the topology
definitions.
<DT><I>Angles defined but no angle types</I>
<DD>The data file header lists angles but no angle types.
<DT><I>Another input script is already being processed</I>
<DD>Cannot attempt to open a 2nd input script, when the original file is
still being processed.
<DT><I>Arccos of invalid value in variable formula</I>
<DD>Argument of arccos() must be between -1 and 1.
<DT><I>Arcsin of invalid value in variable formula</I>
<DD>Argument of arcsin() must be between -1 and 1.
<DT><I>Atom IDs must be consecutive for velocity create loop all</I>
<DD>Self-explanatory.
<DT><I>Atom count changed in fix neb</I>
<DD>This is not allowed in a NEB calculation.
<DT><I>Atom count is inconsistent, cannot write restart file</I>
<DD>Sum of atoms across processors does not equal initial total count.
This is probably because you have lost some atoms.
<DT><I>Atom in too many rigid bodies - boost MAXBODY</I>
<DD>Fix poems has a parameter MAXBODY (in fix_poems.cpp) which determines
the maximum number of rigid bodies a single atom can belong to (i.e. a
multibody joint). The bodies you have defined exceed this limit.
<DT><I>Atom sort did not operate correctly</I>
<DD>This is an internal LAMMPS error. Please report it to the
developers.
<DT><I>Atom sorting has bin size = 0.0</I>
<DD>The neighbor cutoff is being used as the bin size, but it is zero.
Thus you must explicitly list a bin size in the atom_modify sort
command or turn off sorting.
<DT><I>Atom style hybrid cannot have hybrid as an argument</I>
<DD>Self-explanatory.
<DT><I>Atom style hybrid cannot use same atom style twice</I>
<DD>Self-explanatory.
<DT><I>Atom vector in equal-style variable formula</I>
<DD>Atom vectors generate one value per atom which is not allowed
in an equal-style variable.
<DT><I>Atom-style variable in equal-style variable formula</I>
<DD>Atom-style variables generate one value per atom which is not allowed
in an equal-style variable.
<DT><I>Atom_modify map command after simulation box is defined</I>
<DD>The atom_modify map command cannot be used after a read_data,
read_restart, or create_box command.
<DT><I>Atom_modify sort and first options cannot be used together</I>
<DD>Self-explanatory.
<DT><I>Atom_style command after simulation box is defined</I>
<DD>The atom_style command cannot be used after a read_data,
read_restart, or create_box command.
<DT><I>Attempt to pop empty stack in fix box/relax</I>
<DD>Internal LAMMPS error. Please report it to the developers.
<DT><I>Attempt to push beyond stack limit in fix box/relax</I>
<DD>Internal LAMMPS error. Please report it to the developers.
<DT><I>Attempting to rescale a 0.0 temperature</I>
<DD>Cannot rescale a temperature that is already 0.0.
<DT><I>Bad FENE bond</I>
<DD>Two atoms in a FENE bond have become so far apart that the bond cannot
be computed.
<DT><I>Bad TIP4P angle type for PPPM/TIP4P</I>
<DD>Specified angle type is not valid.
<DT><I>Bad TIP4P bond type for PPPM/TIP4P</I>
<DD>Specified bond type is not valid.
<DT><I>Bad grid of processors</I>
<DD>The 3d grid of processors defined by the processors command does not
match the number of processors LAMMPS is being run on.
<DT><I>Bad kspace_modify slab parameter</I>
<DD>Kspace_modify value for the slab/volume keyword must be >= 2.0.
<DT><I>Bad principal moments</I>
<DD>Fix rigid did not compute the principal moments of inertia of a rigid
group of atoms correctly.
<DT><I>Bias compute does not calculate a velocity bias</I>
<DD>The specified compute must compute a bias for temperature.
<DT><I>Bias compute does not calculate temperature</I>
<DD>The specified compute must compute temperature.
<DT><I>Bias compute group does not match compute group</I>
<DD>The specified compute must operate on the same group as the parent
compute.
<DT><I>Big particle in fix srd cannot be point particle</I>
<DD>Big particles must be extended spheriods or ellipsoids.
<DT><I>Bigint setting in lmptype.h is invalid</I>
<DD>Size of bigint is less than size of tagint.
<DT><I>Bigint setting in lmptype.h is not compatible</I>
<DD>Bigint stored in restart file is not consistent with LAMMPS version
you are running.
<DT><I>Bitmapped lookup tables require int/float be same size</I>
<DD>Cannot use pair tables on this machine, because of word sizes. Use
the pair_modify command with table 0 instead.
<DT><I>Bitmapped table in file does not match requested table</I>
<DD>Setting for bitmapped table in pair_coeff command must match table
in file exactly.
<DT><I>Bitmapped table is incorrect length in table file</I>
<DD>Number of table entries is not a correct power of 2.
<DT><I>Bond and angle potentials must be defined for TIP4P</I>
<DD>Cannot use TIP4P pair potential unless bond and angle potentials
are defined.
<DT><I>Bond atom missing in delete_bonds</I>
<DD>The delete_bonds command cannot find one or more atoms in a particular
bond on a particular processor. The pairwise cutoff is too short or
the atoms are too far apart to make a valid bond.
<DT><I>Bond atom missing in set command</I>
<DD>The set command cannot find one or more atoms in a particular bond on
a particular processor. The pairwise cutoff is too short or the atoms
are too far apart to make a valid bond.
<DT><I>Bond atoms %d %d missing on proc %d at step</I>
<DD>One or both of 2 atoms needed to compute a particular bond are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the bond has blown apart and an atom is
too far away.
<DT><I>Bond coeff for hybrid has invalid style</I>
<DD>Bond style hybrid uses another bond style as one of its coefficients.
The bond style used in the bond_coeff command or read from a restart
file is not recognized.
<DT><I>Bond coeffs are not set</I>
<DD>No bond coefficients have been assigned in the data file or via the
bond_coeff command.
<DT><I>Bond potential must be defined for SHAKE</I>
<DD>Cannot use fix shake unless bond potential is defined.
<DT><I>Bond style hybrid cannot have hybrid as an argument</I>
<DD>Self-explanatory.
<DT><I>Bond style hybrid cannot have none as an argument</I>
<DD>Self-explanatory.
<DT><I>Bond style hybrid cannot use same pair style twice</I>
<DD>Self-explanatory.
<DT><I>Bond style quartic cannot be used with 3,4-body interactions</I>
<DD>No angle, dihedral, or improper styles can be defined when using
bond style quartic.
<DT><I>Bond style quartic requires special_bonds = 1,1,1</I>
<DD>This is a restriction of the current bond quartic implementation.
<DT><I>Bond table parameters did not set N</I>
<DD>List of bond table parameters must include N setting.
<DT><I>Bond table values are not increasing</I>
<DD>The values in the tabulated file must be monotonically increasing.
<DT><I>Bond_coeff command before bond_style is defined</I>
<DD>Coefficients cannot be set in the data file or via the bond_coeff
command until an bond_style has been assigned.
<DT><I>Bond_coeff command before simulation box is defined</I>
<DD>The bond_coeff command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Bond_coeff command when no bonds allowed</I>
<DD>The chosen atom style does not allow for bonds to be defined.
<DT><I>Bond_style command when no bonds allowed</I>
<DD>The chosen atom style does not allow for bonds to be defined.
<DT><I>Bonds assigned incorrectly</I>
<DD>Bonds read in from the data file were not assigned correctly to atoms.
This means there is something invalid about the topology definitions.
<DT><I>Bonds defined but no bond types</I>
<DD>The data file header lists bonds but no bond types.
<DT><I>Both sides of boundary must be periodic</I>
<DD>Cannot specify a boundary as periodic only on the lo or hi side. Must
be periodic on both sides.
<DT><I>Boundary command after simulation box is defined</I>
<DD>The boundary command cannot be used after a read_data, read_restart,
or create_box command.
<DT><I>Box bounds are invalid</I>
<DD>The box boundaries specified in the read_data file are invalid. The
lo value must be less than the hi value for all 3 dimensions.
<DT><I>Can not specify Pxy/Pxz/Pyz in fix box/relax with non-triclinic box</I>
<DD>Only triclinic boxes can be used with off-diagonal pressure components.
See the region prism command for details.
<DT><I>Can not specify Pxy/Pxz/Pyz in fix nvt/npt/nph with non-triclinic box</I>
<DD>Only triclinic boxes can be used with off-diagonal pressure components.
See the region prism command for details.
<DT><I>Can only use NEB with 1-processor replicas</I>
<DD>This is current restriction for NEB as implemented in LAMMPS.
<DT><I>Can only use TAD with 1-processor replicas for NEB</I>
<DD>This is current restriction for NEB as implemented in LAMMPS.
<DT><I>Cannot (yet) use PPPM with triclinic box</I>
<DD>This feature is not yet supported.
<DT><I>Cannot add atoms to fix move variable</I>
<DD>Atoms can not be added afterwards to this fix option.
<DT><I>Cannot change box to orthogonal when tilt is non-zero</I>
<DD>Self-explanatory
<DT><I>Cannot change box with certain fixes defined</I>
<DD>The change_box command cannot be used when fix ave/spatial or
fix/deform are defined .
<DT><I>Cannot change box with dumps defined</I>
<DD>Self-explanatory.
<DT><I>Cannot change dump_modify every for dump dcd</I>
<DD>The frequency of writing dump dcd snapshots cannot be changed.
<DT><I>Cannot change dump_modify every for dump xtc</I>
<DD>The frequency of writing dump xtc snapshots cannot be changed.
<DT><I>Cannot change timestep once fix srd is setup</I>
<DD>This is because various SRD properties depend on the timestep
size.
<DT><I>Cannot change timestep with fix pour</I>
<DD>This fix pre-computes some values based on the timestep, so it cannot
be changed during a simulation run.
<DT><I>Cannot compute PPPM G</I>
<DD>LAMMPS failed to compute a valid approximation for the PPPM g_ewald
factor that partitions the computation between real space and k-space.
<DT><I>Cannot create an atom map unless atoms have IDs</I>
<DD>The simulation requires a mapping from global atom IDs to local atoms,
but the atoms that have been defined have no IDs.
<DT><I>Cannot create atoms with undefined lattice</I>
<DD>Must use the lattice command before using the create_atoms
command.
<DT><I>Cannot create/grow a vector/array of pointers for %s</I>
<DD>LAMMPS code is making an illegal call to the templated memory
allocaters, to create a vector or array of pointers.
<DT><I>Cannot create_atoms after reading restart file with per-atom info</I>
<DD>The per-atom info was stored to be used when by a fix that you
may re-define. If you add atoms before re-defining the fix, then
there will not be a correct amount of per-atom info.
<DT><I>Cannot create_box after simulation box is defined</I>
<DD>The create_box command cannot be used after a read_data, read_restart,
or create_box command.
<DT><I>Cannot currently use pair reax with pair hybrid</I>
<DD>This is not yet supported.
<DT><I>Cannot delete group all</I>
<DD>Self-explanatory.
<DT><I>Cannot delete group currently used by a compute</I>
<DD>Self-explanatory.
<DT><I>Cannot delete group currently used by a dump</I>
<DD>Self-explanatory.
<DT><I>Cannot delete group currently used by a fix</I>
<DD>Self-explanatory.
<DT><I>Cannot delete group currently used by atom_modify first</I>
<DD>Self-explanatory.
<DT><I>Cannot displace_atoms after reading restart file with per-atom info</I>
<DD>This is because the restart file info cannot be migrated with the
atoms. You can get around this by performing a 0-timestep run which
will assign the restart file info to actual atoms.
<DT><I>Cannot displace_box after reading restart file with per-atom info</I>
<DD>This is because the restart file info cannot be migrated with the
atoms. You can get around this by performing a 0-timestep run which
will assign the restart file info to actual atoms.
<DT><I>Cannot displace_box on a non-periodic boundary</I>
<DD>Self-explanatory.
<DT><I>Cannot dump sort on atom IDs with no atom IDs defined</I>
<DD>Self-explanatory.
<DT><I>Cannot evaporate atoms in atom_modify first group</I>
<DD>This is a restriction due to the way atoms are organized in
a list to enable the atom_modify first command.
<DT><I>Cannot find delete_bonds group ID</I>
<DD>Group ID used in the delete_bonds command does not exist.
<DT><I>Cannot have both pair_modify shift and tail set to yes</I>
<DD>These 2 options are contradictory.
<DT><I>Cannot open AIREBO potential file %s</I>
<DD>The specified AIREBO potential file cannot be opened. Check that the
path and name are correct.
<DT><I>Cannot open COMB potential file %s</I>
<DD>The specified COMB potential file cannot be opened. Check that the
path and name are correct.
<DT><I>Cannot open EAM potential file %s</I>
<DD>The specified EAM potential file cannot be opened. Check that the
path and name are correct.
<DT><I>Cannot open EIM potential file %s</I>
<DD>The specified EIM potential file cannot be opened. Check that the
path and name are correct.
<DT><I>Cannot open MEAM potential file %s</I>
<DD>The specified MEAM potential file cannot be opened. Check that the
path and name are correct.
<DT><I>Cannot open Stillinger-Weber potential file %s</I>
<DD>The specified SW potential file cannot be opened. Check that the path
and name are correct.
<DT><I>Cannot open Tersoff potential file %s</I>
<DD>The specified Tersoff potential file cannot be opened. Check that the
path and name are correct.
<DT><I>Cannot open dir to search for restart file</I>
<DD>Using a "*" in the name of the restart file will open the current
directory to search for matching file names.
<DT><I>Cannot open dump file</I>
<DD>The output file for the dump command cannot be opened. Check that the
path and name are correct.
<DT><I>Cannot open file %s</I>
<DD>The specified file cannot be opened. Check that the path and name are
correct.
<DT><I>Cannot open fix ave/correlate file %s</I>
<DD>The specified file cannot be opened. Check that the path and name are
correct.
<DT><I>Cannot open fix ave/histo file %s</I>
<DD>The specified file cannot be opened. Check that the path and name are
correct.
<DT><I>Cannot open fix ave/spatial file %s</I>
<DD>The specified file cannot be opened. Check that the path and name are
correct.
<DT><I>Cannot open fix ave/time file %s</I>
<DD>The specified file cannot be opened. Check that the path and name are
correct.
<DT><I>Cannot open fix poems file %s</I>
<DD>The specified file cannot be opened. Check that the path and name are
correct.
<DT><I>Cannot open fix print file %s</I>
<DD>The output file generated by the fix print command cannot be opened
<DT><I>Cannot open fix qeq/comb file %s</I>
<DD>The output file for the fix qeq/combs command cannot be opened.
Check that the path and name are correct.
<DT><I>Cannot open fix reax/bonds file %s</I>
<DD>The output file for the fix reax/bonds command cannot be opened.
Check that the path and name are correct.
<DT><I>Cannot open fix tmd file %s</I>
<DD>The output file for the fix tmd command cannot be opened. Check that
the path and name are correct.
<DT><I>Cannot open fix ttm file %s</I>
<DD>The output file for the fix ttm command cannot be opened. Check that
the path and name are correct.
<DT><I>Cannot open gzipped file</I>
<DD>LAMMPS is attempting to open a gzipped version of the specified file
but was unsuccessful. Check that the path and name are correct.
<DT><I>Cannot open input script %s</I>
<DD>Self-explanatory.
<DT><I>Cannot open log.lammps</I>
<DD>The default LAMMPS log file cannot be opened. Check that the
directory you are running in allows for files to be created.
<DT><I>Cannot open logfile %s</I>
<DD>The LAMMPS log file specified in the input script cannot be opened.
Check that the path and name are correct.
<DT><I>Cannot open logfile</I>
<DD>The LAMMPS log file named in a command-line argument cannot be opened.
Check that the path and name are correct.
<DT><I>Cannot open pair_write file</I>
<DD>The specified output file for pair energies and forces cannot be
opened. Check that the path and name are correct.
<DT><I>Cannot open restart file %s</I>
<DD>Self-explanatory.
<DT><I>Cannot open screen file</I>
<DD>The screen file specified as a command-line argument cannot be
opened. Check that the directory you are running in allows for files
to be created.
<DT><I>Cannot open universe log file</I>
<DD>For a multi-partition run, the master log file cannot be opened.
Check that the directory you are running in allows for files to be
created.
<DT><I>Cannot open universe screen file</I>
<DD>For a multi-partition run, the master screen file cannot be opened.
Check that the directory you are running in allows for files to be
created.
<DT><I>Cannot read_data after simulation box is defined</I>
<DD>The read_data command cannot be used after a read_data,
read_restart, or create_box command.
<DT><I>Cannot read_restart after simulation box is defined</I>
<DD>The read_restart command cannot be used after a read_data,
read_restart, or create_box command.
<DT><I>Cannot redefine variable as a different style</I>
<DD>An equal-style variable can be re-defined but only if it was
originally an equal-style variable.
<DT><I>Cannot replicate 2d simulation in z dimension</I>
<DD>The replicate command cannot replicate a 2d simulation in the z
dimension.
<DT><I>Cannot replicate with fixes that store atom quantities</I>
<DD>Either fixes are defined that create and store atom-based vectors or a
restart file was read which included atom-based vectors for fixes.
The replicate command cannot duplicate that information for new atoms.
You should use the replicate command before fixes are applied to the
system.
<DT><I>Cannot reset timestep with a dynamic region defined</I>
<DD>Dynamic regions (see the region command) have a time dependence.
Thus you cannot change the timestep when one or more of these
are defined.
<DT><I>Cannot reset timestep with a time-dependent fix defined</I>
<DD>You cannot reset the timestep when a fix that keeps track of elapsed
time is in place.
<DT><I>Cannot reset timestep with dump file already written to</I>
<DD>Changing the timestep will confuse when a dump file is written. Use
the undump command, then restart the dump file.
<DT><I>Cannot reset timestep with restart file already written</I>
<DD>Changing the timestep will confuse when a restart file is written.
Use the "restart 0" command to turn off restarts, then start them
again.
<DT><I>Cannot restart fix rigid/nvt with different # of chains</I>
<DD>This is because the restart file contains per-chain info.
<DT><I>Cannot run 2d simulation with nonperiodic Z dimension</I>
<DD>Use the boundary command to make the z dimension periodic in order to
run a 2d simulation.
<DT><I>Cannot set both respa pair and inner/middle/outer</I>
<DD>In the rRESPA integrator, you must compute pairwise potentials either
all together (pair), or in pieces (inner/middle/outer). You can't do
both.
<DT><I>Cannot set dipole for this atom style</I>
<DD>This atom style does not support dipole settings for each atom type.
<DT><I>Cannot set dump_modify flush for dump xtc</I>
<DD>Self-explanatory.
<DT><I>Cannot set mass for this atom style</I>
<DD>This atom style does not support mass settings for each atom type.
Instead they are defined on a per-atom basis in the data file.
<DT><I>Cannot set non-zero image flag for non-periodic dimension</I>
<DD>Self-explanatory.
<DT><I>Cannot set non-zero z velocity for 2d simulation</I>
<DD>Self-explanatory.
<DT><I>Cannot set respa middle without inner/outer</I>
<DD>In the rRESPA integrator, you must define both a inner and outer
setting in order to use a middle setting.
<DT><I>Cannot set shape for this atom style</I>
<DD>The atom style does not support this setting.
<DT><I>Cannot set this attribute for this atom style</I>
<DD>The attribute being set does not exist for the defined atom style.
<DT><I>Cannot set variable z velocity for 2d simulation</I>
<DD>Self-explanatory.
<DT><I>Cannot skew triclinic box in z for 2d simulation</I>
<DD>Self-explanatory.
<DT><I>Cannot use Ewald with 2d simulation</I>
<DD>The kspace style ewald cannot be used in 2d simulations. You can use
2d Ewald in a 3d simulation; see the kspace_modify command.
<DT><I>Cannot use Ewald with triclinic box</I>
<DD>This feature is not yet supported.
<DT><I>Cannot use NEB unless atom map exists</I>
<DD>Use the atom_modify command to create an atom map.
<DT><I>Cannot use NEB with a single replica</I>
<DD>Self-explanatory.
<DT><I>Cannot use NEB with atom_modify sort enabled</I>
<DD>This is current restriction for NEB implemented in LAMMPS.
<DT><I>Cannot use PPPM with 2d simulation</I>
<DD>The kspace style pppm cannot be used in 2d simulations. You can use
2d PPPM in a 3d simulation; see the kspace_modify command.
<DT><I>Cannot use PRD with a time-dependent fix defined</I>
<DD>PRD alters the timestep in ways that will mess up these fixes.
<DT><I>Cannot use PRD with a time-dependent region defined</I>
<DD>PRD alters the timestep in ways that will mess up these regions.
<DT><I>Cannot use PRD with atom_modify sort enabled</I>
<DD>This is a current restriction of PRD. You must turn off sorting,
which is enabled by default, via the atom_modify command.
<DT><I>Cannot use PRD with multi-processor replicas unless atom map exists</I>
<DD>Use the atom_modify command to create an atom map.
<DT><I>Cannot use TAD unless atom map exists for NEB</I>
<DD>See atom_modify map command to set this.
<DT><I>Cannot use TAD with a single replica for NEB</I>
<DD>NEB requires multiple replicas.
<DT><I>Cannot use TAD with atom_modify sort enabled for NEB</I>
<DD>This is a current restriction of NEB.
<DT><I>Cannot use a damped dynamics min style with fix box/relax</I>
<DD>This is a current restriction in LAMMPS. Use another minimizer
style.
<DT><I>Cannot use a damped dynamics min style with per-atom DOF</I>
<DD>This is a current restriction in LAMMPS. Use another minimizer
style.
<DT><I>Cannot use compute cluster/atom unless atoms have IDs</I>
<DD>Atom IDs are used to identify clusters.
<DT><I>Cannot use cwiggle in variable formula between runs</I>
<DD>This is a function of elapsed time.
<DT><I>Cannot use delete_atoms unless atoms have IDs</I>
<DD>Your atoms do not have IDs, so the delete_atoms command cannot be
used.
<DT><I>Cannot use delete_bonds with non-molecular system</I>
<DD>Your choice of atom style does not have bonds.
<DT><I>Cannot use fix TMD unless atom map exists</I>
<DD>Using this fix requires the ability to lookup an atom index, which is
provided by an atom map. An atom map does not exist (by default) for
non-molecular problems. Using the atom_modify map command will force
an atom map to be created.
<DT><I>Cannot use fix ave/spatial z for 2 dimensional model</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix bond/break with non-molecular systems</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix bond/create with non-molecular systems</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix box/relax on a 2nd non-periodic dimension</I>
<DD>When specifying an off-diagonal pressure component, the 2nd of the two
dimensions must be periodic. E.g. if the xy component is specified,
then the y dimension must be periodic.
<DT><I>Cannot use fix box/relax on a non-periodic dimension</I>
<DD>When specifying a diagonal pressure component, the dimension must be
periodic.
<DT><I>Cannot use fix deform on a 2nd non-periodic boundary</I>
<DD>When specifying a tilt factor change, the 2nd of the two dimensions
must be periodic. E.g. if the xy tilt is specified, then the y
dimension must be periodic.
<DT><I>Cannot use fix deform on a non-periodic boundary</I>
<DD>When specifying a change is a box dimension, the dimension must be
periodic.
<DT><I>Cannot use fix deform trate on a box with zero tilt</I>
<DD>The trate style alters the current strain.
<DT><I>Cannot use fix enforce2d with 3d simulation</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix msst without per-type mass defined</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix npt and fix deform on same component of stress tensor</I>
<DD>This would be changing the same box dimension twice.
<DT><I>Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension</I>
<DD>When specifying an off-diagonal pressure component, the 2nd of the two
dimensions must be periodic. E.g. if the xy component is specified,
then the y dimension must be periodic.
<DT><I>Cannot use fix nvt/npt/nph on a non-periodic dimension</I>
<DD>When specifying a diagonal pressure component, the dimension must be
periodic.
<DT><I>Cannot use fix pour with triclinic box</I>
<DD>This feature is not yet supported.
<DT><I>Cannot use fix press/berendsen and fix deform on same component of stress tensor</I>
<DD>These commands both change the box size/shape, so you cannot use both
together.
<DT><I>Cannot use fix press/berendsen on a non-periodic dimension</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix press/berendsen with triclinic box</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix reax/bonds without pair_style reax</I>
<DD>Self-explantory.
<DT><I>Cannot use fix shake with non-molecular system</I>
<DD>Your choice of atom style does not have bonds.
<DT><I>Cannot use fix ttm with 2d simulation</I>
<DD>This is a current restriction of this fix due to the grid it creates.
<DT><I>Cannot use fix ttm with triclinic box</I>
<DD>This is a current restriction of this fix due to the grid it creates.
<DT><I>Cannot use fix wall in periodic dimension</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix wall zlo/zhi for a 2d simulation</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix wall/reflect in periodic dimension</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix wall/reflect zlo/zhi for a 2d simulation</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix wall/srd in periodic dimension</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix wall/srd more than once</I>
<DD>Nor is their a need to since multiple walls can be specified
in one command.
<DT><I>Cannot use fix wall/srd without fix srd</I>
<DD>Self-explanatory.
<DT><I>Cannot use fix wall/srd zlo/zhi for a 2d simulation</I>
<DD>Self-explanatory.
<DT><I>Cannot use force/neigh with triclinic box</I>
<DD>This is a current limitation of the GPU implementation
in LAMMPS.
<DT><I>Cannot use kspace solver on system with no charge</I>
<DD>No atoms in system have a non-zero charge.
<DT><I>Cannot use neighbor bins - box size << cutoff</I>
<DD>Too many neighbor bins will be created. This typically happens when
the simulation box is very small in some dimension, compared to the
neighbor cutoff. Use the "nsq" style instead of "bin" style.
<DT><I>Cannot use newton pair with GPU CHARMM pair style</I>
<DD>See the newton command to change the setting.
<DT><I>Cannot use newton pair with GPU Gay-Berne pair style</I>
<DD>See the newton command to change the setting.
<DT><I>Cannot use newton pair with GPU LJ pair style</I>
<DD>See the newton command to change the setting.
<DT><I>Cannot use newton pair with GPU LJ96 pair style</I>
<DD>See the newton command to change the setting.
<DT><I>Cannot use non-zero forces in an energy minimization</I>
<DD>Fix setforce cannot be used in this manner. Use fix addforce
instead.
<DT><I>Cannot use nonperiodic boundares with fix ttm</I>
<DD>This fix requires a fully periodic simulation box.
<DT><I>Cannot use nonperiodic boundaries with Ewald</I>
<DD>For kspace style ewald, all 3 dimensions must have periodic boundaries
unless you use the kspace_modify command to define a 2d slab with a
non-periodic z dimension.
<DT><I>Cannot use nonperiodic boundaries with PPPM</I>
<DD>For kspace style pppm, all 3 dimensions must have periodic boundaries
unless you use the kspace_modify command to define a 2d slab with a
non-periodic z dimension.
<DT><I>Cannot use pair hybrid with GPU neighbor builds</I>
<DD>See documentation for fix gpu.
<DT><I>Cannot use pair tail corrections with 2d simulations</I>
<DD>The correction factors are only currently defined for 3d systems.
<DT><I>Cannot use ramp in variable formula between runs</I>
<DD>This is because the ramp() function is time dependent.
<DT><I>Cannot use region INF or EDGE when box does not exist</I>
<DD>Regions that extend to the box boundaries can only be used after the
create_box command has been used.
<DT><I>Cannot use set atom with no atom IDs defined</I>
<DD>Atom IDs are not defined, so they cannot be used to identify an atom.
<DT><I>Cannot use swiggle in variable formula between runs</I>
<DD>This is a function of elapsed time.
<DT><I>Cannot use variable energy with constant force in fix addforce</I>
<DD>This is because for constant force, LAMMPS can compute the change
in energy directly.
<DT><I>Cannot use variable every setting for dump dcd</I>
<DD>The format of DCD dump files requires snapshots be output
at a constant frequency.
<DT><I>Cannot use variable every setting for dump xtc</I>
<DD>The format of this file requires snapshots at regular intervals.
<DT><I>Cannot use vdisplace in variable formula between runs</I>
<DD>This is a function of elapsed time.
<DT><I>Cannot use velocity create loop all unless atoms have IDs</I>
<DD>Atoms in the simulation to do not have IDs, so this style
of velocity creation cannot be performed.
<DT><I>Cannot use wall in periodic dimension</I>
<DD>Self-explanatory.
<DT><I>Cannot wiggle and shear fix wall/gran</I>
<DD>Cannot specify both options at the same time.
<DT><I>Cannot zero momentum of 0 atoms</I>
<DD>The collection of atoms for which momentum is being computed has no
atoms.
<DT><I>Change_box command before simulation box is defined</I>
<DD>Self-explanatory.
<DT><I>Change_box operation is invalid</I>
<DD>Cannot change orthogonal box to orthogonal or a triclinic box to
triclinic.
<DT><I>Communicate group != atom_modify first group</I>
<DD>Self-explanatory.
<DT><I>Compute ID for compute atom/molecule does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID for compute reduce does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID for fix ave/atom does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID for fix ave/correlate does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID for fix ave/histo does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID for fix ave/spatial does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID for fix ave/time does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID for fix store/state does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ID must be alphanumeric or underscore characters</I>
<DD>Self-explanatory.
<DT><I>Compute angle/local used when angles are not allowed</I>
<DD>The atom style does not support angles.
<DT><I>Compute atom/molecule compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule compute does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule compute does not calculate a per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule compute does not calculate per-atom values</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule fix does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule fix does not calculate a per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule fix does not calculate per-atom values</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule requires molecular atom style</I>
<DD>Self-explanatory.
<DT><I>Compute atom/molecule variable is not atom-style variable</I>
<DD>Self-explanatory.
<DT><I>Compute bond/local used when bonds are not allowed</I>
<DD>The atom style does not support bonds.
<DT><I>Compute centro/atom requires a pair style be defined</I>
<DD>This is because the computation of the centro-symmetry values
uses a pairwise neighbor list.
<DT><I>Compute cluster/atom cutoff is longer than pairwise cutoff</I>
<DD>Cannot identify clusters beyond cutoff.
<DT><I>Compute cluster/atom requires a pair style be defined</I>
<DD>This is so that the pair style defines a cutoff distance which
is used to find clusters.
<DT><I>Compute cna/atom cutoff is longer than pairwise cutoff</I>
<DD>Self-explantory.
<DT><I>Compute cna/atom requires a pair style be defined</I>
<DD>Self-explantory.
<DT><I>Compute com/molecule requires molecular atom style</I>
<DD>Self-explanatory.
<DT><I>Compute coord/atom cutoff is longer than pairwise cutoff</I>
<DD>Cannot compute coordination at distances longer than the pair cutoff,
since those atoms are not in the neighbor list.
<DT><I>Compute coord/atom requires a pair style be defined</I>
<DD>Self-explantory.
<DT><I>Compute damage/atom requires peridynamic potential</I>
<DD>Damage is a Peridynamic-specific metric. It requires you
to be running a Peridynamics simulation.
<DT><I>Compute dihedral/local used when dihedrals are not allowed</I>
<DD>The atom style does not support dihedrals.
<DT><I>Compute does not allow an extra compute or fix to be reset</I>
<DD>This is an internal LAMMPS error. Please report it to the
developers.
<DT><I>Compute erotate/asphere cannot be used with atom attributes diameter or rmass</I>
<DD>These attributes override the shape and mass settings, so cannot be
used.
<DT><I>Compute erotate/asphere requires atom attributes angmom, quat, shape</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Compute erotate/asphere requires extended particles</I>
<DD>This compute cannot be used with point paritlces.
<DT><I>Compute erotate/sphere requires atom attribute omega</I>
<DD>An atom style that defines this attribute must be used.
<DT><I>Compute erotate/sphere requires atom attribute radius or shape</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Compute erotate/sphere requires spherical particle shapes</I>
<DD>Self-explanatory.
<DT><I>Compute event/displace has invalid fix event assigned</I>
<DD>This is an internal LAMMPS error. Please report it to the
developers.
<DT><I>Compute group/group group ID does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute gyration/molecule requires molecular atom style</I>
<DD>Self-explanatory.
<DT><I>Compute heat/flux compute ID does not compute ke/atom</I>
<DD>Self-explanatory.
<DT><I>Compute heat/flux compute ID does not compute pe/atom</I>
<DD>Self-explanatory.
<DT><I>Compute heat/flux compute ID does not compute stress/atom</I>
<DD>Self-explanatory.
<DT><I>Compute improper/local used when impropers are not allowed</I>
<DD>The atom style does not support impropers.
<DT><I>Compute msd/molecule requires molecular atom style</I>
<DD>Self-explanatory.
<DT><I>Compute pair must use group all</I>
<DD>Pair styles accumlate energy on all atoms.
<DT><I>Compute pe must use group all</I>
<DD>Energies computed by potentials (pair, bond, etc) are computed on all
atoms.
<DT><I>Compute pressure must use group all</I>
<DD>Virial contributions computed by potentials (pair, bond, etc) are
computed on all atoms.
<DT><I>Compute pressure temperature ID does not compute temperature</I>
<DD>The compute ID assigned to a pressure computation must compute
temperature.
<DT><I>Compute property/atom for atom property that isn't allocated</I>
<DD>Self-explanatory.
<DT><I>Compute property/local cannot use these inputs together</I>
<DD>Only inputs that generate the same number of datums can be used
togther. E.g. bond and angle quantities cannot be mixed.
<DT><I>Compute property/local for property that isn't allocated</I>
<DD>Self-explanatory.
<DT><I>Compute property/molecule requires molecular atom style</I>
<DD>Self-explanatory.
<DT><I>Compute rdf requires a pair style be defined</I>
<DD>Self-explanatory.
<DT><I>Compute reduce compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Compute reduce compute calculates global values</I>
<DD>A compute that calculates peratom or local values is required.
<DT><I>Compute reduce compute does not calculate a local array</I>
<DD>Self-explanatory.
<DT><I>Compute reduce compute does not calculate a local vector</I>
<DD>Self-explanatory.
<DT><I>Compute reduce compute does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Compute reduce compute does not calculate a per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Compute reduce fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Compute reduce fix calculates global values</I>
<DD>A fix that calculates peratom or local values is required.
<DT><I>Compute reduce fix does not calculate a local array</I>
<DD>Self-explanatory.
<DT><I>Compute reduce fix does not calculate a local vector</I>
<DD>Self-explanatory.
<DT><I>Compute reduce fix does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Compute reduce fix does not calculate a per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Compute reduce replace requires min or max mode</I>
<DD>Self-explanatory.
<DT><I>Compute reduce variable is not atom-style variable</I>
<DD>Self-explanatory.
<DT><I>Compute temp/asphere cannot be used with atom attributes diameter or rmass</I>
<DD>These attributes override the shape and mass settings, so cannot be
used.
<DT><I>Compute temp/asphere requires atom attributes angmom, quat, shape</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Compute temp/asphere requires extended particles</I>
<DD>This compute cannot be used with point paritlces.
<DT><I>Compute temp/partial cannot use vz for 2d systemx</I>
<DD>Self-explanatory.
<DT><I>Compute temp/profile cannot bin z for 2d systems</I>
<DD>Self-explanatory.
<DT><I>Compute temp/profile cannot use vz for 2d systemx</I>
<DD>Self-explanatory.
<DT><I>Compute temp/sphere requires atom attribute omega</I>
<DD>An atom style that defines this attribute must be used.
<DT><I>Compute temp/sphere requires atom attribute radius or shape</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Compute temp/sphere requires spherical particle shapes</I>
<DD>Self-explanatory.
<DT><I>Compute ti kspace style does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ti pair style does not exist</I>
<DD>Self-explanatory.
<DT><I>Compute ti tail when pair style does not compute tail corrections</I>
<DD>Self-explanatory.
<DT><I>Compute used in variable between runs is not current</I>
<DD>Computes cannot be invoked by a variable in between runs. Thus they
must have been evaluated on the last timestep of the previous run in
order for their value(s) to be accessed. See the doc page for the
variable command for more info.
<DT><I>Compute used in variable thermo keyword between runs is not current</I>
<DD>Some thermo keywords rely on a compute to calculate their value(s).
Computes cannot be invoked by a variable in between runs. Thus they
must have been evaluated on the last timestep of the previous run in
order for their value(s) to be accessed. See the doc page for the
variable command for more info.
<DT><I>Computed temperature for fix temp/berendsen cannot be 0.0</I>
<DD>Self-explanatory.
<DT><I>Computed temperature for fix temp/rescale cannot be 0.0</I>
<DD>Cannot rescale the temperature to a new value if the current
temperature is 0.0.
<DT><I>Could not count initial bonds in fix bond/create</I>
<DD>Could not find one of the atoms in a bond on this processor.
<DT><I>Could not create 3d FFT plan</I>
<DD>The FFT setup in pppm failed.
<DT><I>Could not create 3d remap plan</I>
<DD>The FFT setup in pppm failed.
<DT><I>Could not find atom_modify first group ID</I>
<DD>Self-explanatory.
<DT><I>Could not find compute ID for PRD</I>
<DD>Self-explanatory.
<DT><I>Could not find compute ID for TAD</I>
<DD>Self-explanatory.
<DT><I>Could not find compute ID for temperature bias</I>
<DD>Self-explanatory.
<DT><I>Could not find compute ID to delete</I>
<DD>Self-explanatory.
<DT><I>Could not find compute displace/atom fix ID</I>
<DD>Self-explanatory.
<DT><I>Could not find compute event/displace fix ID</I>
<DD>Self-explanatory.
<DT><I>Could not find compute group ID</I>
<DD>Self-explanatory.
<DT><I>Could not find compute heat/flux compute ID</I>
<DD>Self-explanatory.
<DT><I>Could not find compute msd fix ID</I>
<DD>Self-explanatory.
<DT><I>Could not find compute pressure temperature ID</I>
<DD>The compute ID for calculating temperature does not exist.
<DT><I>Could not find compute_modify ID</I>
<DD>Self-explanatory.
<DT><I>Could not find delete_atoms group ID</I>
<DD>Group ID used in the delete_atoms command does not exist.
<DT><I>Could not find delete_atoms region ID</I>
<DD>Region ID used in the delete_atoms command does not exist.
<DT><I>Could not find displace_atoms group ID</I>
<DD>Group ID used in the displace_atoms command does not exist.
<DT><I>Could not find displace_box group ID</I>
<DD>Group ID used in the displace_box command does not exist.
<DT><I>Could not find dump cfg compute ID</I>
<DD>Self-explanatory.
<DT><I>Could not find dump cfg fix ID</I>
<DD>Self-explanatory.
<DT><I>Could not find dump cfg variable name</I>
<DD>Self-explanatory.
<DT><I>Could not find dump custom compute ID</I>
<DD>The compute ID needed by dump custom to compute a per-atom quantity
does not exist.
<DT><I>Could not find dump custom fix ID</I>
<DD>Self-explanatory.
<DT><I>Could not find dump custom variable name</I>
<DD>Self-explanatory.
<DT><I>Could not find dump group ID</I>
<DD>A group ID used in the dump command does not exist.
<DT><I>Could not find dump local compute ID</I>
<DD>Self-explanatory.
<DT><I>Could not find dump local fix ID</I>
<DD>Self-explanatory.
<DT><I>Could not find dump modify compute ID</I>
<DD>Self-explanatory.
<DT><I>Could not find dump modify fix ID</I>
<DD>Self-explanatory.
<DT><I>Could not find dump modify variable name</I>
<DD>Self-explanatory.
<DT><I>Could not find fix ID to delete</I>
<DD>Self-explanatory.
<DT><I>Could not find fix group ID</I>
<DD>A group ID used in the fix command does not exist.
<DT><I>Could not find fix msst compute ID</I>
<DD>Self-explanatory.
<DT><I>Could not find fix poems group ID</I>
<DD>A group ID used in the fix poems command does not exist.
<DT><I>Could not find fix recenter group ID</I>
<DD>A group ID used in the fix recenter command does not exist.
<DT><I>Could not find fix rigid group ID</I>
<DD>A group ID used in the fix rigid command does not exist.
<DT><I>Could not find fix srd group ID</I>
<DD>Self-explanatory.
<DT><I>Could not find fix_modify ID</I>
<DD>A fix ID used in the fix_modify command does not exist.
<DT><I>Could not find fix_modify pressure ID</I>
<DD>The compute ID for computing pressure does not exist.
<DT><I>Could not find fix_modify temperature ID</I>
<DD>The compute ID for computing temperature does not exist.
<DT><I>Could not find group delete group ID</I>
<DD>Self-explanatory.
<DT><I>Could not find/initialize a specified accelerator device</I>
<DD>Your GPU setup is invalid.
<DT><I>Could not find set group ID</I>
<DD>Group ID specified in set command does not exist.
<DT><I>Could not find thermo compute ID</I>
<DD>Compute ID specified in thermo_style command does not exist.
<DT><I>Could not find thermo custom compute ID</I>
<DD>The compute ID needed by thermo style custom to compute a requested
quantity does not exist.
<DT><I>Could not find thermo custom fix ID</I>
<DD>The fix ID needed by thermo style custom to compute a requested
quantity does not exist.
<DT><I>Could not find thermo custom variable name</I>
<DD>Self-explanatory.
<DT><I>Could not find thermo fix ID</I>
<DD>Fix ID specified in thermo_style command does not exist.
<DT><I>Could not find thermo_modify pressure ID</I>
<DD>The compute ID needed by thermo style custom to compute pressure does
not exist.
<DT><I>Could not find thermo_modify temperature ID</I>
<DD>The compute ID needed by thermo style custom to compute temperature does
not exist.
<DT><I>Could not find undump ID</I>
<DD>A dump ID used in the undump command does not exist.
<DT><I>Could not find velocity group ID</I>
<DD>A group ID used in the velocity command does not exist.
<DT><I>Could not find velocity temperature ID</I>
<DD>The compute ID needed by the velocity command to compute temperature
does not exist.
<DT><I>Could not grab element entry from EIM potential file</I>
<DD>Self-explanatory
<DT><I>Could not grab global entry from EIM potential file</I>
<DD>Self-explanatory.
<DT><I>Could not grab pair entry from EIM potential file</I>
<DD>Self-explanatory.
<DT><I>Could not set finite-size particle attribute in fix rigid</I>
<DD>The particle has a finite size but its attributes could not be
determined.
<DT><I>Coulomb cutoffs of pair hybrid sub-styles do not match</I>
<DD>If using a Kspace solver, all Coulomb cutoffs of long pair styles must
be the same.
<DT><I>Cound not find dump_modify ID</I>
<DD>Self-explanatory.
<DT><I>Create_atoms command before simulation box is defined</I>
<DD>The create_atoms command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Create_atoms region ID does not exist</I>
<DD>A region ID used in the create_atoms command does not exist.
<DT><I>Create_box region ID does not exist</I>
<DD>A region ID used in the create_box command does not exist.
<DT><I>Create_box region does not support a bounding box</I>
<DD>Not all regions represent bounded volumes. You cannot use
such a region with the create_box command.
<DT><I>Cyclic loop in joint connections</I>
<DD>Fix poems cannot (yet) work with coupled bodies whose joints connect
the bodies in a ring (or cycle).
<DT><I>Degenerate lattice primitive vectors</I>
<DD>Invalid set of 3 lattice vectors for lattice command.
<DT><I>Delete region ID does not exist</I>
<DD>Self-explanatory.
<DT><I>Delete_atoms command before simulation box is defined</I>
<DD>The delete_atoms command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Delete_atoms cutoff > neighbor cutoff</I>
<DD>Cannot delete atoms further away than a processor knows about.
<DT><I>Delete_atoms requires a pair style be defined</I>
<DD>This is because atom deletion within a cutoff uses a pairwise
neighbor list.
<DT><I>Delete_bonds command before simulation box is defined</I>
<DD>The delete_bonds command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Delete_bonds command with no atoms existing</I>
<DD>No atoms are yet defined so the delete_bonds command cannot be used.
<DT><I>Deposition region extends outside simulation box</I>
<DD>Self-explanatory.
<DT><I>Did not assign all atoms correctly</I>
<DD>Atoms read in from a data file were not assigned correctly to
processors. This is likely due to some atom coordinates being
outside a non-periodic simulation box.
<DT><I>Did not find all elements in MEAM library file</I>
<DD>The requested elements were not found in the MEAM file.
<DT><I>Did not find fix shake partner info</I>
<DD>Could not find bond partners implied by fix shake command. This error
can be triggered if the delete_bonds command was used before fix
shake, and it removed bonds without resetting the 1-2, 1-3, 1-4
weighting list via the special keyword.
<DT><I>Did not find keyword in table file</I>
<DD>Keyword used in pair_coeff command was not found in table file.
<DT><I>Did not set temp for fix rigid/nvt</I>
<DD>The temp keyword must be used.
<DT><I>Dihedral atom missing in delete_bonds</I>
<DD>The delete_bonds command cannot find one or more atoms in a particular
dihedral on a particular processor. The pairwise cutoff is too short
or the atoms are too far apart to make a valid dihedral.
<DT><I>Dihedral atom missing in set command</I>
<DD>The set command cannot find one or more atoms in a particular dihedral
on a particular processor. The pairwise cutoff is too short or the
atoms are too far apart to make a valid dihedral.
<DT><I>Dihedral atoms %d %d %d %d missing on proc %d at step</I>
<DD>One or more of 4 atoms needed to compute a particular dihedral are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the dihedral has blown apart and an atom is
too far away.
<DT><I>Dihedral charmm is incompatible with Pair style</I>
<DD>Dihedral style charmm must be used with a pair style charmm
in order for the 1-4 epsilon/sigma parameters to be defined.
<DT><I>Dihedral coeff for hybrid has invalid style</I>
<DD>Dihedral style hybrid uses another dihedral style as one of its
coefficients. The dihedral style used in the dihedral_coeff command
or read from a restart file is not recognized.
<DT><I>Dihedral coeffs are not set</I>
<DD>No dihedral coefficients have been assigned in the data file or via
the dihedral_coeff command.
<DT><I>Dihedral style hybrid cannot have hybrid as an argument</I>
<DD>Self-explanatory.
<DT><I>Dihedral style hybrid cannot have none as an argument</I>
<DD>Self-explanatory.
<DT><I>Dihedral style hybrid cannot use same dihedral style twice</I>
<DD>Self-explanatory.
<DT><I>Dihedral_coeff command before dihedral_style is defined</I>
<DD>Coefficients cannot be set in the data file or via the dihedral_coeff
command until an dihedral_style has been assigned.
<DT><I>Dihedral_coeff command before simulation box is defined</I>
<DD>The dihedral_coeff command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Dihedral_coeff command when no dihedrals allowed</I>
<DD>The chosen atom style does not allow for dihedrals to be defined.
<DT><I>Dihedral_style command when no dihedrals allowed</I>
<DD>The chosen atom style does not allow for dihedrals to be defined.
<DT><I>Dihedrals assigned incorrectly</I>
<DD>Dihedrals read in from the data file were not assigned correctly to
atoms. This means there is something invalid about the topology
definitions.
<DT><I>Dihedrals defined but no dihedral types</I>
<DD>The data file header lists dihedrals but no dihedral types.
<DT><I>Dimension command after simulation box is defined</I>
<DD>The dimension command cannot be used after a read_data,
read_restart, or create_box command.
<DT><I>Dipole command before simulation box is defined</I>
<DD>The dipole command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Displace_atoms command before simulation box is defined</I>
<DD>The displace_atoms command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Displace_box command before simulation box is defined</I>
<DD>Self-explanatory.
<DT><I>Displace_box tilt factors require triclinic box</I>
<DD>Cannot use tilt factors unless the simulation box is
non-orthogonal.
<DT><I>Distance must be > 0 for compute event/displace</I>
<DD>Self-explanatory.
<DT><I>Divide by 0 in influence function of pair peri/lps</I>
<DD>This should not normally occur. It is likely a problem with your
model.
<DT><I>Divide by 0 in variable formula</I>
<DD>Self-explanatory.
<DT><I>Domain too large for neighbor bins</I>
<DD>The domain has become extremely large so that neighbor bins cannot be
used. Most likely, one or more atoms have been blown out of the
simulation box to a great distance.
<DT><I>Double precision is not supported on this accelerator.</I>
<DD>In this case, you must compile the GPU library for single precision.
<DT><I>Dump cfg and fix not computed at compatible times</I>
<DD>The fix must produce per-atom quantities on timesteps that dump cfg
needs them.
<DT><I>Dump cfg arguments must start with 'id type xs ys zs'</I>
<DD>This is a requirement of the CFG output format.
<DT><I>Dump cfg requires one snapshot per file</I>
<DD>Use the wildcard "*" character in the filename.
<DT><I>Dump custom and fix not computed at compatible times</I>
<DD>The fix must produce per-atom quantities on timesteps that dump custom
needs them.
<DT><I>Dump custom compute does not calculate per-atom array</I>
<DD>Self-explanatory.
<DT><I>Dump custom compute does not calculate per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Dump custom compute does not compute per-atom info</I>
<DD>Self-explanatory.
<DT><I>Dump custom compute vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Dump custom fix does not compute per-atom array</I>
<DD>Self-explanatory.
<DT><I>Dump custom fix does not compute per-atom info</I>
<DD>Self-explanatory.
<DT><I>Dump custom fix does not compute per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Dump custom fix vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Dump custom variable is not atom-style variable</I>
<DD>Only atom-style variables generate per-atom quantities, needed for
dump output.
<DT><I>Dump dcd of non-matching # of atoms</I>
<DD>Every snapshot written by dump dcd must contain the same # of atoms.
<DT><I>Dump dcd requires sorting by atom ID</I>
<DD>Use the dump_modify sort command to enable this.
<DT><I>Dump every variable returned a bad timestep</I>
<DD>The variable must return a timestep greater than the current timestep.
<DT><I>Dump local and fix not computed at compatible times</I>
<DD>The fix must produce per-atom quantities on timesteps that dump local
needs them.
<DT><I>Dump local attributes contain no compute or fix</I>
<DD>Self-explanatory.
<DT><I>Dump local cannot sort by atom ID</I>
<DD>This is because dump local does not really dump per-atom info.
<DT><I>Dump local compute does not calculate local array</I>
<DD>Self-explanatory.
<DT><I>Dump local compute does not calculate local vector</I>
<DD>Self-explanatory.
<DT><I>Dump local compute does not compute local info</I>
<DD>Self-explanatory.
<DT><I>Dump local compute vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Dump local count is not consistent across input fields</I>
<DD>Every column of output must be the same length.
<DT><I>Dump local fix does not compute local array</I>
<DD>Self-explanatory.
<DT><I>Dump local fix does not compute local info</I>
<DD>Self-explanatory.
<DT><I>Dump local fix does not compute local vector</I>
<DD>Self-explanatory.
<DT><I>Dump local fix vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Dump modify compute ID does not compute per-atom array</I>
<DD>Self-explanatory.
<DT><I>Dump modify compute ID does not compute per-atom info</I>
<DD>Self-explanatory.
<DT><I>Dump modify compute ID does not compute per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Dump modify compute ID vector is not large enough</I>
<DD>Self-explanatory.
<DT><I>Dump modify element names do not match atom types</I>
<DD>Number of element names must equal number of atom types.
<DT><I>Dump modify fix ID does not compute per-atom array</I>
<DD>Self-explanatory.
<DT><I>Dump modify fix ID does not compute per-atom info</I>
<DD>Self-explanatory.
<DT><I>Dump modify fix ID does not compute per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Dump modify fix ID vector is not large enough</I>
<DD>Self-explanatory.
<DT><I>Dump modify variable is not atom-style variable</I>
<DD>Self-explanatory.
<DT><I>Dump sort column is invalid</I>
<DD>Self-explanatory.
<DT><I>Dump xtc requires sorting by atom ID</I>
<DD>Use the dump_modify sort command to enable this.
<DT><I>Dump_modify region ID does not exist</I>
<DD>Self-explanatory.
<DT><I>Dumping an atom property that isn't allocated</I>
<DD>The chosen atom style does not define the per-atom quantity being
dumped.
<DT><I>Dumping an atom quantity that isn't allocated</I>
<DD>Only per-atom quantities that are defined for the atom style being
used are allowed.
<DT><I>Duplicate particle in PeriDynamic bond - simulation box is too small</I>
<DD>This is likely because your box length is shorter than 2 times
the bond length.
<DT><I>Electronic temperature dropped below zero</I>
<DD>Something has gone wrong with the fix ttm electron temperature model.
<DT><I>Empty brackets in variable</I>
<DD>There is no variable syntax that uses empty brackets. Check
the variable doc page.
<DT><I>Energy was not tallied on needed timestep</I>
<DD>You are using a thermo keyword that requires potentials to
have tallied energy, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work.
<DT><I>Expected floating point parameter in input script or data file</I>
<DD>The quantity being read is an integer on non-numeric value.
<DT><I>Expected floating point parameter in variable definition</I>
<DD>The quantity being read is a non-numeric value.
<DT><I>Expected integer parameter in input script or data file</I>
<DD>The quantity being read is a floating point or non-numeric value.
<DT><I>Expected integer parameter in variable definition</I>
<DD>The quantity being read is a floating point or non-numeric value.
<DT><I>Failed to allocate %d bytes for array %s</I>
<DD>Your LAMMPS simulation has run out of memory. You need to run a
smaller simulation or on more processors.
<DT><I>Failed to reallocate %d bytes for array %s</I>
<DD>Your LAMMPS simulation has run out of memory. You need to run a
smaller simulation or on more processors.
<DT><I>Fewer SRD bins than processors in some dimension</I>
<DD>This is not allowed. Make your SRD bin size smaller.
<DT><I>Final box dimension due to fix deform is < 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix gpu split must be positive for hybrid pair styles.</I>
<DD>See documentation for fix gpu.
<DT><I>Fix ID for compute atom/molecule does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix ID for compute reduce does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix ID for fix ave/atom does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix ID for fix ave/correlate does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix ID for fix ave/histo does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix ID for fix ave/spatial does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix ID for fix ave/time does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix ID for fix store/state does not exist</I>
<DD>Self-explanatory
<DT><I>Fix ID must be alphanumeric or underscore characters</I>
<DD>Self-explanatory.
<DT><I>Fix SRD cannot have both atom attributes angmom and omega</I>
<DD>Use either spheroid solute particles or fully generalized
aspherical solute particles.
<DT><I>Fix SRD no-slip requires atom attribute torque</I>
<DD>This is because the SRD collisions will impart torque to the solute
particles.
<DT><I>Fix SRD requires atom attribute angmom or omega</I>
<DD>This is because the SRD collisions with cause the solute particles to
rotate.
<DT><I>Fix SRD requires atom attribute radius or shape</I>
<DD>This is because the solute particles must be finite-size particles,
not point particles.
<DT><I>Fix SRD: bad bin assignment for SRD advection</I>
<DD>Something has gone wrong in your SRD model; try using more
conservative settings.
<DT><I>Fix SRD: bad search bin assignment</I>
<DD>Something has gone wrong in your SRD model; try using more
conservative settings.
<DT><I>Fix SRD: bad stencil bin for big particle</I>
<DD>Something has gone wrong in your SRD model; try using more
conservative settings.
<DT><I>Fix SRD: too many big particles in bin</I>
<DD>Reset the ATOMPERBIN parameter at the top of fix_srd.cpp
to a larger value, and re-compile the code.
<DT><I>Fix SRD: too many walls in bin</I>
<DD>This should not happen unless your system has been setup incorrectly.
<DT><I>Fix adapt kspace style does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix adapt pair style does not exist</I>
<DD>Self-explanatory
<DT><I>Fix adapt pair style param not supported</I>
<DD>The pair style does not know about the parameter you specified.
<DT><I>Fix adapt requires atom attribute diameter</I>
<DD>The atom style being used does not specify an atom diameter.
<DT><I>Fix adapt type pair range is not valid for pair hybrid sub-style</I>
<DD>Self-explanatory.
<DT><I>Fix ave/atom compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/atom compute does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/atom compute does not calculate a per-atom vector</I>
<DD>A compute used by fix ave/atom must generate per-atom values.
<DT><I>Fix ave/atom compute does not calculate per-atom values</I>
<DD>A compute used by fix ave/atom must generate per-atom values.
<DT><I>Fix ave/atom fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/atom fix does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/atom fix does not calculate a per-atom vector</I>
<DD>A fix used by fix ave/atom must generate per-atom values.
<DT><I>Fix ave/atom fix does not calculate per-atom values</I>
<DD>A fix used by fix ave/atom must generate per-atom values.
<DT><I>Fix ave/atom variable is not atom-style variable</I>
<DD>A variable used by fix ave/atom must generate per-atom values.
<DT><I>Fix ave/histo cannot input local values in scalar mode</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo cannot input per-atom values in scalar mode</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate a global array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate a global scalar</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate a global vector</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate a local array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate a local vector</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate a per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate local values</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute does not calculate per-atom values</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo compute vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate a global array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate a global scalar</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate a global vector</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate a local array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate a local vector</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate a per-atom vector</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate local values</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix does not calculate per-atom values</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo fix vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo input is invalid compute</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo input is invalid fix</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo input is invalid variable</I>
<DD>Self-explanatory.
<DT><I>Fix ave/histo inputs are not all global, peratom, or local</I>
<DD>All inputs in a single fix ave/histo command must be of the
same style.
<DT><I>Fix ave/spatial compute does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/spatial compute does not calculate a per-atom vector</I>
<DD>A compute used by fix ave/spatial must generate per-atom values.
<DT><I>Fix ave/spatial compute does not calculate per-atom values</I>
<DD>A compute used by fix ave/spatial must generate per-atom values.
<DT><I>Fix ave/spatial compute vector is accessed out-of-range</I>
<DD>The index for the vector is out of bounds.
<DT><I>Fix ave/spatial fix does not calculate a per-atom array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/spatial fix does not calculate a per-atom vector</I>
<DD>A fix used by fix ave/spatial must generate per-atom values.
<DT><I>Fix ave/spatial fix does not calculate per-atom values</I>
<DD>A fix used by fix ave/spatial must generate per-atom values.
<DT><I>Fix ave/spatial fix vector is accessed out-of-range</I>
<DD>The index for the vector is out of bounds.
<DT><I>Fix ave/spatial for triclinic boxes requires units reduced</I>
<DD>Self-explanatory.
<DT><I>Fix ave/spatial settings invalid with changing box</I>
<DD>If the ave setting is "running" or "window" and the box size/shape
changes during the simulation, then the units setting must be
"reduced", else the number of bins may change.
<DT><I>Fix ave/spatial variable is not atom-style variable</I>
<DD>A variable used by fix ave/spatial must generate per-atom values.
<DT><I>Fix ave/time cannot set output array intensive/extensive from these inputs</I>
<DD>One of more of the vector inputs has individual elements which are
flagged as intensive or extensive. Such an input cannot be flagged as
all intensive/extensive when turned into an array by fix ave/time.
<DT><I>Fix ave/time cannot use variable with vector mode</I>
<DD>Variables produce scalar values.
<DT><I>Fix ave/time columns are inconsistent lengths</I>
<DD>Self-explanatory.
<DT><I>Fix ave/time compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/time compute does not calculate a scalar</I>
<DD>Only computes that calculate a scalar or vector quantity (not a
per-atom quantity) can be used with fix ave/time.
<DT><I>Fix ave/time compute does not calculate a vector</I>
<DD>Only computes that calculate a scalar or vector quantity (not a
per-atom quantity) can be used with fix ave/time.
<DT><I>Fix ave/time compute does not calculate an array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/time compute vector is accessed out-of-range</I>
<DD>The index for the vector is out of bounds.
<DT><I>Fix ave/time fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix ave/time fix does not calculate a scalar</I>
<DD>A fix used by fix ave/time must generate global values.
<DT><I>Fix ave/time fix does not calculate a vector</I>
<DD>A fix used by fix ave/time must generate global values.
<DT><I>Fix ave/time fix does not calculate an array</I>
<DD>Self-explanatory.
<DT><I>Fix ave/time fix vector is accessed out-of-range</I>
<DD>The index for the vector is out of bounds.
<DT><I>Fix ave/time variable is not equal-style variable</I>
<DD>A variable used by fix ave/time must generate a global value.
<DT><I>Fix bond/break requires special_bonds = 0,1,1</I>
<DD>This is a restriction of the current fix bond/break implementation.
<DT><I>Fix bond/create cutoff is longer than pairwise cutoff</I>
<DD>This is not allowed because bond creation is done using the
pairwise neighbor list.
<DT><I>Fix bond/create requires special_bonds coul = 0,1,1</I>
<DD>Self-explanatory.
<DT><I>Fix bond/create requires special_bonds lj = 0,1,1</I>
<DD>Self-explanatory.
<DT><I>Fix bond/swap cannot use dihedral or improper styles</I>
<DD>These styles cannot be defined when using this fix.
<DT><I>Fix bond/swap requires pair and bond styles</I>
<DD>Self-explanatory.
<DT><I>Fix bond/swap requires special_bonds = 0,1,1</I>
<DD>Self-explanatory.
<DT><I>Fix box/relax generated negative box length</I>
<DD>The pressure being applied is likely too large. Try applying
it incrementally, to build to the high pressure.
<DT><I>Fix command before simulation box is defined</I>
<DD>The fix command cannot be used before a read_data, read_restart, or
create_box command.
<DT><I>Fix deform is changing yz by too much with changing xy</I>
<DD>When both yz and xy are changing, it induces changes in xz if the
box must flip from one tilt extreme to another. Thus it is not
allowed for yz to grow so much that a flip is induced.
<DT><I>Fix deform tilt factors require triclinic box</I>
<DD>Cannot deform the tilt factors of a simulation box unless it
is a triclinic (non-orthogonal) box.
<DT><I>Fix deform volume setting is invalid</I>
<DD>Cannot use volume style unless other dimensions are being controlled.
<DT><I>Fix deposit region cannot be dynamic</I>
<DD>Only static regions can be used with fix deposit.
<DT><I>Fix deposit region does not support a bounding box</I>
<DD>Not all regions represent bounded volumes. You cannot use
such a region with the fix deposit command.
<DT><I>Fix efield requires atom attribute q</I>
<DD>Self-explanatory.
<DT><I>Fix evaporate molecule requires atom attribute molecule</I>
<DD>The atom style being used does not define a molecule ID.
<DT><I>Fix external callback function not set</I>
<DD>This must be done by an external program in order to use this fix.
<DT><I>Fix for fix ave/atom not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. Fix ave/atom is
requesting a value on a non-allowed timestep.
<DT><I>Fix for fix ave/correlate not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. Fix ave/correlate
is requesting a value on a non-allowed timestep.
<DT><I>Fix for fix ave/histo not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. Fix ave/histo is
requesting a value on a non-allowed timestep.
<DT><I>Fix for fix ave/spatial not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. Fix ave/spatial is
requesting a value on a non-allowed timestep.
<DT><I>Fix for fix ave/time not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. Fix ave/time
is requesting a value on a non-allowed timestep.
<DT><I>Fix for fix store/state not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. Fix store/state
is requesting a value on a non-allowed timestep.
<DT><I>Fix freeze requires atom attribute torque</I>
<DD>The atom style defined does not have this attribute.
<DT><I>Fix heat group has no atoms</I>
<DD>Self-explanatory.
<DT><I>Fix heat kinetic energy went negative</I>
<DD>This will cause the velocity rescaling about to be performed by fix
heat to be invalid.
<DT><I>Fix in variable not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. The variable is
requesting the values on a non-allowed timestep.
<DT><I>Fix langevin period must be > 0.0</I>
<DD>The time window for temperature relaxation must be > 0
<DT><I>Fix momentum group has no atoms</I>
<DD>Self-explanatory.
<DT><I>Fix move cannot define z or vz variable for 2d problem</I>
<DD>Self-explanatory.
<DT><I>Fix move cannot have 0 length rotation vector</I>
<DD>Self-explanatory.
<DT><I>Fix move cannot rotate aroung non z-axis for 2d problem</I>
<DD>Self-explanatory.
<DT><I>Fix move cannot set linear z motion for 2d problem</I>
<DD>Self-explanatory.
<DT><I>Fix move cannot set wiggle z motion for 2d problem</I>
<DD>Self-explanatory.
<DT><I>Fix msst compute ID does not compute potential energy</I>
<DD>Self-explanatory.
<DT><I>Fix msst compute ID does not compute pressure</I>
<DD>Self-explanatory.
<DT><I>Fix msst compute ID does not compute temperature</I>
<DD>Self-explanatory.
<DT><I>Fix msst requires a periodic box</I>
<DD>Self-explanatory.
<DT><I>Fix msst tscale must satisfy 0 <= tscale < 1</I>
<DD>Self-explanatory.
<DT><I>Fix npt/nph has tilted box too far - box flips are not yet implemented</I>
<DD>This feature has not yet been added. However, if you are applying
an off-diagonal pressure to a fluid, the box may want to tilt indefinitely,
because the fluid cannot support the pressure you are imposing.
<DT><I>Fix nve/asphere cannot be used with atom attributes diameter or rmass</I>
<DD>These attributes override the shape and mass settings, so cannot be
used.
<DT><I>Fix nve/asphere requires atom attributes angmom, quat, torque, shape</I>
<DD>An atom style that specifies these quantities is needed.
<DT><I>Fix nve/asphere requires extended particles</I>
<DD>This fix can only be used for particles with a shape setting.
<DT><I>Fix nve/sphere requires atom attribute diameter or shape</I>
<DD>An atom style that specifies these quantities is needed.
<DT><I>Fix nve/sphere requires atom attribute mu</I>
<DD>An atom style with this attribute is needed.
<DT><I>Fix nve/sphere requires atom attributes omega, torque</I>
<DD>An atom style with these attributes is needed.
<DT><I>Fix nve/sphere requires extended particles</I>
<DD>This fix can only be used for particles of a finite size.
<DT><I>Fix nve/sphere requires spherical particle shapes</I>
<DD>Self-explanatory.
<DT><I>Fix nvt/nph/npt asphere cannot be used with atom attributes diameter or rmass</I>
<DD>Those attributes are for spherical particles.
<DT><I>Fix nvt/nph/npt asphere requires atom attributes quat, angmom, torque, shape</I>
<DD>Those attributes are what are used to define aspherical particles.
<DT><I>Fix nvt/nph/npt asphere requires extended particles</I>
<DD>The shape setting for a particle in the fix group has shape = 0.0,
which means it is a point particle.
<DT><I>Fix nvt/nph/npt sphere requires atom attribute diameter or shape</I>
<DD>An atom style that specifies these quantities is needed.
<DT><I>Fix nvt/nph/npt sphere requires atom attributes omega, torque</I>
<DD>Those attributes are what are used to define spherical particles.
<DT><I>Fix nvt/npt/nph damping parameters must be > 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix nvt/sphere requires extended particles</I>
<DD>This fix can only be used for particles of a finite size.
<DT><I>Fix nvt/sphere requires spherical particle shapes</I>
<DD>Self-explanatory.
<DT><I>Fix orient/fcc file open failed</I>
<DD>The fix orient/fcc command could not open a specified file.
<DT><I>Fix orient/fcc file read failed</I>
<DD>The fix orient/fcc command could not read the needed parameters from a
specified file.
<DT><I>Fix orient/fcc found self twice</I>
<DD>The neighbor lists used by fix orient/fcc are messed up. If this
error occurs, it is likely a bug, so send an email to the
<A HREF = "http://lammps.sandia.gov/authors.html">developers</A>.
<DT><I>Fix peri neigh does not exist</I>
<DD>Somehow a fix that the pair style defines has been deleted.
<DT><I>Fix pour region ID does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix pour region cannot be dynamic</I>
<DD>Only static regions can be used with fix pour.
<DT><I>Fix pour region does not support a bounding box</I>
<DD>Not all regions represent bounded volumes. You cannot use
such a region with the fix pour command.
<DT><I>Fix pour requires atom attributes radius, rmass</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Fix press/berendsen damping parameters must be > 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix qeq/comb group has no atoms</I>
<DD>Self-explanatory.
<DT><I>Fix qeq/comb requires atom attribute q</I>
<DD>An atom style with charge must be used to perform charge equilibration.
<DT><I>Fix reax/bonds numbonds > nsbmax_most</I>
<DD>The limit of the number of bonds expected by the ReaxFF force field
was exceeded.
<DT><I>Fix recenter group has no atoms</I>
<DD>Self-explanatory.
<DT><I>Fix rigid atom has non-zero image flag in a non-periodic dimension</I>
<DD>You cannot set image flags for non-periodic dimensions.
<DT><I>Fix rigid molecule requires atom attribute molecule</I>
<DD>Self-explanatory.
<DT><I>Fix rigid/nvt period must be > 0.0</I>
<DD>Self-explanatory
<DT><I>Fix rigid: Bad principal moments</I>
<DD>The principal moments of inertia computed for a rigid body
are not within the required tolerances.
<DT><I>Fix shake cannot be used with minimization</I>
<DD>Cannot use fix shake while doing an energy minimization since
it turns off bonds that should contribute to the energy.
<DT><I>Fix spring couple group ID does not exist</I>
<DD>Self-explanatory.
<DT><I>Fix srd lamda must be >= 0.6 of SRD grid size</I>
<DD>This is a requirement for accuracy reasons.
<DT><I>Fix srd requires SRD particles all have same mass</I>
<DD>Self-explanatory.
<DT><I>Fix srd requires ghost atoms store velocity</I>
<DD>Use the communicate vel yes command to enable this.
<DT><I>Fix srd requires newton pair on</I>
<DD>Self-explanatory.
<DT><I>Fix store/state compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix store/state compute does not calculate a per-atom array</I>
<DD>The compute calculates a per-atom vector.
<DT><I>Fix store/state compute does not calculate a per-atom vector</I>
<DD>The compute calculates a per-atom vector.
<DT><I>Fix store/state compute does not calculate per-atom values</I>
<DD>Computes that calculate global or local quantities cannot be used
with fix store/state.
<DT><I>Fix store/state fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Fix store/state fix does not calculate a per-atom array</I>
<DD>The fix calculates a per-atom vector.
<DT><I>Fix store/state fix does not calculate a per-atom vector</I>
<DD>The fix calculates a per-atom array.
<DT><I>Fix store/state fix does not calculate per-atom values</I>
<DD>Fixes that calculate global or local quantities cannot be used with
fix store/state.
<DT><I>Fix store/state for atom property that isn't allocated</I>
<DD>Self-explanatory.
<DT><I>Fix store/state variable is not atom-style variable</I>
<DD>Only atom-style variables calculate per-atom quantities.
<DT><I>Fix temp/berendsen period must be > 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix thermal/conductivity swap value must be positive</I>
<DD>Self-explanatory.
<DT><I>Fix tmd must come after integration fixes</I>
<DD>Any fix tmd command must appear in the input script after all time
integration fixes (nve, nvt, npt). See the fix tmd documentation for
details.
<DT><I>Fix ttm electron temperatures must be > 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix ttm electronic_density must be > 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix ttm electronic_specific_heat must be > 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix ttm electronic_thermal_conductivity must be >= 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix ttm gamma_p must be > 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix ttm gamma_s must be >= 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix ttm number of nodes must be > 0</I>
<DD>Self-explanatory.
<DT><I>Fix ttm v_0 must be >= 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix used in compute atom/molecule not computed at compatible time</I>
<DD>The fix must produce per-atom quantities on timesteps that the compute
needs them.
<DT><I>Fix used in compute reduce not computed at compatible time</I>
<DD>Fixes generate their values on specific timesteps. Compute sum is
requesting a value on a non-allowed timestep.
<DT><I>Fix viscosity swap value must be positive</I>
<DD>Self-explanatory.
<DT><I>Fix viscosity vtarget value must be positive</I>
<DD>Self-explanatory.
<DT><I>Fix wall cutoff <= 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix wall/colloid cannot be used with atom attribute diameter</I>
<DD>Only finite-size particles defined by the shape command can be used.
<DT><I>Fix wall/colloid requires atom attribute shape</I>
<DD>Self-explanatory.
<DT><I>Fix wall/colloid requires extended particles</I>
<DD>Self-explanatory.
<DT><I>Fix wall/colloid requires spherical particles</I>
<DD>Self-explanatory.
<DT><I>Fix wall/gran is incompatible with Pair style</I>
<DD>Must use a granular pair style to define the parameters needed for
this fix.
<DT><I>Fix wall/gran requires atom attributes radius, omega, torque</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Fix wall/region colloid cannot be used with atom attribute diameter</I>
<DD>Only finite-size particles defined by the shape command can be used.
<DT><I>Fix wall/region colloid requires atom attribute shape</I>
<DD>Self-explanatory.
<DT><I>Fix wall/region colloid requires extended particles</I>
<DD>Self-explanatory.
<DT><I>Fix wall/region colloid requires spherical particles</I>
<DD>Self-explanatory.
<DT><I>Fix wall/region cutoff <= 0.0</I>
<DD>Self-explanatory.
<DT><I>Fix_modify order must be 3 or 5</I>
<DD>Self-explanatory.
<DT><I>Fix_modify pressure ID does not compute pressure</I>
<DD>The compute ID assigned to the fix must compute pressure.
<DT><I>Fix_modify temperature ID does not compute temperature</I>
<DD>The compute ID assigned to the fix must compute temperature.
<DT><I>Found no restart file matching pattern</I>
<DD>When using a "*" in the restart file name, no matching file was found.
<DT><I>GPU is not the first fix for this run</I>
<DD>This is the way the fix must be defined in your input script.
<DT><I>GPU library not compiled for this accelerator</I>
<DD>The GPU library was not built for your accelerator. Check the arch flag in
lib/gpu.
<DT><I>Gmask function in equal-style variable formula</I>
<DD>Gmask is per-atom operation.
<DT><I>Gravity changed since fix pour was created</I>
<DD>Gravity must be static and not dynamic for use with fix pour.
<DT><I>Gravity must point in -y to use with fix pour in 2d</I>
<DD>Gravity must be pointing "down" in a 2d box.
<DT><I>Gravity must point in -z to use with fix pour in 3d</I>
<DD>Gravity must be pointing "down" in a 3d box, i.e. theta = 180.0.
<DT><I>Grmask function in equal-style variable formula</I>
<DD>Grmask is per-atom operation.
<DT><I>Group ID does not exist</I>
<DD>A group ID used in the group command does not exist.
<DT><I>Group ID in variable formula does not exist</I>
<DD>Self-explanatory.
<DT><I>Group command before simulation box is defined</I>
<DD>The group command cannot be used before a read_data, read_restart, or
create_box command.
<DT><I>Group region ID does not exist</I>
<DD>A region ID used in the group command does not exist.
<DT><I>Illegal ... command</I>
<DD>Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
<DT><I>Illegal COMB parameter</I>
<DD>One or more of the coefficients defined in the potential file is
invalid.
<DT><I>Illegal Stillinger-Weber parameter</I>
<DD>One or more of the coefficients defined in the potential file is
invalid.
<DT><I>Illegal Tersoff parameter</I>
<DD>One or more of the coefficients defined in the potential file is
invalid.
<DT><I>Illegal chemical element names</I>
<DD>The name is too long to be a chemical element.
<DT><I>Illegal fix gpu command</I>
<DD>Self-explanatory.
<DT><I>Illegal number of angle table entries</I>
<DD>There must be at least 2 table entries.
<DT><I>Illegal number of bond table entries</I>
<DD>There must be at least 2 table entries.
<DT><I>Illegal number of pair table entries</I>
<DD>There must be at least 2 table entries.
<DT><I>Illegal simulation box</I>
<DD>The lower bound of the simulation box is greater than the upper bound.
<DT><I>Improper atom missing in delete_bonds</I>
<DD>The delete_bonds command cannot find one or more atoms in a particular
improper on a particular processor. The pairwise cutoff is too short
or the atoms are too far apart to make a valid improper.
<DT><I>Improper atom missing in set command</I>
<DD>The set command cannot find one or more atoms in a particular improper
on a particular processor. The pairwise cutoff is too short or the
atoms are too far apart to make a valid improper.
<DT><I>Improper atoms %d %d %d %d missing on proc %d at step</I>
<DD>One or more of 4 atoms needed to compute a particular improper are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the improper has blown apart and an atom is
too far away.
<DT><I>Improper coeff for hybrid has invalid style</I>
<DD>Improper style hybrid uses another improper style as one of its
coefficients. The improper style used in the improper_coeff command
or read from a restart file is not recognized.
<DT><I>Improper coeffs are not set</I>
<DD>No improper coefficients have been assigned in the data file or via
the improper_coeff command.
<DT><I>Improper style hybrid cannot have hybrid as an argument</I>
<DD>Self-explanatory.
<DT><I>Improper style hybrid cannot have none as an argument</I>
<DD>Self-explanatory.
<DT><I>Improper style hybrid cannot use same improper style twice</I>
<DD>Self-explanatory.
<DT><I>Improper_coeff command before improper_style is defined</I>
<DD>Coefficients cannot be set in the data file or via the improper_coeff
command until an improper_style has been assigned.
<DT><I>Improper_coeff command before simulation box is defined</I>
<DD>The improper_coeff command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Improper_coeff command when no impropers allowed</I>
<DD>The chosen atom style does not allow for impropers to be defined.
<DT><I>Improper_style command when no impropers allowed</I>
<DD>The chosen atom style does not allow for impropers to be defined.
<DT><I>Impropers assigned incorrectly</I>
<DD>Impropers read in from the data file were not assigned correctly to
atoms. This means there is something invalid about the topology
definitions.
<DT><I>Impropers defined but no improper types</I>
<DD>The data file header lists improper but no improper types.
<DT><I>Inconsistent iparam/jparam values in fix bond/create command</I>
<DD>If itype and jtype are the same, then their maxbond and newtype
settings must also be the same.
<DT><I>Incorrect args for angle coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Incorrect args for bond coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Incorrect args for dihedral coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Incorrect args for improper coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Incorrect args for pair coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Incorrect args in pair_style command</I>
<DD>Self-explanatory.
<DT><I>Incorrect atom format in data file</I>
<DD>Number of values per atom line in the data file is not consistent with
the atom style.
<DT><I>Incorrect boundaries with slab Ewald</I>
<DD>Must have periodic x,y dimensions and non-periodic z dimension to use
2d slab option with Ewald.
<DT><I>Incorrect boundaries with slab PPPM</I>
<DD>Must have periodic x,y dimensions and non-periodic z dimension to use
2d slab option with PPPM.
<DT><I>Incorrect element names in EAM potential file</I>
<DD>The element names in the EAM file do not match those requested.
<DT><I>Incorrect format in COMB potential file</I>
<DD>Incorrect number of words per line in the potential file.
<DT><I>Incorrect format in MEAM potential file</I>
<DD>Incorrect number of words per line in the potential file.
<DT><I>Incorrect format in NEB coordinate file</I>
<DD>Self-explanatory.
<DT><I>Incorrect format in Stillinger-Weber potential file</I>
<DD>Incorrect number of words per line in the potential file.
<DT><I>Incorrect format in TMD target file</I>
<DD>Format of file read by fix tmd command is incorrect.
<DT><I>Incorrect format in Tersoff potential file</I>
<DD>Incorrect number of words per line in the potential file.
<DT><I>Incorrect multiplicity arg for dihedral coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Incorrect sign arg for dihedral coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Incorrect velocity format in data file</I>
<DD>Each atom style defines a format for the Velocity section
of the data file. The read-in lines do not match.
<DT><I>Incorrect weight arg for dihedral coefficients</I>
<DD>Self-explanatory. Check the input script or data file.
<DT><I>Index between variable brackets must be positive</I>
<DD>Self-explanatory.
<DT><I>Indexed per-atom vector in variable formula without atom map</I>
<DD>Accessing a value from an atom vector requires the ability to lookup
an atom index, which is provided by an atom map. An atom map does not
exist (by default) for non-molecular problems. Using the atom_modify
map command will force an atom map to be created.
<DT><I>Induced tilt by displace_box is too large</I>
<DD>The final tilt value must be between -1/2 and 1/2 of the perpendicular
box length.
<DT><I>Initial temperatures not all set in fix ttm</I>
<DD>Self-explantory.
<DT><I>Input line too long after variable substitution</I>
<DD>This is a hard (very large) limit defined in the input.cpp file.
<DT><I>Input line too long: %s</I>
<DD>This is a hard (very large) limit defined in the input.cpp file.
<DT><I>Insertion region extends outside simulation box</I>
<DD>Region specified with fix pour command extends outside the global
simulation box.
<DT><I>Insufficient Jacobi rotations for POEMS body</I>
<DD>Eigensolve for rigid body was not sufficiently accurate.
<DT><I>Insufficient Jacobi rotations for rigid body</I>
<DD>Eigensolve for rigid body was not sufficiently accurate.
<DT><I>Insufficient memory on accelerator. </I>
<DD>Self-explanatory.
<DT><I>Invalid Boolean syntax in if command</I>
<DD>Self-explanatory.
<DT><I>Invalid REAX atom type</I>
<DD>There is a mis-match between LAMMPS atom types and the elements
listed in the ReaxFF force field file.
<DT><I>Invalid angle style</I>
<DD>The choice of angle style is unknown.
<DT><I>Invalid angle table length</I>
<DD>Length must be 2 or greater.
<DT><I>Invalid angle type in Angles section of data file</I>
<DD>Angle type must be positive integer and within range of specified angle
types.
<DT><I>Invalid angle type index for fix shake</I>
<DD>Self-explanatory.
<DT><I>Invalid atom ID in Angles section of data file</I>
<DD>Atom IDs must be positive integers and within range of defined
atoms.
<DT><I>Invalid atom ID in Atoms section of data file</I>
<DD>Atom IDs must be positive integers.
<DT><I>Invalid atom ID in Bonds section of data file</I>
<DD>Atom IDs must be positive integers and within range of defined
atoms.
<DT><I>Invalid atom ID in Dihedrals section of data file</I>
<DD>Atom IDs must be positive integers and within range of defined
atoms.
<DT><I>Invalid atom ID in Impropers section of data file</I>
<DD>Atom IDs must be positive integers and within range of defined
atoms.
<DT><I>Invalid atom ID in Velocities section of data file</I>
<DD>Atom IDs must be positive integers and within range of defined
atoms.
<DT><I>Invalid atom mass for fix shake</I>
<DD>Mass specified in fix shake command must be > 0.0.
<DT><I>Invalid atom style</I>
<DD>The choice of atom style is unknown.
<DT><I>Invalid atom type in Atoms section of data file</I>
<DD>Atom types must range from 1 to specified # of types.
<DT><I>Invalid atom type in create_atoms command</I>
<DD>The create_box command specified the range of valid atom types.
An invalid type is being requested.
<DT><I>Invalid atom type in fix bond/create command</I>
<DD>Self-explanatory.
<DT><I>Invalid atom type in neighbor exclusion list</I>
<DD>Atom types must range from 1 to Ntypes inclusive.
<DT><I>Invalid atom type index for fix shake</I>
<DD>Atom types must range from 1 to Ntypes inclusive.
<DT><I>Invalid atom types in pair_write command</I>
<DD>Atom types must range from 1 to Ntypes inclusive.
<DT><I>Invalid atom vector in variable formula</I>
<DD>The atom vector is not recognized.
<DT><I>Invalid attribute in dump custom command</I>
<DD>Self-explantory.
<DT><I>Invalid attribute in dump local command</I>
<DD>Self-explantory.
<DT><I>Invalid attribute in dump modify command</I>
<DD>Self-explantory.
<DT><I>Invalid bond style</I>
<DD>The choice of bond style is unknown.
<DT><I>Invalid bond table length</I>
<DD>Length must be 2 or greater.
<DT><I>Invalid bond type in Bonds section of data file</I>
<DD>Bond type must be positive integer and within range of specified bond
types.
<DT><I>Invalid bond type in fix bond/break command</I>
<DD>Self-explanatory.
<DT><I>Invalid bond type in fix bond/create command</I>
<DD>Self-explanatory.
<DT><I>Invalid bond type index for fix shake</I>
<DD>Self-explanatory. Check the fix shake command in the input script.
<DT><I>Invalid coeffs for this dihedral style</I>
<DD>Cannot set class 2 coeffs in data file for this dihedral style.
<DT><I>Invalid command-line argument</I>
<DD>One or more command-line arguments is invalid. Check the syntax of
the command you are using to launch LAMMPS.
<DT><I>Invalid compute ID in variable formula</I>
<DD>The compute is not recognized.
<DT><I>Invalid compute style</I>
<DD>Self-explanatory.
<DT><I>Invalid cutoff in communicate command</I>
<DD>Specified cutoff must be >= 0.0.
<DT><I>Invalid cutoffs in pair_write command</I>
<DD>Inner cutoff must be larger than 0.0 and less than outer cutoff.
<DT><I>Invalid d1 or d2 value for pair colloid coeff</I>
<DD>Neither d1 or d2 can be < 0.
<DT><I>Invalid data file section: Angle Coeffs</I>
<DD>Atom style does not allow angles.
<DT><I>Invalid data file section: AngleAngle Coeffs</I>
<DD>Atom style does not allow impropers.
<DT><I>Invalid data file section: AngleAngleTorsion Coeffs</I>
<DD>Atom style does not allow dihedrals.
<DT><I>Invalid data file section: AngleTorsion Coeffs</I>
<DD>Atom style does not allow dihedrals.
<DT><I>Invalid data file section: Angles</I>
<DD>Atom style does not allow angles.
<DT><I>Invalid data file section: Bond Coeffs</I>
<DD>Atom style does not allow bonds.
<DT><I>Invalid data file section: BondAngle Coeffs</I>
<DD>Atom style does not allow angles.
<DT><I>Invalid data file section: BondBond Coeffs</I>
<DD>Atom style does not allow angles.
<DT><I>Invalid data file section: BondBond13 Coeffs</I>
<DD>Atom style does not allow dihedrals.
<DT><I>Invalid data file section: Bonds</I>
<DD>Atom style does not allow bonds.
<DT><I>Invalid data file section: Dihedral Coeffs</I>
<DD>Atom style does not allow dihedrals.
<DT><I>Invalid data file section: Dihedrals</I>
<DD>Atom style does not allow dihedrals.
<DT><I>Invalid data file section: EndBondTorsion Coeffs</I>
<DD>Atom style does not allow dihedrals.
<DT><I>Invalid data file section: Improper Coeffs</I>
<DD>Atom style does not allow impropers.
<DT><I>Invalid data file section: Impropers</I>
<DD>Atom style does not allow impropers.
<DT><I>Invalid data file section: MiddleBondTorsion Coeffs</I>
<DD>Atom style does not allow dihedrals.
<DT><I>Invalid delta_conf in tad command</I>
<DD>The value must be between 0 and 1 inclusive.
<DT><I>Invalid density in Atoms section of data file</I>
<DD>Density value cannot be <= 0.0.
<DT><I>Invalid dihedral style</I>
<DD>The choice of dihedral style is unknown.
<DT><I>Invalid dihedral type in Dihedrals section of data file</I>
<DD>Dihedral type must be positive integer and within range of specified
dihedral types.
<DT><I>Invalid dipole line in data file</I>
<DD>Self-explanatory.
<DT><I>Invalid dipole value</I>
<DD>Self-explanatory.
<DT><I>Invalid dump dcd filename</I>
<DD>Filenames used with the dump dcd style cannot be binary or compressed
or cause multiple files to be written.
<DT><I>Invalid dump frequency</I>
<DD>Dump frequency must be 1 or greater.
<DT><I>Invalid dump style</I>
<DD>The choice of dump style is unknown.
<DT><I>Invalid dump xtc filename</I>
<DD>Filenames used with the dump xtc style cannot be binary or compressed
or cause multiple files to be written.
<DT><I>Invalid dump xyz filename</I>
<DD>Filenames used with the dump xyz style cannot be binary or cause files
to be written by each processor.
<DT><I>Invalid dump_modify threshhold operator</I>
<DD>Operator keyword used for threshold specification in not recognized.
<DT><I>Invalid fix ID in variable formula</I>
<DD>The fix is not recognized.
<DT><I>Invalid fix ave/time off column</I>
<DD>Self-explantory.
<DT><I>Invalid fix box/relax command for a 2d simulation</I>
<DD>Fix box/relax styles involving the z dimension cannot be used in
a 2d simulation.
<DT><I>Invalid fix box/relax command pressure settings</I>
<DD>If multiple dimensions are coupled, those dimensions must be specified.
<DT><I>Invalid fix box/relax pressure settings</I>
<DD>Settings for coupled dimensions must be the same.
<DT><I>Invalid fix nvt/npt/nph command for a 2d simulation</I>
<DD>Cannot control z dimension in a 2d model.
<DT><I>Invalid fix nvt/npt/nph command pressure settings</I>
<DD>If multiple dimensions are coupled, those dimensions must be
specified.
<DT><I>Invalid fix nvt/npt/nph pressure settings</I>
<DD>Settings for coupled dimensions must be the same.
<DT><I>Invalid fix press/berendsen for a 2d simulation</I>
<DD>The z component of pressure cannot be controlled for a 2d model.
<DT><I>Invalid fix press/berendsen pressure settings</I>
<DD>Settings for coupled dimensions must be the same.
<DT><I>Invalid fix style</I>
<DD>The choice of fix style is unknown.
<DT><I>Invalid flag in force field section of restart file</I>
<DD>Unrecognized entry in restart file.
<DT><I>Invalid flag in header section of restart file</I>
<DD>Unrecognized entry in restart file.
<DT><I>Invalid flag in type arrays section of restart file</I>
<DD>Unrecognized entry in restart file.
<DT><I>Invalid frequency in temper command</I>
<DD>Nevery must be > 0.
<DT><I>Invalid group ID in neigh_modify command</I>
<DD>A group ID used in the neigh_modify command does not exist.
<DT><I>Invalid group function in variable formula</I>
<DD>Group function is not recognized.
<DT><I>Invalid group in communicate command</I>
<DD>Self-explanatory.
<DT><I>Invalid improper style</I>
<DD>The choice of improper style is unknown.
<DT><I>Invalid improper type in Impropers section of data file</I>
<DD>Improper type must be positive integer and within range of specified
improper types.
<DT><I>Invalid keyword in angle table parameters</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in bond table parameters</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute angle/local command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute bond/local command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute dihedral/local command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute improper/local command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute pair/local command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute property/atom command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute property/local command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in compute property/molecule command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in dump cfg command</I>
<DD>Self-explanatory.
<DT><I>Invalid keyword in pair table parameters</I>
<DD>Keyword used in list of table parameters is not recognized.
<DT><I>Invalid keyword in thermo_style custom command</I>
<DD>One or more specified keywords are not recognized.
<DT><I>Invalid kspace style</I>
<DD>The choice of kspace style is unknown.
<DT><I>Invalid mass line in data file</I>
<DD>Self-explanatory.
<DT><I>Invalid mass value</I>
<DD>Self-explanatory.
<DT><I>Invalid math function in variable formula</I>
<DD>Self-explanatory.
<DT><I>Invalid math/group/special function in variable formula</I>
<DD>Self-explanatory.
<DT><I>Invalid option in lattice command for non-custom style</I>
<DD>Certain lattice keywords are not supported unless the
lattice style is "custom".
<DT><I>Invalid order of forces within respa levels</I>
<DD>For respa, ordering of force computations within respa levels must
obey certain rules. E.g. bonds cannot be compute less frequently than
angles, pairwise forces cannot be computed less frequently than
kspace, etc.
<DT><I>Invalid pair style</I>
<DD>The choice of pair style is unknown.
<DT><I>Invalid pair table cutoff</I>
<DD>Cutoffs in pair_coeff command are not valid with read-in pair table.
<DT><I>Invalid pair table length</I>
<DD>Length of read-in pair table is invalid
<DT><I>Invalid radius in Atoms section of data file</I>
<DD>Radius must be >= 0.0.
<DT><I>Invalid random number seed in fix ttm command</I>
<DD>Random number seed must be > 0.
<DT><I>Invalid random number seed in set command</I>
<DD>Random number seed must be > 0.
<DT><I>Invalid region style</I>
<DD>The choice of region style is unknown.
<DT><I>Invalid replace values in compute reduce</I>
<DD>Self-explanatory.
<DT><I>Invalid run command N value</I>
<DD>The number of timesteps must fit in a 32-bit integer. If you want to
run for more steps than this, perform multiple shorter runs.
<DT><I>Invalid run command start/stop value</I>
<DD>Self-explanatory.
<DT><I>Invalid run command upto value</I>
<DD>Self-explanatory.
<DT><I>Invalid seed for Marsaglia random # generator</I>
<DD>The initial seed for this random number generator must be a positive
integer less than or equal to 900 million.
<DT><I>Invalid seed for Park random # generator</I>
<DD>The initial seed for this random number generator must be a positive
integer.
<DT><I>Invalid shape line in data file</I>
<DD>Self-explanatory.
<DT><I>Invalid shape line in data file</I>
<DD>Self-explanatory.
<DT><I>Invalid shape value</I>
<DD>Self-explanatory.
<DT><I>Invalid shear direction for fix wall/gran</I>
<DD>Self-explanatory.
<DT><I>Invalid special function in variable formula</I>
<DD>Self-explanatory.
<DT><I>Invalid style in pair_write command</I>
<DD>Self-explanatory. Check the input script.
<DT><I>Invalid syntax in variable formula</I>
<DD>Self-explanatory.
<DT><I>Invalid t_event in prd command</I>
<DD>Self-explanatory.
<DT><I>Invalid t_event in tad command</I>
<DD>The value must be greater than 0.
<DT><I>Invalid thermo keyword in variable formula</I>
<DD>The keyword is not recognized.
<DT><I>Invalid tmax in tad command</I>
<DD>The value must be greater than 0.0.
<DT><I>Invalid type for dipole set</I>
<DD>Dipole command must set a type from 1-N where N is the number of atom
types.
<DT><I>Invalid type for mass set</I>
<DD>Mass command must set a type from 1-N where N is the number of atom
types.
<DT><I>Invalid type for shape set</I>
<DD>Atom type is out of bounds.
<DT><I>Invalid value in set command</I>
<DD>The value specified for the setting is invalid, likely because it is
too small or too large.
<DT><I>Invalid variable evaluation in variable formula</I>
<DD>A variable used in a formula could not be evaluated.
<DT><I>Invalid variable in next command</I>
<DD>Self-explanatory.
<DT><I>Invalid variable name in variable formula</I>
<DD>Variable name is not recognized.
<DT><I>Invalid variable name</I>
<DD>Variable name used in an input script line is invalid.
<DT><I>Invalid variable style with next command</I>
<DD>Variable styles <I>equal</I> and <I>world</I> cannot be used in a next
command.
<DT><I>Invalid wiggle direction for fix wall/gran</I>
<DD>Self-explanatory.
<DT><I>Invoked angle equil angle on angle style none</I>
<DD>Self-explanatory.
<DT><I>Invoked angle single on angle style none</I>
<DD>Self-explanatory.
<DT><I>Invoked bond equil distance on bond style none</I>
<DD>Self-explanatory.
<DT><I>Invoked bond single on bond style none</I>
<DD>Self-explanatory.
<DT><I>Invoked pair single on pair style none</I>
<DD>A command (e.g. a dump) attempted to invoke the single() function on a
pair style none, which is illegal. You are probably attempting to
compute per-atom quantities with an undefined pair style.
<DT><I>KSpace style has not yet been set</I>
<DD>Cannot use kspace_modify command until a kspace style is set.
<DT><I>KSpace style is incompatible with Pair style</I>
<DD>Setting a kspace style requires that a pair style with a long-range
Coulombic component be selected.
<DT><I>Keyword %s in MEAM parameter file not recognized</I>
<DD>Self-explanatory.
<DT><I>Kspace style requires atom attribute q</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Label wasn't found in input script</I>
<DD>Self-explanatory.
<DT><I>Lattice orient vectors are not orthogonal</I>
<DD>The three specified lattice orientation vectors must be mutually
orthogonal.
<DT><I>Lattice orient vectors are not right-handed</I>
<DD>The three specified lattice orientation vectors must create a
right-handed coordinate system such that a1 cross a2 = a3.
<DT><I>Lattice primitive vectors are collinear</I>
<DD>The specified lattice primitive vectors do not for a unit cell with
non-zero volume.
<DT><I>Lattice settings are not compatible with 2d simulation</I>
<DD>One or more of the specified lattice vectors has a non-zero z
component.
<DT><I>Lattice spacings are invalid</I>
<DD>Each x,y,z spacing must be > 0.
<DT><I>Lattice style incompatible with simulation dimension</I>
<DD>2d simulation can use sq, sq2, or hex lattice. 3d simulation can use
sc, bcc, or fcc lattice.
<DT><I>Log of zero/negative value in variable formula</I>
<DD>Self-explanatory.
<DT><I>MEAM library error %d</I>
<DD>A call to the MEAM Fortran library returned an error.
<DT><I>MPI_LMP_BIGINT and bigint in lmptype.h are not compatible</I>
<DD>The size of the MPI datatype does not match the size of a bigint.
<DT><I>MPI_LMP_TAGINT and tagint in lmptype.h are not compatible</I>
<DD>The size of the MPI datatype does not match the size of a tagint.
<DT><I>Mass command before simulation box is defined</I>
<DD>The mass command cannot be used before a read_data, read_restart, or
create_box command.
<DT><I>Min_style command before simulation box is defined</I>
<DD>The min_style command cannot be used before a read_data, read_restart,
or create_box command.
<DT><I>Minimization could not find thermo_pe compute</I>
<DD>This compute is created by the thermo command. It must have been
explicitly deleted by a uncompute command.
<DT><I>Minimize command before simulation box is defined</I>
<DD>The minimize command cannot be used before a read_data, read_restart,
or create_box command.
<DT><I>Mismatched brackets in variable</I>
<DD>Self-explanatory.
<DT><I>Mismatched compute in variable formula</I>
<DD>A compute is referenced incorrectly or a compute that produces per-atom
values is used in an equal-style variable formula.
<DT><I>Mismatched fix in variable formula</I>
<DD>A fix is referenced incorrectly or a fix that produces per-atom
values is used in an equal-style variable formula.
<DT><I>Mismatched variable in variable formula</I>
<DD>A variable is referenced incorrectly or an atom-style variable that
produces per-atom values is used in an equal-style variable
formula.
<DT><I>Molecular data file has too many atoms</I>
<DD>These kids of data files are currently limited to a number
of atoms that fits in a 32-bit integer.
<DT><I>Molecule count changed in compute atom/molecule</I>
<DD>Number of molecules must remain constant over time.
<DT><I>Molecule count changed in compute com/molecule</I>
<DD>Number of molecules must remain constant over time.
<DT><I>Molecule count changed in compute gyration/molecule</I>
<DD>Number of molecules must remain constant over time.
<DT><I>Molecule count changed in compute msd/molecule</I>
<DD>Number of molecules must remain constant over time.
<DT><I>Molecule count changed in compute property/molecule</I>
<DD>Number of molecules must remain constant over time.
<DT><I>More than one fix deform</I>
<DD>Only one fix deform can be defined at a time.
<DT><I>More than one fix freeze</I>
<DD>Only one of these fixes can be defined, since the granular pair
potentials access it.
<DT><I>More than one fix shake</I>
<DD>Only one fix shake can be defined.
<DT><I>Must define angle_style before Angle Coeffs</I>
<DD>Must use an angle_style command before reading a data file that
defines Angle Coeffs.
<DT><I>Must define angle_style before BondAngle Coeffs</I>
<DD>Must use an angle_style command before reading a data file that
defines Angle Coeffs.
<DT><I>Must define angle_style before BondBond Coeffs</I>
<DD>Must use an angle_style command before reading a data file that
defines Angle Coeffs.
<DT><I>Must define bond_style before Bond Coeffs</I>
<DD>Must use a bond_style command before reading a data file that
defines Bond Coeffs.
<DT><I>Must define dihedral_style before AngleAngleTorsion Coeffs</I>
<DD>Must use a dihedral_style command before reading a data file that
defines AngleAngleTorsion Coeffs.
<DT><I>Must define dihedral_style before AngleTorsion Coeffs</I>
<DD>Must use a dihedral_style command before reading a data file that
defines AngleTorsion Coeffs.
<DT><I>Must define dihedral_style before BondBond13 Coeffs</I>
<DD>Must use a dihedral_style command before reading a data file that
defines BondBond13 Coeffs.
<DT><I>Must define dihedral_style before Dihedral Coeffs</I>
<DD>Must use a dihedral_style command before reading a data file that
defines Dihedral Coeffs.
<DT><I>Must define dihedral_style before EndBondTorsion Coeffs</I>
<DD>Must use a dihedral_style command before reading a data file that
defines EndBondTorsion Coeffs.
<DT><I>Must define dihedral_style before MiddleBondTorsion Coeffs</I>
<DD>Must use a dihedral_style command before reading a data file that
defines MiddleBondTorsion Coeffs.
<DT><I>Must define improper_style before AngleAngle Coeffs</I>
<DD>Must use an improper_style command before reading a data file that
defines AngleAngle Coeffs.
<DT><I>Must define improper_style before Improper Coeffs</I>
<DD>Must use an improper_style command before reading a data file that
defines Improper Coeffs.
<DT><I>Must define pair_style before Pair Coeffs</I>
<DD>Must use a pair_style command before reading a data file that defines
Pair Coeffs.
<DT><I>Must have more than one processor partition to temper</I>
<DD>Cannot use the temper command with only one processor partition. Use
the -partition command-line option.
<DT><I>Must read Atoms before Angles</I>
<DD>The Atoms section of a data file must come before an Angles section.
<DT><I>Must read Atoms before Bonds</I>
<DD>The Atoms section of a data file must come before a Bonds section.
<DT><I>Must read Atoms before Dihedrals</I>
<DD>The Atoms section of a data file must come before a Dihedrals section.
<DT><I>Must read Atoms before Impropers</I>
<DD>The Atoms section of a data file must come before an Impropers
section.
<DT><I>Must read Atoms before Velocities</I>
<DD>The Atoms section of a data file must come before a Velocities
section.
<DT><I>Must set both respa inner and outer</I>
<DD>Cannot use just the inner or outer option with respa without using the
other.
<DT><I>Must specify a region in fix deposit</I>
<DD>The region keyword must be specified with this fix.
<DT><I>Must specify a region in fix pour</I>
<DD>The region keyword must be specified with this fix.
<DT><I>Must use -in switch with multiple partitions</I>
<DD>A multi-partition simulation cannot read the input script from stdin.
The -in command-line option must be used to specify a file.
<DT><I>Must use a block or cylinder region with fix pour</I>
<DD>Self-explanatory.
<DT><I>Must use a block region with fix pour for 2d simulations</I>
<DD>Self-explanatory.
<DT><I>Must use a bond style with TIP4P potential</I>
<DD>TIP4P potentials assume bond lengths in water are constrained
by a fix shake command.
<DT><I>Must use a molecular atom style with fix poems molecule</I>
<DD>Self-explanatory.
<DT><I>Must use a z-axis cylinder with fix pour</I>
<DD>The axis of the cylinder region used with the fix pour command must
be oriented along the z dimension.
<DT><I>Must use an angle style with TIP4P potential</I>
<DD>TIP4P potentials assume angles in water are constrained by a fix shake
command.
<DT><I>Must use atom style with molecule IDs with fix bond/swap</I>
<DD>Self-explanatory.
<DT><I>Must use pair_style comb with fix qeq/comb</I>
<DD>Self-explanatory.
<DT><I>Must use variable energy with fix addforce</I>
<DD>Must define an energy vartiable when applyting a dynamic
force during minimization.
<DT><I>NEB command before simulation box is defined</I>
<DD>Self-explanatory.
<DT><I>NEB requires damped dynamics minimizer</I>
<DD>Use a different minimization style.
<DT><I>NEB requires use of fix neb</I>
<DD>Self-explanatory.
<DT><I>Needed topology not in data file</I>
<DD>The header of the data file indicated that bonds or angles or
dihedrals or impropers would be included, but they were not present.
<DT><I>Neigh_modify exclude molecule requires atom attribute molecule</I>
<DD>Self-explanatory.
<DT><I>Neigh_modify include group != atom_modify first group</I>
<DD>Self-explanatory.
<DT><I>Neighbor delay must be 0 or multiple of every setting</I>
<DD>The delay and every parameters set via the neigh_modify command are
inconsistent. If the delay setting is non-zero, then it must be a
multiple of the every setting.
<DT><I>Neighbor include group not allowed with ghost neighbors</I>
<DD>This is a current restriction within LAMMPS.
<DT><I>Neighbor list overflow, boost neigh_modify one or page</I>
<DD>There are too many neighbors of a single atom. Use the neigh_modify
command to increase the neighbor page size and the max number of
neighbors allowed for one atom.
<DT><I>Neighbor multi not yet enabled for ghost neighbors</I>
<DD>This is a current restriction within LAMMPS.
<DT><I>Neighbor multi not yet enabled for granular</I>
<DD>Self-explanatory.
<DT><I>Neighbor multi not yet enabled for rRESPA</I>
<DD>Self-explanatory.
<DT><I>Neighbor page size must be >= 10x the one atom setting</I>
<DD>This is required to prevent wasting too much memory.
<DT><I>Neighbors of ghost atoms only allowed for full neighbor lists</I>
<DD>This is a current restriction within LAMMPS.
<DT><I>New bond exceeded bonds per atom in fix bond/create</I>
<DD>See the read_data command for info on setting the "extra bond per
atom" header value to allow for additional bonds to be formed.
<DT><I>New bond exceeded special list size in fix bond/create</I>
<DD>See the special_bonds extra command for info on how to leave space in
the special bonds list to allow for additional bonds to be formed.
<DT><I>Newton bond change after simulation box is defined</I>
<DD>The newton command cannot be used to change the newton bond value
after a read_data, read_restart, or create_box command.
<DT><I>No angle style is defined for compute angle/local</I>
<DD>Self-explanatory.
<DT><I>No angles allowed with this atom style</I>
<DD>Self-explanatory. Check data file.
<DT><I>No atoms in data file</I>
<DD>The header of the data file indicated that atoms would be included,
but they were not present.
<DT><I>No basis atoms in lattice</I>
<DD>Basis atoms must be defined for lattice style user.
<DT><I>No bond style is defined for compute bond/local</I>
<DD>Self-explanatory.
<DT><I>No bonds allowed with this atom style</I>
<DD>Self-explanatory. Check data file.
<DT><I>No dihedral style is defined for compute dihedral/local</I>
<DD>Self-explanatory.
<DT><I>No dihedrals allowed with this atom style</I>
<DD>Self-explanatory. Check data file.
<DT><I>No dump custom arguments specified</I>
<DD>The dump custom command requires that atom quantities be specified to
output to dump file.
<DT><I>No dump local arguments specified</I>
<DD>Self-explanatory.
<DT><I>No fix gravity defined for fix pour</I>
<DD>Cannot add poured particles without gravity to move them.
<DT><I>No improper style is defined for compute improper/local</I>
<DD>Self-explanatory.
<DT><I>No impropers allowed with this atom style</I>
<DD>Self-explanatory. Check data file.
<DT><I>No matching element in EAM potential file</I>
<DD>The EAM potential file does not contain elements that match the
requested elements.
<DT><I>No pair hbond/dreiding coefficients set</I>
<DD>Self-explanatory.
<DT><I>No pair style defined for compute group/group</I>
<DD>Cannot calculate group interactions without a pair style defined.
<DT><I>No pair style is defined for compute pair/local</I>
<DD>Self-explanatory.
<DT><I>No pair style is defined for compute property/local</I>
<DD>Self-explanatory.
<DT><I>No rigid bodies defined</I>
<DD>The fix specification did not end up defining any rigid bodies.
<DT><I>Non digit character between brackets in variable</I>
<DD>Self-explantory.
<DT><I>Non integer # of swaps in temper command</I>
<DD>Swap frequency in temper command must evenly divide the total # of
timesteps.
<DT><I>One or more atoms belong to multiple rigid bodies</I>
<DD>Two or more rigid bodies defined by the fix rigid command cannot
contain the same atom.
<DT><I>One or zero atoms in rigid body</I>
<DD>Any rigid body defined by the fix rigid command must contain 2 or more
atoms.
<DT><I>Out of range atoms - cannot compute PPPM</I>
<DD>One or more atoms are attempting to map their charge to a PPPM grid
point that is not owned by a processor. This is likely for one of two
reasons, both of them bad. First, it may mean that an atom near the
boundary of a processor's sub-domain has moved more than 1/2 the
<A HREF = "neighbor.html">neighbor skin distance</A> without neighbor lists being
rebuilt and atoms being migrated to new processors. This also means
you may be missing pairwise interactions that need to be computed.
The solution is to change the re-neighboring criteria via the
<A HREF = "neigh_modify">neigh_modify</A> command. The safest settings are "delay 0
every 1 check yes". Second, it may mean that an atom has moved far
outside a processor's sub-domain or even the entire simulation box.
This indicates bad physics, e.g. due to highly overlapping atoms, too
large a timestep, etc.
<DT><I>Overlapping large/large in pair colloid</I>
<DD>This potential is infinite when there is an overlap.
<DT><I>Overlapping small/large in pair colloid</I>
<DD>This potential is inifinte when there is an overlap.
<DT><I>POEMS fix must come before NPT/NPH fix</I>
<DD>NPT/NPH fix must be defined in input script after all poems fixes,
else the fix contribution to the pressure virial is incorrect.
<DT><I>PPPM grid is too large</I>
<DD>The global PPPM grid is larger than OFFSET in one or more dimensions.
OFFSET is currently set to 4096. You likely need to decrease the
requested precision.
<DT><I>PPPM order cannot be greater than %d</I>
<DD>Self-explanatory.
<DT><I>PPPM order has been reduced to 0</I>
<DD>LAMMPS has attempted to reduce the PPPM order to enable the simulation
to run, but can reduce the order no further. Try increasing the
accuracy of PPPM by reducing the tolerance size, thus inducing a
larger PPPM grid.
<DT><I>PRD command before simulation box is defined</I>
<DD>The prd command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>PRD nsteps must be multiple of t_event</I>
<DD>Self-explanatory.
<DT><I>PRD t_corr must be multiple of t_event</I>
<DD>Self-explanatory.
<DT><I>Pair coeff for hybrid has invalid style</I>
<DD>Style in pair coeff must have been listed in pair_style command.
<DT><I>Pair cutoff < Respa interior cutoff</I>
<DD>One or more pairwise cutoffs are too short to use with the specified
rRESPA cutoffs.
<DT><I>Pair dipole/cut requires atom attributes q, mu, torque, dipole</I>
<DD>An atom style that specifies these quantities is needed.
<DT><I>Pair distance < table inner cutoff</I>
<DD>Two atoms are closer together than the pairwise table allows.
<DT><I>Pair distance > table outer cutoff</I>
<DD>Two atoms are further apart than the pairwise table allows.
<DT><I>Pair dpd requires ghost atoms store velocity</I>
<DD>Use the communicate vel yes command to enable this.
<DT><I>Pair gayberne cannot be used with atom attribute diameter</I>
<DD>Finite-size particles must be defined with the shape command.
<DT><I>Pair gayberne epsilon a,b,c coeffs are not all set</I>
<DD>Each atom type involved in pair_style gayberne must
have these 3 coefficients set at least once.
<DT><I>Pair gayberne requires atom attributes quat, torque, shape</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Pair granular requires atom attributes radius, omega, torque</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Pair granular requires ghost atoms store velocity</I>
<DD>Use the communicate vel yes command to enable this.
<DT><I>Pair granular with shear history requires newton pair off</I>
<DD>This is a current restriction of the implementation of pair
granular styles with history.
<DT><I>Pair hybrid sub-style does not support single call</I>
<DD>You are attempting to invoke a single() call on a pair style
that doesn't support it.
<DT><I>Pair hybrid sub-style is not used</I>
<DD>No pair_coeff command used a sub-style specified in the pair_style
command.
<DT><I>Pair inner cutoff < Respa interior cutoff</I>
<DD>One or more pairwise cutoffs are too short to use with the specified
rRESPA cutoffs.
<DT><I>Pair inner cutoff >= Pair outer cutoff</I>
<DD>The specified cutoffs for the pair style are inconsistent.
<DT><I>Pair lubricate cannot be used with atom attributes diameter or rmass</I>
<DD>These attributes override the shape and mass settings, so cannot be
used.
<DT><I>Pair lubricate requires atom attribute omega or angmom</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Pair lubricate requires atom attributes torque and shape</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Pair lubricate requires extended particles</I>
<DD>This pair style can only be used for particles with a shape
setting.
<DT><I>Pair lubricate requires ghost atoms store velocity</I>
<DD>Use the communicate vel yes command to enable this.
<DT><I>Pair lubricate requires spherical, mono-disperse particles</I>
<DD>This is a current restriction of this pair style.
<DT><I>Pair peri lattice is not identical in x, y, and z</I>
<DD>The lattice defined by the lattice command must be cubic.
<DT><I>Pair peri requires a lattice be defined</I>
<DD>Use the lattice command for this purpose.
<DT><I>Pair peri requires an atom map, see atom_modify</I>
<DD>Even for atomic systems, an atom map is required to find Peridynamic
bonds. Use the atom_modify command to define one.
<DT><I>Pair resquared cannot be used with atom attribute diameter</I>
<DD>This attribute overrides the shape settings, so cannot be used.
<DT><I>Pair resquared epsilon a,b,c coeffs are not all set</I>
<DD>Self-explanatory.
<DT><I>Pair resquared epsilon and sigma coeffs are not all set</I>
<DD>Self-explanatory.
<DT><I>Pair resquared requires atom attributes quat, torque, shape</I>
<DD>An atom style that defines these attributes must be used.
<DT><I>Pair style AIREBO requires atom IDs</I>
<DD>This is a requirement to use the AIREBO potential.
<DT><I>Pair style AIREBO requires newton pair on</I>
<DD>See the newton command. This is a restriction to use the AIREBO
potential.
<DT><I>Pair style COMB requires atom IDs</I>
<DD>This is a requirement to use the AIREBO potential.
<DT><I>Pair style COMB requires atom attribute q</I>
<DD>Self-explanatory.
<DT><I>Pair style COMB requires newton pair on</I>
<DD>See the newton command. This is a restriction to use the COMB
potential.
<DT><I>Pair style MEAM requires newton pair on</I>
<DD>See the newton command. This is a restriction to use the MEAM
potential.
<DT><I>Pair style Stillinger-Weber requires atom IDs</I>
<DD>This is a requirement to use the SW potential.
<DT><I>Pair style Stillinger-Weber requires newton pair on</I>
<DD>See the newton command. This is a restriction to use the SW
potential.
<DT><I>Pair style Tersoff requires atom IDs</I>
<DD>This is a requirement to use the Tersoff potential.
<DT><I>Pair style Tersoff requires newton pair on</I>
<DD>See the newton command. This is a restriction to use the Tersoff
potential.
<DT><I>Pair style born/coul/long requires atom attribute q</I>
<DD>An atom style that defines this attribute must be used.
<DT><I>Pair style buck/coul/cut requires atom attribute q</I>
<DD>The atom style defined does not have this attribute.
<DT><I>Pair style buck/coul/long requires atom attribute q</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Pair style coul/cut requires atom attribute q</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Pair style does not support bond_style quartic</I>
<DD>The pair style does not have a single() function, so it can
not be invoked by bond_style quartic.
<DT><I>Pair style does not support compute group/group</I>
<DD>The pair_style does not have a single() function, so it cannot be
invokded by the compute group/group command.
<DT><I>Pair style does not support compute pair/local</I>
<DD>The pair style does not have a single() function, so it can
not be invoked by fix bond/swap.
<DT><I>Pair style does not support compute property/local</I>
<DD>The pair style does not have a single() function, so it can
not be invoked by fix bond/swap.
<DT><I>Pair style does not support fix bond/swap</I>
<DD>The pair style does not have a single() function, so it can
not be invoked by fix bond/swap.
<DT><I>Pair style does not support pair_write</I>
<DD>The pair style does not have a single() function, so it can
not be invoked by pair write.
<DT><I>Pair style does not support rRESPA inner/middle/outer</I>
<DD>You are attempting to use rRESPA options with a pair style that
does not support them.
<DT><I>Pair style granular with history requires atoms have IDs</I>
<DD>Atoms in the simulation do not have IDs, so history effects
cannot be tracked by the granular pair potential.
<DT><I>Pair style hbond/dreiding requires an atom map, see atom_modify</I>
<DD>Self-explanatory.
<DT><I>Pair style hbond/dreiding requires atom IDs</I>
<DD>Self-explanatory.
<DT><I>Pair style hbond/dreiding requires molecular system</I>
<DD>Self-explanatory.
<DT><I>Pair style hbond/dreiding requires newton pair on</I>
<DD>See the newton command for details.
<DT><I>Pair style hybrid cannot have hybrid as an argument</I>
<DD>Self-explanatory.
<DT><I>Pair style hybrid cannot have none as an argument</I>
<DD>Self-explanatory.
<DT><I>Pair style hybrid cannot use same pair style twice</I>
<DD>The sub-style arguments of pair_style hybrid cannot be duplicated.
Check the input script.
<DT><I>Pair style is incompatible with KSpace style</I>
<DD>If a pair style with a long-range Coulombic component is selected,
then a kspace style must also be used.
<DT><I>Pair style lj/charmm/coul/charmm requires atom attribute q</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Pair style lj/charmm/coul/long requires atom attribute q</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Pair style lj/class2/coul/cut requires atom attribute q</I>
<DD>The atom style defined does not have this attribute.
<DT><I>Pair style lj/class2/coul/long requires atom attribute q</I>
<DD>The atom style defined does not have this attribute.
<DT><I>Pair style lj/cut/coul/cut requires atom attribute q</I>
<DD>The atom style defined does not have this attribute.
<DT><I>Pair style lj/cut/coul/long requires atom attribute q</I>
<DD>The atom style defined does not have this attribute.
<DT><I>Pair style lj/cut/coul/long/tip4p requires atom IDs</I>
<DD>There are no atom IDs defined in the system and the TIP4P potential
requires them to find O,H atoms with a water molecule.
<DT><I>Pair style lj/cut/coul/long/tip4p requires atom attribute q</I>
<DD>The atom style defined does not have these attributes.
<DT><I>Pair style lj/cut/coul/long/tip4p requires newton pair on</I>
<DD>This is because the computation of constraint forces within a water
molecule adds forces to atoms owned by other processors.
<DT><I>Pair style lj/gromacs/coul/gromacs requires atom attribute q</I>
<DD>An atom_style with this attribute is needed.
<DT><I>Pair style peri_lps requires atom style peri</I>
<DD>This is because atom style peri stores quantities needed by
the peridynamic potential.
<DT><I>Pair style peri_pmb requires atom style peri</I>
<DD>This is because atom style peri stores quantities needed by
the peridynamic potential.
<DT><I>Pair style reax requires atom IDs</I>
<DD>This is a requirement to use the ReaxFF potential.
<DT><I>Pair style reax requires newton pair on</I>
<DD>This is a requirement to use the ReaxFF potential.
<DT><I>Pair table cutoffs must all be equal to use with KSpace</I>
<DD>When using pair style table with a long-range KSpace solver, the
cutoffs for all atom type pairs must all be the same, since the
long-range solver starts at that cutoff.
<DT><I>Pair table parameters did not set N</I>
<DD>List of pair table parameters must include N setting.
<DT><I>Pair tersoff/zbl requires metal or real units</I>
<DD>This is a current restriction of this pair potential.
<DT><I>Pair yukawa/colloid cannot be used with atom attribute diameter</I>
<DD>Only finite-size particles defined by the shape command can be used.
<DT><I>Pair yukawa/colloid requires atom attribute shape</I>
<DD>Self-explanatory.
<DT><I>Pair yukawa/colloid requires spherical particles</I>
<DD>Self-explanatory.
<DT><I>Pair_coeff command before pair_style is defined</I>
<DD>Self-explanatory.
<DT><I>Pair_coeff command before simulation box is defined</I>
<DD>The pair_coeff command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Pair_modify command before pair_style is defined</I>
<DD>Self-explanatory.
<DT><I>Pair_write command before pair_style is defined</I>
<DD>Self-explanatory.
<DT><I>Particle on or inside fix wall surface</I>
<DD>Particles must be "exterior" to the wall in order for energy/force to
be calculated.
<DT><I>Particle on or inside surface of region used in fix wall/region</I>
<DD>Particles must be "exterior" to the region surface in order for
energy/force to be calculated.
<DT><I>Per-atom compute in equal-style variable formula</I>
<DD>Equal-style variables cannot use per-atom quantities.
<DT><I>Per-atom energy was not tallied on needed timestep</I>
<DD>You are using a thermo keyword that requires potentials to
have tallied energy, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work.
<DT><I>Per-atom fix in equal-style variable formula</I>
<DD>Equal-style variables cannot use per-atom quantities.
<DT><I>Per-atom virial was not tallied on needed timestep</I>
<DD>You are using a thermo keyword that requires potentials to have
tallied the virial, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work.
<DT><I>Per-processor system is too big</I>
<DD>The number of owned atoms plus ghost atoms on a single
processor must fit in 32-bit integer.
<DT><I>Potential energy ID for fix neb does not exist</I>
<DD>Self-explanatory.
<DT><I>Potential file has duplicate entry</I>
<DD>The potential file for a SW or Tersoff potential has more than
one entry for the same 3 ordered elements.
<DT><I>Potential file is missing an entry</I>
<DD>The potential file for a SW or Tersoff potential does not have a
needed entry.
<DT><I>Power by 0 in variable formula</I>
<DD>Self-explanatory.
<DT><I>Pressure ID for fix box/relax does not exist</I>
<DD>The compute ID needed to compute pressure for the fix does not
exist.
<DT><I>Pressure ID for fix modify does not exist</I>
<DD>Self-explanatory.
<DT><I>Pressure ID for fix npt/nph does not exist</I>
<DD>Self-explanatory.
<DT><I>Pressure ID for fix press/berendsen does not exist</I>
<DD>The compute ID needed to compute pressure for the fix does not
exist.
<DT><I>Pressure ID for thermo does not exist</I>
<DD>The compute ID needed to compute pressure for thermodynamics does not
exist.
<DT><I>Pressure control can not be used with fix nvt/asphere</I>
<DD>Self-explanatory.
<DT><I>Pressure control can not be used with fix nvt/sllod</I>
<DD>Self-explanatory.
<DT><I>Pressure control can not be used with fix nvt/sphere</I>
<DD>Self-explanatory.
<DT><I>Pressure control can not be used with fix nvt</I>
<DD>Self-explanatory.
<DT><I>Pressure control must be used with fix nph/asphere</I>
<DD>Self-explanatory.
<DT><I>Pressure control must be used with fix nph/sphere</I>
<DD>Self-explanatory.
<DT><I>Pressure control must be used with fix nph</I>
<DD>Self-explanatory.
<DT><I>Pressure control must be used with fix npt/asphere</I>
<DD>Self-explanatory.
<DT><I>Pressure control must be used with fix npt/sphere</I>
<DD>Self-explanatory.
<DT><I>Pressure control must be used with fix npt</I>
<DD>Self-explanatory.
<DT><I>Processor count in z must be 1 for 2d simulation</I>
<DD>Self-explanatory.
<DT><I>Processor partitions are inconsistent</I>
<DD>The total number of processors in all partitions must match the number
of processors LAMMPS is running on.
<DT><I>Processors command after simulation box is defined</I>
<DD>The processors command cannot be used after a read_data, read_restart,
or create_box command.
<DT><I>Quaternion creation numeric error</I>
<DD>A numeric error occurred in the creation of a rigid body by the fix
rigid command.
<DT><I>R0 < 0 for fix spring command</I>
<DD>Equilibrium spring length is invalid.
<DT><I>Reax_defs.h setting for NATDEF is too small</I>
<DD>Edit the setting in the ReaxFF library and re-compile the
library and re-build LAMMPS.
<DT><I>Reax_defs.h setting for NNEIGHMAXDEF is too small</I>
<DD>Edit the setting in the ReaxFF library and re-compile the
library and re-build LAMMPS.
<DT><I>Region ID for compute reduce/region does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for compute temp/region does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for dump cfg does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for dump custom does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix addforce does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix ave/spatial does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix aveforce does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix deposit does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix evaporate does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix heat does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix setforce does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID for fix wall/region does not exist</I>
<DD>Self-explanatory.
<DT><I>Region ID in variable formula does not exist</I>
<DD>Self-explanatory.
<DT><I>Region cannot have 0 length rotation vector</I>
<DD>Self-explanatory.
<DT><I>Region intersect region ID does not exist</I>
<DD>Self-explanatory.
<DT><I>Region union or intersect cannot be dynamic</I>
<DD>The sub-regions can be dynamic, but not the combined region.
<DT><I>Region union region ID does not exist</I>
<DD>One or more of the region IDs specified by the region union command
does not exist.
<DT><I>Replacing a fix, but new style != old style</I>
<DD>A fix ID can be used a 2nd time, but only if the style matches the
previous fix. In this case it is assumed you with to reset a fix's
parameters. This error may mean you are mistakenly re-using a fix ID
when you do not intend to.
<DT><I>Replicate command before simulation box is defined</I>
<DD>The replicate command cannot be used before a read_data, read_restart,
or create_box command.
<DT><I>Replicate did not assign all atoms correctly</I>
<DD>Atoms replicated by the replicate command were not assigned correctly
to processors. This is likely due to some atom coordinates being
outside a non-periodic simulation box.
<DT><I>Replicated molecular system atom IDs are too big</I>
<DD>See the setting for the allowed atom ID size in the src/lmptype.h
file.
<DT><I>Replicated system is too big</I>
<DD>See the setting for bigint in the src/lmptype.h file.
<DT><I>Resetting timestep is not allowed with fix move</I>
<DD>This is because fix move is moving atoms based on elapsed time.
<DT><I>Respa inner cutoffs are invalid</I>
<DD>The first cutoff must be <= the second cutoff.
<DT><I>Respa levels must be >= 1</I>
<DD>Self-explanatory.
<DT><I>Respa middle cutoffs are invalid</I>
<DD>The first cutoff must be <= the second cutoff.
<DT><I>Reuse of compute ID</I>
<DD>A compute ID cannot be used twice.
<DT><I>Reuse of dump ID</I>
<DD>A dump ID cannot be used twice.
<DT><I>Reuse of region ID</I>
<DD>A region ID cannot be used twice.
<DT><I>Rigid body has degenerate moment of inertia</I>
<DD>Fix poems will only work with bodies (collections of atoms) that have
non-zero principal moments of inertia. This means they must be 3 or
more non-collinear atoms, even with joint atoms removed.
<DT><I>Rigid fix must come before NPT/NPH fix</I>
<DD>NPT/NPH fix must be defined in input script after all rigid fixes,
else the rigid fix contribution to the pressure virial is
incorrect.
<DT><I>Rmask function in equal-style variable formula</I>
<DD>Rmask is per-atom operation.
<DT><I>Run command before simulation box is defined</I>
<DD>The run command cannot be used before a read_data, read_restart, or
create_box command.
<DT><I>Run command start value is after start of run</I>
<DD>Self-explanatory.
<DT><I>Run command stop value is before end of run</I>
<DD>Self-explanatory.
<DT><I>Run_style command before simulation box is defined</I>
<DD>The run_style command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>SRD bin size for fix srd differs from user request</I>
<DD>Fix SRD had to adjust the bin size to fit the simulation box.
<DT><I>SRD bins for fix srd are not cubic enough</I>
<DD>The bin shape is not within tolerance of cubic.
<DT><I>Same dimension twice in fix ave/spatial</I>
<DD>Self-explanatory.
<DT><I>Set command before simulation box is defined</I>
<DD>The set command cannot be used before a read_data, read_restart,
or create_box command.
<DT><I>Set command with no atoms existing</I>
<DD>No atoms are yet defined so the set command cannot be used.
<DT><I>Set region ID does not exist</I>
<DD>Region ID specified in set command does not exist.
<DT><I>Shake angles have different bond types</I>
<DD>All 3-atom angle-constrained SHAKE clusters specified by the fix shake
command that are the same angle type, must also have the same bond
types for the 2 bonds in the angle.
<DT><I>Shake atoms %d %d %d %d missing on proc %d at step</I>
<DD>The 4 atoms in a single shake cluster specified by the fix shake
command are not all accessible to a processor. This probably means
an atom has moved too far.
<DT><I>Shake atoms %d %d %d missing on proc %d at step</I>
<DD>The 3 atoms in a single shake cluster specified by the fix shake
command are not all accessible to a processor. This probably means
an atom has moved too far.
<DT><I>Shake atoms %d %d missing on proc %d at step</I>
<DD>The 2 atoms in a single shake cluster specified by the fix shake
command are not all accessible to a processor. This probably means
an atom has moved too far.
<DT><I>Shake cluster of more than 4 atoms</I>
<DD>A single cluster specified by the fix shake command can have no more
than 4 atoms.
<DT><I>Shake clusters are connected</I>
<DD>A single cluster specified by the fix shake command must have a single
central atom with up to 3 other atoms bonded to it.
<DT><I>Shake determinant = 0.0</I>
<DD>The determinant of the matrix being solved for a single cluster
specified by the fix shake command is numerically invalid.
<DT><I>Shake fix must come before NPT/NPH fix</I>
<DD>NPT fix must be defined in input script after SHAKE fix, else the
SHAKE fix contribution to the pressure virial is incorrect.
<DT><I>Shape command before simulation box is defined</I>
<DD>Self-explanatory.
<DT><I>Smallint setting in lmptype.h is invalid</I>
<DD>It has to be the size of an integer.
<DT><I>Smallint setting in lmptype.h is not compatible</I>
<DD>Smallint stored in restart file is not consistent with LAMMPS version
you are running.
<DT><I>Sqrt of negative value in variable formula</I>
<DD>Self-explanatory.
<DT><I>Substitution for illegal variable</I>
<DD>Input script line contained a variable that could not be substituted
for.
<DT><I>System in data file is too big</I>
<DD>See the setting for bigint in the src/lmptype.h file.
<DT><I>TAD nsteps must be multiple of t_event</I>
<DD>Self-explanatory.
<DT><I>TIP4P hydrogen has incorrect atom type</I>
<DD>The TIP4P pairwise computation found an H atom whose type does not
agree with the specified H type.
<DT><I>TIP4P hydrogen is missing</I>
<DD>The TIP4P pairwise computation failed to find the correct H atom
within a water molecule.
<DT><I>TMD target file did not list all group atoms</I>
<DD>The target file for the fix tmd command did not list all atoms in the
fix group.
<DT><I>Tad command before simulation box is defined</I>
<DD>Self-explanatory.
<DT><I>Tagint setting in lmptype.h is invalid</I>
<DD>Tagint must be as large or larger than smallint.
<DT><I>Tagint setting in lmptype.h is not compatible</I>
<DD>Smallint stored in restart file is not consistent with LAMMPS version
you are running.
<DT><I>Target temperature for fix nvt/npt/nph cannot be 0.0</I>
<DD>Self-explanatory.
<DT><I>Target temperature for fix rigid/nvt cannot be 0.0</I>
<DD>Self-explanatory.
<DT><I>Temper command before simulation box is defined</I>
<DD>The temper command cannot be used before a read_data, read_restart, or
create_box command.
<DT><I>Temperature ID for fix bond/swap does not exist</I>
<DD>Self-explanatory.
<DT><I>Temperature ID for fix box/relax does not exist</I>
<DD>Self-explanatory.
<DT><I>Temperature ID for fix nvt/nph/npt does not exist</I>
<DD>Self-explanatory.
<DT><I>Temperature ID for fix press/berendsen does not exist</I>
<DD>Self-explanatory.
<DT><I>Temperature ID for fix temp/berendsen does not exist</I>
<DD>Self-explanatory.
<DT><I>Temperature ID for fix temp/rescale does not exist</I>
<DD>Self-explanatory.
<DT><I>Temperature control can not be used with fix nph/asphere</I>
<DD>Self-explanatory.
<DT><I>Temperature control can not be used with fix nph/sphere</I>
<DD>Self-explanatory.
<DT><I>Temperature control can not be used with fix nph</I>
<DD>Self-explanatory.
<DT><I>Temperature control must be used with fix npt/asphere</I>
<DD>Self-explanatory.
<DT><I>Temperature control must be used with fix npt/sphere</I>
<DD>Self-explanatory.
<DT><I>Temperature control must be used with fix npt</I>
<DD>Self-explanatory.
<DT><I>Temperature control must be used with fix nvt/asphere</I>
<DD>Self-explanatory.
<DT><I>Temperature control must be used with fix nvt/sllod</I>
<DD>Self-explanatory.
<DT><I>Temperature control must be used with fix nvt/sphere</I>
<DD>Self-explanatory.
<DT><I>Temperature control must be used with fix nvt</I>
<DD>Self-explanatory.
<DT><I>Temperature for fix nvt/sllod does not have a bias</I>
<DD>The specified compute must compute temperature with a bias.
<DT><I>Tempering could not find thermo_pe compute</I>
<DD>This compute is created by the thermo command. It must have been
explicitly deleted by a uncompute command.
<DT><I>Tempering fix ID is not defined</I>
<DD>The fix ID specified by the temper command does not exist.
<DT><I>Tempering temperature fix is not valid</I>
<DD>The fix specified by the temper command is not one that controls
temperature (nvt or langevin).
<DT><I>Thermo and fix not computed at compatible times</I>
<DD>Fixes generate values on specific timesteps. The thermo output
does not match these timesteps.
<DT><I>Thermo compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Thermo compute does not compute array</I>
<DD>Self-explanatory.
<DT><I>Thermo compute does not compute scalar</I>
<DD>Self-explanatory.
<DT><I>Thermo compute does not compute vector</I>
<DD>Self-explanatory.
<DT><I>Thermo compute vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Thermo custom variable cannot be indexed</I>
<DD>Self-explanatory.
<DT><I>Thermo custom variable is not equal-style variable</I>
<DD>Only equal-style variables can be output with thermodynamics, not
atom-style variables.
<DT><I>Thermo every variable returned a bad timestep</I>
<DD>The variable must return a timestep greater than the current timestep.
<DT><I>Thermo fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Thermo fix does not compute array</I>
<DD>Self-explanatory.
<DT><I>Thermo fix does not compute scalar</I>
<DD>Self-explanatory.
<DT><I>Thermo fix does not compute vector</I>
<DD>Self-explanatory.
<DT><I>Thermo fix vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Thermo keyword in variable requires lattice be defined</I>
<DD>The xlat, ylat, zlat keywords refer to lattice properties.
<DT><I>Thermo keyword in variable requires thermo to use/init pe</I>
<DD>You are using a thermo keyword in a variable that requires
potential energy to be calculated, but your thermo output
does not use it. Add it to your thermo output.
<DT><I>Thermo keyword in variable requires thermo to use/init press</I>
<DD>You are using a thermo keyword in a variable that requires pressure to
be calculated, but your thermo output does not use it. Add it to your
thermo output.
<DT><I>Thermo keyword in variable requires thermo to use/init temp</I>
<DD>You are using a thermo keyword in a variable that requires temperature
to be calculated, but your thermo output does not use it. Add it to
your thermo output.
<DT><I>Thermo keyword requires lattice be defined</I>
<DD>The xlat, ylat, zlat keywords refer to lattice properties.
<DT><I>Thermo style does not use press</I>
<DD>Cannot use thermo_modify to set this parameter since the thermo_style
is not computing this quantity.
<DT><I>Thermo style does not use temp</I>
<DD>Cannot use thermo_modify to set this parameter since the thermo_style
is not computing this quantity.
<DT><I>Thermo_modify int format does not contain d character</I>
<DD>Self-explanatory.
<DT><I>Thermo_modify pressure ID does not compute pressure</I>
<DD>The specified compute ID does not compute pressure.
<DT><I>Thermo_modify temperature ID does not compute temperature</I>
<DD>The specified compute ID does not compute temperature.
<DT><I>Thermo_style command before simulation box is defined</I>
<DD>The thermo_style command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>This variable thermo keyword cannot be used between runs</I>
<DD>Keywords that refer to time (such as cpu, elapsed) do not
make sense in between runs.
<DT><I>Threshhold for an atom property that isn't allocated</I>
<DD>A dump threshhold has been requested on a quantity that is
not defined by the atom style used in this simulation.
<DT><I>Timestep must be >= 0</I>
<DD>Specified timestep size is invalid.
<DT><I>Too big a problem to use velocity create loop all</I>
<DD>The system size must fit in a 32-bit integer to use this option.
<DT><I>Too big a timestep for dump dcd</I>
<DD>The timestep must fit in a 32-bit integer to use this dump style.
<DT><I>Too big a timestep for dump xtc</I>
<DD>The timestep must fit in a 32-bit integer to use this dump style.
<DT><I>Too few bits for lookup table</I>
<DD>Table size specified via pair_modify command does not work with your
machine's floating point representation.
<DT><I>Too many atom sorting bins</I>
<DD>This is likely due to an immense simulation box that has blown up
to a large size.
<DT><I>Too many atoms for dump dcd</I>
<DD>The system size must fit in a 32-bit integer to use this dump
style.
<DT><I>Too many atoms for dump xtc</I>
<DD>The system size must fit in a 32-bit integer to use this dump
style.
<DT><I>Too many atoms to dump sort</I>
<DD>Cannot sort when running with more than 2^31 atoms.
<DT><I>Too many exponent bits for lookup table</I>
<DD>Table size specified via pair_modify command does not work with your
machine's floating point representation.
<DT><I>Too many groups</I>
<DD>The maximum number of atom groups (including the "all" group) is
given by MAX_GROUP in group.cpp and is 32.
<DT><I>Too many iterations</I>
<DD>You must use a number of iterations that fit in a 32-bit integer
for minimization.
<DT><I>Too many mantissa bits for lookup table</I>
<DD>Table size specified via pair_modify command does not work with your
machine's floating point representation.
<DT><I>Too many masses for fix shake</I>
<DD>The fix shake command cannot list more masses than there are atom
types.
<DT><I>Too many neighbor bins</I>
<DD>This is likely due to an immense simulation box that has blown up
to a large size.
<DT><I>Too many timesteps for NEB</I>
<DD>You must use a number of timesteps that fit in a 32-bit integer
for NEB.
<DT><I>Too many total atoms</I>
<DD>See the setting for bigint in the src/lmptype.h file.
<DT><I>Too many total bits for bitmapped lookup table</I>
<DD>Table size specified via pair_modify command is too large. Note that
a value of N generates a 2^N size table.
<DT><I>Too many touching neighbors - boost MAXTOUCH</I>
<DD>A granular simulation has too many neighbors touching one atom. The
MAXTOUCH parameter in fix_shear_history.cpp must be set larger and
LAMMPS must be re-built.
<DT><I>Too much per-proc info for dump</I>
<DD>Number of local atoms times number of columns must fit in a 32-bit
integer for dump.
<DT><I>Tree structure in joint connections</I>
<DD>Fix poems cannot (yet) work with coupled bodies whose joints connect
the bodies in a tree structure.
<DT><I>Triclinic box must be periodic in skewed dimensions</I>
<DD>This is a requirement for using a non-orthogonal box. E.g. to set a
non-zero xy tilt, both x and y must be periodic dimensions.
<DT><I>Triclinic box skew is too large</I>
<DD>The displacement in a skewed direction must be less than half the box
length in that dimension. E.g. the xy tilt must be between -half and
+half of the x box length.
<DT><I>Tried to convert a double to int, but input_double > INT_MAX</I>
<DD>Self-explanatory.
<DT><I>Two groups cannot be the same in fix spring couple</I>
<DD>Self-explanatory.
<DT><I>Unbalanced quotes in input line</I>
<DD>No matching end double quote was found following a leading double
quote.
<DT><I>Unexpected end of data file</I>
<DD>LAMMPS hit the end of the data file while attempting to read a
section. Something is wrong with the format of the data file.
<DT><I>Units command after simulation box is defined</I>
<DD>The units command cannot be used after a read_data, read_restart, or
create_box command.
<DT><I>Universe/uloop variable count < # of partitions</I>
<DD>A universe or uloop style variable must specify a number of values >= to the
number of processor partitions.
<DT><I>Unknown command: %s</I>
<DD>The command is not known to LAMMPS. Check the input script.
<DT><I>Unknown identifier in data file: %s</I>
<DD>A section of the data file cannot be read by LAMMPS.
<DT><I>Unknown table style in angle style table</I>
<DD>Self-explanatory.
<DT><I>Unknown table style in bond style table</I>
<DD>Self-explanatory.
<DT><I>Unknown table style in pair_style command</I>
<DD>Style of table is invalid for use with pair_style table command.
<DT><I>Unrecognized lattice type in MEAM file 1</I>
<DD>The lattice type in an entry of the MEAM library file is not
valid.
<DT><I>Unrecognized lattice type in MEAM file 2</I>
<DD>The lattice type in an entry of the MEAM parameter file is not
valid.
<DT><I>Unrecognized pair style in compute pair command</I>
<DD>Self-explanatory.
<DT><I>Use of compute temp/ramp with undefined lattice</I>
<DD>Must use lattice command with compute temp/ramp command if units
option is set to lattice.
<DT><I>Use of displace_atoms with undefined lattice</I>
<DD>Must use lattice command with displace_atoms command if units option
is set to lattice.
<DT><I>Use of displace_box with undefined lattice</I>
<DD>Must use lattice command with displace_box command if units option is
set to lattice.
<DT><I>Use of fix ave/spatial with undefined lattice</I>
<DD>A lattice must be defined to use fix ave/spatial with units = lattice.
<DT><I>Use of fix deform with undefined lattice</I>
<DD>A lattice must be defined to use fix deform with units = lattice.
<DT><I>Use of fix deposit with undefined lattice</I>
<DD>Must use lattice command with compute fix deposit command if units
option is set to lattice.
<DT><I>Use of fix dt/reset with undefined lattice</I>
<DD>Must use lattice command with fix dt/reset command if units option is
set to lattice.
<DT><I>Use of fix indent with undefined lattice</I>
<DD>The lattice command must be used to define a lattice before using the
fix indent command.
<DT><I>Use of fix move with undefined lattice</I>
<DD>Must use lattice command with fix move command if units option is
set to lattice.
<DT><I>Use of fix recenter with undefined lattice</I>
<DD>Must use lattice command with fix recenter command if units option is
set to lattice.
<DT><I>Use of fix wall with undefined lattice</I>
<DD>Must use lattice command with fix wall command if units option is set
to lattice.
<DT><I>Use of region with undefined lattice</I>
<DD>If scale = lattice (the default) for the region command, then a
lattice must first be defined via the lattice command.
<DT><I>Use of velocity with undefined lattice</I>
<DD>If scale = lattice (the default) for the velocity set or velocity ramp
command, then a lattice must first be defined via the lattice command.
<DT><I>Using fix nvt/sllod with inconsistent fix deform remap option</I>
<DD>Fix nvt/sllod requires that deforming atoms have a velocity profile
provided by "remap v" as a fix deform option.
<DT><I>Using fix nvt/sllod with no fix deform defined</I>
<DD>Self-explanatory.
<DT><I>Using fix srd with inconsistent fix deform remap option</I>
<DD>When shearing the box in an SRD simulation, the remap v option for fix
deform needs to be used.
<DT><I>Variable evaluation before simulation box is defined</I>
<DD>Cannot evaluate a compute or fix or atom-based value in a variable
before the simulation has been setup.
<DT><I>Variable for compute ti is invalid style</I>
<DD>Self-explanatory.
<DT><I>Variable for dump every is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix adapt is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix addforce is invalid style</I>
<DD>Self-explanatory.
<DT><I>Variable for fix aveforce is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix efield is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix indent is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix indent is not equal style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix move is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix setforce is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix wall is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix wall/reflect is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for fix wall/srd is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for region is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for region is not equal style</I>
<DD>Self-explanatory.
<DT><I>Variable for thermo every is invalid style</I>
<DD>Only equal-style variables can be used.
<DT><I>Variable for velocity set is invalid style</I>
<DD>Only atom-style variables can be used.
<DT><I>Variable formula compute array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Variable formula compute vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Variable formula fix array is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Variable formula fix vector is accessed out-of-range</I>
<DD>Self-explanatory.
<DT><I>Variable name for compute atom/molecule does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for compute reduce does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for compute ti does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for dump every does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix adapt does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix addforce does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix ave/atom does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix ave/correlate does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix ave/histo does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix ave/spatial does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix ave/time does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix aveforce does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix efield does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix indent does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix move does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix setforce does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix store/state does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix wall does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix wall/reflect does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for fix wall/srd does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for region does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for thermo every does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name for velocity set does not exist</I>
<DD>Self-explanatory.
<DT><I>Variable name must be alphanumeric or underscore characters</I>
<DD>Self-explanatory.
<DT><I>Velocity command before simulation box is defined</I>
<DD>The velocity command cannot be used before a read_data, read_restart,
or create_box command.
<DT><I>Velocity command with no atoms existing</I>
<DD>A velocity command has been used, but no atoms yet exist.
<DT><I>Velocity ramp in z for a 2d problem</I>
<DD>Self-explanatory.
<DT><I>Velocity temperature ID does not compute temperature</I>
<DD>The compute ID given to the velocity command must compute
temperature.
<DT><I>Virial was not tallied on needed timestep</I>
<DD>You are using a thermo keyword that requires potentials to
have tallied the virial, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work.
<DT><I>Wall defined twice in fix wall command</I>
<DD>Self-explanatory.
<DT><I>Wall defined twice in fix wall/reflect command</I>
<DD>Self-explanatory.
<DT><I>Wall defined twice in fix wall/srd command</I>
<DD>Self-explanatory.
<DT><I>Weighted neighbor list values are too big</I>
<DD>You must have less atoms per processor to use this
style neighbor list.
<DT><I>World variable count doesn't match # of partitions</I>
<DD>A world-style variable must specify a number of values equal to the
number of processor partitions.
<DT><I>Write_restart command before simulation box is defined</I>
<DD>The write_restart command cannot be used before a read_data,
read_restart, or create_box command.
<DT><I>Zero-length lattice orient vector</I>
<DD>Self-explanatory.
</DL>
<H4><A NAME = "warn"></A>Warnings:
</H4>
<DL>
<DT><I>All element names have been set to 'C' for dump cfg</I>
<DD>Use the dump_modify command if you wish to override this.
<DT><I>Atom with molecule ID = 0 included in compute molecule group</I>
<DD>The group used in a compute command that operates on moleclues
includes atoms with no molecule ID. This is probably not what you
want.
<DT><I>Broken bonds will not alter angles, dihedrals, or impropers</I>
<DD>See the doc page for fix bond/break for more info on this
restriction.
<DT><I>Building an occasional neighobr list when atoms may have moved too far</I>
<DD>This can cause LAMMPS to crash when the neighbor list is built.
The solution is to check for building the regular neighbor lists
more frequently.
<DT><I>Compute cna/atom cutoff may be too large to find ghost atom neighbors</I>
<DD>The neighbor cutoff used may not encompass enough ghost atoms
to perform this operation correctly.
<DT><I>Computing temperature of portions of rigid bodies</I>
<DD>The group defined by the temperature compute does not encompass all
the atoms in one or more rigid bodies, so the change in
degrees-of-freedom for the atoms in those partial rigid bodies will
not be accounted for.
<DT><I>Created bonds will not create angles, dihedrals, or impropers</I>
<DD>See the doc page for fix bond/create for more info on this
restriction.
<DT><I>Dihedral problem: %d %d %d %d %d %d</I>
<DD>Conformation of the 4 listed dihedral atoms is extreme; you may want
to check your simulation geometry.
<DT><I>Dump dcd/xtc timestamp may be wrong with fix dt/reset</I>
<DD>If the fix changes the timestep, the dump dcd file will not
reflect the change.
<DT><I>FENE bond too long: %d %d %d %g</I>
<DD>A FENE bond has stretched dangerously far. It's interaction strength
will be truncated to attempt to prevent the bond from blowing up.
<DT><I>FENE bond too long: %d %g</I>
<DD>A FENE bond has stretched dangerously far. It's interaction strength
will be truncated to attempt to prevent the bond from blowing up.
<DT><I>Fix SRD walls overlap but fix srd overlap not set</I>
<DD>You likely want to set this in your input script.
<DT><I>Fix bond/swap will ignore defined angles</I>
<DD>See the doc page for fix bond/swap for more info on this
restriction.
<DT><I>Fix move does not update angular momentum</I>
<DD>Atoms store this quantity, but fix move does not (yet) update it.
<DT><I>Fix move does not update quaternions</I>
<DD>Atoms store this quantity, but fix move does not (yet) update it.
<DT><I>Fix recenter should come after all other integration fixes</I>
<DD>Other fixes may change the position of the center-of-mass, so
fix recenter should come last.
<DT><I>Fix srd SRD moves may trigger frequent reneighboring</I>
<DD>This is because the SRD particles may move long distances.
<DT><I>Fix srd grid size > 1/4 of big particle diameter</I>
<DD>This may cause accuracy problems.
<DT><I>Fix srd no-slip wall collisions with bin shifting</I>
<DD>This is an inconsistent setting in your input script.
<DT><I>Fix srd particle moved outside valid domain</I>
<DD>This may indicate a problem with your simulation parameters.
<DT><I>Fix srd particles may move > big particle diameter</I>
<DD>This may cause accuracy problems.
<DT><I>Fix srd viscosity < 0.0 due to low SRD density</I>
<DD>This may cause accuracy problems.
<DT><I>Fix thermal/conductivity comes before fix ave/spatial</I>
<DD>The order of these 2 fixes in your input script is such that fix
thermal/conductivity comes first. If you are using fix ave/spatial to
measure the temperature profile induced by fix viscosity, then this
may cause a glitch in the profile since you are averaging immediately
after swaps have occurred. Flipping the order of the 2 fixes
typically helps.
<DT><I>Fix viscosity comes before fix ave/spatial</I>
<DD>The order of these 2 fixes in your input script is such that
fix viscosity comes first. If you are using fix ave/spatial
to measure the velocity profile induced by fix viscosity, then
this may cause a glitch in the profile since you are averaging
immediately after swaps have occurred. Flipping the order
of the 2 fixes typically helps.
<DT><I>Group for fix_modify temp != fix group</I>
<DD>The fix_modify command is specifying a temperature computation that
computes a temperature on a different group of atoms than the fix
itself operates on. This is probably not what you want to do.
<DT><I>Improper problem: %d %d %d %d %d %d</I>
<DD>Conformation of the 4 listed improper atoms is extreme; you may want
to check your simulation geometry.
<DT><I>Kspace_modify slab param < 2.0 may cause unphysical behavior</I>
<DD>The kspace_modify slab parameter should be larger to insure periodic
grids padded with empty space do not overlap.
<DT><I>Less insertions than requested</I>
<DD>Less atom insertions occurred on this timestep due to the fix pour
command than were scheduled. This is probably because there were too
many overlaps detected.
<DT><I>Lost atoms: original %.15g current %.15g</I>
<DD>A thermodynamic computation has detected lost atoms.
<DT><I>Mismatch between velocity and compute groups</I>
<DD>The temperature computation used by the velocity command will not be
on the same group of atoms that velocities are being set for.
<DT><I>More than one compute centro/atom</I>
<DD>It is not efficient to use compute centro/atom more than once.
<DT><I>More than one compute cluster/atom</I>
<DD>It is not efficient to use compute cluster/atom more than once.
<DT><I>More than one compute cna/atom defined</I>
<DD>It is not efficient to use compute cna/atom more than once.
<DT><I>More than one compute coord/atom</I>
<DD>It is not efficient to use compute coord/atom more than once.
<DT><I>More than one compute damage/atom</I>
<DD>It is not efficient to use compute ke/atom more than once.
<DT><I>More than one compute ke/atom</I>
<DD>It is not efficient to use compute ke/atom more than once.
<DT><I>More than one fix poems</I>
<DD>It is not efficient to use fix poems more than once.
<DT><I>More than one fix rigid</I>
<DD>It is not efficient to use fix rigid more than once.
<DT><I>New thermo_style command, previous thermo_modify settings will be lost</I>
<DD>If a thermo_style command is used after a thermo_modify command, the
settings changed by the thermo_modify command will be reset to their
default values. This is because the thermo_modify commmand acts on
the currently defined thermo style, and a thermo_style command creates
a new style.
<DT><I>No fixes defined, atoms won't move</I>
<DD>If you are not using a fix like nve, nvt, npt then atom velocities and
coordinates will not be updated during timestepping.
<DT><I>No joints between rigid bodies, use fix rigid instead</I>
<DD>The bodies defined by fix poems are not connected by joints. POEMS
will integrate the body motion, but it would be more efficient to use
fix rigid.
<DT><I>Not using real units with pair reax</I>
<DD>This is most likely an error, unless you have created your own ReaxFF
parameter file in a different set of units.
<DT><I>One or more atoms are time integrated more than once</I>
<DD>This is probably an error since you typically do not want to
advance the positions or velocities of an atom more than once
per timestep.
<DT><I>One or more compute molecules has atoms not in group</I>
<DD>The group used in a compute command that operates on moleclues does
not include all the atoms in some molecules. This is probably not
what you want.
<DT><I>One or more respa levels compute no forces</I>
<DD>This is computationally inefficient.
<DT><I>Pair COMB charge %.10f with force %.10f hit max barrier</I>
<DD>Something is possibly wrong with your model.
<DT><I>Pair COMB charge %.10f with force %.10f hit min barrier</I>
<DD>Something is possibly wrong with your model.
<DT><I>Pair dsmc: num_of_collisions > number_of_A</I>
<DD>Collision model in DSMC is breaking down.
<DT><I>Pair dsmc: num_of_collisions > number_of_B</I>
<DD>Collision model in DSMC is breaking down.
<DT><I>Particle deposition was unsuccessful</I>
<DD>The fix deposit command was not able to insert as many atoms as
needed. The requested volume fraction may be too high, or other atoms
may be in the insertion region.
<DT><I>Reducing PPPM order b/c stencil extends beyond neighbor processor</I>
<DD>LAMMPS is attempting this in order to allow the simulation
to run. It should not effect the PPPM accuracy.
<DT><I>Replacing a fix, but new group != old group</I>
<DD>The ID and style of a fix match for a fix you are changing with a fix
command, but the new group you are specifying does not match the old
group.
<DT><I>Replicating in a non-periodic dimension</I>
<DD>The parameters for a replicate command will cause a non-periodic
dimension to be replicated; this may cause unwanted behavior.
<DT><I>Resetting reneighboring criteria during PRD</I>
<DD>A PRD simulation requires that neigh_modify settings be delay = 0,
every = 1, check = yes. Since these settings were not in place,
LAMMPS changed them and will restore them to their original values
after the PRD simulation.
<DT><I>Resetting reneighboring criteria during TAD</I>
<DD>A TAD simulation requires that neigh_modify settings be delay = 0,
every = 1, check = yes. Since these settings were not in place,
LAMMPS changed them and will restore them to their original values
after the PRD simulation.
<DT><I>Resetting reneighboring criteria during minimization</I>
<DD>Minimization requires that neigh_modify settings be delay = 0, every =
1, check = yes. Since these settings were not in place, LAMMPS
changed them and will restore them to their original values after the
minimization.
<DT><I>Restart file used different # of processors</I>
<DD>The restart file was written out by a LAMMPS simulation running on a
different number of processors. Due to round-off, the trajectories of
your restarted simulation may diverge a little more quickly than if
you ran on the same # of processors.
<DT><I>Restart file used different 3d processor grid</I>
<DD>The restart file was written out by a LAMMPS simulation running on a
different 3d grid of processors. Due to round-off, the trajectories
of your restarted simulation may diverge a little more quickly than if
you ran on the same # of processors.
<DT><I>Restart file used different boundary settings, using restart file values</I>
<DD>Your input script cannot change these restart file settings.
<DT><I>Restart file used different newton bond setting, using restart file value</I>
<DD>The restart file value will override the setting in the input script.
<DT><I>Restart file used different newton pair setting, using input script value</I>
<DD>The input script value will override the setting in the restart file.
<DT><I>Restart file version does not match LAMMPS version</I>
<DD>This may cause problems when reading the restart file.
<DT><I>Running PRD with only one replica</I>
<DD>This is allowed, but you will get no parallel speed-up.
<DT><I>SRD bin shifting turned on due to small lamda</I>
<DD>This is done to try to preserve accuracy.
<DT><I>SRD bin size for fix srd differs from user request</I>
<DD>Check if the new bin size is acceptable.
<DT><I>SRD bins for fix srd are not cubic enough</I>
<DD>Check if the bin shape is acceptable.
<DT><I>SRD particle %d started inside big particle %d on step %d bounce %d</I>
<DD>This may not be a problem, but indicates one or more SRD particles are
being left inside solute particles.
<DT><I>Shake determinant < 0.0</I>
<DD>The determinant of the quadratic equation being solved for a single
cluster specified by the fix shake command is numerically suspect. LAMMPS
will set it to 0.0 and continue.
<DT><I>Should not allow rigid bodies to bounce off relecting walls</I>
<DD>LAMMPS allows this, but their dynamics are not computed correctly.
<DT><I>System is not charge neutral, net charge = %g</I>
<DD>The total charge on all atoms on the system is not 0.0, which
is not valid for Ewald or PPPM.
<DT><I>Table inner cutoff >= outer cutoff</I>
<DD>You specified an inner cutoff for a Coulombic table that is longer
than the global cutoff. Probably not what you wanted.
<DT><I>Temperature for MSST is not for group all</I>
<DD>User-assigned temperature to MSST fix does not compute temperature for
all atoms. Since MSST computes a global pressure, the kinetic energy
contribution from the temperature is assumed to also be for all atoms.
Thus the pressure used by MSST could be inaccurate.
<DT><I>Temperature for NPT is not for group all</I>
<DD>User-assigned temperature to NPT fix does not compute temperature for
all atoms. Since NPT computes a global pressure, the kinetic energy
contribution from the temperature is assumed to also be for all atoms.
Thus the pressure used by NPT could be inaccurate.
<DT><I>Temperature for fix modify is not for group all</I>
<DD>The temperature compute is being used with a pressure calculation
which does operate on group all, so this may be inconsistent.
<DT><I>Temperature for thermo pressure is not for group all</I>
<DD>User-assigned temperature to thermo via the thermo_modify command does
not compute temperature for all atoms. Since thermo computes a global
pressure, the kinetic energy contribution from the temperature is
assumed to also be for all atoms. Thus the pressure printed by thermo
could be inaccurate.
<DT><I>Too many common neighbors in CNA %d times</I>
<DD>More than the maximum # of neighbors was found multiple times. This
was unexpected.
<DT><I>Too many inner timesteps in fix ttm</I>
<DD>Self-explanatory.
<DT><I>Too many neighbors in CNA for %d atoms</I>
<DD>More than the maximum # of neighbors was found multiple times. This
was unexpected.
<DT><I>Use special bonds = 0,1,1 with bond style fene/expand</I>
<DD>Most FENE models need this setting for the special_bonds command.
<DT><I>Use special bonds = 0,1,1 with bond style fene</I>
<DD>Most FENE models need this setting for the special_bonds command.
<DT><I>Using compute temp/deform with inconsistent fix deform remap option</I>
<DD>Fix nvt/sllod assumes deforming atoms have a velocity profile provided
by "remap v" or "remap none" as a fix deform option.
<DT><I>Using compute temp/deform with no fix deform defined</I>
<DD>This is probably an error, since it makes little sense to use
compute temp/deform in this case.
<DT><I>Using pair tail corrections with nonperiodic system</I>
<DD>This is probably a bogus thing to do, since tail corrections are
computed by integrating the density of a periodic system out to
infinity.
</DL>
</HTML>
diff --git a/doc/Section_errors.txt b/doc/Section_errors.txt
index 0712fb922..dab3e05cf 100644
--- a/doc/Section_errors.txt
+++ b/doc/Section_errors.txt
@@ -1,6592 +1,6596 @@
"Previous Section"_Section_python.html - "LAMMPS WWW Site"_lws -
"LAMMPS Documentation"_ld - "LAMMPS Commands"_lc - "Next
Section"_Section_history.html :c
:link(lws,http://lammps.sandia.gov)
:link(ld,Manual.html)
:link(lc,Section_commands.html#comm)
:line
12. Errors :h3
This section describes the various kinds of errors you can encounter
when using LAMMPS.
12.1 "Common problems"_#err_1
12.2 "Reporting bugs"_#err_2
12.3 "Error & warning messages"_#err_3 :all(b)
:line
12.1 Common problems :link(err_1),h4
If two LAMMPS runs do not produce the same answer on different
machines or different numbers of processors, this is typically not a
bug. In theory you should get identical answers on any number of
processors and on any machine. In practice, numerical round-off can
cause slight differences and eventual divergence of molecular dynamics
phase space trajectories within a few 100s or few 1000s of timesteps.
However, the statistical properties of the two runs (e.g. average
energy or temperature) should still be the same.
If the "velocity"_velocity.html command is used to set initial atom
velocities, a particular atom can be assigned a different velocity
when the problem is run on a different number of processors or on
different machines. If this happens, the phase space trajectories of
the two simulations will rapidly diverge. See the discussion of the
{loop} option in the "velocity"_velocity.html command for details and
options that avoid this issue.
Similarly, the "create_atoms"_create_atoms.html command generates a
lattice of atoms. For the same physical system, the ordering and
numbering of atoms by atom ID may be different depending on the number
of processors.
Some commands use random number generators which may be setup to
produce different random number streams on each processor and hence
will produce different effects when run on different numbers of
processors. A commonly-used example is the "fix
langevin"_fix_langevin.html command for thermostatting.
A LAMMPS simulation typically has two stages, setup and run. Most
LAMMPS errors are detected at setup time; others like a bond
stretching too far may not occur until the middle of a run.
LAMMPS tries to flag errors and print informative error messages so
you can fix the problem. Of course, LAMMPS cannot figure out your
physics or numerical mistakes, like choosing too big a timestep,
specifying erroneous force field coefficients, or putting 2 atoms on
top of each other! If you run into errors that LAMMPS doesn't catch
that you think it should flag, please send an email to the
"developers"_http://lammps.sandia.gov/authors.html.
If you get an error message about an invalid command in your input
script, you can determine what command is causing the problem by
looking in the log.lammps file or using the "echo command"_echo.html
to see it on the screen. For a given command, LAMMPS expects certain
arguments in a specified order. If you mess this up, LAMMPS will
often flag the error, but it may read a bogus argument and assign a
value that is valid, but not what you wanted. E.g. trying to read the
string "abc" as an integer value and assigning the associated variable
a value of 0.
Generally, LAMMPS will print a message to the screen and logfile and
exit gracefully when it encounters a fatal error. Sometimes it will
print a WARNING to the screen and logfile and continue on; you can
decide if the WARNING is important or not. A WARNING message that is
generated in the middle of a run is only printed to the screen, not to
the logfile, to avoid cluttering up thermodynamic output. If LAMMPS
crashes or hangs without spitting out an error message first then it
could be a bug (see "this section"_#err_2) or one of the following
cases:
LAMMPS runs in the available memory a processor allows to be
allocated. Most reasonable MD runs are compute limited, not memory
limited, so this shouldn't be a bottleneck on most platforms. Almost
all large memory allocations in the code are done via C-style malloc's
which will generate an error message if you run out of memory.
Smaller chunks of memory are allocated via C++ "new" statements. If
you are unlucky you could run out of memory just when one of these
small requests is made, in which case the code will crash or hang (in
parallel), since LAMMPS doesn't trap on those errors.
Illegal arithmetic can cause LAMMPS to run slow or crash. This is
typically due to invalid physics and numerics that your simulation is
computing. If you see wild thermodynamic values or NaN values in your
LAMMPS output, something is wrong with your simulation. If you
suspect this is happening, it is a good idea to print out
thermodynamic info frequently (e.g. every timestep) via the
"thermo"_thermo.html so you can monitor what is happening.
Visualizing the atom movement is also a good idea to insure your model
is behaving as you expect.
In parallel, one way LAMMPS can hang is due to how different MPI
implementations handle buffering of messages. If the code hangs
without an error message, it may be that you need to specify an MPI
setting or two (usually via an environment variable) to enable
buffering or boost the sizes of messages that can be buffered.
:line
12.2 Reporting bugs :link(err_2),h4
If you are confident that you have found a bug in LAMMPS, follow these
steps.
Check the "New features and bug
fixes"_http://lammps.sandia.gov/bug.html section of the "LAMMPS WWW
site"_lws to see if the bug has already been reported or fixed or the
"Unfixed bug"_http://lammps.sandia.gov/unbug.html to see if a fix is
pending.
Check the "mailing list"_http://lammps.sandia.gov/mail.html
to see if it has been discussed before.
If not, send an email to the mailing list describing the problem with
any ideas you have as to what is causing it or where in the code the
problem might be. The developers will ask for more info if needed,
such as an input script or data files.
The most useful thing you can do to help us fix the bug is to isolate
the problem. Run it on the smallest number of atoms and fewest number
of processors and with the simplest input script that reproduces the
bug and try to identify what command or combination of commands is
causing the problem.
As a last resort, you can send an email directly to the
"developers"_http://lammps.sandia.gov/authors.html.
:line
12.3 Error & warning messages :h4,link(err_3)
These are two alphabetic lists of the "ERROR"_#error and
"WARNING"_#warn messages LAMMPS prints out and the reason why. If the
explanation here is not sufficient, the documentation for the
-offending command may help. Grepping the source files for the text of
-the error message and staring at the source code and comments is also
-not a bad idea! Note that sometimes the same message can be printed
-from multiple places in the code.
+offending command may help.
+Error and warning messages also list the source file and line number
+where the error was generated. For example, this message
-Also note that error messages from "user-contributed
-packages"_Section_start.html#start_3 are not listed here. Is such an
+ERROR: Illegal velocity command (velocity.cpp:78)
+
+means that line #78 in the file src/velocity.cpp generated the error.
+Looking in the source code may help you figure out what went wrong.
+
+Note that error messages from "user-contributed
+packages"_Section_start.html#start_3 are not listed here. If such an
error occurs and is not self-explanatory, you'll need to look in the
source code or contact the author of the package.
Errors: :h4,link(error)
:dlb
{1-3 bond count is inconsistent} :dt
An inconsistency was detected when computing the number of 1-3
neighbors for each atom. This likely means something is wrong with
the bond topologies you have defined. :dd
{1-4 bond count is inconsistent} :dt
An inconsistency was detected when computing the number of 1-4
neighbors for each atom. This likely means something is wrong with
the bond topologies you have defined. :dd
{Accelerated style in input script but no fix gpu} :dt
GPU acceleration requires fix gpu in the input script. :dd
{All angle coeffs are not set} :dt
All angle coefficients must be set in the data file or by the
angle_coeff command before running a simulation. :dd
{All bond coeffs are not set} :dt
All bond coefficients must be set in the data file or by the
bond_coeff command before running a simulation. :dd
{All dihedral coeffs are not set} :dt
All dihedral coefficients must be set in the data file or by the
dihedral_coeff command before running a simulation. :dd
{All dipole moments are not set} :dt
For atom styles that define dipole moments for each atom type, all
moments must be set in the data file or by the dipole command before
running a simulation. :dd
{All improper coeffs are not set} :dt
All improper coefficients must be set in the data file or by the
improper_coeff command before running a simulation. :dd
{All masses are not set} :dt
For atom styles that define masses for each atom type, all masses must
be set in the data file or by the mass command before running a
simulation. They must also be set before using the velocity
command. :dd
{All pair coeffs are not set} :dt
All pair coefficients must be set in the data file or by the
pair_coeff command before running a simulation. :dd
{All shapes are not set} :dt
All atom types must have a shape setting, even if the particles
are spherical. :dd
{All universe/uloop variables must have same # of values} :dt
Self-explanatory. :dd
{All variables in next command must be same style} :dt
Self-explanatory. :dd
{Angle atom missing in delete_bonds} :dt
The delete_bonds command cannot find one or more atoms in a particular
angle on a particular processor. The pairwise cutoff is too short or
the atoms are too far apart to make a valid angle. :dd
{Angle atom missing in set command} :dt
The set command cannot find one or more atoms in a particular angle on
a particular processor. The pairwise cutoff is too short or the atoms
are too far apart to make a valid angle. :dd
{Angle atoms %d %d %d missing on proc %d at step} :dt
One or more of 3 atoms needed to compute a particular angle are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the angle has blown apart and an atom is
too far away. :dd
{Angle coeff for hybrid has invalid style} :dt
Angle style hybrid uses another angle style as one of its
coefficients. The angle style used in the angle_coeff command or read
from a restart file is not recognized. :dd
{Angle coeffs are not set} :dt
No angle coefficients have been assigned in the data file or via the
angle_coeff command. :dd
{Angle potential must be defined for SHAKE} :dt
When shaking angles, an angle_style potential must be used. :dd
{Angle style hybrid cannot have hybrid as an argument} :dt
Self-explanatory. :dd
{Angle style hybrid cannot have none as an argument} :dt
Self-explanatory. :dd
{Angle style hybrid cannot use same pair style twice} :dt
Self-explanatory. :dd
{Angle table must range from 0 to 180 degrees} :dt
Self-explanatory. :dd
{Angle table parameters did not set N} :dt
List of angle table parameters must include N setting. :dd
{Angle_coeff command before angle_style is defined} :dt
Coefficients cannot be set in the data file or via the angle_coeff
command until an angle_style has been assigned. :dd
{Angle_coeff command before simulation box is defined} :dt
The angle_coeff command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Angle_coeff command when no angles allowed} :dt
The chosen atom style does not allow for angles to be defined. :dd
{Angle_style command when no angles allowed} :dt
The chosen atom style does not allow for angles to be defined. :dd
{Angles assigned incorrectly} :dt
Angles read in from the data file were not assigned correctly to
atoms. This means there is something invalid about the topology
definitions. :dd
{Angles defined but no angle types} :dt
The data file header lists angles but no angle types. :dd
{Another input script is already being processed} :dt
Cannot attempt to open a 2nd input script, when the original file is
still being processed. :dd
{Arccos of invalid value in variable formula} :dt
Argument of arccos() must be between -1 and 1. :dd
{Arcsin of invalid value in variable formula} :dt
Argument of arcsin() must be between -1 and 1. :dd
{Atom IDs must be consecutive for velocity create loop all} :dt
Self-explanatory. :dd
{Atom count changed in fix neb} :dt
This is not allowed in a NEB calculation. :dd
{Atom count is inconsistent, cannot write restart file} :dt
Sum of atoms across processors does not equal initial total count.
This is probably because you have lost some atoms. :dd
{Atom in too many rigid bodies - boost MAXBODY} :dt
Fix poems has a parameter MAXBODY (in fix_poems.cpp) which determines
the maximum number of rigid bodies a single atom can belong to (i.e. a
multibody joint). The bodies you have defined exceed this limit. :dd
{Atom sort did not operate correctly} :dt
This is an internal LAMMPS error. Please report it to the
developers. :dd
{Atom sorting has bin size = 0.0} :dt
The neighbor cutoff is being used as the bin size, but it is zero.
Thus you must explicitly list a bin size in the atom_modify sort
command or turn off sorting. :dd
{Atom style hybrid cannot have hybrid as an argument} :dt
Self-explanatory. :dd
{Atom style hybrid cannot use same atom style twice} :dt
Self-explanatory. :dd
{Atom vector in equal-style variable formula} :dt
Atom vectors generate one value per atom which is not allowed
in an equal-style variable. :dd
{Atom-style variable in equal-style variable formula} :dt
Atom-style variables generate one value per atom which is not allowed
in an equal-style variable. :dd
{Atom_modify map command after simulation box is defined} :dt
The atom_modify map command cannot be used after a read_data,
read_restart, or create_box command. :dd
{Atom_modify sort and first options cannot be used together} :dt
Self-explanatory. :dd
{Atom_style command after simulation box is defined} :dt
The atom_style command cannot be used after a read_data,
read_restart, or create_box command. :dd
{Attempt to pop empty stack in fix box/relax} :dt
Internal LAMMPS error. Please report it to the developers. :dd
{Attempt to push beyond stack limit in fix box/relax} :dt
Internal LAMMPS error. Please report it to the developers. :dd
{Attempting to rescale a 0.0 temperature} :dt
Cannot rescale a temperature that is already 0.0. :dd
{Bad FENE bond} :dt
Two atoms in a FENE bond have become so far apart that the bond cannot
be computed. :dd
{Bad TIP4P angle type for PPPM/TIP4P} :dt
Specified angle type is not valid. :dd
{Bad TIP4P bond type for PPPM/TIP4P} :dt
Specified bond type is not valid. :dd
{Bad grid of processors} :dt
The 3d grid of processors defined by the processors command does not
match the number of processors LAMMPS is being run on. :dd
{Bad kspace_modify slab parameter} :dt
Kspace_modify value for the slab/volume keyword must be >= 2.0. :dd
{Bad principal moments} :dt
Fix rigid did not compute the principal moments of inertia of a rigid
group of atoms correctly. :dd
{Bias compute does not calculate a velocity bias} :dt
The specified compute must compute a bias for temperature. :dd
{Bias compute does not calculate temperature} :dt
The specified compute must compute temperature. :dd
{Bias compute group does not match compute group} :dt
The specified compute must operate on the same group as the parent
compute. :dd
{Big particle in fix srd cannot be point particle} :dt
Big particles must be extended spheriods or ellipsoids. :dd
{Bigint setting in lmptype.h is invalid} :dt
Size of bigint is less than size of tagint. :dd
{Bigint setting in lmptype.h is not compatible} :dt
Bigint stored in restart file is not consistent with LAMMPS version
you are running. :dd
{Bitmapped lookup tables require int/float be same size} :dt
Cannot use pair tables on this machine, because of word sizes. Use
the pair_modify command with table 0 instead. :dd
{Bitmapped table in file does not match requested table} :dt
Setting for bitmapped table in pair_coeff command must match table
in file exactly. :dd
{Bitmapped table is incorrect length in table file} :dt
Number of table entries is not a correct power of 2. :dd
{Bond and angle potentials must be defined for TIP4P} :dt
Cannot use TIP4P pair potential unless bond and angle potentials
are defined. :dd
{Bond atom missing in delete_bonds} :dt
The delete_bonds command cannot find one or more atoms in a particular
bond on a particular processor. The pairwise cutoff is too short or
the atoms are too far apart to make a valid bond. :dd
{Bond atom missing in set command} :dt
The set command cannot find one or more atoms in a particular bond on
a particular processor. The pairwise cutoff is too short or the atoms
are too far apart to make a valid bond. :dd
{Bond atoms %d %d missing on proc %d at step} :dt
One or both of 2 atoms needed to compute a particular bond are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the bond has blown apart and an atom is
too far away. :dd
{Bond coeff for hybrid has invalid style} :dt
Bond style hybrid uses another bond style as one of its coefficients.
The bond style used in the bond_coeff command or read from a restart
file is not recognized. :dd
{Bond coeffs are not set} :dt
No bond coefficients have been assigned in the data file or via the
bond_coeff command. :dd
{Bond potential must be defined for SHAKE} :dt
Cannot use fix shake unless bond potential is defined. :dd
{Bond style hybrid cannot have hybrid as an argument} :dt
Self-explanatory. :dd
{Bond style hybrid cannot have none as an argument} :dt
Self-explanatory. :dd
{Bond style hybrid cannot use same pair style twice} :dt
Self-explanatory. :dd
{Bond style quartic cannot be used with 3,4-body interactions} :dt
No angle, dihedral, or improper styles can be defined when using
bond style quartic. :dd
{Bond style quartic requires special_bonds = 1,1,1} :dt
This is a restriction of the current bond quartic implementation. :dd
{Bond table parameters did not set N} :dt
List of bond table parameters must include N setting. :dd
{Bond table values are not increasing} :dt
The values in the tabulated file must be monotonically increasing. :dd
{Bond_coeff command before bond_style is defined} :dt
Coefficients cannot be set in the data file or via the bond_coeff
command until an bond_style has been assigned. :dd
{Bond_coeff command before simulation box is defined} :dt
The bond_coeff command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Bond_coeff command when no bonds allowed} :dt
The chosen atom style does not allow for bonds to be defined. :dd
{Bond_style command when no bonds allowed} :dt
The chosen atom style does not allow for bonds to be defined. :dd
{Bonds assigned incorrectly} :dt
Bonds read in from the data file were not assigned correctly to atoms.
This means there is something invalid about the topology definitions. :dd
{Bonds defined but no bond types} :dt
The data file header lists bonds but no bond types. :dd
{Both sides of boundary must be periodic} :dt
Cannot specify a boundary as periodic only on the lo or hi side. Must
be periodic on both sides. :dd
{Boundary command after simulation box is defined} :dt
The boundary command cannot be used after a read_data, read_restart,
or create_box command. :dd
{Box bounds are invalid} :dt
The box boundaries specified in the read_data file are invalid. The
lo value must be less than the hi value for all 3 dimensions. :dd
{Can not specify Pxy/Pxz/Pyz in fix box/relax with non-triclinic box} :dt
Only triclinic boxes can be used with off-diagonal pressure components.
See the region prism command for details. :dd
{Can not specify Pxy/Pxz/Pyz in fix nvt/npt/nph with non-triclinic box} :dt
Only triclinic boxes can be used with off-diagonal pressure components.
See the region prism command for details. :dd
{Can only use NEB with 1-processor replicas} :dt
This is current restriction for NEB as implemented in LAMMPS. :dd
{Can only use TAD with 1-processor replicas for NEB} :dt
This is current restriction for NEB as implemented in LAMMPS. :dd
{Cannot (yet) use PPPM with triclinic box} :dt
This feature is not yet supported. :dd
{Cannot add atoms to fix move variable} :dt
Atoms can not be added afterwards to this fix option. :dd
{Cannot change box to orthogonal when tilt is non-zero} :dt
Self-explanatory :dd
{Cannot change box with certain fixes defined} :dt
The change_box command cannot be used when fix ave/spatial or
fix/deform are defined . :dd
{Cannot change box with dumps defined} :dt
Self-explanatory. :dd
{Cannot change dump_modify every for dump dcd} :dt
The frequency of writing dump dcd snapshots cannot be changed. :dd
{Cannot change dump_modify every for dump xtc} :dt
The frequency of writing dump xtc snapshots cannot be changed. :dd
{Cannot change timestep once fix srd is setup} :dt
This is because various SRD properties depend on the timestep
size. :dd
{Cannot change timestep with fix pour} :dt
This fix pre-computes some values based on the timestep, so it cannot
be changed during a simulation run. :dd
{Cannot compute PPPM G} :dt
LAMMPS failed to compute a valid approximation for the PPPM g_ewald
factor that partitions the computation between real space and k-space. :dd
{Cannot create an atom map unless atoms have IDs} :dt
The simulation requires a mapping from global atom IDs to local atoms,
but the atoms that have been defined have no IDs. :dd
{Cannot create atoms with undefined lattice} :dt
Must use the lattice command before using the create_atoms
command. :dd
{Cannot create/grow a vector/array of pointers for %s} :dt
LAMMPS code is making an illegal call to the templated memory
allocaters, to create a vector or array of pointers. :dd
{Cannot create_atoms after reading restart file with per-atom info} :dt
The per-atom info was stored to be used when by a fix that you
may re-define. If you add atoms before re-defining the fix, then
there will not be a correct amount of per-atom info. :dd
{Cannot create_box after simulation box is defined} :dt
The create_box command cannot be used after a read_data, read_restart,
or create_box command. :dd
{Cannot currently use pair reax with pair hybrid} :dt
This is not yet supported. :dd
{Cannot delete group all} :dt
Self-explanatory. :dd
{Cannot delete group currently used by a compute} :dt
Self-explanatory. :dd
{Cannot delete group currently used by a dump} :dt
Self-explanatory. :dd
{Cannot delete group currently used by a fix} :dt
Self-explanatory. :dd
{Cannot delete group currently used by atom_modify first} :dt
Self-explanatory. :dd
{Cannot displace_atoms after reading restart file with per-atom info} :dt
This is because the restart file info cannot be migrated with the
atoms. You can get around this by performing a 0-timestep run which
will assign the restart file info to actual atoms. :dd
{Cannot displace_box after reading restart file with per-atom info} :dt
This is because the restart file info cannot be migrated with the
atoms. You can get around this by performing a 0-timestep run which
will assign the restart file info to actual atoms. :dd
{Cannot displace_box on a non-periodic boundary} :dt
Self-explanatory. :dd
{Cannot dump sort on atom IDs with no atom IDs defined} :dt
Self-explanatory. :dd
{Cannot evaporate atoms in atom_modify first group} :dt
This is a restriction due to the way atoms are organized in
a list to enable the atom_modify first command. :dd
{Cannot find delete_bonds group ID} :dt
Group ID used in the delete_bonds command does not exist. :dd
{Cannot have both pair_modify shift and tail set to yes} :dt
These 2 options are contradictory. :dd
{Cannot open AIREBO potential file %s} :dt
The specified AIREBO potential file cannot be opened. Check that the
path and name are correct. :dd
{Cannot open COMB potential file %s} :dt
The specified COMB potential file cannot be opened. Check that the
path and name are correct. :dd
{Cannot open EAM potential file %s} :dt
The specified EAM potential file cannot be opened. Check that the
path and name are correct. :dd
{Cannot open EIM potential file %s} :dt
The specified EIM potential file cannot be opened. Check that the
path and name are correct. :dd
{Cannot open MEAM potential file %s} :dt
The specified MEAM potential file cannot be opened. Check that the
path and name are correct. :dd
{Cannot open Stillinger-Weber potential file %s} :dt
The specified SW potential file cannot be opened. Check that the path
and name are correct. :dd
{Cannot open Tersoff potential file %s} :dt
The specified Tersoff potential file cannot be opened. Check that the
path and name are correct. :dd
{Cannot open dir to search for restart file} :dt
Using a "*" in the name of the restart file will open the current
directory to search for matching file names. :dd
{Cannot open dump file} :dt
The output file for the dump command cannot be opened. Check that the
path and name are correct. :dd
{Cannot open file %s} :dt
The specified file cannot be opened. Check that the path and name are
correct. :dd
{Cannot open fix ave/correlate file %s} :dt
The specified file cannot be opened. Check that the path and name are
correct. :dd
{Cannot open fix ave/histo file %s} :dt
The specified file cannot be opened. Check that the path and name are
correct. :dd
{Cannot open fix ave/spatial file %s} :dt
The specified file cannot be opened. Check that the path and name are
correct. :dd
{Cannot open fix ave/time file %s} :dt
The specified file cannot be opened. Check that the path and name are
correct. :dd
{Cannot open fix poems file %s} :dt
The specified file cannot be opened. Check that the path and name are
correct. :dd
{Cannot open fix print file %s} :dt
The output file generated by the fix print command cannot be opened :dd
{Cannot open fix qeq/comb file %s} :dt
The output file for the fix qeq/combs command cannot be opened.
Check that the path and name are correct. :dd
{Cannot open fix reax/bonds file %s} :dt
The output file for the fix reax/bonds command cannot be opened.
Check that the path and name are correct. :dd
{Cannot open fix tmd file %s} :dt
The output file for the fix tmd command cannot be opened. Check that
the path and name are correct. :dd
{Cannot open fix ttm file %s} :dt
The output file for the fix ttm command cannot be opened. Check that
the path and name are correct. :dd
{Cannot open gzipped file} :dt
LAMMPS is attempting to open a gzipped version of the specified file
but was unsuccessful. Check that the path and name are correct. :dd
{Cannot open input script %s} :dt
Self-explanatory. :dd
{Cannot open log.lammps} :dt
The default LAMMPS log file cannot be opened. Check that the
directory you are running in allows for files to be created. :dd
{Cannot open logfile %s} :dt
The LAMMPS log file specified in the input script cannot be opened.
Check that the path and name are correct. :dd
{Cannot open logfile} :dt
The LAMMPS log file named in a command-line argument cannot be opened.
Check that the path and name are correct. :dd
{Cannot open pair_write file} :dt
The specified output file for pair energies and forces cannot be
opened. Check that the path and name are correct. :dd
{Cannot open restart file %s} :dt
Self-explanatory. :dd
{Cannot open screen file} :dt
The screen file specified as a command-line argument cannot be
opened. Check that the directory you are running in allows for files
to be created. :dd
{Cannot open universe log file} :dt
For a multi-partition run, the master log file cannot be opened.
Check that the directory you are running in allows for files to be
created. :dd
{Cannot open universe screen file} :dt
For a multi-partition run, the master screen file cannot be opened.
Check that the directory you are running in allows for files to be
created. :dd
{Cannot read_data after simulation box is defined} :dt
The read_data command cannot be used after a read_data,
read_restart, or create_box command. :dd
{Cannot read_restart after simulation box is defined} :dt
The read_restart command cannot be used after a read_data,
read_restart, or create_box command. :dd
{Cannot redefine variable as a different style} :dt
An equal-style variable can be re-defined but only if it was
originally an equal-style variable. :dd
{Cannot replicate 2d simulation in z dimension} :dt
The replicate command cannot replicate a 2d simulation in the z
dimension. :dd
{Cannot replicate with fixes that store atom quantities} :dt
Either fixes are defined that create and store atom-based vectors or a
restart file was read which included atom-based vectors for fixes.
The replicate command cannot duplicate that information for new atoms.
You should use the replicate command before fixes are applied to the
system. :dd
{Cannot reset timestep with a dynamic region defined} :dt
Dynamic regions (see the region command) have a time dependence.
Thus you cannot change the timestep when one or more of these
are defined. :dd
{Cannot reset timestep with a time-dependent fix defined} :dt
You cannot reset the timestep when a fix that keeps track of elapsed
time is in place. :dd
{Cannot reset timestep with dump file already written to} :dt
Changing the timestep will confuse when a dump file is written. Use
the undump command, then restart the dump file. :dd
{Cannot reset timestep with restart file already written} :dt
Changing the timestep will confuse when a restart file is written.
Use the "restart 0" command to turn off restarts, then start them
again. :dd
{Cannot restart fix rigid/nvt with different # of chains} :dt
This is because the restart file contains per-chain info. :dd
{Cannot run 2d simulation with nonperiodic Z dimension} :dt
Use the boundary command to make the z dimension periodic in order to
run a 2d simulation. :dd
{Cannot set both respa pair and inner/middle/outer} :dt
In the rRESPA integrator, you must compute pairwise potentials either
all together (pair), or in pieces (inner/middle/outer). You can't do
both. :dd
{Cannot set dipole for this atom style} :dt
This atom style does not support dipole settings for each atom type. :dd
{Cannot set dump_modify flush for dump xtc} :dt
Self-explanatory. :dd
{Cannot set mass for this atom style} :dt
This atom style does not support mass settings for each atom type.
Instead they are defined on a per-atom basis in the data file. :dd
{Cannot set non-zero image flag for non-periodic dimension} :dt
Self-explanatory. :dd
{Cannot set non-zero z velocity for 2d simulation} :dt
Self-explanatory. :dd
{Cannot set respa middle without inner/outer} :dt
In the rRESPA integrator, you must define both a inner and outer
setting in order to use a middle setting. :dd
{Cannot set shape for this atom style} :dt
The atom style does not support this setting. :dd
{Cannot set this attribute for this atom style} :dt
The attribute being set does not exist for the defined atom style. :dd
{Cannot set variable z velocity for 2d simulation} :dt
Self-explanatory. :dd
{Cannot skew triclinic box in z for 2d simulation} :dt
Self-explanatory. :dd
{Cannot use Ewald with 2d simulation} :dt
The kspace style ewald cannot be used in 2d simulations. You can use
2d Ewald in a 3d simulation; see the kspace_modify command. :dd
{Cannot use Ewald with triclinic box} :dt
This feature is not yet supported. :dd
{Cannot use NEB unless atom map exists} :dt
Use the atom_modify command to create an atom map. :dd
{Cannot use NEB with a single replica} :dt
Self-explanatory. :dd
{Cannot use NEB with atom_modify sort enabled} :dt
This is current restriction for NEB implemented in LAMMPS. :dd
{Cannot use PPPM with 2d simulation} :dt
The kspace style pppm cannot be used in 2d simulations. You can use
2d PPPM in a 3d simulation; see the kspace_modify command. :dd
{Cannot use PRD with a time-dependent fix defined} :dt
PRD alters the timestep in ways that will mess up these fixes. :dd
{Cannot use PRD with a time-dependent region defined} :dt
PRD alters the timestep in ways that will mess up these regions. :dd
{Cannot use PRD with atom_modify sort enabled} :dt
This is a current restriction of PRD. You must turn off sorting,
which is enabled by default, via the atom_modify command. :dd
{Cannot use PRD with multi-processor replicas unless atom map exists} :dt
Use the atom_modify command to create an atom map. :dd
{Cannot use TAD unless atom map exists for NEB} :dt
See atom_modify map command to set this. :dd
{Cannot use TAD with a single replica for NEB} :dt
NEB requires multiple replicas. :dd
{Cannot use TAD with atom_modify sort enabled for NEB} :dt
This is a current restriction of NEB. :dd
{Cannot use a damped dynamics min style with fix box/relax} :dt
This is a current restriction in LAMMPS. Use another minimizer
style. :dd
{Cannot use a damped dynamics min style with per-atom DOF} :dt
This is a current restriction in LAMMPS. Use another minimizer
style. :dd
{Cannot use compute cluster/atom unless atoms have IDs} :dt
Atom IDs are used to identify clusters. :dd
{Cannot use cwiggle in variable formula between runs} :dt
This is a function of elapsed time. :dd
{Cannot use delete_atoms unless atoms have IDs} :dt
Your atoms do not have IDs, so the delete_atoms command cannot be
used. :dd
{Cannot use delete_bonds with non-molecular system} :dt
Your choice of atom style does not have bonds. :dd
{Cannot use fix TMD unless atom map exists} :dt
Using this fix requires the ability to lookup an atom index, which is
provided by an atom map. An atom map does not exist (by default) for
non-molecular problems. Using the atom_modify map command will force
an atom map to be created. :dd
{Cannot use fix ave/spatial z for 2 dimensional model} :dt
Self-explanatory. :dd
{Cannot use fix bond/break with non-molecular systems} :dt
Self-explanatory. :dd
{Cannot use fix bond/create with non-molecular systems} :dt
Self-explanatory. :dd
{Cannot use fix box/relax on a 2nd non-periodic dimension} :dt
When specifying an off-diagonal pressure component, the 2nd of the two
dimensions must be periodic. E.g. if the xy component is specified,
then the y dimension must be periodic. :dd
{Cannot use fix box/relax on a non-periodic dimension} :dt
When specifying a diagonal pressure component, the dimension must be
periodic. :dd
{Cannot use fix deform on a 2nd non-periodic boundary} :dt
When specifying a tilt factor change, the 2nd of the two dimensions
must be periodic. E.g. if the xy tilt is specified, then the y
dimension must be periodic. :dd
{Cannot use fix deform on a non-periodic boundary} :dt
When specifying a change is a box dimension, the dimension must be
periodic. :dd
{Cannot use fix deform trate on a box with zero tilt} :dt
The trate style alters the current strain. :dd
{Cannot use fix enforce2d with 3d simulation} :dt
Self-explanatory. :dd
{Cannot use fix msst without per-type mass defined} :dt
Self-explanatory. :dd
{Cannot use fix npt and fix deform on same component of stress tensor} :dt
This would be changing the same box dimension twice. :dd
{Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension} :dt
When specifying an off-diagonal pressure component, the 2nd of the two
dimensions must be periodic. E.g. if the xy component is specified,
then the y dimension must be periodic. :dd
{Cannot use fix nvt/npt/nph on a non-periodic dimension} :dt
When specifying a diagonal pressure component, the dimension must be
periodic. :dd
{Cannot use fix pour with triclinic box} :dt
This feature is not yet supported. :dd
{Cannot use fix press/berendsen and fix deform on same component of stress tensor} :dt
These commands both change the box size/shape, so you cannot use both
together. :dd
{Cannot use fix press/berendsen on a non-periodic dimension} :dt
Self-explanatory. :dd
{Cannot use fix press/berendsen with triclinic box} :dt
Self-explanatory. :dd
{Cannot use fix reax/bonds without pair_style reax} :dt
Self-explantory. :dd
{Cannot use fix shake with non-molecular system} :dt
Your choice of atom style does not have bonds. :dd
{Cannot use fix ttm with 2d simulation} :dt
This is a current restriction of this fix due to the grid it creates. :dd
{Cannot use fix ttm with triclinic box} :dt
This is a current restriction of this fix due to the grid it creates. :dd
{Cannot use fix wall in periodic dimension} :dt
Self-explanatory. :dd
{Cannot use fix wall zlo/zhi for a 2d simulation} :dt
Self-explanatory. :dd
{Cannot use fix wall/reflect in periodic dimension} :dt
Self-explanatory. :dd
{Cannot use fix wall/reflect zlo/zhi for a 2d simulation} :dt
Self-explanatory. :dd
{Cannot use fix wall/srd in periodic dimension} :dt
Self-explanatory. :dd
{Cannot use fix wall/srd more than once} :dt
Nor is their a need to since multiple walls can be specified
in one command. :dd
{Cannot use fix wall/srd without fix srd} :dt
Self-explanatory. :dd
{Cannot use fix wall/srd zlo/zhi for a 2d simulation} :dt
Self-explanatory. :dd
{Cannot use force/neigh with triclinic box} :dt
This is a current limitation of the GPU implementation
in LAMMPS. :dd
{Cannot use kspace solver on system with no charge} :dt
No atoms in system have a non-zero charge. :dd
{Cannot use neighbor bins - box size << cutoff} :dt
Too many neighbor bins will be created. This typically happens when
the simulation box is very small in some dimension, compared to the
neighbor cutoff. Use the "nsq" style instead of "bin" style. :dd
{Cannot use newton pair with GPU CHARMM pair style} :dt
See the newton command to change the setting. :dd
{Cannot use newton pair with GPU Gay-Berne pair style} :dt
See the newton command to change the setting. :dd
{Cannot use newton pair with GPU LJ pair style} :dt
See the newton command to change the setting. :dd
{Cannot use newton pair with GPU LJ96 pair style} :dt
See the newton command to change the setting. :dd
{Cannot use non-zero forces in an energy minimization} :dt
Fix setforce cannot be used in this manner. Use fix addforce
instead. :dd
{Cannot use nonperiodic boundares with fix ttm} :dt
This fix requires a fully periodic simulation box. :dd
{Cannot use nonperiodic boundaries with Ewald} :dt
For kspace style ewald, all 3 dimensions must have periodic boundaries
unless you use the kspace_modify command to define a 2d slab with a
non-periodic z dimension. :dd
{Cannot use nonperiodic boundaries with PPPM} :dt
For kspace style pppm, all 3 dimensions must have periodic boundaries
unless you use the kspace_modify command to define a 2d slab with a
non-periodic z dimension. :dd
{Cannot use pair hybrid with GPU neighbor builds} :dt
See documentation for fix gpu. :dd
{Cannot use pair tail corrections with 2d simulations} :dt
The correction factors are only currently defined for 3d systems. :dd
{Cannot use ramp in variable formula between runs} :dt
This is because the ramp() function is time dependent. :dd
{Cannot use region INF or EDGE when box does not exist} :dt
Regions that extend to the box boundaries can only be used after the
create_box command has been used. :dd
{Cannot use set atom with no atom IDs defined} :dt
Atom IDs are not defined, so they cannot be used to identify an atom. :dd
{Cannot use swiggle in variable formula between runs} :dt
This is a function of elapsed time. :dd
{Cannot use variable energy with constant force in fix addforce} :dt
This is because for constant force, LAMMPS can compute the change
in energy directly. :dd
{Cannot use variable every setting for dump dcd} :dt
The format of DCD dump files requires snapshots be output
at a constant frequency. :dd
{Cannot use variable every setting for dump xtc} :dt
The format of this file requires snapshots at regular intervals. :dd
{Cannot use vdisplace in variable formula between runs} :dt
This is a function of elapsed time. :dd
{Cannot use velocity create loop all unless atoms have IDs} :dt
Atoms in the simulation to do not have IDs, so this style
of velocity creation cannot be performed. :dd
{Cannot use wall in periodic dimension} :dt
Self-explanatory. :dd
{Cannot wiggle and shear fix wall/gran} :dt
Cannot specify both options at the same time. :dd
{Cannot zero momentum of 0 atoms} :dt
The collection of atoms for which momentum is being computed has no
atoms. :dd
{Change_box command before simulation box is defined} :dt
Self-explanatory. :dd
{Change_box operation is invalid} :dt
Cannot change orthogonal box to orthogonal or a triclinic box to
triclinic. :dd
{Communicate group != atom_modify first group} :dt
Self-explanatory. :dd
{Compute ID for compute atom/molecule does not exist} :dt
Self-explanatory. :dd
{Compute ID for compute reduce does not exist} :dt
Self-explanatory. :dd
{Compute ID for fix ave/atom does not exist} :dt
Self-explanatory. :dd
{Compute ID for fix ave/correlate does not exist} :dt
Self-explanatory. :dd
{Compute ID for fix ave/histo does not exist} :dt
Self-explanatory. :dd
{Compute ID for fix ave/spatial does not exist} :dt
Self-explanatory. :dd
{Compute ID for fix ave/time does not exist} :dt
Self-explanatory. :dd
{Compute ID for fix store/state does not exist} :dt
Self-explanatory. :dd
{Compute ID must be alphanumeric or underscore characters} :dt
Self-explanatory. :dd
{Compute angle/local used when angles are not allowed} :dt
The atom style does not support angles. :dd
{Compute atom/molecule compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Compute atom/molecule compute does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Compute atom/molecule compute does not calculate a per-atom vector} :dt
Self-explanatory. :dd
{Compute atom/molecule compute does not calculate per-atom values} :dt
Self-explanatory. :dd
{Compute atom/molecule fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Compute atom/molecule fix does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Compute atom/molecule fix does not calculate a per-atom vector} :dt
Self-explanatory. :dd
{Compute atom/molecule fix does not calculate per-atom values} :dt
Self-explanatory. :dd
{Compute atom/molecule requires molecular atom style} :dt
Self-explanatory. :dd
{Compute atom/molecule variable is not atom-style variable} :dt
Self-explanatory. :dd
{Compute bond/local used when bonds are not allowed} :dt
The atom style does not support bonds. :dd
{Compute centro/atom requires a pair style be defined} :dt
This is because the computation of the centro-symmetry values
uses a pairwise neighbor list. :dd
{Compute cluster/atom cutoff is longer than pairwise cutoff} :dt
Cannot identify clusters beyond cutoff. :dd
{Compute cluster/atom requires a pair style be defined} :dt
This is so that the pair style defines a cutoff distance which
is used to find clusters. :dd
{Compute cna/atom cutoff is longer than pairwise cutoff} :dt
Self-explantory. :dd
{Compute cna/atom requires a pair style be defined} :dt
Self-explantory. :dd
{Compute com/molecule requires molecular atom style} :dt
Self-explanatory. :dd
{Compute coord/atom cutoff is longer than pairwise cutoff} :dt
Cannot compute coordination at distances longer than the pair cutoff,
since those atoms are not in the neighbor list. :dd
{Compute coord/atom requires a pair style be defined} :dt
Self-explantory. :dd
{Compute damage/atom requires peridynamic potential} :dt
Damage is a Peridynamic-specific metric. It requires you
to be running a Peridynamics simulation. :dd
{Compute dihedral/local used when dihedrals are not allowed} :dt
The atom style does not support dihedrals. :dd
{Compute does not allow an extra compute or fix to be reset} :dt
This is an internal LAMMPS error. Please report it to the
developers. :dd
{Compute erotate/asphere cannot be used with atom attributes diameter or rmass} :dt
These attributes override the shape and mass settings, so cannot be
used. :dd
{Compute erotate/asphere requires atom attributes angmom, quat, shape} :dt
An atom style that defines these attributes must be used. :dd
{Compute erotate/asphere requires extended particles} :dt
This compute cannot be used with point paritlces. :dd
{Compute erotate/sphere requires atom attribute omega} :dt
An atom style that defines this attribute must be used. :dd
{Compute erotate/sphere requires atom attribute radius or shape} :dt
An atom style that defines these attributes must be used. :dd
{Compute erotate/sphere requires spherical particle shapes} :dt
Self-explanatory. :dd
{Compute event/displace has invalid fix event assigned} :dt
This is an internal LAMMPS error. Please report it to the
developers. :dd
{Compute group/group group ID does not exist} :dt
Self-explanatory. :dd
{Compute gyration/molecule requires molecular atom style} :dt
Self-explanatory. :dd
{Compute heat/flux compute ID does not compute ke/atom} :dt
Self-explanatory. :dd
{Compute heat/flux compute ID does not compute pe/atom} :dt
Self-explanatory. :dd
{Compute heat/flux compute ID does not compute stress/atom} :dt
Self-explanatory. :dd
{Compute improper/local used when impropers are not allowed} :dt
The atom style does not support impropers. :dd
{Compute msd/molecule requires molecular atom style} :dt
Self-explanatory. :dd
{Compute pair must use group all} :dt
Pair styles accumlate energy on all atoms. :dd
{Compute pe must use group all} :dt
Energies computed by potentials (pair, bond, etc) are computed on all
atoms. :dd
{Compute pressure must use group all} :dt
Virial contributions computed by potentials (pair, bond, etc) are
computed on all atoms. :dd
{Compute pressure temperature ID does not compute temperature} :dt
The compute ID assigned to a pressure computation must compute
temperature. :dd
{Compute property/atom for atom property that isn't allocated} :dt
Self-explanatory. :dd
{Compute property/local cannot use these inputs together} :dt
Only inputs that generate the same number of datums can be used
togther. E.g. bond and angle quantities cannot be mixed. :dd
{Compute property/local for property that isn't allocated} :dt
Self-explanatory. :dd
{Compute property/molecule requires molecular atom style} :dt
Self-explanatory. :dd
{Compute rdf requires a pair style be defined} :dt
Self-explanatory. :dd
{Compute reduce compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Compute reduce compute calculates global values} :dt
A compute that calculates peratom or local values is required. :dd
{Compute reduce compute does not calculate a local array} :dt
Self-explanatory. :dd
{Compute reduce compute does not calculate a local vector} :dt
Self-explanatory. :dd
{Compute reduce compute does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Compute reduce compute does not calculate a per-atom vector} :dt
Self-explanatory. :dd
{Compute reduce fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Compute reduce fix calculates global values} :dt
A fix that calculates peratom or local values is required. :dd
{Compute reduce fix does not calculate a local array} :dt
Self-explanatory. :dd
{Compute reduce fix does not calculate a local vector} :dt
Self-explanatory. :dd
{Compute reduce fix does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Compute reduce fix does not calculate a per-atom vector} :dt
Self-explanatory. :dd
{Compute reduce replace requires min or max mode} :dt
Self-explanatory. :dd
{Compute reduce variable is not atom-style variable} :dt
Self-explanatory. :dd
{Compute temp/asphere cannot be used with atom attributes diameter or rmass} :dt
These attributes override the shape and mass settings, so cannot be
used. :dd
{Compute temp/asphere requires atom attributes angmom, quat, shape} :dt
An atom style that defines these attributes must be used. :dd
{Compute temp/asphere requires extended particles} :dt
This compute cannot be used with point paritlces. :dd
{Compute temp/partial cannot use vz for 2d systemx} :dt
Self-explanatory. :dd
{Compute temp/profile cannot bin z for 2d systems} :dt
Self-explanatory. :dd
{Compute temp/profile cannot use vz for 2d systemx} :dt
Self-explanatory. :dd
{Compute temp/sphere requires atom attribute omega} :dt
An atom style that defines this attribute must be used. :dd
{Compute temp/sphere requires atom attribute radius or shape} :dt
An atom style that defines these attributes must be used. :dd
{Compute temp/sphere requires spherical particle shapes} :dt
Self-explanatory. :dd
{Compute ti kspace style does not exist} :dt
Self-explanatory. :dd
{Compute ti pair style does not exist} :dt
Self-explanatory. :dd
{Compute ti tail when pair style does not compute tail corrections} :dt
Self-explanatory. :dd
{Compute used in variable between runs is not current} :dt
Computes cannot be invoked by a variable in between runs. Thus they
must have been evaluated on the last timestep of the previous run in
order for their value(s) to be accessed. See the doc page for the
variable command for more info. :dd
{Compute used in variable thermo keyword between runs is not current} :dt
Some thermo keywords rely on a compute to calculate their value(s).
Computes cannot be invoked by a variable in between runs. Thus they
must have been evaluated on the last timestep of the previous run in
order for their value(s) to be accessed. See the doc page for the
variable command for more info. :dd
{Computed temperature for fix temp/berendsen cannot be 0.0} :dt
Self-explanatory. :dd
{Computed temperature for fix temp/rescale cannot be 0.0} :dt
Cannot rescale the temperature to a new value if the current
temperature is 0.0. :dd
{Could not count initial bonds in fix bond/create} :dt
Could not find one of the atoms in a bond on this processor. :dd
{Could not create 3d FFT plan} :dt
The FFT setup in pppm failed. :dd
{Could not create 3d remap plan} :dt
The FFT setup in pppm failed. :dd
{Could not find atom_modify first group ID} :dt
Self-explanatory. :dd
{Could not find compute ID for PRD} :dt
Self-explanatory. :dd
{Could not find compute ID for TAD} :dt
Self-explanatory. :dd
{Could not find compute ID for temperature bias} :dt
Self-explanatory. :dd
{Could not find compute ID to delete} :dt
Self-explanatory. :dd
{Could not find compute displace/atom fix ID} :dt
Self-explanatory. :dd
{Could not find compute event/displace fix ID} :dt
Self-explanatory. :dd
{Could not find compute group ID} :dt
Self-explanatory. :dd
{Could not find compute heat/flux compute ID} :dt
Self-explanatory. :dd
{Could not find compute msd fix ID} :dt
Self-explanatory. :dd
{Could not find compute pressure temperature ID} :dt
The compute ID for calculating temperature does not exist. :dd
{Could not find compute_modify ID} :dt
Self-explanatory. :dd
{Could not find delete_atoms group ID} :dt
Group ID used in the delete_atoms command does not exist. :dd
{Could not find delete_atoms region ID} :dt
Region ID used in the delete_atoms command does not exist. :dd
{Could not find displace_atoms group ID} :dt
Group ID used in the displace_atoms command does not exist. :dd
{Could not find displace_box group ID} :dt
Group ID used in the displace_box command does not exist. :dd
{Could not find dump cfg compute ID} :dt
Self-explanatory. :dd
{Could not find dump cfg fix ID} :dt
Self-explanatory. :dd
{Could not find dump cfg variable name} :dt
Self-explanatory. :dd
{Could not find dump custom compute ID} :dt
The compute ID needed by dump custom to compute a per-atom quantity
does not exist. :dd
{Could not find dump custom fix ID} :dt
Self-explanatory. :dd
{Could not find dump custom variable name} :dt
Self-explanatory. :dd
{Could not find dump group ID} :dt
A group ID used in the dump command does not exist. :dd
{Could not find dump local compute ID} :dt
Self-explanatory. :dd
{Could not find dump local fix ID} :dt
Self-explanatory. :dd
{Could not find dump modify compute ID} :dt
Self-explanatory. :dd
{Could not find dump modify fix ID} :dt
Self-explanatory. :dd
{Could not find dump modify variable name} :dt
Self-explanatory. :dd
{Could not find fix ID to delete} :dt
Self-explanatory. :dd
{Could not find fix group ID} :dt
A group ID used in the fix command does not exist. :dd
{Could not find fix msst compute ID} :dt
Self-explanatory. :dd
{Could not find fix poems group ID} :dt
A group ID used in the fix poems command does not exist. :dd
{Could not find fix recenter group ID} :dt
A group ID used in the fix recenter command does not exist. :dd
{Could not find fix rigid group ID} :dt
A group ID used in the fix rigid command does not exist. :dd
{Could not find fix srd group ID} :dt
Self-explanatory. :dd
{Could not find fix_modify ID} :dt
A fix ID used in the fix_modify command does not exist. :dd
{Could not find fix_modify pressure ID} :dt
The compute ID for computing pressure does not exist. :dd
{Could not find fix_modify temperature ID} :dt
The compute ID for computing temperature does not exist. :dd
{Could not find group delete group ID} :dt
Self-explanatory. :dd
{Could not find/initialize a specified accelerator device} :dt
Your GPU setup is invalid. :dd
{Could not find set group ID} :dt
Group ID specified in set command does not exist. :dd
{Could not find thermo compute ID} :dt
Compute ID specified in thermo_style command does not exist. :dd
{Could not find thermo custom compute ID} :dt
The compute ID needed by thermo style custom to compute a requested
quantity does not exist. :dd
{Could not find thermo custom fix ID} :dt
The fix ID needed by thermo style custom to compute a requested
quantity does not exist. :dd
{Could not find thermo custom variable name} :dt
Self-explanatory. :dd
{Could not find thermo fix ID} :dt
Fix ID specified in thermo_style command does not exist. :dd
{Could not find thermo_modify pressure ID} :dt
The compute ID needed by thermo style custom to compute pressure does
not exist. :dd
{Could not find thermo_modify temperature ID} :dt
The compute ID needed by thermo style custom to compute temperature does
not exist. :dd
{Could not find undump ID} :dt
A dump ID used in the undump command does not exist. :dd
{Could not find velocity group ID} :dt
A group ID used in the velocity command does not exist. :dd
{Could not find velocity temperature ID} :dt
The compute ID needed by the velocity command to compute temperature
does not exist. :dd
{Could not grab element entry from EIM potential file} :dt
Self-explanatory :dd
{Could not grab global entry from EIM potential file} :dt
Self-explanatory. :dd
{Could not grab pair entry from EIM potential file} :dt
Self-explanatory. :dd
{Could not set finite-size particle attribute in fix rigid} :dt
The particle has a finite size but its attributes could not be
determined. :dd
{Coulomb cutoffs of pair hybrid sub-styles do not match} :dt
If using a Kspace solver, all Coulomb cutoffs of long pair styles must
be the same. :dd
{Cound not find dump_modify ID} :dt
Self-explanatory. :dd
{Create_atoms command before simulation box is defined} :dt
The create_atoms command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Create_atoms region ID does not exist} :dt
A region ID used in the create_atoms command does not exist. :dd
{Create_box region ID does not exist} :dt
A region ID used in the create_box command does not exist. :dd
{Create_box region does not support a bounding box} :dt
Not all regions represent bounded volumes. You cannot use
such a region with the create_box command. :dd
{Cyclic loop in joint connections} :dt
Fix poems cannot (yet) work with coupled bodies whose joints connect
the bodies in a ring (or cycle). :dd
{Degenerate lattice primitive vectors} :dt
Invalid set of 3 lattice vectors for lattice command. :dd
{Delete region ID does not exist} :dt
Self-explanatory. :dd
{Delete_atoms command before simulation box is defined} :dt
The delete_atoms command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Delete_atoms cutoff > neighbor cutoff} :dt
Cannot delete atoms further away than a processor knows about. :dd
{Delete_atoms requires a pair style be defined} :dt
This is because atom deletion within a cutoff uses a pairwise
neighbor list. :dd
{Delete_bonds command before simulation box is defined} :dt
The delete_bonds command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Delete_bonds command with no atoms existing} :dt
No atoms are yet defined so the delete_bonds command cannot be used. :dd
{Deposition region extends outside simulation box} :dt
Self-explanatory. :dd
{Did not assign all atoms correctly} :dt
Atoms read in from a data file were not assigned correctly to
processors. This is likely due to some atom coordinates being
outside a non-periodic simulation box. :dd
{Did not find all elements in MEAM library file} :dt
The requested elements were not found in the MEAM file. :dd
{Did not find fix shake partner info} :dt
Could not find bond partners implied by fix shake command. This error
can be triggered if the delete_bonds command was used before fix
shake, and it removed bonds without resetting the 1-2, 1-3, 1-4
weighting list via the special keyword. :dd
{Did not find keyword in table file} :dt
Keyword used in pair_coeff command was not found in table file. :dd
{Did not set temp for fix rigid/nvt} :dt
The temp keyword must be used. :dd
{Dihedral atom missing in delete_bonds} :dt
The delete_bonds command cannot find one or more atoms in a particular
dihedral on a particular processor. The pairwise cutoff is too short
or the atoms are too far apart to make a valid dihedral. :dd
{Dihedral atom missing in set command} :dt
The set command cannot find one or more atoms in a particular dihedral
on a particular processor. The pairwise cutoff is too short or the
atoms are too far apart to make a valid dihedral. :dd
{Dihedral atoms %d %d %d %d missing on proc %d at step} :dt
One or more of 4 atoms needed to compute a particular dihedral are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the dihedral has blown apart and an atom is
too far away. :dd
{Dihedral charmm is incompatible with Pair style} :dt
Dihedral style charmm must be used with a pair style charmm
in order for the 1-4 epsilon/sigma parameters to be defined. :dd
{Dihedral coeff for hybrid has invalid style} :dt
Dihedral style hybrid uses another dihedral style as one of its
coefficients. The dihedral style used in the dihedral_coeff command
or read from a restart file is not recognized. :dd
{Dihedral coeffs are not set} :dt
No dihedral coefficients have been assigned in the data file or via
the dihedral_coeff command. :dd
{Dihedral style hybrid cannot have hybrid as an argument} :dt
Self-explanatory. :dd
{Dihedral style hybrid cannot have none as an argument} :dt
Self-explanatory. :dd
{Dihedral style hybrid cannot use same dihedral style twice} :dt
Self-explanatory. :dd
{Dihedral_coeff command before dihedral_style is defined} :dt
Coefficients cannot be set in the data file or via the dihedral_coeff
command until an dihedral_style has been assigned. :dd
{Dihedral_coeff command before simulation box is defined} :dt
The dihedral_coeff command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Dihedral_coeff command when no dihedrals allowed} :dt
The chosen atom style does not allow for dihedrals to be defined. :dd
{Dihedral_style command when no dihedrals allowed} :dt
The chosen atom style does not allow for dihedrals to be defined. :dd
{Dihedrals assigned incorrectly} :dt
Dihedrals read in from the data file were not assigned correctly to
atoms. This means there is something invalid about the topology
definitions. :dd
{Dihedrals defined but no dihedral types} :dt
The data file header lists dihedrals but no dihedral types. :dd
{Dimension command after simulation box is defined} :dt
The dimension command cannot be used after a read_data,
read_restart, or create_box command. :dd
{Dipole command before simulation box is defined} :dt
The dipole command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Displace_atoms command before simulation box is defined} :dt
The displace_atoms command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Displace_box command before simulation box is defined} :dt
Self-explanatory. :dd
{Displace_box tilt factors require triclinic box} :dt
Cannot use tilt factors unless the simulation box is
non-orthogonal. :dd
{Distance must be > 0 for compute event/displace} :dt
Self-explanatory. :dd
{Divide by 0 in influence function of pair peri/lps} :dt
This should not normally occur. It is likely a problem with your
model. :dd
{Divide by 0 in variable formula} :dt
Self-explanatory. :dd
{Domain too large for neighbor bins} :dt
The domain has become extremely large so that neighbor bins cannot be
used. Most likely, one or more atoms have been blown out of the
simulation box to a great distance. :dd
{Double precision is not supported on this accelerator.} :dt
In this case, you must compile the GPU library for single precision. :dd
{Dump cfg and fix not computed at compatible times} :dt
The fix must produce per-atom quantities on timesteps that dump cfg
needs them. :dd
{Dump cfg arguments must start with 'id type xs ys zs'} :dt
This is a requirement of the CFG output format. :dd
{Dump cfg requires one snapshot per file} :dt
Use the wildcard "*" character in the filename. :dd
{Dump custom and fix not computed at compatible times} :dt
The fix must produce per-atom quantities on timesteps that dump custom
needs them. :dd
{Dump custom compute does not calculate per-atom array} :dt
Self-explanatory. :dd
{Dump custom compute does not calculate per-atom vector} :dt
Self-explanatory. :dd
{Dump custom compute does not compute per-atom info} :dt
Self-explanatory. :dd
{Dump custom compute vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Dump custom fix does not compute per-atom array} :dt
Self-explanatory. :dd
{Dump custom fix does not compute per-atom info} :dt
Self-explanatory. :dd
{Dump custom fix does not compute per-atom vector} :dt
Self-explanatory. :dd
{Dump custom fix vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Dump custom variable is not atom-style variable} :dt
Only atom-style variables generate per-atom quantities, needed for
dump output. :dd
{Dump dcd of non-matching # of atoms} :dt
Every snapshot written by dump dcd must contain the same # of atoms. :dd
{Dump dcd requires sorting by atom ID} :dt
Use the dump_modify sort command to enable this. :dd
{Dump every variable returned a bad timestep} :dt
The variable must return a timestep greater than the current timestep. :dd
{Dump local and fix not computed at compatible times} :dt
The fix must produce per-atom quantities on timesteps that dump local
needs them. :dd
{Dump local attributes contain no compute or fix} :dt
Self-explanatory. :dd
{Dump local cannot sort by atom ID} :dt
This is because dump local does not really dump per-atom info. :dd
{Dump local compute does not calculate local array} :dt
Self-explanatory. :dd
{Dump local compute does not calculate local vector} :dt
Self-explanatory. :dd
{Dump local compute does not compute local info} :dt
Self-explanatory. :dd
{Dump local compute vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Dump local count is not consistent across input fields} :dt
Every column of output must be the same length. :dd
{Dump local fix does not compute local array} :dt
Self-explanatory. :dd
{Dump local fix does not compute local info} :dt
Self-explanatory. :dd
{Dump local fix does not compute local vector} :dt
Self-explanatory. :dd
{Dump local fix vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Dump modify compute ID does not compute per-atom array} :dt
Self-explanatory. :dd
{Dump modify compute ID does not compute per-atom info} :dt
Self-explanatory. :dd
{Dump modify compute ID does not compute per-atom vector} :dt
Self-explanatory. :dd
{Dump modify compute ID vector is not large enough} :dt
Self-explanatory. :dd
{Dump modify element names do not match atom types} :dt
Number of element names must equal number of atom types. :dd
{Dump modify fix ID does not compute per-atom array} :dt
Self-explanatory. :dd
{Dump modify fix ID does not compute per-atom info} :dt
Self-explanatory. :dd
{Dump modify fix ID does not compute per-atom vector} :dt
Self-explanatory. :dd
{Dump modify fix ID vector is not large enough} :dt
Self-explanatory. :dd
{Dump modify variable is not atom-style variable} :dt
Self-explanatory. :dd
{Dump sort column is invalid} :dt
Self-explanatory. :dd
{Dump xtc requires sorting by atom ID} :dt
Use the dump_modify sort command to enable this. :dd
{Dump_modify region ID does not exist} :dt
Self-explanatory. :dd
{Dumping an atom property that isn't allocated} :dt
The chosen atom style does not define the per-atom quantity being
dumped. :dd
{Dumping an atom quantity that isn't allocated} :dt
Only per-atom quantities that are defined for the atom style being
used are allowed. :dd
{Duplicate particle in PeriDynamic bond - simulation box is too small} :dt
This is likely because your box length is shorter than 2 times
the bond length. :dd
{Electronic temperature dropped below zero} :dt
Something has gone wrong with the fix ttm electron temperature model. :dd
{Empty brackets in variable} :dt
There is no variable syntax that uses empty brackets. Check
the variable doc page. :dd
{Energy was not tallied on needed timestep} :dt
You are using a thermo keyword that requires potentials to
have tallied energy, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work. :dd
{Expected floating point parameter in input script or data file} :dt
The quantity being read is an integer on non-numeric value. :dd
{Expected floating point parameter in variable definition} :dt
The quantity being read is a non-numeric value. :dd
{Expected integer parameter in input script or data file} :dt
The quantity being read is a floating point or non-numeric value. :dd
{Expected integer parameter in variable definition} :dt
The quantity being read is a floating point or non-numeric value. :dd
{Failed to allocate %d bytes for array %s} :dt
Your LAMMPS simulation has run out of memory. You need to run a
smaller simulation or on more processors. :dd
{Failed to reallocate %d bytes for array %s} :dt
Your LAMMPS simulation has run out of memory. You need to run a
smaller simulation or on more processors. :dd
{Fewer SRD bins than processors in some dimension} :dt
This is not allowed. Make your SRD bin size smaller. :dd
{Final box dimension due to fix deform is < 0.0} :dt
Self-explanatory. :dd
{Fix gpu split must be positive for hybrid pair styles.} :dt
See documentation for fix gpu. :dd
{Fix ID for compute atom/molecule does not exist} :dt
Self-explanatory. :dd
{Fix ID for compute reduce does not exist} :dt
Self-explanatory. :dd
{Fix ID for fix ave/atom does not exist} :dt
Self-explanatory. :dd
{Fix ID for fix ave/correlate does not exist} :dt
Self-explanatory. :dd
{Fix ID for fix ave/histo does not exist} :dt
Self-explanatory. :dd
{Fix ID for fix ave/spatial does not exist} :dt
Self-explanatory. :dd
{Fix ID for fix ave/time does not exist} :dt
Self-explanatory. :dd
{Fix ID for fix store/state does not exist} :dt
Self-explanatory :dd
{Fix ID must be alphanumeric or underscore characters} :dt
Self-explanatory. :dd
{Fix SRD cannot have both atom attributes angmom and omega} :dt
Use either spheroid solute particles or fully generalized
aspherical solute particles. :dd
{Fix SRD no-slip requires atom attribute torque} :dt
This is because the SRD collisions will impart torque to the solute
particles. :dd
{Fix SRD requires atom attribute angmom or omega} :dt
This is because the SRD collisions with cause the solute particles to
rotate. :dd
{Fix SRD requires atom attribute radius or shape} :dt
This is because the solute particles must be finite-size particles,
not point particles. :dd
{Fix SRD: bad bin assignment for SRD advection} :dt
Something has gone wrong in your SRD model; try using more
conservative settings. :dd
{Fix SRD: bad search bin assignment} :dt
Something has gone wrong in your SRD model; try using more
conservative settings. :dd
{Fix SRD: bad stencil bin for big particle} :dt
Something has gone wrong in your SRD model; try using more
conservative settings. :dd
{Fix SRD: too many big particles in bin} :dt
Reset the ATOMPERBIN parameter at the top of fix_srd.cpp
to a larger value, and re-compile the code. :dd
{Fix SRD: too many walls in bin} :dt
This should not happen unless your system has been setup incorrectly. :dd
{Fix adapt kspace style does not exist} :dt
Self-explanatory. :dd
{Fix adapt pair style does not exist} :dt
Self-explanatory :dd
{Fix adapt pair style param not supported} :dt
The pair style does not know about the parameter you specified. :dd
{Fix adapt requires atom attribute diameter} :dt
The atom style being used does not specify an atom diameter. :dd
{Fix adapt type pair range is not valid for pair hybrid sub-style} :dt
Self-explanatory. :dd
{Fix ave/atom compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/atom compute does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Fix ave/atom compute does not calculate a per-atom vector} :dt
A compute used by fix ave/atom must generate per-atom values. :dd
{Fix ave/atom compute does not calculate per-atom values} :dt
A compute used by fix ave/atom must generate per-atom values. :dd
{Fix ave/atom fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/atom fix does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Fix ave/atom fix does not calculate a per-atom vector} :dt
A fix used by fix ave/atom must generate per-atom values. :dd
{Fix ave/atom fix does not calculate per-atom values} :dt
A fix used by fix ave/atom must generate per-atom values. :dd
{Fix ave/atom variable is not atom-style variable} :dt
A variable used by fix ave/atom must generate per-atom values. :dd
{Fix ave/histo cannot input local values in scalar mode} :dt
Self-explanatory. :dd
{Fix ave/histo cannot input per-atom values in scalar mode} :dt
Self-explanatory. :dd
{Fix ave/histo compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate a global array} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate a global scalar} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate a global vector} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate a local array} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate a local vector} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate a per-atom vector} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate local values} :dt
Self-explanatory. :dd
{Fix ave/histo compute does not calculate per-atom values} :dt
Self-explanatory. :dd
{Fix ave/histo compute vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/histo fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate a global array} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate a global scalar} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate a global vector} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate a local array} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate a local vector} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate a per-atom vector} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate local values} :dt
Self-explanatory. :dd
{Fix ave/histo fix does not calculate per-atom values} :dt
Self-explanatory. :dd
{Fix ave/histo fix vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/histo input is invalid compute} :dt
Self-explanatory. :dd
{Fix ave/histo input is invalid fix} :dt
Self-explanatory. :dd
{Fix ave/histo input is invalid variable} :dt
Self-explanatory. :dd
{Fix ave/histo inputs are not all global, peratom, or local} :dt
All inputs in a single fix ave/histo command must be of the
same style. :dd
{Fix ave/spatial compute does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Fix ave/spatial compute does not calculate a per-atom vector} :dt
A compute used by fix ave/spatial must generate per-atom values. :dd
{Fix ave/spatial compute does not calculate per-atom values} :dt
A compute used by fix ave/spatial must generate per-atom values. :dd
{Fix ave/spatial compute vector is accessed out-of-range} :dt
The index for the vector is out of bounds. :dd
{Fix ave/spatial fix does not calculate a per-atom array} :dt
Self-explanatory. :dd
{Fix ave/spatial fix does not calculate a per-atom vector} :dt
A fix used by fix ave/spatial must generate per-atom values. :dd
{Fix ave/spatial fix does not calculate per-atom values} :dt
A fix used by fix ave/spatial must generate per-atom values. :dd
{Fix ave/spatial fix vector is accessed out-of-range} :dt
The index for the vector is out of bounds. :dd
{Fix ave/spatial for triclinic boxes requires units reduced} :dt
Self-explanatory. :dd
{Fix ave/spatial settings invalid with changing box} :dt
If the ave setting is "running" or "window" and the box size/shape
changes during the simulation, then the units setting must be
"reduced", else the number of bins may change. :dd
{Fix ave/spatial variable is not atom-style variable} :dt
A variable used by fix ave/spatial must generate per-atom values. :dd
{Fix ave/time cannot set output array intensive/extensive from these inputs} :dt
One of more of the vector inputs has individual elements which are
flagged as intensive or extensive. Such an input cannot be flagged as
all intensive/extensive when turned into an array by fix ave/time. :dd
{Fix ave/time cannot use variable with vector mode} :dt
Variables produce scalar values. :dd
{Fix ave/time columns are inconsistent lengths} :dt
Self-explanatory. :dd
{Fix ave/time compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/time compute does not calculate a scalar} :dt
Only computes that calculate a scalar or vector quantity (not a
per-atom quantity) can be used with fix ave/time. :dd
{Fix ave/time compute does not calculate a vector} :dt
Only computes that calculate a scalar or vector quantity (not a
per-atom quantity) can be used with fix ave/time. :dd
{Fix ave/time compute does not calculate an array} :dt
Self-explanatory. :dd
{Fix ave/time compute vector is accessed out-of-range} :dt
The index for the vector is out of bounds. :dd
{Fix ave/time fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix ave/time fix does not calculate a scalar} :dt
A fix used by fix ave/time must generate global values. :dd
{Fix ave/time fix does not calculate a vector} :dt
A fix used by fix ave/time must generate global values. :dd
{Fix ave/time fix does not calculate an array} :dt
Self-explanatory. :dd
{Fix ave/time fix vector is accessed out-of-range} :dt
The index for the vector is out of bounds. :dd
{Fix ave/time variable is not equal-style variable} :dt
A variable used by fix ave/time must generate a global value. :dd
{Fix bond/break requires special_bonds = 0,1,1} :dt
This is a restriction of the current fix bond/break implementation. :dd
{Fix bond/create cutoff is longer than pairwise cutoff} :dt
This is not allowed because bond creation is done using the
pairwise neighbor list. :dd
{Fix bond/create requires special_bonds coul = 0,1,1} :dt
Self-explanatory. :dd
{Fix bond/create requires special_bonds lj = 0,1,1} :dt
Self-explanatory. :dd
{Fix bond/swap cannot use dihedral or improper styles} :dt
These styles cannot be defined when using this fix. :dd
{Fix bond/swap requires pair and bond styles} :dt
Self-explanatory. :dd
{Fix bond/swap requires special_bonds = 0,1,1} :dt
Self-explanatory. :dd
{Fix box/relax generated negative box length} :dt
The pressure being applied is likely too large. Try applying
it incrementally, to build to the high pressure. :dd
{Fix command before simulation box is defined} :dt
The fix command cannot be used before a read_data, read_restart, or
create_box command. :dd
{Fix deform is changing yz by too much with changing xy} :dt
When both yz and xy are changing, it induces changes in xz if the
box must flip from one tilt extreme to another. Thus it is not
allowed for yz to grow so much that a flip is induced. :dd
{Fix deform tilt factors require triclinic box} :dt
Cannot deform the tilt factors of a simulation box unless it
is a triclinic (non-orthogonal) box. :dd
{Fix deform volume setting is invalid} :dt
Cannot use volume style unless other dimensions are being controlled. :dd
{Fix deposit region cannot be dynamic} :dt
Only static regions can be used with fix deposit. :dd
{Fix deposit region does not support a bounding box} :dt
Not all regions represent bounded volumes. You cannot use
such a region with the fix deposit command. :dd
{Fix efield requires atom attribute q} :dt
Self-explanatory. :dd
{Fix evaporate molecule requires atom attribute molecule} :dt
The atom style being used does not define a molecule ID. :dd
{Fix external callback function not set} :dt
This must be done by an external program in order to use this fix. :dd
{Fix for fix ave/atom not computed at compatible time} :dt
Fixes generate their values on specific timesteps. Fix ave/atom is
requesting a value on a non-allowed timestep. :dd
{Fix for fix ave/correlate not computed at compatible time} :dt
Fixes generate their values on specific timesteps. Fix ave/correlate
is requesting a value on a non-allowed timestep. :dd
{Fix for fix ave/histo not computed at compatible time} :dt
Fixes generate their values on specific timesteps. Fix ave/histo is
requesting a value on a non-allowed timestep. :dd
{Fix for fix ave/spatial not computed at compatible time} :dt
Fixes generate their values on specific timesteps. Fix ave/spatial is
requesting a value on a non-allowed timestep. :dd
{Fix for fix ave/time not computed at compatible time} :dt
Fixes generate their values on specific timesteps. Fix ave/time
is requesting a value on a non-allowed timestep. :dd
{Fix for fix store/state not computed at compatible time} :dt
Fixes generate their values on specific timesteps. Fix store/state
is requesting a value on a non-allowed timestep. :dd
{Fix freeze requires atom attribute torque} :dt
The atom style defined does not have this attribute. :dd
{Fix heat group has no atoms} :dt
Self-explanatory. :dd
{Fix heat kinetic energy went negative} :dt
This will cause the velocity rescaling about to be performed by fix
heat to be invalid. :dd
{Fix in variable not computed at compatible time} :dt
Fixes generate their values on specific timesteps. The variable is
requesting the values on a non-allowed timestep. :dd
{Fix langevin period must be > 0.0} :dt
The time window for temperature relaxation must be > 0 :dd
{Fix momentum group has no atoms} :dt
Self-explanatory. :dd
{Fix move cannot define z or vz variable for 2d problem} :dt
Self-explanatory. :dd
{Fix move cannot have 0 length rotation vector} :dt
Self-explanatory. :dd
{Fix move cannot rotate aroung non z-axis for 2d problem} :dt
Self-explanatory. :dd
{Fix move cannot set linear z motion for 2d problem} :dt
Self-explanatory. :dd
{Fix move cannot set wiggle z motion for 2d problem} :dt
Self-explanatory. :dd
{Fix msst compute ID does not compute potential energy} :dt
Self-explanatory. :dd
{Fix msst compute ID does not compute pressure} :dt
Self-explanatory. :dd
{Fix msst compute ID does not compute temperature} :dt
Self-explanatory. :dd
{Fix msst requires a periodic box} :dt
Self-explanatory. :dd
{Fix msst tscale must satisfy 0 <= tscale < 1} :dt
Self-explanatory. :dd
{Fix npt/nph has tilted box too far - box flips are not yet implemented} :dt
This feature has not yet been added. However, if you are applying
an off-diagonal pressure to a fluid, the box may want to tilt indefinitely,
because the fluid cannot support the pressure you are imposing. :dd
{Fix nve/asphere cannot be used with atom attributes diameter or rmass} :dt
These attributes override the shape and mass settings, so cannot be
used. :dd
{Fix nve/asphere requires atom attributes angmom, quat, torque, shape} :dt
An atom style that specifies these quantities is needed. :dd
{Fix nve/asphere requires extended particles} :dt
This fix can only be used for particles with a shape setting. :dd
{Fix nve/sphere requires atom attribute diameter or shape} :dt
An atom style that specifies these quantities is needed. :dd
{Fix nve/sphere requires atom attribute mu} :dt
An atom style with this attribute is needed. :dd
{Fix nve/sphere requires atom attributes omega, torque} :dt
An atom style with these attributes is needed. :dd
{Fix nve/sphere requires extended particles} :dt
This fix can only be used for particles of a finite size. :dd
{Fix nve/sphere requires spherical particle shapes} :dt
Self-explanatory. :dd
{Fix nvt/nph/npt asphere cannot be used with atom attributes diameter or rmass} :dt
Those attributes are for spherical particles. :dd
{Fix nvt/nph/npt asphere requires atom attributes quat, angmom, torque, shape} :dt
Those attributes are what are used to define aspherical particles. :dd
{Fix nvt/nph/npt asphere requires extended particles} :dt
The shape setting for a particle in the fix group has shape = 0.0,
which means it is a point particle. :dd
{Fix nvt/nph/npt sphere requires atom attribute diameter or shape} :dt
An atom style that specifies these quantities is needed. :dd
{Fix nvt/nph/npt sphere requires atom attributes omega, torque} :dt
Those attributes are what are used to define spherical particles. :dd
{Fix nvt/npt/nph damping parameters must be > 0.0} :dt
Self-explanatory. :dd
{Fix nvt/sphere requires extended particles} :dt
This fix can only be used for particles of a finite size. :dd
{Fix nvt/sphere requires spherical particle shapes} :dt
Self-explanatory. :dd
{Fix orient/fcc file open failed} :dt
The fix orient/fcc command could not open a specified file. :dd
{Fix orient/fcc file read failed} :dt
The fix orient/fcc command could not read the needed parameters from a
specified file. :dd
{Fix orient/fcc found self twice} :dt
The neighbor lists used by fix orient/fcc are messed up. If this
error occurs, it is likely a bug, so send an email to the
"developers"_http://lammps.sandia.gov/authors.html. :dd
{Fix peri neigh does not exist} :dt
Somehow a fix that the pair style defines has been deleted. :dd
{Fix pour region ID does not exist} :dt
Self-explanatory. :dd
{Fix pour region cannot be dynamic} :dt
Only static regions can be used with fix pour. :dd
{Fix pour region does not support a bounding box} :dt
Not all regions represent bounded volumes. You cannot use
such a region with the fix pour command. :dd
{Fix pour requires atom attributes radius, rmass} :dt
The atom style defined does not have these attributes. :dd
{Fix press/berendsen damping parameters must be > 0.0} :dt
Self-explanatory. :dd
{Fix qeq/comb group has no atoms} :dt
Self-explanatory. :dd
{Fix qeq/comb requires atom attribute q} :dt
An atom style with charge must be used to perform charge equilibration. :dd
{Fix reax/bonds numbonds > nsbmax_most} :dt
The limit of the number of bonds expected by the ReaxFF force field
was exceeded. :dd
{Fix recenter group has no atoms} :dt
Self-explanatory. :dd
{Fix rigid atom has non-zero image flag in a non-periodic dimension} :dt
You cannot set image flags for non-periodic dimensions. :dd
{Fix rigid molecule requires atom attribute molecule} :dt
Self-explanatory. :dd
{Fix rigid/nvt period must be > 0.0} :dt
Self-explanatory :dd
{Fix rigid: Bad principal moments} :dt
The principal moments of inertia computed for a rigid body
are not within the required tolerances. :dd
{Fix shake cannot be used with minimization} :dt
Cannot use fix shake while doing an energy minimization since
it turns off bonds that should contribute to the energy. :dd
{Fix spring couple group ID does not exist} :dt
Self-explanatory. :dd
{Fix srd lamda must be >= 0.6 of SRD grid size} :dt
This is a requirement for accuracy reasons. :dd
{Fix srd requires SRD particles all have same mass} :dt
Self-explanatory. :dd
{Fix srd requires ghost atoms store velocity} :dt
Use the communicate vel yes command to enable this. :dd
{Fix srd requires newton pair on} :dt
Self-explanatory. :dd
{Fix store/state compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix store/state compute does not calculate a per-atom array} :dt
The compute calculates a per-atom vector. :dd
{Fix store/state compute does not calculate a per-atom vector} :dt
The compute calculates a per-atom vector. :dd
{Fix store/state compute does not calculate per-atom values} :dt
Computes that calculate global or local quantities cannot be used
with fix store/state. :dd
{Fix store/state fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Fix store/state fix does not calculate a per-atom array} :dt
The fix calculates a per-atom vector. :dd
{Fix store/state fix does not calculate a per-atom vector} :dt
The fix calculates a per-atom array. :dd
{Fix store/state fix does not calculate per-atom values} :dt
Fixes that calculate global or local quantities cannot be used with
fix store/state. :dd
{Fix store/state for atom property that isn't allocated} :dt
Self-explanatory. :dd
{Fix store/state variable is not atom-style variable} :dt
Only atom-style variables calculate per-atom quantities. :dd
{Fix temp/berendsen period must be > 0.0} :dt
Self-explanatory. :dd
{Fix thermal/conductivity swap value must be positive} :dt
Self-explanatory. :dd
{Fix tmd must come after integration fixes} :dt
Any fix tmd command must appear in the input script after all time
integration fixes (nve, nvt, npt). See the fix tmd documentation for
details. :dd
{Fix ttm electron temperatures must be > 0.0} :dt
Self-explanatory. :dd
{Fix ttm electronic_density must be > 0.0} :dt
Self-explanatory. :dd
{Fix ttm electronic_specific_heat must be > 0.0} :dt
Self-explanatory. :dd
{Fix ttm electronic_thermal_conductivity must be >= 0.0} :dt
Self-explanatory. :dd
{Fix ttm gamma_p must be > 0.0} :dt
Self-explanatory. :dd
{Fix ttm gamma_s must be >= 0.0} :dt
Self-explanatory. :dd
{Fix ttm number of nodes must be > 0} :dt
Self-explanatory. :dd
{Fix ttm v_0 must be >= 0.0} :dt
Self-explanatory. :dd
{Fix used in compute atom/molecule not computed at compatible time} :dt
The fix must produce per-atom quantities on timesteps that the compute
needs them. :dd
{Fix used in compute reduce not computed at compatible time} :dt
Fixes generate their values on specific timesteps. Compute sum is
requesting a value on a non-allowed timestep. :dd
{Fix viscosity swap value must be positive} :dt
Self-explanatory. :dd
{Fix viscosity vtarget value must be positive} :dt
Self-explanatory. :dd
{Fix wall cutoff <= 0.0} :dt
Self-explanatory. :dd
{Fix wall/colloid cannot be used with atom attribute diameter} :dt
Only finite-size particles defined by the shape command can be used. :dd
{Fix wall/colloid requires atom attribute shape} :dt
Self-explanatory. :dd
{Fix wall/colloid requires extended particles} :dt
Self-explanatory. :dd
{Fix wall/colloid requires spherical particles} :dt
Self-explanatory. :dd
{Fix wall/gran is incompatible with Pair style} :dt
Must use a granular pair style to define the parameters needed for
this fix. :dd
{Fix wall/gran requires atom attributes radius, omega, torque} :dt
The atom style defined does not have these attributes. :dd
{Fix wall/region colloid cannot be used with atom attribute diameter} :dt
Only finite-size particles defined by the shape command can be used. :dd
{Fix wall/region colloid requires atom attribute shape} :dt
Self-explanatory. :dd
{Fix wall/region colloid requires extended particles} :dt
Self-explanatory. :dd
{Fix wall/region colloid requires spherical particles} :dt
Self-explanatory. :dd
{Fix wall/region cutoff <= 0.0} :dt
Self-explanatory. :dd
{Fix_modify order must be 3 or 5} :dt
Self-explanatory. :dd
{Fix_modify pressure ID does not compute pressure} :dt
The compute ID assigned to the fix must compute pressure. :dd
{Fix_modify temperature ID does not compute temperature} :dt
The compute ID assigned to the fix must compute temperature. :dd
{Found no restart file matching pattern} :dt
When using a "*" in the restart file name, no matching file was found. :dd
{GPU is not the first fix for this run} :dt
This is the way the fix must be defined in your input script. :dd
{GPU library not compiled for this accelerator} :dt
The GPU library was not built for your accelerator. Check the arch flag in
lib/gpu. :dd
{Gmask function in equal-style variable formula} :dt
Gmask is per-atom operation. :dd
{Gravity changed since fix pour was created} :dt
Gravity must be static and not dynamic for use with fix pour. :dd
{Gravity must point in -y to use with fix pour in 2d} :dt
Gravity must be pointing "down" in a 2d box. :dd
{Gravity must point in -z to use with fix pour in 3d} :dt
Gravity must be pointing "down" in a 3d box, i.e. theta = 180.0. :dd
{Grmask function in equal-style variable formula} :dt
Grmask is per-atom operation. :dd
{Group ID does not exist} :dt
A group ID used in the group command does not exist. :dd
{Group ID in variable formula does not exist} :dt
Self-explanatory. :dd
{Group command before simulation box is defined} :dt
The group command cannot be used before a read_data, read_restart, or
create_box command. :dd
{Group region ID does not exist} :dt
A region ID used in the group command does not exist. :dd
{Illegal ... command} :dt
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line. :dd
{Illegal COMB parameter} :dt
One or more of the coefficients defined in the potential file is
invalid. :dd
{Illegal Stillinger-Weber parameter} :dt
One or more of the coefficients defined in the potential file is
invalid. :dd
{Illegal Tersoff parameter} :dt
One or more of the coefficients defined in the potential file is
invalid. :dd
{Illegal chemical element names} :dt
The name is too long to be a chemical element. :dd
{Illegal fix gpu command} :dt
Self-explanatory. :dd
{Illegal number of angle table entries} :dt
There must be at least 2 table entries. :dd
{Illegal number of bond table entries} :dt
There must be at least 2 table entries. :dd
{Illegal number of pair table entries} :dt
There must be at least 2 table entries. :dd
{Illegal simulation box} :dt
The lower bound of the simulation box is greater than the upper bound. :dd
{Improper atom missing in delete_bonds} :dt
The delete_bonds command cannot find one or more atoms in a particular
improper on a particular processor. The pairwise cutoff is too short
or the atoms are too far apart to make a valid improper. :dd
{Improper atom missing in set command} :dt
The set command cannot find one or more atoms in a particular improper
on a particular processor. The pairwise cutoff is too short or the
atoms are too far apart to make a valid improper. :dd
{Improper atoms %d %d %d %d missing on proc %d at step} :dt
One or more of 4 atoms needed to compute a particular improper are
missing on this processor. Typically this is because the pairwise
cutoff is set too short or the improper has blown apart and an atom is
too far away. :dd
{Improper coeff for hybrid has invalid style} :dt
Improper style hybrid uses another improper style as one of its
coefficients. The improper style used in the improper_coeff command
or read from a restart file is not recognized. :dd
{Improper coeffs are not set} :dt
No improper coefficients have been assigned in the data file or via
the improper_coeff command. :dd
{Improper style hybrid cannot have hybrid as an argument} :dt
Self-explanatory. :dd
{Improper style hybrid cannot have none as an argument} :dt
Self-explanatory. :dd
{Improper style hybrid cannot use same improper style twice} :dt
Self-explanatory. :dd
{Improper_coeff command before improper_style is defined} :dt
Coefficients cannot be set in the data file or via the improper_coeff
command until an improper_style has been assigned. :dd
{Improper_coeff command before simulation box is defined} :dt
The improper_coeff command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Improper_coeff command when no impropers allowed} :dt
The chosen atom style does not allow for impropers to be defined. :dd
{Improper_style command when no impropers allowed} :dt
The chosen atom style does not allow for impropers to be defined. :dd
{Impropers assigned incorrectly} :dt
Impropers read in from the data file were not assigned correctly to
atoms. This means there is something invalid about the topology
definitions. :dd
{Impropers defined but no improper types} :dt
The data file header lists improper but no improper types. :dd
{Inconsistent iparam/jparam values in fix bond/create command} :dt
If itype and jtype are the same, then their maxbond and newtype
settings must also be the same. :dd
{Incorrect args for angle coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Incorrect args for bond coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Incorrect args for dihedral coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Incorrect args for improper coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Incorrect args for pair coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Incorrect args in pair_style command} :dt
Self-explanatory. :dd
{Incorrect atom format in data file} :dt
Number of values per atom line in the data file is not consistent with
the atom style. :dd
{Incorrect boundaries with slab Ewald} :dt
Must have periodic x,y dimensions and non-periodic z dimension to use
2d slab option with Ewald. :dd
{Incorrect boundaries with slab PPPM} :dt
Must have periodic x,y dimensions and non-periodic z dimension to use
2d slab option with PPPM. :dd
{Incorrect element names in EAM potential file} :dt
The element names in the EAM file do not match those requested. :dd
{Incorrect format in COMB potential file} :dt
Incorrect number of words per line in the potential file. :dd
{Incorrect format in MEAM potential file} :dt
Incorrect number of words per line in the potential file. :dd
{Incorrect format in NEB coordinate file} :dt
Self-explanatory. :dd
{Incorrect format in Stillinger-Weber potential file} :dt
Incorrect number of words per line in the potential file. :dd
{Incorrect format in TMD target file} :dt
Format of file read by fix tmd command is incorrect. :dd
{Incorrect format in Tersoff potential file} :dt
Incorrect number of words per line in the potential file. :dd
{Incorrect multiplicity arg for dihedral coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Incorrect sign arg for dihedral coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Incorrect velocity format in data file} :dt
Each atom style defines a format for the Velocity section
of the data file. The read-in lines do not match. :dd
{Incorrect weight arg for dihedral coefficients} :dt
Self-explanatory. Check the input script or data file. :dd
{Index between variable brackets must be positive} :dt
Self-explanatory. :dd
{Indexed per-atom vector in variable formula without atom map} :dt
Accessing a value from an atom vector requires the ability to lookup
an atom index, which is provided by an atom map. An atom map does not
exist (by default) for non-molecular problems. Using the atom_modify
map command will force an atom map to be created. :dd
{Induced tilt by displace_box is too large} :dt
The final tilt value must be between -1/2 and 1/2 of the perpendicular
box length. :dd
{Initial temperatures not all set in fix ttm} :dt
Self-explantory. :dd
{Input line too long after variable substitution} :dt
This is a hard (very large) limit defined in the input.cpp file. :dd
{Input line too long: %s} :dt
This is a hard (very large) limit defined in the input.cpp file. :dd
{Insertion region extends outside simulation box} :dt
Region specified with fix pour command extends outside the global
simulation box. :dd
{Insufficient Jacobi rotations for POEMS body} :dt
Eigensolve for rigid body was not sufficiently accurate. :dd
{Insufficient Jacobi rotations for rigid body} :dt
Eigensolve for rigid body was not sufficiently accurate. :dd
{Insufficient memory on accelerator. } :dt
Self-explanatory. :dd
{Invalid Boolean syntax in if command} :dt
Self-explanatory. :dd
{Invalid REAX atom type} :dt
There is a mis-match between LAMMPS atom types and the elements
listed in the ReaxFF force field file. :dd
{Invalid angle style} :dt
The choice of angle style is unknown. :dd
{Invalid angle table length} :dt
Length must be 2 or greater. :dd
{Invalid angle type in Angles section of data file} :dt
Angle type must be positive integer and within range of specified angle
types. :dd
{Invalid angle type index for fix shake} :dt
Self-explanatory. :dd
{Invalid atom ID in Angles section of data file} :dt
Atom IDs must be positive integers and within range of defined
atoms. :dd
{Invalid atom ID in Atoms section of data file} :dt
Atom IDs must be positive integers. :dd
{Invalid atom ID in Bonds section of data file} :dt
Atom IDs must be positive integers and within range of defined
atoms. :dd
{Invalid atom ID in Dihedrals section of data file} :dt
Atom IDs must be positive integers and within range of defined
atoms. :dd
{Invalid atom ID in Impropers section of data file} :dt
Atom IDs must be positive integers and within range of defined
atoms. :dd
{Invalid atom ID in Velocities section of data file} :dt
Atom IDs must be positive integers and within range of defined
atoms. :dd
{Invalid atom mass for fix shake} :dt
Mass specified in fix shake command must be > 0.0. :dd
{Invalid atom style} :dt
The choice of atom style is unknown. :dd
{Invalid atom type in Atoms section of data file} :dt
Atom types must range from 1 to specified # of types. :dd
{Invalid atom type in create_atoms command} :dt
The create_box command specified the range of valid atom types.
An invalid type is being requested. :dd
{Invalid atom type in fix bond/create command} :dt
Self-explanatory. :dd
{Invalid atom type in neighbor exclusion list} :dt
Atom types must range from 1 to Ntypes inclusive. :dd
{Invalid atom type index for fix shake} :dt
Atom types must range from 1 to Ntypes inclusive. :dd
{Invalid atom types in pair_write command} :dt
Atom types must range from 1 to Ntypes inclusive. :dd
{Invalid atom vector in variable formula} :dt
The atom vector is not recognized. :dd
{Invalid attribute in dump custom command} :dt
Self-explantory. :dd
{Invalid attribute in dump local command} :dt
Self-explantory. :dd
{Invalid attribute in dump modify command} :dt
Self-explantory. :dd
{Invalid bond style} :dt
The choice of bond style is unknown. :dd
{Invalid bond table length} :dt
Length must be 2 or greater. :dd
{Invalid bond type in Bonds section of data file} :dt
Bond type must be positive integer and within range of specified bond
types. :dd
{Invalid bond type in fix bond/break command} :dt
Self-explanatory. :dd
{Invalid bond type in fix bond/create command} :dt
Self-explanatory. :dd
{Invalid bond type index for fix shake} :dt
Self-explanatory. Check the fix shake command in the input script. :dd
{Invalid coeffs for this dihedral style} :dt
Cannot set class 2 coeffs in data file for this dihedral style. :dd
{Invalid command-line argument} :dt
One or more command-line arguments is invalid. Check the syntax of
the command you are using to launch LAMMPS. :dd
{Invalid compute ID in variable formula} :dt
The compute is not recognized. :dd
{Invalid compute style} :dt
Self-explanatory. :dd
{Invalid cutoff in communicate command} :dt
Specified cutoff must be >= 0.0. :dd
{Invalid cutoffs in pair_write command} :dt
Inner cutoff must be larger than 0.0 and less than outer cutoff. :dd
{Invalid d1 or d2 value for pair colloid coeff} :dt
Neither d1 or d2 can be < 0. :dd
{Invalid data file section: Angle Coeffs} :dt
Atom style does not allow angles. :dd
{Invalid data file section: AngleAngle Coeffs} :dt
Atom style does not allow impropers. :dd
{Invalid data file section: AngleAngleTorsion Coeffs} :dt
Atom style does not allow dihedrals. :dd
{Invalid data file section: AngleTorsion Coeffs} :dt
Atom style does not allow dihedrals. :dd
{Invalid data file section: Angles} :dt
Atom style does not allow angles. :dd
{Invalid data file section: Bond Coeffs} :dt
Atom style does not allow bonds. :dd
{Invalid data file section: BondAngle Coeffs} :dt
Atom style does not allow angles. :dd
{Invalid data file section: BondBond Coeffs} :dt
Atom style does not allow angles. :dd
{Invalid data file section: BondBond13 Coeffs} :dt
Atom style does not allow dihedrals. :dd
{Invalid data file section: Bonds} :dt
Atom style does not allow bonds. :dd
{Invalid data file section: Dihedral Coeffs} :dt
Atom style does not allow dihedrals. :dd
{Invalid data file section: Dihedrals} :dt
Atom style does not allow dihedrals. :dd
{Invalid data file section: EndBondTorsion Coeffs} :dt
Atom style does not allow dihedrals. :dd
{Invalid data file section: Improper Coeffs} :dt
Atom style does not allow impropers. :dd
{Invalid data file section: Impropers} :dt
Atom style does not allow impropers. :dd
{Invalid data file section: MiddleBondTorsion Coeffs} :dt
Atom style does not allow dihedrals. :dd
{Invalid delta_conf in tad command} :dt
The value must be between 0 and 1 inclusive. :dd
{Invalid density in Atoms section of data file} :dt
Density value cannot be <= 0.0. :dd
{Invalid dihedral style} :dt
The choice of dihedral style is unknown. :dd
{Invalid dihedral type in Dihedrals section of data file} :dt
Dihedral type must be positive integer and within range of specified
dihedral types. :dd
{Invalid dipole line in data file} :dt
Self-explanatory. :dd
{Invalid dipole value} :dt
Self-explanatory. :dd
{Invalid dump dcd filename} :dt
Filenames used with the dump dcd style cannot be binary or compressed
or cause multiple files to be written. :dd
{Invalid dump frequency} :dt
Dump frequency must be 1 or greater. :dd
{Invalid dump style} :dt
The choice of dump style is unknown. :dd
{Invalid dump xtc filename} :dt
Filenames used with the dump xtc style cannot be binary or compressed
or cause multiple files to be written. :dd
{Invalid dump xyz filename} :dt
Filenames used with the dump xyz style cannot be binary or cause files
to be written by each processor. :dd
{Invalid dump_modify threshhold operator} :dt
Operator keyword used for threshold specification in not recognized. :dd
{Invalid fix ID in variable formula} :dt
The fix is not recognized. :dd
{Invalid fix ave/time off column} :dt
Self-explantory. :dd
{Invalid fix box/relax command for a 2d simulation} :dt
Fix box/relax styles involving the z dimension cannot be used in
a 2d simulation. :dd
{Invalid fix box/relax command pressure settings} :dt
If multiple dimensions are coupled, those dimensions must be specified. :dd
{Invalid fix box/relax pressure settings} :dt
Settings for coupled dimensions must be the same. :dd
{Invalid fix nvt/npt/nph command for a 2d simulation} :dt
Cannot control z dimension in a 2d model. :dd
{Invalid fix nvt/npt/nph command pressure settings} :dt
If multiple dimensions are coupled, those dimensions must be
specified. :dd
{Invalid fix nvt/npt/nph pressure settings} :dt
Settings for coupled dimensions must be the same. :dd
{Invalid fix press/berendsen for a 2d simulation} :dt
The z component of pressure cannot be controlled for a 2d model. :dd
{Invalid fix press/berendsen pressure settings} :dt
Settings for coupled dimensions must be the same. :dd
{Invalid fix style} :dt
The choice of fix style is unknown. :dd
{Invalid flag in force field section of restart file} :dt
Unrecognized entry in restart file. :dd
{Invalid flag in header section of restart file} :dt
Unrecognized entry in restart file. :dd
{Invalid flag in type arrays section of restart file} :dt
Unrecognized entry in restart file. :dd
{Invalid frequency in temper command} :dt
Nevery must be > 0. :dd
{Invalid group ID in neigh_modify command} :dt
A group ID used in the neigh_modify command does not exist. :dd
{Invalid group function in variable formula} :dt
Group function is not recognized. :dd
{Invalid group in communicate command} :dt
Self-explanatory. :dd
{Invalid improper style} :dt
The choice of improper style is unknown. :dd
{Invalid improper type in Impropers section of data file} :dt
Improper type must be positive integer and within range of specified
improper types. :dd
{Invalid keyword in angle table parameters} :dt
Self-explanatory. :dd
{Invalid keyword in bond table parameters} :dt
Self-explanatory. :dd
{Invalid keyword in compute angle/local command} :dt
Self-explanatory. :dd
{Invalid keyword in compute bond/local command} :dt
Self-explanatory. :dd
{Invalid keyword in compute dihedral/local command} :dt
Self-explanatory. :dd
{Invalid keyword in compute improper/local command} :dt
Self-explanatory. :dd
{Invalid keyword in compute pair/local command} :dt
Self-explanatory. :dd
{Invalid keyword in compute property/atom command} :dt
Self-explanatory. :dd
{Invalid keyword in compute property/local command} :dt
Self-explanatory. :dd
{Invalid keyword in compute property/molecule command} :dt
Self-explanatory. :dd
{Invalid keyword in dump cfg command} :dt
Self-explanatory. :dd
{Invalid keyword in pair table parameters} :dt
Keyword used in list of table parameters is not recognized. :dd
{Invalid keyword in thermo_style custom command} :dt
One or more specified keywords are not recognized. :dd
{Invalid kspace style} :dt
The choice of kspace style is unknown. :dd
{Invalid mass line in data file} :dt
Self-explanatory. :dd
{Invalid mass value} :dt
Self-explanatory. :dd
{Invalid math function in variable formula} :dt
Self-explanatory. :dd
{Invalid math/group/special function in variable formula} :dt
Self-explanatory. :dd
{Invalid option in lattice command for non-custom style} :dt
Certain lattice keywords are not supported unless the
lattice style is "custom". :dd
{Invalid order of forces within respa levels} :dt
For respa, ordering of force computations within respa levels must
obey certain rules. E.g. bonds cannot be compute less frequently than
angles, pairwise forces cannot be computed less frequently than
kspace, etc. :dd
{Invalid pair style} :dt
The choice of pair style is unknown. :dd
{Invalid pair table cutoff} :dt
Cutoffs in pair_coeff command are not valid with read-in pair table. :dd
{Invalid pair table length} :dt
Length of read-in pair table is invalid :dd
{Invalid radius in Atoms section of data file} :dt
Radius must be >= 0.0. :dd
{Invalid random number seed in fix ttm command} :dt
Random number seed must be > 0. :dd
{Invalid random number seed in set command} :dt
Random number seed must be > 0. :dd
{Invalid region style} :dt
The choice of region style is unknown. :dd
{Invalid replace values in compute reduce} :dt
Self-explanatory. :dd
{Invalid run command N value} :dt
The number of timesteps must fit in a 32-bit integer. If you want to
run for more steps than this, perform multiple shorter runs. :dd
{Invalid run command start/stop value} :dt
Self-explanatory. :dd
{Invalid run command upto value} :dt
Self-explanatory. :dd
{Invalid seed for Marsaglia random # generator} :dt
The initial seed for this random number generator must be a positive
integer less than or equal to 900 million. :dd
{Invalid seed for Park random # generator} :dt
The initial seed for this random number generator must be a positive
integer. :dd
{Invalid shape line in data file} :dt
Self-explanatory. :dd
{Invalid shape line in data file} :dt
Self-explanatory. :dd
{Invalid shape value} :dt
Self-explanatory. :dd
{Invalid shear direction for fix wall/gran} :dt
Self-explanatory. :dd
{Invalid special function in variable formula} :dt
Self-explanatory. :dd
{Invalid style in pair_write command} :dt
Self-explanatory. Check the input script. :dd
{Invalid syntax in variable formula} :dt
Self-explanatory. :dd
{Invalid t_event in prd command} :dt
Self-explanatory. :dd
{Invalid t_event in tad command} :dt
The value must be greater than 0. :dd
{Invalid thermo keyword in variable formula} :dt
The keyword is not recognized. :dd
{Invalid tmax in tad command} :dt
The value must be greater than 0.0. :dd
{Invalid type for dipole set} :dt
Dipole command must set a type from 1-N where N is the number of atom
types. :dd
{Invalid type for mass set} :dt
Mass command must set a type from 1-N where N is the number of atom
types. :dd
{Invalid type for shape set} :dt
Atom type is out of bounds. :dd
{Invalid value in set command} :dt
The value specified for the setting is invalid, likely because it is
too small or too large. :dd
{Invalid variable evaluation in variable formula} :dt
A variable used in a formula could not be evaluated. :dd
{Invalid variable in next command} :dt
Self-explanatory. :dd
{Invalid variable name in variable formula} :dt
Variable name is not recognized. :dd
{Invalid variable name} :dt
Variable name used in an input script line is invalid. :dd
{Invalid variable style with next command} :dt
Variable styles {equal} and {world} cannot be used in a next
command. :dd
{Invalid wiggle direction for fix wall/gran} :dt
Self-explanatory. :dd
{Invoked angle equil angle on angle style none} :dt
Self-explanatory. :dd
{Invoked angle single on angle style none} :dt
Self-explanatory. :dd
{Invoked bond equil distance on bond style none} :dt
Self-explanatory. :dd
{Invoked bond single on bond style none} :dt
Self-explanatory. :dd
{Invoked pair single on pair style none} :dt
A command (e.g. a dump) attempted to invoke the single() function on a
pair style none, which is illegal. You are probably attempting to
compute per-atom quantities with an undefined pair style. :dd
{KSpace style has not yet been set} :dt
Cannot use kspace_modify command until a kspace style is set. :dd
{KSpace style is incompatible with Pair style} :dt
Setting a kspace style requires that a pair style with a long-range
Coulombic component be selected. :dd
{Keyword %s in MEAM parameter file not recognized} :dt
Self-explanatory. :dd
{Kspace style requires atom attribute q} :dt
The atom style defined does not have these attributes. :dd
{Label wasn't found in input script} :dt
Self-explanatory. :dd
{Lattice orient vectors are not orthogonal} :dt
The three specified lattice orientation vectors must be mutually
orthogonal. :dd
{Lattice orient vectors are not right-handed} :dt
The three specified lattice orientation vectors must create a
right-handed coordinate system such that a1 cross a2 = a3. :dd
{Lattice primitive vectors are collinear} :dt
The specified lattice primitive vectors do not for a unit cell with
non-zero volume. :dd
{Lattice settings are not compatible with 2d simulation} :dt
One or more of the specified lattice vectors has a non-zero z
component. :dd
{Lattice spacings are invalid} :dt
Each x,y,z spacing must be > 0. :dd
{Lattice style incompatible with simulation dimension} :dt
2d simulation can use sq, sq2, or hex lattice. 3d simulation can use
sc, bcc, or fcc lattice. :dd
{Log of zero/negative value in variable formula} :dt
Self-explanatory. :dd
{MEAM library error %d} :dt
A call to the MEAM Fortran library returned an error. :dd
{MPI_LMP_BIGINT and bigint in lmptype.h are not compatible} :dt
The size of the MPI datatype does not match the size of a bigint. :dd
{MPI_LMP_TAGINT and tagint in lmptype.h are not compatible} :dt
The size of the MPI datatype does not match the size of a tagint. :dd
{Mass command before simulation box is defined} :dt
The mass command cannot be used before a read_data, read_restart, or
create_box command. :dd
{Min_style command before simulation box is defined} :dt
The min_style command cannot be used before a read_data, read_restart,
or create_box command. :dd
{Minimization could not find thermo_pe compute} :dt
This compute is created by the thermo command. It must have been
explicitly deleted by a uncompute command. :dd
{Minimize command before simulation box is defined} :dt
The minimize command cannot be used before a read_data, read_restart,
or create_box command. :dd
{Mismatched brackets in variable} :dt
Self-explanatory. :dd
{Mismatched compute in variable formula} :dt
A compute is referenced incorrectly or a compute that produces per-atom
values is used in an equal-style variable formula. :dd
{Mismatched fix in variable formula} :dt
A fix is referenced incorrectly or a fix that produces per-atom
values is used in an equal-style variable formula. :dd
{Mismatched variable in variable formula} :dt
A variable is referenced incorrectly or an atom-style variable that
produces per-atom values is used in an equal-style variable
formula. :dd
{Molecular data file has too many atoms} :dt
These kids of data files are currently limited to a number
of atoms that fits in a 32-bit integer. :dd
{Molecule count changed in compute atom/molecule} :dt
Number of molecules must remain constant over time. :dd
{Molecule count changed in compute com/molecule} :dt
Number of molecules must remain constant over time. :dd
{Molecule count changed in compute gyration/molecule} :dt
Number of molecules must remain constant over time. :dd
{Molecule count changed in compute msd/molecule} :dt
Number of molecules must remain constant over time. :dd
{Molecule count changed in compute property/molecule} :dt
Number of molecules must remain constant over time. :dd
{More than one fix deform} :dt
Only one fix deform can be defined at a time. :dd
{More than one fix freeze} :dt
Only one of these fixes can be defined, since the granular pair
potentials access it. :dd
{More than one fix shake} :dt
Only one fix shake can be defined. :dd
{Must define angle_style before Angle Coeffs} :dt
Must use an angle_style command before reading a data file that
defines Angle Coeffs. :dd
{Must define angle_style before BondAngle Coeffs} :dt
Must use an angle_style command before reading a data file that
defines Angle Coeffs. :dd
{Must define angle_style before BondBond Coeffs} :dt
Must use an angle_style command before reading a data file that
defines Angle Coeffs. :dd
{Must define bond_style before Bond Coeffs} :dt
Must use a bond_style command before reading a data file that
defines Bond Coeffs. :dd
{Must define dihedral_style before AngleAngleTorsion Coeffs} :dt
Must use a dihedral_style command before reading a data file that
defines AngleAngleTorsion Coeffs. :dd
{Must define dihedral_style before AngleTorsion Coeffs} :dt
Must use a dihedral_style command before reading a data file that
defines AngleTorsion Coeffs. :dd
{Must define dihedral_style before BondBond13 Coeffs} :dt
Must use a dihedral_style command before reading a data file that
defines BondBond13 Coeffs. :dd
{Must define dihedral_style before Dihedral Coeffs} :dt
Must use a dihedral_style command before reading a data file that
defines Dihedral Coeffs. :dd
{Must define dihedral_style before EndBondTorsion Coeffs} :dt
Must use a dihedral_style command before reading a data file that
defines EndBondTorsion Coeffs. :dd
{Must define dihedral_style before MiddleBondTorsion Coeffs} :dt
Must use a dihedral_style command before reading a data file that
defines MiddleBondTorsion Coeffs. :dd
{Must define improper_style before AngleAngle Coeffs} :dt
Must use an improper_style command before reading a data file that
defines AngleAngle Coeffs. :dd
{Must define improper_style before Improper Coeffs} :dt
Must use an improper_style command before reading a data file that
defines Improper Coeffs. :dd
{Must define pair_style before Pair Coeffs} :dt
Must use a pair_style command before reading a data file that defines
Pair Coeffs. :dd
{Must have more than one processor partition to temper} :dt
Cannot use the temper command with only one processor partition. Use
the -partition command-line option. :dd
{Must read Atoms before Angles} :dt
The Atoms section of a data file must come before an Angles section. :dd
{Must read Atoms before Bonds} :dt
The Atoms section of a data file must come before a Bonds section. :dd
{Must read Atoms before Dihedrals} :dt
The Atoms section of a data file must come before a Dihedrals section. :dd
{Must read Atoms before Impropers} :dt
The Atoms section of a data file must come before an Impropers
section. :dd
{Must read Atoms before Velocities} :dt
The Atoms section of a data file must come before a Velocities
section. :dd
{Must set both respa inner and outer} :dt
Cannot use just the inner or outer option with respa without using the
other. :dd
{Must specify a region in fix deposit} :dt
The region keyword must be specified with this fix. :dd
{Must specify a region in fix pour} :dt
The region keyword must be specified with this fix. :dd
{Must use -in switch with multiple partitions} :dt
A multi-partition simulation cannot read the input script from stdin.
The -in command-line option must be used to specify a file. :dd
{Must use a block or cylinder region with fix pour} :dt
Self-explanatory. :dd
{Must use a block region with fix pour for 2d simulations} :dt
Self-explanatory. :dd
{Must use a bond style with TIP4P potential} :dt
TIP4P potentials assume bond lengths in water are constrained
by a fix shake command. :dd
{Must use a molecular atom style with fix poems molecule} :dt
Self-explanatory. :dd
{Must use a z-axis cylinder with fix pour} :dt
The axis of the cylinder region used with the fix pour command must
be oriented along the z dimension. :dd
{Must use an angle style with TIP4P potential} :dt
TIP4P potentials assume angles in water are constrained by a fix shake
command. :dd
{Must use atom style with molecule IDs with fix bond/swap} :dt
Self-explanatory. :dd
{Must use pair_style comb with fix qeq/comb} :dt
Self-explanatory. :dd
{Must use variable energy with fix addforce} :dt
Must define an energy vartiable when applyting a dynamic
force during minimization. :dd
{NEB command before simulation box is defined} :dt
Self-explanatory. :dd
{NEB requires damped dynamics minimizer} :dt
Use a different minimization style. :dd
{NEB requires use of fix neb} :dt
Self-explanatory. :dd
{Needed topology not in data file} :dt
The header of the data file indicated that bonds or angles or
dihedrals or impropers would be included, but they were not present. :dd
{Neigh_modify exclude molecule requires atom attribute molecule} :dt
Self-explanatory. :dd
{Neigh_modify include group != atom_modify first group} :dt
Self-explanatory. :dd
{Neighbor delay must be 0 or multiple of every setting} :dt
The delay and every parameters set via the neigh_modify command are
inconsistent. If the delay setting is non-zero, then it must be a
multiple of the every setting. :dd
{Neighbor include group not allowed with ghost neighbors} :dt
This is a current restriction within LAMMPS. :dd
{Neighbor list overflow, boost neigh_modify one or page} :dt
There are too many neighbors of a single atom. Use the neigh_modify
command to increase the neighbor page size and the max number of
neighbors allowed for one atom. :dd
{Neighbor multi not yet enabled for ghost neighbors} :dt
This is a current restriction within LAMMPS. :dd
{Neighbor multi not yet enabled for granular} :dt
Self-explanatory. :dd
{Neighbor multi not yet enabled for rRESPA} :dt
Self-explanatory. :dd
{Neighbor page size must be >= 10x the one atom setting} :dt
This is required to prevent wasting too much memory. :dd
{Neighbors of ghost atoms only allowed for full neighbor lists} :dt
This is a current restriction within LAMMPS. :dd
{New bond exceeded bonds per atom in fix bond/create} :dt
See the read_data command for info on setting the "extra bond per
atom" header value to allow for additional bonds to be formed. :dd
{New bond exceeded special list size in fix bond/create} :dt
See the special_bonds extra command for info on how to leave space in
the special bonds list to allow for additional bonds to be formed. :dd
{Newton bond change after simulation box is defined} :dt
The newton command cannot be used to change the newton bond value
after a read_data, read_restart, or create_box command. :dd
{No angle style is defined for compute angle/local} :dt
Self-explanatory. :dd
{No angles allowed with this atom style} :dt
Self-explanatory. Check data file. :dd
{No atoms in data file} :dt
The header of the data file indicated that atoms would be included,
but they were not present. :dd
{No basis atoms in lattice} :dt
Basis atoms must be defined for lattice style user. :dd
{No bond style is defined for compute bond/local} :dt
Self-explanatory. :dd
{No bonds allowed with this atom style} :dt
Self-explanatory. Check data file. :dd
{No dihedral style is defined for compute dihedral/local} :dt
Self-explanatory. :dd
{No dihedrals allowed with this atom style} :dt
Self-explanatory. Check data file. :dd
{No dump custom arguments specified} :dt
The dump custom command requires that atom quantities be specified to
output to dump file. :dd
{No dump local arguments specified} :dt
Self-explanatory. :dd
{No fix gravity defined for fix pour} :dt
Cannot add poured particles without gravity to move them. :dd
{No improper style is defined for compute improper/local} :dt
Self-explanatory. :dd
{No impropers allowed with this atom style} :dt
Self-explanatory. Check data file. :dd
{No matching element in EAM potential file} :dt
The EAM potential file does not contain elements that match the
requested elements. :dd
{No pair hbond/dreiding coefficients set} :dt
Self-explanatory. :dd
{No pair style defined for compute group/group} :dt
Cannot calculate group interactions without a pair style defined. :dd
{No pair style is defined for compute pair/local} :dt
Self-explanatory. :dd
{No pair style is defined for compute property/local} :dt
Self-explanatory. :dd
{No rigid bodies defined} :dt
The fix specification did not end up defining any rigid bodies. :dd
{Non digit character between brackets in variable} :dt
Self-explantory. :dd
{Non integer # of swaps in temper command} :dt
Swap frequency in temper command must evenly divide the total # of
timesteps. :dd
{One or more atoms belong to multiple rigid bodies} :dt
Two or more rigid bodies defined by the fix rigid command cannot
contain the same atom. :dd
{One or zero atoms in rigid body} :dt
Any rigid body defined by the fix rigid command must contain 2 or more
atoms. :dd
{Out of range atoms - cannot compute PPPM} :dt
One or more atoms are attempting to map their charge to a PPPM grid
point that is not owned by a processor. This is likely for one of two
reasons, both of them bad. First, it may mean that an atom near the
boundary of a processor's sub-domain has moved more than 1/2 the
"neighbor skin distance"_neighbor.html without neighbor lists being
rebuilt and atoms being migrated to new processors. This also means
you may be missing pairwise interactions that need to be computed.
The solution is to change the re-neighboring criteria via the
"neigh_modify"_neigh_modify command. The safest settings are "delay 0
every 1 check yes". Second, it may mean that an atom has moved far
outside a processor's sub-domain or even the entire simulation box.
This indicates bad physics, e.g. due to highly overlapping atoms, too
large a timestep, etc. :dd
{Overlapping large/large in pair colloid} :dt
This potential is infinite when there is an overlap. :dd
{Overlapping small/large in pair colloid} :dt
This potential is inifinte when there is an overlap. :dd
{POEMS fix must come before NPT/NPH fix} :dt
NPT/NPH fix must be defined in input script after all poems fixes,
else the fix contribution to the pressure virial is incorrect. :dd
{PPPM grid is too large} :dt
The global PPPM grid is larger than OFFSET in one or more dimensions.
OFFSET is currently set to 4096. You likely need to decrease the
requested precision. :dd
{PPPM order cannot be greater than %d} :dt
Self-explanatory. :dd
{PPPM order has been reduced to 0} :dt
LAMMPS has attempted to reduce the PPPM order to enable the simulation
to run, but can reduce the order no further. Try increasing the
accuracy of PPPM by reducing the tolerance size, thus inducing a
larger PPPM grid. :dd
{PRD command before simulation box is defined} :dt
The prd command cannot be used before a read_data,
read_restart, or create_box command. :dd
{PRD nsteps must be multiple of t_event} :dt
Self-explanatory. :dd
{PRD t_corr must be multiple of t_event} :dt
Self-explanatory. :dd
{Pair coeff for hybrid has invalid style} :dt
Style in pair coeff must have been listed in pair_style command. :dd
{Pair cutoff < Respa interior cutoff} :dt
One or more pairwise cutoffs are too short to use with the specified
rRESPA cutoffs. :dd
{Pair dipole/cut requires atom attributes q, mu, torque, dipole} :dt
An atom style that specifies these quantities is needed. :dd
{Pair distance < table inner cutoff} :dt
Two atoms are closer together than the pairwise table allows. :dd
{Pair distance > table outer cutoff} :dt
Two atoms are further apart than the pairwise table allows. :dd
{Pair dpd requires ghost atoms store velocity} :dt
Use the communicate vel yes command to enable this. :dd
{Pair gayberne cannot be used with atom attribute diameter} :dt
Finite-size particles must be defined with the shape command. :dd
{Pair gayberne epsilon a,b,c coeffs are not all set} :dt
Each atom type involved in pair_style gayberne must
have these 3 coefficients set at least once. :dd
{Pair gayberne requires atom attributes quat, torque, shape} :dt
An atom style that defines these attributes must be used. :dd
{Pair granular requires atom attributes radius, omega, torque} :dt
The atom style defined does not have these attributes. :dd
{Pair granular requires ghost atoms store velocity} :dt
Use the communicate vel yes command to enable this. :dd
{Pair granular with shear history requires newton pair off} :dt
This is a current restriction of the implementation of pair
granular styles with history. :dd
{Pair hybrid sub-style does not support single call} :dt
You are attempting to invoke a single() call on a pair style
that doesn't support it. :dd
{Pair hybrid sub-style is not used} :dt
No pair_coeff command used a sub-style specified in the pair_style
command. :dd
{Pair inner cutoff < Respa interior cutoff} :dt
One or more pairwise cutoffs are too short to use with the specified
rRESPA cutoffs. :dd
{Pair inner cutoff >= Pair outer cutoff} :dt
The specified cutoffs for the pair style are inconsistent. :dd
{Pair lubricate cannot be used with atom attributes diameter or rmass} :dt
These attributes override the shape and mass settings, so cannot be
used. :dd
{Pair lubricate requires atom attribute omega or angmom} :dt
An atom style that defines these attributes must be used. :dd
{Pair lubricate requires atom attributes torque and shape} :dt
An atom style that defines these attributes must be used. :dd
{Pair lubricate requires extended particles} :dt
This pair style can only be used for particles with a shape
setting. :dd
{Pair lubricate requires ghost atoms store velocity} :dt
Use the communicate vel yes command to enable this. :dd
{Pair lubricate requires spherical, mono-disperse particles} :dt
This is a current restriction of this pair style. :dd
{Pair peri lattice is not identical in x, y, and z} :dt
The lattice defined by the lattice command must be cubic. :dd
{Pair peri requires a lattice be defined} :dt
Use the lattice command for this purpose. :dd
{Pair peri requires an atom map, see atom_modify} :dt
Even for atomic systems, an atom map is required to find Peridynamic
bonds. Use the atom_modify command to define one. :dd
{Pair resquared cannot be used with atom attribute diameter} :dt
This attribute overrides the shape settings, so cannot be used. :dd
{Pair resquared epsilon a,b,c coeffs are not all set} :dt
Self-explanatory. :dd
{Pair resquared epsilon and sigma coeffs are not all set} :dt
Self-explanatory. :dd
{Pair resquared requires atom attributes quat, torque, shape} :dt
An atom style that defines these attributes must be used. :dd
{Pair style AIREBO requires atom IDs} :dt
This is a requirement to use the AIREBO potential. :dd
{Pair style AIREBO requires newton pair on} :dt
See the newton command. This is a restriction to use the AIREBO
potential. :dd
{Pair style COMB requires atom IDs} :dt
This is a requirement to use the AIREBO potential. :dd
{Pair style COMB requires atom attribute q} :dt
Self-explanatory. :dd
{Pair style COMB requires newton pair on} :dt
See the newton command. This is a restriction to use the COMB
potential. :dd
{Pair style MEAM requires newton pair on} :dt
See the newton command. This is a restriction to use the MEAM
potential. :dd
{Pair style Stillinger-Weber requires atom IDs} :dt
This is a requirement to use the SW potential. :dd
{Pair style Stillinger-Weber requires newton pair on} :dt
See the newton command. This is a restriction to use the SW
potential. :dd
{Pair style Tersoff requires atom IDs} :dt
This is a requirement to use the Tersoff potential. :dd
{Pair style Tersoff requires newton pair on} :dt
See the newton command. This is a restriction to use the Tersoff
potential. :dd
{Pair style born/coul/long requires atom attribute q} :dt
An atom style that defines this attribute must be used. :dd
{Pair style buck/coul/cut requires atom attribute q} :dt
The atom style defined does not have this attribute. :dd
{Pair style buck/coul/long requires atom attribute q} :dt
The atom style defined does not have these attributes. :dd
{Pair style coul/cut requires atom attribute q} :dt
The atom style defined does not have these attributes. :dd
{Pair style does not support bond_style quartic} :dt
The pair style does not have a single() function, so it can
not be invoked by bond_style quartic. :dd
{Pair style does not support compute group/group} :dt
The pair_style does not have a single() function, so it cannot be
invokded by the compute group/group command. :dd
{Pair style does not support compute pair/local} :dt
The pair style does not have a single() function, so it can
not be invoked by fix bond/swap. :dd
{Pair style does not support compute property/local} :dt
The pair style does not have a single() function, so it can
not be invoked by fix bond/swap. :dd
{Pair style does not support fix bond/swap} :dt
The pair style does not have a single() function, so it can
not be invoked by fix bond/swap. :dd
{Pair style does not support pair_write} :dt
The pair style does not have a single() function, so it can
not be invoked by pair write. :dd
{Pair style does not support rRESPA inner/middle/outer} :dt
You are attempting to use rRESPA options with a pair style that
does not support them. :dd
{Pair style granular with history requires atoms have IDs} :dt
Atoms in the simulation do not have IDs, so history effects
cannot be tracked by the granular pair potential. :dd
{Pair style hbond/dreiding requires an atom map, see atom_modify} :dt
Self-explanatory. :dd
{Pair style hbond/dreiding requires atom IDs} :dt
Self-explanatory. :dd
{Pair style hbond/dreiding requires molecular system} :dt
Self-explanatory. :dd
{Pair style hbond/dreiding requires newton pair on} :dt
See the newton command for details. :dd
{Pair style hybrid cannot have hybrid as an argument} :dt
Self-explanatory. :dd
{Pair style hybrid cannot have none as an argument} :dt
Self-explanatory. :dd
{Pair style hybrid cannot use same pair style twice} :dt
The sub-style arguments of pair_style hybrid cannot be duplicated.
Check the input script. :dd
{Pair style is incompatible with KSpace style} :dt
If a pair style with a long-range Coulombic component is selected,
then a kspace style must also be used. :dd
{Pair style lj/charmm/coul/charmm requires atom attribute q} :dt
The atom style defined does not have these attributes. :dd
{Pair style lj/charmm/coul/long requires atom attribute q} :dt
The atom style defined does not have these attributes. :dd
{Pair style lj/class2/coul/cut requires atom attribute q} :dt
The atom style defined does not have this attribute. :dd
{Pair style lj/class2/coul/long requires atom attribute q} :dt
The atom style defined does not have this attribute. :dd
{Pair style lj/cut/coul/cut requires atom attribute q} :dt
The atom style defined does not have this attribute. :dd
{Pair style lj/cut/coul/long requires atom attribute q} :dt
The atom style defined does not have this attribute. :dd
{Pair style lj/cut/coul/long/tip4p requires atom IDs} :dt
There are no atom IDs defined in the system and the TIP4P potential
requires them to find O,H atoms with a water molecule. :dd
{Pair style lj/cut/coul/long/tip4p requires atom attribute q} :dt
The atom style defined does not have these attributes. :dd
{Pair style lj/cut/coul/long/tip4p requires newton pair on} :dt
This is because the computation of constraint forces within a water
molecule adds forces to atoms owned by other processors. :dd
{Pair style lj/gromacs/coul/gromacs requires atom attribute q} :dt
An atom_style with this attribute is needed. :dd
{Pair style peri_lps requires atom style peri} :dt
This is because atom style peri stores quantities needed by
the peridynamic potential. :dd
{Pair style peri_pmb requires atom style peri} :dt
This is because atom style peri stores quantities needed by
the peridynamic potential. :dd
{Pair style reax requires atom IDs} :dt
This is a requirement to use the ReaxFF potential. :dd
{Pair style reax requires newton pair on} :dt
This is a requirement to use the ReaxFF potential. :dd
{Pair table cutoffs must all be equal to use with KSpace} :dt
When using pair style table with a long-range KSpace solver, the
cutoffs for all atom type pairs must all be the same, since the
long-range solver starts at that cutoff. :dd
{Pair table parameters did not set N} :dt
List of pair table parameters must include N setting. :dd
{Pair tersoff/zbl requires metal or real units} :dt
This is a current restriction of this pair potential. :dd
{Pair yukawa/colloid cannot be used with atom attribute diameter} :dt
Only finite-size particles defined by the shape command can be used. :dd
{Pair yukawa/colloid requires atom attribute shape} :dt
Self-explanatory. :dd
{Pair yukawa/colloid requires spherical particles} :dt
Self-explanatory. :dd
{Pair_coeff command before pair_style is defined} :dt
Self-explanatory. :dd
{Pair_coeff command before simulation box is defined} :dt
The pair_coeff command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Pair_modify command before pair_style is defined} :dt
Self-explanatory. :dd
{Pair_write command before pair_style is defined} :dt
Self-explanatory. :dd
{Particle on or inside fix wall surface} :dt
Particles must be "exterior" to the wall in order for energy/force to
be calculated. :dd
{Particle on or inside surface of region used in fix wall/region} :dt
Particles must be "exterior" to the region surface in order for
energy/force to be calculated. :dd
{Per-atom compute in equal-style variable formula} :dt
Equal-style variables cannot use per-atom quantities. :dd
{Per-atom energy was not tallied on needed timestep} :dt
You are using a thermo keyword that requires potentials to
have tallied energy, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work. :dd
{Per-atom fix in equal-style variable formula} :dt
Equal-style variables cannot use per-atom quantities. :dd
{Per-atom virial was not tallied on needed timestep} :dt
You are using a thermo keyword that requires potentials to have
tallied the virial, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work. :dd
{Per-processor system is too big} :dt
The number of owned atoms plus ghost atoms on a single
processor must fit in 32-bit integer. :dd
{Potential energy ID for fix neb does not exist} :dt
Self-explanatory. :dd
{Potential file has duplicate entry} :dt
The potential file for a SW or Tersoff potential has more than
one entry for the same 3 ordered elements. :dd
{Potential file is missing an entry} :dt
The potential file for a SW or Tersoff potential does not have a
needed entry. :dd
{Power by 0 in variable formula} :dt
Self-explanatory. :dd
{Pressure ID for fix box/relax does not exist} :dt
The compute ID needed to compute pressure for the fix does not
exist. :dd
{Pressure ID for fix modify does not exist} :dt
Self-explanatory. :dd
{Pressure ID for fix npt/nph does not exist} :dt
Self-explanatory. :dd
{Pressure ID for fix press/berendsen does not exist} :dt
The compute ID needed to compute pressure for the fix does not
exist. :dd
{Pressure ID for thermo does not exist} :dt
The compute ID needed to compute pressure for thermodynamics does not
exist. :dd
{Pressure control can not be used with fix nvt/asphere} :dt
Self-explanatory. :dd
{Pressure control can not be used with fix nvt/sllod} :dt
Self-explanatory. :dd
{Pressure control can not be used with fix nvt/sphere} :dt
Self-explanatory. :dd
{Pressure control can not be used with fix nvt} :dt
Self-explanatory. :dd
{Pressure control must be used with fix nph/asphere} :dt
Self-explanatory. :dd
{Pressure control must be used with fix nph/sphere} :dt
Self-explanatory. :dd
{Pressure control must be used with fix nph} :dt
Self-explanatory. :dd
{Pressure control must be used with fix npt/asphere} :dt
Self-explanatory. :dd
{Pressure control must be used with fix npt/sphere} :dt
Self-explanatory. :dd
{Pressure control must be used with fix npt} :dt
Self-explanatory. :dd
{Processor count in z must be 1 for 2d simulation} :dt
Self-explanatory. :dd
{Processor partitions are inconsistent} :dt
The total number of processors in all partitions must match the number
of processors LAMMPS is running on. :dd
{Processors command after simulation box is defined} :dt
The processors command cannot be used after a read_data, read_restart,
or create_box command. :dd
{Quaternion creation numeric error} :dt
A numeric error occurred in the creation of a rigid body by the fix
rigid command. :dd
{R0 < 0 for fix spring command} :dt
Equilibrium spring length is invalid. :dd
{Reax_defs.h setting for NATDEF is too small} :dt
Edit the setting in the ReaxFF library and re-compile the
library and re-build LAMMPS. :dd
{Reax_defs.h setting for NNEIGHMAXDEF is too small} :dt
Edit the setting in the ReaxFF library and re-compile the
library and re-build LAMMPS. :dd
{Region ID for compute reduce/region does not exist} :dt
Self-explanatory. :dd
{Region ID for compute temp/region does not exist} :dt
Self-explanatory. :dd
{Region ID for dump cfg does not exist} :dt
Self-explanatory. :dd
{Region ID for dump custom does not exist} :dt
Self-explanatory. :dd
{Region ID for fix addforce does not exist} :dt
Self-explanatory. :dd
{Region ID for fix ave/spatial does not exist} :dt
Self-explanatory. :dd
{Region ID for fix aveforce does not exist} :dt
Self-explanatory. :dd
{Region ID for fix deposit does not exist} :dt
Self-explanatory. :dd
{Region ID for fix evaporate does not exist} :dt
Self-explanatory. :dd
{Region ID for fix heat does not exist} :dt
Self-explanatory. :dd
{Region ID for fix setforce does not exist} :dt
Self-explanatory. :dd
{Region ID for fix wall/region does not exist} :dt
Self-explanatory. :dd
{Region ID in variable formula does not exist} :dt
Self-explanatory. :dd
{Region cannot have 0 length rotation vector} :dt
Self-explanatory. :dd
{Region intersect region ID does not exist} :dt
Self-explanatory. :dd
{Region union or intersect cannot be dynamic} :dt
The sub-regions can be dynamic, but not the combined region. :dd
{Region union region ID does not exist} :dt
One or more of the region IDs specified by the region union command
does not exist. :dd
{Replacing a fix, but new style != old style} :dt
A fix ID can be used a 2nd time, but only if the style matches the
previous fix. In this case it is assumed you with to reset a fix's
parameters. This error may mean you are mistakenly re-using a fix ID
when you do not intend to. :dd
{Replicate command before simulation box is defined} :dt
The replicate command cannot be used before a read_data, read_restart,
or create_box command. :dd
{Replicate did not assign all atoms correctly} :dt
Atoms replicated by the replicate command were not assigned correctly
to processors. This is likely due to some atom coordinates being
outside a non-periodic simulation box. :dd
{Replicated molecular system atom IDs are too big} :dt
See the setting for the allowed atom ID size in the src/lmptype.h
file. :dd
{Replicated system is too big} :dt
See the setting for bigint in the src/lmptype.h file. :dd
{Resetting timestep is not allowed with fix move} :dt
This is because fix move is moving atoms based on elapsed time. :dd
{Respa inner cutoffs are invalid} :dt
The first cutoff must be <= the second cutoff. :dd
{Respa levels must be >= 1} :dt
Self-explanatory. :dd
{Respa middle cutoffs are invalid} :dt
The first cutoff must be <= the second cutoff. :dd
{Reuse of compute ID} :dt
A compute ID cannot be used twice. :dd
{Reuse of dump ID} :dt
A dump ID cannot be used twice. :dd
{Reuse of region ID} :dt
A region ID cannot be used twice. :dd
{Rigid body has degenerate moment of inertia} :dt
Fix poems will only work with bodies (collections of atoms) that have
non-zero principal moments of inertia. This means they must be 3 or
more non-collinear atoms, even with joint atoms removed. :dd
{Rigid fix must come before NPT/NPH fix} :dt
NPT/NPH fix must be defined in input script after all rigid fixes,
else the rigid fix contribution to the pressure virial is
incorrect. :dd
{Rmask function in equal-style variable formula} :dt
Rmask is per-atom operation. :dd
{Run command before simulation box is defined} :dt
The run command cannot be used before a read_data, read_restart, or
create_box command. :dd
{Run command start value is after start of run} :dt
Self-explanatory. :dd
{Run command stop value is before end of run} :dt
Self-explanatory. :dd
{Run_style command before simulation box is defined} :dt
The run_style command cannot be used before a read_data,
read_restart, or create_box command. :dd
{SRD bin size for fix srd differs from user request} :dt
Fix SRD had to adjust the bin size to fit the simulation box. :dd
{SRD bins for fix srd are not cubic enough} :dt
The bin shape is not within tolerance of cubic. :dd
{Same dimension twice in fix ave/spatial} :dt
Self-explanatory. :dd
{Set command before simulation box is defined} :dt
The set command cannot be used before a read_data, read_restart,
or create_box command. :dd
{Set command with no atoms existing} :dt
No atoms are yet defined so the set command cannot be used. :dd
{Set region ID does not exist} :dt
Region ID specified in set command does not exist. :dd
{Shake angles have different bond types} :dt
All 3-atom angle-constrained SHAKE clusters specified by the fix shake
command that are the same angle type, must also have the same bond
types for the 2 bonds in the angle. :dd
{Shake atoms %d %d %d %d missing on proc %d at step} :dt
The 4 atoms in a single shake cluster specified by the fix shake
command are not all accessible to a processor. This probably means
an atom has moved too far. :dd
{Shake atoms %d %d %d missing on proc %d at step} :dt
The 3 atoms in a single shake cluster specified by the fix shake
command are not all accessible to a processor. This probably means
an atom has moved too far. :dd
{Shake atoms %d %d missing on proc %d at step} :dt
The 2 atoms in a single shake cluster specified by the fix shake
command are not all accessible to a processor. This probably means
an atom has moved too far. :dd
{Shake cluster of more than 4 atoms} :dt
A single cluster specified by the fix shake command can have no more
than 4 atoms. :dd
{Shake clusters are connected} :dt
A single cluster specified by the fix shake command must have a single
central atom with up to 3 other atoms bonded to it. :dd
{Shake determinant = 0.0} :dt
The determinant of the matrix being solved for a single cluster
specified by the fix shake command is numerically invalid. :dd
{Shake fix must come before NPT/NPH fix} :dt
NPT fix must be defined in input script after SHAKE fix, else the
SHAKE fix contribution to the pressure virial is incorrect. :dd
{Shape command before simulation box is defined} :dt
Self-explanatory. :dd
{Smallint setting in lmptype.h is invalid} :dt
It has to be the size of an integer. :dd
{Smallint setting in lmptype.h is not compatible} :dt
Smallint stored in restart file is not consistent with LAMMPS version
you are running. :dd
{Sqrt of negative value in variable formula} :dt
Self-explanatory. :dd
{Substitution for illegal variable} :dt
Input script line contained a variable that could not be substituted
for. :dd
{System in data file is too big} :dt
See the setting for bigint in the src/lmptype.h file. :dd
{TAD nsteps must be multiple of t_event} :dt
Self-explanatory. :dd
{TIP4P hydrogen has incorrect atom type} :dt
The TIP4P pairwise computation found an H atom whose type does not
agree with the specified H type. :dd
{TIP4P hydrogen is missing} :dt
The TIP4P pairwise computation failed to find the correct H atom
within a water molecule. :dd
{TMD target file did not list all group atoms} :dt
The target file for the fix tmd command did not list all atoms in the
fix group. :dd
{Tad command before simulation box is defined} :dt
Self-explanatory. :dd
{Tagint setting in lmptype.h is invalid} :dt
Tagint must be as large or larger than smallint. :dd
{Tagint setting in lmptype.h is not compatible} :dt
Smallint stored in restart file is not consistent with LAMMPS version
you are running. :dd
{Target temperature for fix nvt/npt/nph cannot be 0.0} :dt
Self-explanatory. :dd
{Target temperature for fix rigid/nvt cannot be 0.0} :dt
Self-explanatory. :dd
{Temper command before simulation box is defined} :dt
The temper command cannot be used before a read_data, read_restart, or
create_box command. :dd
{Temperature ID for fix bond/swap does not exist} :dt
Self-explanatory. :dd
{Temperature ID for fix box/relax does not exist} :dt
Self-explanatory. :dd
{Temperature ID for fix nvt/nph/npt does not exist} :dt
Self-explanatory. :dd
{Temperature ID for fix press/berendsen does not exist} :dt
Self-explanatory. :dd
{Temperature ID for fix temp/berendsen does not exist} :dt
Self-explanatory. :dd
{Temperature ID for fix temp/rescale does not exist} :dt
Self-explanatory. :dd
{Temperature control can not be used with fix nph/asphere} :dt
Self-explanatory. :dd
{Temperature control can not be used with fix nph/sphere} :dt
Self-explanatory. :dd
{Temperature control can not be used with fix nph} :dt
Self-explanatory. :dd
{Temperature control must be used with fix npt/asphere} :dt
Self-explanatory. :dd
{Temperature control must be used with fix npt/sphere} :dt
Self-explanatory. :dd
{Temperature control must be used with fix npt} :dt
Self-explanatory. :dd
{Temperature control must be used with fix nvt/asphere} :dt
Self-explanatory. :dd
{Temperature control must be used with fix nvt/sllod} :dt
Self-explanatory. :dd
{Temperature control must be used with fix nvt/sphere} :dt
Self-explanatory. :dd
{Temperature control must be used with fix nvt} :dt
Self-explanatory. :dd
{Temperature for fix nvt/sllod does not have a bias} :dt
The specified compute must compute temperature with a bias. :dd
{Tempering could not find thermo_pe compute} :dt
This compute is created by the thermo command. It must have been
explicitly deleted by a uncompute command. :dd
{Tempering fix ID is not defined} :dt
The fix ID specified by the temper command does not exist. :dd
{Tempering temperature fix is not valid} :dt
The fix specified by the temper command is not one that controls
temperature (nvt or langevin). :dd
{Thermo and fix not computed at compatible times} :dt
Fixes generate values on specific timesteps. The thermo output
does not match these timesteps. :dd
{Thermo compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Thermo compute does not compute array} :dt
Self-explanatory. :dd
{Thermo compute does not compute scalar} :dt
Self-explanatory. :dd
{Thermo compute does not compute vector} :dt
Self-explanatory. :dd
{Thermo compute vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Thermo custom variable cannot be indexed} :dt
Self-explanatory. :dd
{Thermo custom variable is not equal-style variable} :dt
Only equal-style variables can be output with thermodynamics, not
atom-style variables. :dd
{Thermo every variable returned a bad timestep} :dt
The variable must return a timestep greater than the current timestep. :dd
{Thermo fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Thermo fix does not compute array} :dt
Self-explanatory. :dd
{Thermo fix does not compute scalar} :dt
Self-explanatory. :dd
{Thermo fix does not compute vector} :dt
Self-explanatory. :dd
{Thermo fix vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Thermo keyword in variable requires lattice be defined} :dt
The xlat, ylat, zlat keywords refer to lattice properties. :dd
{Thermo keyword in variable requires thermo to use/init pe} :dt
You are using a thermo keyword in a variable that requires
potential energy to be calculated, but your thermo output
does not use it. Add it to your thermo output. :dd
{Thermo keyword in variable requires thermo to use/init press} :dt
You are using a thermo keyword in a variable that requires pressure to
be calculated, but your thermo output does not use it. Add it to your
thermo output. :dd
{Thermo keyword in variable requires thermo to use/init temp} :dt
You are using a thermo keyword in a variable that requires temperature
to be calculated, but your thermo output does not use it. Add it to
your thermo output. :dd
{Thermo keyword requires lattice be defined} :dt
The xlat, ylat, zlat keywords refer to lattice properties. :dd
{Thermo style does not use press} :dt
Cannot use thermo_modify to set this parameter since the thermo_style
is not computing this quantity. :dd
{Thermo style does not use temp} :dt
Cannot use thermo_modify to set this parameter since the thermo_style
is not computing this quantity. :dd
{Thermo_modify int format does not contain d character} :dt
Self-explanatory. :dd
{Thermo_modify pressure ID does not compute pressure} :dt
The specified compute ID does not compute pressure. :dd
{Thermo_modify temperature ID does not compute temperature} :dt
The specified compute ID does not compute temperature. :dd
{Thermo_style command before simulation box is defined} :dt
The thermo_style command cannot be used before a read_data,
read_restart, or create_box command. :dd
{This variable thermo keyword cannot be used between runs} :dt
Keywords that refer to time (such as cpu, elapsed) do not
make sense in between runs. :dd
{Threshhold for an atom property that isn't allocated} :dt
A dump threshhold has been requested on a quantity that is
not defined by the atom style used in this simulation. :dd
{Timestep must be >= 0} :dt
Specified timestep size is invalid. :dd
{Too big a problem to use velocity create loop all} :dt
The system size must fit in a 32-bit integer to use this option. :dd
{Too big a timestep for dump dcd} :dt
The timestep must fit in a 32-bit integer to use this dump style. :dd
{Too big a timestep for dump xtc} :dt
The timestep must fit in a 32-bit integer to use this dump style. :dd
{Too few bits for lookup table} :dt
Table size specified via pair_modify command does not work with your
machine's floating point representation. :dd
{Too many atom sorting bins} :dt
This is likely due to an immense simulation box that has blown up
to a large size. :dd
{Too many atoms for dump dcd} :dt
The system size must fit in a 32-bit integer to use this dump
style. :dd
{Too many atoms for dump xtc} :dt
The system size must fit in a 32-bit integer to use this dump
style. :dd
{Too many atoms to dump sort} :dt
Cannot sort when running with more than 2^31 atoms. :dd
{Too many exponent bits for lookup table} :dt
Table size specified via pair_modify command does not work with your
machine's floating point representation. :dd
{Too many groups} :dt
The maximum number of atom groups (including the "all" group) is
given by MAX_GROUP in group.cpp and is 32. :dd
{Too many iterations} :dt
You must use a number of iterations that fit in a 32-bit integer
for minimization. :dd
{Too many mantissa bits for lookup table} :dt
Table size specified via pair_modify command does not work with your
machine's floating point representation. :dd
{Too many masses for fix shake} :dt
The fix shake command cannot list more masses than there are atom
types. :dd
{Too many neighbor bins} :dt
This is likely due to an immense simulation box that has blown up
to a large size. :dd
{Too many timesteps for NEB} :dt
You must use a number of timesteps that fit in a 32-bit integer
for NEB. :dd
{Too many total atoms} :dt
See the setting for bigint in the src/lmptype.h file. :dd
{Too many total bits for bitmapped lookup table} :dt
Table size specified via pair_modify command is too large. Note that
a value of N generates a 2^N size table. :dd
{Too many touching neighbors - boost MAXTOUCH} :dt
A granular simulation has too many neighbors touching one atom. The
MAXTOUCH parameter in fix_shear_history.cpp must be set larger and
LAMMPS must be re-built. :dd
{Too much per-proc info for dump} :dt
Number of local atoms times number of columns must fit in a 32-bit
integer for dump. :dd
{Tree structure in joint connections} :dt
Fix poems cannot (yet) work with coupled bodies whose joints connect
the bodies in a tree structure. :dd
{Triclinic box must be periodic in skewed dimensions} :dt
This is a requirement for using a non-orthogonal box. E.g. to set a
non-zero xy tilt, both x and y must be periodic dimensions. :dd
{Triclinic box skew is too large} :dt
The displacement in a skewed direction must be less than half the box
length in that dimension. E.g. the xy tilt must be between -half and
+half of the x box length. :dd
{Tried to convert a double to int, but input_double > INT_MAX} :dt
Self-explanatory. :dd
{Two groups cannot be the same in fix spring couple} :dt
Self-explanatory. :dd
{Unbalanced quotes in input line} :dt
No matching end double quote was found following a leading double
quote. :dd
{Unexpected end of data file} :dt
LAMMPS hit the end of the data file while attempting to read a
section. Something is wrong with the format of the data file. :dd
{Units command after simulation box is defined} :dt
The units command cannot be used after a read_data, read_restart, or
create_box command. :dd
{Universe/uloop variable count < # of partitions} :dt
A universe or uloop style variable must specify a number of values >= to the
number of processor partitions. :dd
{Unknown command: %s} :dt
The command is not known to LAMMPS. Check the input script. :dd
{Unknown identifier in data file: %s} :dt
A section of the data file cannot be read by LAMMPS. :dd
{Unknown table style in angle style table} :dt
Self-explanatory. :dd
{Unknown table style in bond style table} :dt
Self-explanatory. :dd
{Unknown table style in pair_style command} :dt
Style of table is invalid for use with pair_style table command. :dd
{Unrecognized lattice type in MEAM file 1} :dt
The lattice type in an entry of the MEAM library file is not
valid. :dd
{Unrecognized lattice type in MEAM file 2} :dt
The lattice type in an entry of the MEAM parameter file is not
valid. :dd
{Unrecognized pair style in compute pair command} :dt
Self-explanatory. :dd
{Use of compute temp/ramp with undefined lattice} :dt
Must use lattice command with compute temp/ramp command if units
option is set to lattice. :dd
{Use of displace_atoms with undefined lattice} :dt
Must use lattice command with displace_atoms command if units option
is set to lattice. :dd
{Use of displace_box with undefined lattice} :dt
Must use lattice command with displace_box command if units option is
set to lattice. :dd
{Use of fix ave/spatial with undefined lattice} :dt
A lattice must be defined to use fix ave/spatial with units = lattice. :dd
{Use of fix deform with undefined lattice} :dt
A lattice must be defined to use fix deform with units = lattice. :dd
{Use of fix deposit with undefined lattice} :dt
Must use lattice command with compute fix deposit command if units
option is set to lattice. :dd
{Use of fix dt/reset with undefined lattice} :dt
Must use lattice command with fix dt/reset command if units option is
set to lattice. :dd
{Use of fix indent with undefined lattice} :dt
The lattice command must be used to define a lattice before using the
fix indent command. :dd
{Use of fix move with undefined lattice} :dt
Must use lattice command with fix move command if units option is
set to lattice. :dd
{Use of fix recenter with undefined lattice} :dt
Must use lattice command with fix recenter command if units option is
set to lattice. :dd
{Use of fix wall with undefined lattice} :dt
Must use lattice command with fix wall command if units option is set
to lattice. :dd
{Use of region with undefined lattice} :dt
If scale = lattice (the default) for the region command, then a
lattice must first be defined via the lattice command. :dd
{Use of velocity with undefined lattice} :dt
If scale = lattice (the default) for the velocity set or velocity ramp
command, then a lattice must first be defined via the lattice command. :dd
{Using fix nvt/sllod with inconsistent fix deform remap option} :dt
Fix nvt/sllod requires that deforming atoms have a velocity profile
provided by "remap v" as a fix deform option. :dd
{Using fix nvt/sllod with no fix deform defined} :dt
Self-explanatory. :dd
{Using fix srd with inconsistent fix deform remap option} :dt
When shearing the box in an SRD simulation, the remap v option for fix
deform needs to be used. :dd
{Variable evaluation before simulation box is defined} :dt
Cannot evaluate a compute or fix or atom-based value in a variable
before the simulation has been setup. :dd
{Variable for compute ti is invalid style} :dt
Self-explanatory. :dd
{Variable for dump every is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix adapt is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix addforce is invalid style} :dt
Self-explanatory. :dd
{Variable for fix aveforce is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix efield is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix indent is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix indent is not equal style} :dt
Only equal-style variables can be used. :dd
{Variable for fix move is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix setforce is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix wall is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix wall/reflect is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for fix wall/srd is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for region is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for region is not equal style} :dt
Self-explanatory. :dd
{Variable for thermo every is invalid style} :dt
Only equal-style variables can be used. :dd
{Variable for velocity set is invalid style} :dt
Only atom-style variables can be used. :dd
{Variable formula compute array is accessed out-of-range} :dt
Self-explanatory. :dd
{Variable formula compute vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Variable formula fix array is accessed out-of-range} :dt
Self-explanatory. :dd
{Variable formula fix vector is accessed out-of-range} :dt
Self-explanatory. :dd
{Variable name for compute atom/molecule does not exist} :dt
Self-explanatory. :dd
{Variable name for compute reduce does not exist} :dt
Self-explanatory. :dd
{Variable name for compute ti does not exist} :dt
Self-explanatory. :dd
{Variable name for dump every does not exist} :dt
Self-explanatory. :dd
{Variable name for fix adapt does not exist} :dt
Self-explanatory. :dd
{Variable name for fix addforce does not exist} :dt
Self-explanatory. :dd
{Variable name for fix ave/atom does not exist} :dt
Self-explanatory. :dd
{Variable name for fix ave/correlate does not exist} :dt
Self-explanatory. :dd
{Variable name for fix ave/histo does not exist} :dt
Self-explanatory. :dd
{Variable name for fix ave/spatial does not exist} :dt
Self-explanatory. :dd
{Variable name for fix ave/time does not exist} :dt
Self-explanatory. :dd
{Variable name for fix aveforce does not exist} :dt
Self-explanatory. :dd
{Variable name for fix efield does not exist} :dt
Self-explanatory. :dd
{Variable name for fix indent does not exist} :dt
Self-explanatory. :dd
{Variable name for fix move does not exist} :dt
Self-explanatory. :dd
{Variable name for fix setforce does not exist} :dt
Self-explanatory. :dd
{Variable name for fix store/state does not exist} :dt
Self-explanatory. :dd
{Variable name for fix wall does not exist} :dt
Self-explanatory. :dd
{Variable name for fix wall/reflect does not exist} :dt
Self-explanatory. :dd
{Variable name for fix wall/srd does not exist} :dt
Self-explanatory. :dd
{Variable name for region does not exist} :dt
Self-explanatory. :dd
{Variable name for thermo every does not exist} :dt
Self-explanatory. :dd
{Variable name for velocity set does not exist} :dt
Self-explanatory. :dd
{Variable name must be alphanumeric or underscore characters} :dt
Self-explanatory. :dd
{Velocity command before simulation box is defined} :dt
The velocity command cannot be used before a read_data, read_restart,
or create_box command. :dd
{Velocity command with no atoms existing} :dt
A velocity command has been used, but no atoms yet exist. :dd
{Velocity ramp in z for a 2d problem} :dt
Self-explanatory. :dd
{Velocity temperature ID does not compute temperature} :dt
The compute ID given to the velocity command must compute
temperature. :dd
{Virial was not tallied on needed timestep} :dt
You are using a thermo keyword that requires potentials to
have tallied the virial, but they didn't on this timestep. See the
variable doc page for ideas on how to make this work. :dd
{Wall defined twice in fix wall command} :dt
Self-explanatory. :dd
{Wall defined twice in fix wall/reflect command} :dt
Self-explanatory. :dd
{Wall defined twice in fix wall/srd command} :dt
Self-explanatory. :dd
{Weighted neighbor list values are too big} :dt
You must have less atoms per processor to use this
style neighbor list. :dd
{World variable count doesn't match # of partitions} :dt
A world-style variable must specify a number of values equal to the
number of processor partitions. :dd
{Write_restart command before simulation box is defined} :dt
The write_restart command cannot be used before a read_data,
read_restart, or create_box command. :dd
{Zero-length lattice orient vector} :dt
Self-explanatory. :dd
:dle
Warnings: :h4,link(warn)
:dlb
{All element names have been set to 'C' for dump cfg} :dt
Use the dump_modify command if you wish to override this. :dd
{Atom with molecule ID = 0 included in compute molecule group} :dt
The group used in a compute command that operates on moleclues
includes atoms with no molecule ID. This is probably not what you
want. :dd
{Broken bonds will not alter angles, dihedrals, or impropers} :dt
See the doc page for fix bond/break for more info on this
restriction. :dd
{Building an occasional neighobr list when atoms may have moved too far} :dt
This can cause LAMMPS to crash when the neighbor list is built.
The solution is to check for building the regular neighbor lists
more frequently. :dd
{Compute cna/atom cutoff may be too large to find ghost atom neighbors} :dt
The neighbor cutoff used may not encompass enough ghost atoms
to perform this operation correctly. :dd
{Computing temperature of portions of rigid bodies} :dt
The group defined by the temperature compute does not encompass all
the atoms in one or more rigid bodies, so the change in
degrees-of-freedom for the atoms in those partial rigid bodies will
not be accounted for. :dd
{Created bonds will not create angles, dihedrals, or impropers} :dt
See the doc page for fix bond/create for more info on this
restriction. :dd
{Dihedral problem: %d %d %d %d %d %d} :dt
Conformation of the 4 listed dihedral atoms is extreme; you may want
to check your simulation geometry. :dd
{Dump dcd/xtc timestamp may be wrong with fix dt/reset} :dt
If the fix changes the timestep, the dump dcd file will not
reflect the change. :dd
{FENE bond too long: %d %d %d %g} :dt
A FENE bond has stretched dangerously far. It's interaction strength
will be truncated to attempt to prevent the bond from blowing up. :dd
{FENE bond too long: %d %g} :dt
A FENE bond has stretched dangerously far. It's interaction strength
will be truncated to attempt to prevent the bond from blowing up. :dd
{Fix SRD walls overlap but fix srd overlap not set} :dt
You likely want to set this in your input script. :dd
{Fix bond/swap will ignore defined angles} :dt
See the doc page for fix bond/swap for more info on this
restriction. :dd
{Fix move does not update angular momentum} :dt
Atoms store this quantity, but fix move does not (yet) update it. :dd
{Fix move does not update quaternions} :dt
Atoms store this quantity, but fix move does not (yet) update it. :dd
{Fix recenter should come after all other integration fixes} :dt
Other fixes may change the position of the center-of-mass, so
fix recenter should come last. :dd
{Fix srd SRD moves may trigger frequent reneighboring} :dt
This is because the SRD particles may move long distances. :dd
{Fix srd grid size > 1/4 of big particle diameter} :dt
This may cause accuracy problems. :dd
{Fix srd no-slip wall collisions with bin shifting} :dt
This is an inconsistent setting in your input script. :dd
{Fix srd particle moved outside valid domain} :dt
This may indicate a problem with your simulation parameters. :dd
{Fix srd particles may move > big particle diameter} :dt
This may cause accuracy problems. :dd
{Fix srd viscosity < 0.0 due to low SRD density} :dt
This may cause accuracy problems. :dd
{Fix thermal/conductivity comes before fix ave/spatial} :dt
The order of these 2 fixes in your input script is such that fix
thermal/conductivity comes first. If you are using fix ave/spatial to
measure the temperature profile induced by fix viscosity, then this
may cause a glitch in the profile since you are averaging immediately
after swaps have occurred. Flipping the order of the 2 fixes
typically helps. :dd
{Fix viscosity comes before fix ave/spatial} :dt
The order of these 2 fixes in your input script is such that
fix viscosity comes first. If you are using fix ave/spatial
to measure the velocity profile induced by fix viscosity, then
this may cause a glitch in the profile since you are averaging
immediately after swaps have occurred. Flipping the order
of the 2 fixes typically helps. :dd
{Group for fix_modify temp != fix group} :dt
The fix_modify command is specifying a temperature computation that
computes a temperature on a different group of atoms than the fix
itself operates on. This is probably not what you want to do. :dd
{Improper problem: %d %d %d %d %d %d} :dt
Conformation of the 4 listed improper atoms is extreme; you may want
to check your simulation geometry. :dd
{Kspace_modify slab param < 2.0 may cause unphysical behavior} :dt
The kspace_modify slab parameter should be larger to insure periodic
grids padded with empty space do not overlap. :dd
{Less insertions than requested} :dt
Less atom insertions occurred on this timestep due to the fix pour
command than were scheduled. This is probably because there were too
many overlaps detected. :dd
{Lost atoms: original %.15g current %.15g} :dt
A thermodynamic computation has detected lost atoms. :dd
{Mismatch between velocity and compute groups} :dt
The temperature computation used by the velocity command will not be
on the same group of atoms that velocities are being set for. :dd
{More than one compute centro/atom} :dt
It is not efficient to use compute centro/atom more than once. :dd
{More than one compute cluster/atom} :dt
It is not efficient to use compute cluster/atom more than once. :dd
{More than one compute cna/atom defined} :dt
It is not efficient to use compute cna/atom more than once. :dd
{More than one compute coord/atom} :dt
It is not efficient to use compute coord/atom more than once. :dd
{More than one compute damage/atom} :dt
It is not efficient to use compute ke/atom more than once. :dd
{More than one compute ke/atom} :dt
It is not efficient to use compute ke/atom more than once. :dd
{More than one fix poems} :dt
It is not efficient to use fix poems more than once. :dd
{More than one fix rigid} :dt
It is not efficient to use fix rigid more than once. :dd
{New thermo_style command, previous thermo_modify settings will be lost} :dt
If a thermo_style command is used after a thermo_modify command, the
settings changed by the thermo_modify command will be reset to their
default values. This is because the thermo_modify commmand acts on
the currently defined thermo style, and a thermo_style command creates
a new style. :dd
{No fixes defined, atoms won't move} :dt
If you are not using a fix like nve, nvt, npt then atom velocities and
coordinates will not be updated during timestepping. :dd
{No joints between rigid bodies, use fix rigid instead} :dt
The bodies defined by fix poems are not connected by joints. POEMS
will integrate the body motion, but it would be more efficient to use
fix rigid. :dd
{Not using real units with pair reax} :dt
This is most likely an error, unless you have created your own ReaxFF
parameter file in a different set of units. :dd
{One or more atoms are time integrated more than once} :dt
This is probably an error since you typically do not want to
advance the positions or velocities of an atom more than once
per timestep. :dd
{One or more compute molecules has atoms not in group} :dt
The group used in a compute command that operates on moleclues does
not include all the atoms in some molecules. This is probably not
what you want. :dd
{One or more respa levels compute no forces} :dt
This is computationally inefficient. :dd
{Pair COMB charge %.10f with force %.10f hit max barrier} :dt
Something is possibly wrong with your model. :dd
{Pair COMB charge %.10f with force %.10f hit min barrier} :dt
Something is possibly wrong with your model. :dd
{Pair dsmc: num_of_collisions > number_of_A} :dt
Collision model in DSMC is breaking down. :dd
{Pair dsmc: num_of_collisions > number_of_B} :dt
Collision model in DSMC is breaking down. :dd
{Particle deposition was unsuccessful} :dt
The fix deposit command was not able to insert as many atoms as
needed. The requested volume fraction may be too high, or other atoms
may be in the insertion region. :dd
{Reducing PPPM order b/c stencil extends beyond neighbor processor} :dt
LAMMPS is attempting this in order to allow the simulation
to run. It should not effect the PPPM accuracy. :dd
{Replacing a fix, but new group != old group} :dt
The ID and style of a fix match for a fix you are changing with a fix
command, but the new group you are specifying does not match the old
group. :dd
{Replicating in a non-periodic dimension} :dt
The parameters for a replicate command will cause a non-periodic
dimension to be replicated; this may cause unwanted behavior. :dd
{Resetting reneighboring criteria during PRD} :dt
A PRD simulation requires that neigh_modify settings be delay = 0,
every = 1, check = yes. Since these settings were not in place,
LAMMPS changed them and will restore them to their original values
after the PRD simulation. :dd
{Resetting reneighboring criteria during TAD} :dt
A TAD simulation requires that neigh_modify settings be delay = 0,
every = 1, check = yes. Since these settings were not in place,
LAMMPS changed them and will restore them to their original values
after the PRD simulation. :dd
{Resetting reneighboring criteria during minimization} :dt
Minimization requires that neigh_modify settings be delay = 0, every =
1, check = yes. Since these settings were not in place, LAMMPS
changed them and will restore them to their original values after the
minimization. :dd
{Restart file used different # of processors} :dt
The restart file was written out by a LAMMPS simulation running on a
different number of processors. Due to round-off, the trajectories of
your restarted simulation may diverge a little more quickly than if
you ran on the same # of processors. :dd
{Restart file used different 3d processor grid} :dt
The restart file was written out by a LAMMPS simulation running on a
different 3d grid of processors. Due to round-off, the trajectories
of your restarted simulation may diverge a little more quickly than if
you ran on the same # of processors. :dd
{Restart file used different boundary settings, using restart file values} :dt
Your input script cannot change these restart file settings. :dd
{Restart file used different newton bond setting, using restart file value} :dt
The restart file value will override the setting in the input script. :dd
{Restart file used different newton pair setting, using input script value} :dt
The input script value will override the setting in the restart file. :dd
{Restart file version does not match LAMMPS version} :dt
This may cause problems when reading the restart file. :dd
{Running PRD with only one replica} :dt
This is allowed, but you will get no parallel speed-up. :dd
{SRD bin shifting turned on due to small lamda} :dt
This is done to try to preserve accuracy. :dd
{SRD bin size for fix srd differs from user request} :dt
Check if the new bin size is acceptable. :dd
{SRD bins for fix srd are not cubic enough} :dt
Check if the bin shape is acceptable. :dd
{SRD particle %d started inside big particle %d on step %d bounce %d} :dt
This may not be a problem, but indicates one or more SRD particles are
being left inside solute particles. :dd
{Shake determinant < 0.0} :dt
The determinant of the quadratic equation being solved for a single
cluster specified by the fix shake command is numerically suspect. LAMMPS
will set it to 0.0 and continue. :dd
{Should not allow rigid bodies to bounce off relecting walls} :dt
LAMMPS allows this, but their dynamics are not computed correctly. :dd
{System is not charge neutral, net charge = %g} :dt
The total charge on all atoms on the system is not 0.0, which
is not valid for Ewald or PPPM. :dd
{Table inner cutoff >= outer cutoff} :dt
You specified an inner cutoff for a Coulombic table that is longer
than the global cutoff. Probably not what you wanted. :dd
{Temperature for MSST is not for group all} :dt
User-assigned temperature to MSST fix does not compute temperature for
all atoms. Since MSST computes a global pressure, the kinetic energy
contribution from the temperature is assumed to also be for all atoms.
Thus the pressure used by MSST could be inaccurate. :dd
{Temperature for NPT is not for group all} :dt
User-assigned temperature to NPT fix does not compute temperature for
all atoms. Since NPT computes a global pressure, the kinetic energy
contribution from the temperature is assumed to also be for all atoms.
Thus the pressure used by NPT could be inaccurate. :dd
{Temperature for fix modify is not for group all} :dt
The temperature compute is being used with a pressure calculation
which does operate on group all, so this may be inconsistent. :dd
{Temperature for thermo pressure is not for group all} :dt
User-assigned temperature to thermo via the thermo_modify command does
not compute temperature for all atoms. Since thermo computes a global
pressure, the kinetic energy contribution from the temperature is
assumed to also be for all atoms. Thus the pressure printed by thermo
could be inaccurate. :dd
{Too many common neighbors in CNA %d times} :dt
More than the maximum # of neighbors was found multiple times. This
was unexpected. :dd
{Too many inner timesteps in fix ttm} :dt
Self-explanatory. :dd
{Too many neighbors in CNA for %d atoms} :dt
More than the maximum # of neighbors was found multiple times. This
was unexpected. :dd
{Use special bonds = 0,1,1 with bond style fene/expand} :dt
Most FENE models need this setting for the special_bonds command. :dd
{Use special bonds = 0,1,1 with bond style fene} :dt
Most FENE models need this setting for the special_bonds command. :dd
{Using compute temp/deform with inconsistent fix deform remap option} :dt
Fix nvt/sllod assumes deforming atoms have a velocity profile provided
by "remap v" or "remap none" as a fix deform option. :dd
{Using compute temp/deform with no fix deform defined} :dt
This is probably an error, since it makes little sense to use
compute temp/deform in this case. :dd
{Using pair tail corrections with nonperiodic system} :dt
This is probably a bogus thing to do, since tail corrections are
computed by integrating the density of a periodic system out to
infinity. :dd
:dle
diff --git a/src/ASPHERE/compute_erotate_asphere.cpp b/src/ASPHERE/compute_erotate_asphere.cpp
index 31d500c4a..80c4083a9 100644
--- a/src/ASPHERE/compute_erotate_asphere.cpp
+++ b/src/ASPHERE/compute_erotate_asphere.cpp
@@ -1,111 +1,111 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "compute_erotate_asphere.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "update.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeERotateAsphere::
ComputeERotateAsphere(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute erotate/asphere command");
+ if (narg != 3) error->all(FLERR,"Illegal compute erotate/asphere command");
scalar_flag = 1;
extscalar = 1;
// error check
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
if (!avec)
- error->all("Compute erotate/asphere requires atom style ellipsoid");
+ error->all(FLERR,"Compute erotate/asphere requires atom style ellipsoid");
}
/* ---------------------------------------------------------------------- */
void ComputeERotateAsphere::init()
{
// check that all particles are finite-size
// no point particles allowed, spherical is OK
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (ellipsoid[i] < 0)
- error->one("Compute erotate/asphere requires extended particles");
+ error->one(FLERR,"Compute erotate/asphere requires extended particles");
pfactor = 0.5 * force->mvv2e;
}
/* ---------------------------------------------------------------------- */
double ComputeERotateAsphere::compute_scalar()
{
invoked_scalar = update->ntimestep;
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// sum rotational energy for each particle
// no point particles since divide by inertia
double *shape,*quat;
double wbody[3],inertia[3];
double rot[3][3];
double erotate = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
shape = bonus[ellipsoid[i]].shape;
quat = bonus[ellipsoid[i]].quat;
// principal moments of inertia
inertia[0] = rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]) / 5.0;
inertia[1] = rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]) / 5.0;
inertia[2] = rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]) / 5.0;
// wbody = angular velocity in body frame
MathExtra::quat_to_mat(quat,rot);
MathExtra::transpose_matvec(rot,angmom[i],wbody);
wbody[0] /= inertia[0];
wbody[1] /= inertia[1];
wbody[2] /= inertia[2];
erotate += inertia[0]*wbody[0]*wbody[0] +
inertia[1]*wbody[1]*wbody[1] + inertia[2]*wbody[2]*wbody[2];
}
MPI_Allreduce(&erotate,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
scalar *= pfactor;
return scalar;
}
diff --git a/src/ASPHERE/compute_temp_asphere.cpp b/src/ASPHERE/compute_temp_asphere.cpp
index b4fb8c79f..69139369c 100755
--- a/src/ASPHERE/compute_temp_asphere.cpp
+++ b/src/ASPHERE/compute_temp_asphere.cpp
@@ -1,381 +1,381 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_temp_asphere.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{ROTATE,ALL};
#define INERTIA 0.2 // moment of inertia prefactor for ellipsoid
/* ---------------------------------------------------------------------- */
ComputeTempAsphere::ComputeTempAsphere(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal compute temp/asphere command");
+ if (narg < 3) error->all(FLERR,"Illegal compute temp/asphere command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 0;
id_bias = NULL;
mode = ALL;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"bias") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute temp/asphere command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/asphere command");
tempbias = 1;
int n = strlen(arg[iarg+1]) + 1;
id_bias = new char[n];
strcpy(id_bias,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"dof") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute temp/asphere command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/asphere command");
if (strcmp(arg[iarg+1],"rotate") == 0) mode = ROTATE;
else if (strcmp(arg[iarg+1],"all") == 0) mode = ALL;
- else error->all("Illegal compute temp/asphere command");
+ else error->all(FLERR,"Illegal compute temp/asphere command");
iarg += 2;
- } else error->all("Illegal compute temp/asphere command");
+ } else error->all(FLERR,"Illegal compute temp/asphere command");
}
vector = new double[6];
// error check
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
if (!avec)
- error->all("Compute temp/asphere requires atom style ellipsoid");
+ error->all(FLERR,"Compute temp/asphere requires atom style ellipsoid");
}
/* ---------------------------------------------------------------------- */
ComputeTempAsphere::~ComputeTempAsphere()
{
delete [] id_bias;
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempAsphere::init()
{
// check that all particles are finite-size, no point particles allowed
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (ellipsoid[i] < 0)
- error->one("Compute temp/asphere requires extended particles");
+ error->one(FLERR,"Compute temp/asphere requires extended particles");
if (tempbias) {
int i = modify->find_compute(id_bias);
- if (i < 0) error->all("Could not find compute ID for temperature bias");
+ if (i < 0) error->all(FLERR,"Could not find compute ID for temperature bias");
tbias = modify->compute[i];
if (tbias->tempflag == 0)
- error->all("Bias compute does not calculate temperature");
+ error->all(FLERR,"Bias compute does not calculate temperature");
if (tbias->tempbias == 0)
- error->all("Bias compute does not calculate a velocity bias");
+ error->all(FLERR,"Bias compute does not calculate a velocity bias");
if (tbias->igroup != igroup)
- error->all("Bias compute group does not match compute group");
+ error->all(FLERR,"Bias compute group does not match compute group");
tbias->init();
if (strcmp(tbias->style,"temp/region") == 0) tempbias = 2;
else tempbias = 1;
}
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ---------------------------------------------------------------------- */
void ComputeTempAsphere::dof_compute()
{
// 6 dof for 3d, 3 dof for 2d
// which dof are included also depends on mode
// assume full rotation of extended particles
// user should correct this via compute_modify if needed
double natoms = group->count(igroup);
int nper;
if (domain->dimension == 3) {
if (mode == ALL) nper = 6;
else nper = 3;
} else {
if (mode == ALL) nper = 3;
else nper = 1;
}
dof = nper*natoms;
// additional adjustments to dof
if (tempbias == 1) {
if (mode == ALL) dof -= tbias->dof_remove(-1) * natoms;
} else if (tempbias == 2) {
int *mask = atom->mask;
int nlocal = atom->nlocal;
int count = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (tbias->dof_remove(i)) count++;
int count_all;
MPI_Allreduce(&count,&count_all,1,MPI_INT,MPI_SUM,world);
dof -= nper*count_all;
}
dof -= extra_dof + fix_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempAsphere::compute_scalar()
{
invoked_scalar = update->ntimestep;
if (tempbias) {
if (tbias->invoked_scalar != update->ntimestep) tbias->compute_scalar();
tbias->remove_bias_all();
}
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
double **v = atom->v;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *shape,*quat;
double wbody[3],inertia[3];
double rot[3][3];
// sum translational and rotational energy for each particle
// no point particles since divide by inertia
double t = 0.0;
if (mode == ALL) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * rmass[i];
// principal moments of inertia
shape = bonus[ellipsoid[i]].shape;
quat = bonus[ellipsoid[i]].quat;
inertia[0] = INERTIA*rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]);
inertia[1] = INERTIA*rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = INERTIA*rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]);
// wbody = angular velocity in body frame
MathExtra::quat_to_mat(quat,rot);
MathExtra::transpose_matvec(rot,angmom[i],wbody);
wbody[0] /= inertia[0];
wbody[1] /= inertia[1];
wbody[2] /= inertia[2];
t += inertia[0]*wbody[0]*wbody[0] +
inertia[1]*wbody[1]*wbody[1] + inertia[2]*wbody[2]*wbody[2];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
// principal moments of inertia
shape = bonus[ellipsoid[i]].shape;
quat = bonus[ellipsoid[i]].quat;
inertia[0] = INERTIA*rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]);
inertia[1] = INERTIA*rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = INERTIA*rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]);
// wbody = angular velocity in body frame
MathExtra::quat_to_mat(quat,rot);
MathExtra::transpose_matvec(rot,angmom[i],wbody);
wbody[0] /= inertia[0];
wbody[1] /= inertia[1];
wbody[2] /= inertia[2];
t += inertia[0]*wbody[0]*wbody[0] +
inertia[1]*wbody[1]*wbody[1] + inertia[2]*wbody[2]*wbody[2];
}
}
if (tempbias) tbias->restore_bias_all();
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic || tempbias == 2) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempAsphere::compute_vector()
{
int i;
invoked_vector = update->ntimestep;
if (tempbias) {
if (tbias->invoked_vector != update->ntimestep) tbias->compute_vector();
tbias->remove_bias_all();
}
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
double **v = atom->v;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *shape,*quat;
double wbody[3],inertia[3],t[6];
double rot[3][3];
double massone;
// sum translational and rotational energy for each particle
// no point particles since divide by inertia
for (i = 0; i < 6; i++) t[i] = 0.0;
if (mode == ALL) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = rmass[i];
t[0] += massone * v[i][0]*v[i][0];
t[1] += massone * v[i][1]*v[i][1];
t[2] += massone * v[i][2]*v[i][2];
t[3] += massone * v[i][0]*v[i][1];
t[4] += massone * v[i][0]*v[i][2];
t[5] += massone * v[i][1]*v[i][2];
// principal moments of inertia
shape = bonus[ellipsoid[i]].shape;
quat = bonus[ellipsoid[i]].quat;
inertia[0] = INERTIA*massone * (shape[1]*shape[1]+shape[2]*shape[2]);
inertia[1] = INERTIA*massone * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = INERTIA*massone * (shape[0]*shape[0]+shape[1]*shape[1]);
// wbody = angular velocity in body frame
MathExtra::quat_to_mat(quat,rot);
MathExtra::transpose_matvec(rot,angmom[i],wbody);
wbody[0] /= inertia[0];
wbody[1] /= inertia[1];
wbody[2] /= inertia[2];
// rotational kinetic energy
t[0] += inertia[0]*wbody[0]*wbody[0];
t[1] += inertia[1]*wbody[1]*wbody[1];
t[2] += inertia[2]*wbody[2]*wbody[2];
t[3] += inertia[0]*wbody[0]*wbody[1];
t[4] += inertia[1]*wbody[0]*wbody[2];
t[5] += inertia[2]*wbody[1]*wbody[2];
}
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
// principal moments of inertia
shape = bonus[ellipsoid[i]].shape;
quat = bonus[ellipsoid[i]].quat;
massone = rmass[i];
inertia[0] = INERTIA*massone * (shape[1]*shape[1]+shape[2]*shape[2]);
inertia[1] = INERTIA*massone * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = INERTIA*massone * (shape[0]*shape[0]+shape[1]*shape[1]);
// wbody = angular velocity in body frame
MathExtra::quat_to_mat(quat,rot);
MathExtra::transpose_matvec(rot,angmom[i],wbody);
wbody[0] /= inertia[0];
wbody[1] /= inertia[1];
wbody[2] /= inertia[2];
// rotational kinetic energy
t[0] += inertia[0]*wbody[0]*wbody[0];
t[1] += inertia[1]*wbody[1]*wbody[1];
t[2] += inertia[2]*wbody[2]*wbody[2];
t[3] += inertia[0]*wbody[0]*wbody[1];
t[4] += inertia[1]*wbody[0]*wbody[2];
t[5] += inertia[2]*wbody[1]*wbody[2];
}
}
if (tempbias) tbias->restore_bias_all();
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempAsphere::remove_bias(int i, double *v)
{
if (tbias) tbias->remove_bias(i,v);
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempAsphere::restore_bias(int i, double *v)
{
if (tbias) tbias->restore_bias(i,v);
}
diff --git a/src/ASPHERE/fix_nh_asphere.cpp b/src/ASPHERE/fix_nh_asphere.cpp
index bc58472bb..3d9126234 100644
--- a/src/ASPHERE/fix_nh_asphere.cpp
+++ b/src/ASPHERE/fix_nh_asphere.cpp
@@ -1,161 +1,161 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "math_extra.h"
#include "fix_nh_asphere.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNHAsphere::FixNHAsphere(LAMMPS *lmp, int narg, char **arg) :
FixNH(lmp, narg, arg)
{
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
if (!avec)
- error->all("Compute nvt/nph/npt asphere requires atom style ellipsoid");
+ error->all(FLERR,"Compute nvt/nph/npt asphere requires atom style ellipsoid");
}
/* ---------------------------------------------------------------------- */
void FixNHAsphere::init()
{
// check that all particles are finite-size
// no point particles allowed, spherical is OK
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (ellipsoid[i] < 0)
- error->one("Fix nvt/nph/npt asphere requires extended particles");
+ error->one(FLERR,"Fix nvt/nph/npt asphere requires extended particles");
FixNH::init();
}
/* ----------------------------------------------------------------------
perform half-step update of angular momentum
-----------------------------------------------------------------------*/
void FixNHAsphere::nve_v()
{
// standard nve_v velocity update
FixNH::nve_v();
double **angmom = atom->angmom;
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// update angular momentum by 1/2 step for all particles
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
angmom[i][0] += dtf*torque[i][0];
angmom[i][1] += dtf*torque[i][1];
angmom[i][2] += dtf*torque[i][2];
}
}
}
/* ----------------------------------------------------------------------
perform full-step update of orientation
-----------------------------------------------------------------------*/
void FixNHAsphere::nve_x()
{
double omega[3];
// standard nve_x position update
FixNH::nve_x();
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// set timestep here since dt may have changed or come via rRESPA
dtq = 0.5 * dtv;
// update quaternion a full step via Richardson iteration
// returns new normalized quaternion
// principal moments of inertia
double *shape,*quat;
double inertia[3];
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
// principal moments of inertia
shape = bonus[ellipsoid[i]].shape;
quat = bonus[ellipsoid[i]].quat;
inertia[0] = rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]) / 5.0;
inertia[1] = rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]) / 5.0;
inertia[2] = rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]) / 5.0;
// compute omega at 1/2 step from angmom at 1/2 step and current q
// update quaternion a full step via Richardson iteration
// returns new normalized quaternion
MathExtra::mq_to_omega(angmom[i],quat,inertia,omega);
MathExtra::richardson(quat,angmom[i],omega,inertia,dtq);
}
}
/* ----------------------------------------------------------------------
perform half-step temperature scaling of angular momentum
-----------------------------------------------------------------------*/
void FixNHAsphere::nh_v_temp()
{
// standard nh_v_temp scaling
FixNH::nh_v_temp();
double **angmom = atom->angmom;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
angmom[i][0] *= factor_eta;
angmom[i][1] *= factor_eta;
angmom[i][2] *= factor_eta;
}
}
}
diff --git a/src/ASPHERE/fix_nph_asphere.cpp b/src/ASPHERE/fix_nph_asphere.cpp
index 025137def..094e0f06a 100644
--- a/src/ASPHERE/fix_nph_asphere.cpp
+++ b/src/ASPHERE/fix_nph_asphere.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_nph_asphere.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPHAsphere::FixNPHAsphere(LAMMPS *lmp, int narg, char **arg) :
FixNHAsphere(lmp, narg, arg)
{
if (tstat_flag)
- error->all("Temperature control can not be used with fix nph/asphere");
+ error->all(FLERR,"Temperature control can not be used with fix nph/asphere");
if (!pstat_flag)
- error->all("Pressure control must be used with fix nph/asphere");
+ error->all(FLERR,"Pressure control must be used with fix nph/asphere");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp/asphere";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/ASPHERE/fix_npt_asphere.cpp b/src/ASPHERE/fix_npt_asphere.cpp
index 44ed01ea4..2c3c70e94 100755
--- a/src/ASPHERE/fix_npt_asphere.cpp
+++ b/src/ASPHERE/fix_npt_asphere.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_npt_asphere.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPTAsphere::FixNPTAsphere(LAMMPS *lmp, int narg, char **arg) :
FixNHAsphere(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix npt/asphere");
+ error->all(FLERR,"Temperature control must be used with fix npt/asphere");
if (!pstat_flag)
- error->all("Pressure control must be used with fix npt/asphere");
+ error->all(FLERR,"Pressure control must be used with fix npt/asphere");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp/asphere";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/ASPHERE/fix_nve_asphere.cpp b/src/ASPHERE/fix_nve_asphere.cpp
index e078d2fb7..17ae8950e 100755
--- a/src/ASPHERE/fix_nve_asphere.cpp
+++ b/src/ASPHERE/fix_nve_asphere.cpp
@@ -1,147 +1,147 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "string.h"
#include "fix_nve_asphere.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define INERTIA 0.2 // moment of inertia prefactor for ellipsoid
/* ---------------------------------------------------------------------- */
FixNVEAsphere::FixNVEAsphere(LAMMPS *lmp, int narg, char **arg) :
FixNVE(lmp, narg, arg)
{
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
if (!avec)
- error->all("Compute nve/asphere requires atom style ellipsoid");
+ error->all(FLERR,"Compute nve/asphere requires atom style ellipsoid");
}
/* ---------------------------------------------------------------------- */
void FixNVEAsphere::init()
{
// check that all particles are finite-size
// no point particles allowed, spherical is OK
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (ellipsoid[i] < 0)
- error->one("Fix nve/asphere requires extended particles");
+ error->one(FLERR,"Fix nve/asphere requires extended particles");
FixNVE::init();
}
/* ---------------------------------------------------------------------- */
void FixNVEAsphere::initial_integrate(int vflag)
{
double dtfm;
double inertia[3],omega[3];
double *shape,*quat;
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **angmom = atom->angmom;
double **torque = atom->torque;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// set timestep here since dt may have changed or come via rRESPA
dtq = 0.5 * dtv;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
// update angular momentum by 1/2 step
angmom[i][0] += dtf * torque[i][0];
angmom[i][1] += dtf * torque[i][1];
angmom[i][2] += dtf * torque[i][2];
// principal moments of inertia
shape = bonus[ellipsoid[i]].shape;
quat = bonus[ellipsoid[i]].quat;
inertia[0] = INERTIA*rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]);
inertia[1] = INERTIA*rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = INERTIA*rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]);
// compute omega at 1/2 step from angmom at 1/2 step and current q
// update quaternion a full step via Richardson iteration
// returns new normalized quaternion
MathExtra::mq_to_omega(angmom[i],quat,inertia,omega);
MathExtra::richardson(quat,angmom[i],omega,inertia,dtq);
}
}
/* ---------------------------------------------------------------------- */
void FixNVEAsphere::final_integrate()
{
double dtfm;
double **v = atom->v;
double **f = atom->f;
double **angmom = atom->angmom;
double **torque = atom->torque;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
angmom[i][0] += dtf * torque[i][0];
angmom[i][1] += dtf * torque[i][1];
angmom[i][2] += dtf * torque[i][2];
}
}
diff --git a/src/ASPHERE/fix_nvt_asphere.cpp b/src/ASPHERE/fix_nvt_asphere.cpp
index 4137941be..8578da033 100755
--- a/src/ASPHERE/fix_nvt_asphere.cpp
+++ b/src/ASPHERE/fix_nvt_asphere.cpp
@@ -1,48 +1,48 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_nvt_asphere.h"
#include "group.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVTAsphere::FixNVTAsphere(LAMMPS *lmp, int narg, char **arg) :
FixNHAsphere(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix nvt/asphere");
+ error->all(FLERR,"Temperature control must be used with fix nvt/asphere");
if (pstat_flag)
- error->all("Pressure control can not be used with fix nvt/asphere");
+ error->all(FLERR,"Pressure control can not be used with fix nvt/asphere");
// create a new compute temp style
// id = fix-ID + temp
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/asphere";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
diff --git a/src/ASPHERE/pair_gayberne.cpp b/src/ASPHERE/pair_gayberne.cpp
index 97a7bc56b..19dfdecde 100755
--- a/src/ASPHERE/pair_gayberne.cpp
+++ b/src/ASPHERE/pair_gayberne.cpp
@@ -1,915 +1,912 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_gayberne.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
using namespace LAMMPS_NS;
enum{SPHERE_SPHERE,SPHERE_ELLIPSE,ELLIPSE_SPHERE,ELLIPSE_ELLIPSE};
/* ---------------------------------------------------------------------- */
PairGayBerne::PairGayBerne(LAMMPS *lmp) : Pair(lmp)
{
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Pair gayberne requires atom style ellipsoid");
+ if (!avec) error->all(FLERR,"Pair gayberne requires atom style ellipsoid");
single_enable = 0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairGayBerne::~PairGayBerne()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(form);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(shape1);
memory->destroy(shape2);
memory->destroy(well);
memory->destroy(cut);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
delete [] lshape;
delete [] setwell;
}
}
/* ---------------------------------------------------------------------- */
void PairGayBerne::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double evdwl,one_eng,rsq,r2inv,r6inv,forcelj,factor_lj;
double fforce[3],ttor[3],rtor[3],r12[3];
double a1[3][3],b1[3][3],g1[3][3],a2[3][3],b2[3][3],g2[3][3],temp[3][3];
int *ilist,*jlist,*numneigh,**firstneigh;
double *iquat,*jquat;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
double **x = atom->x;
double **f = atom->f;
double **tor = atom->torque;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
if (form[itype][itype] == ELLIPSE_ELLIPSE) {
iquat = bonus[ellipsoid[i]].quat;
MathExtra::quat_to_mat_trans(iquat,a1);
MathExtra::diag_times3(well[itype],a1,temp);
MathExtra::transpose_times3(a1,temp,b1);
MathExtra::diag_times3(shape2[itype],a1,temp);
MathExtra::transpose_times3(a1,temp,g1);
}
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
// r12 = center to center vector
r12[0] = x[j][0]-x[i][0];
r12[1] = x[j][1]-x[i][1];
r12[2] = x[j][2]-x[i][2];
rsq = MathExtra::dot3(r12,r12);
jtype = type[j];
// compute if less than cutoff
if (rsq < cutsq[itype][jtype]) {
switch (form[itype][jtype]) {
case SPHERE_SPHERE:
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
forcelj *= -r2inv;
if (eflag) one_eng =
r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) -
offset[itype][jtype];
fforce[0] = r12[0]*forcelj;
fforce[1] = r12[1]*forcelj;
fforce[2] = r12[2]*forcelj;
ttor[0] = ttor[1] = ttor[2] = 0.0;
rtor[0] = rtor[1] = rtor[2] = 0.0;
break;
case SPHERE_ELLIPSE:
jquat = bonus[ellipsoid[j]].quat;
MathExtra::quat_to_mat_trans(jquat,a2);
MathExtra::diag_times3(well[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,b2);
MathExtra::diag_times3(shape2[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,g2);
one_eng = gayberne_lj(j,i,a2,b2,g2,r12,rsq,fforce,rtor);
ttor[0] = ttor[1] = ttor[2] = 0.0;
break;
case ELLIPSE_SPHERE:
one_eng = gayberne_lj(i,j,a1,b1,g1,r12,rsq,fforce,ttor);
rtor[0] = rtor[1] = rtor[2] = 0.0;
break;
default:
jquat = bonus[ellipsoid[j]].quat;
MathExtra::quat_to_mat_trans(jquat,a2);
MathExtra::diag_times3(well[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,b2);
MathExtra::diag_times3(shape2[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,g2);
one_eng = gayberne_analytic(i,j,a1,a2,b1,b2,g1,g2,r12,rsq,
fforce,ttor,rtor);
break;
}
fforce[0] *= factor_lj;
fforce[1] *= factor_lj;
fforce[2] *= factor_lj;
ttor[0] *= factor_lj;
ttor[1] *= factor_lj;
ttor[2] *= factor_lj;
f[i][0] += fforce[0];
f[i][1] += fforce[1];
f[i][2] += fforce[2];
tor[i][0] += ttor[0];
tor[i][1] += ttor[1];
tor[i][2] += ttor[2];
if (newton_pair || j < nlocal) {
rtor[0] *= factor_lj;
rtor[1] *= factor_lj;
rtor[2] *= factor_lj;
f[j][0] -= fforce[0];
f[j][1] -= fforce[1];
f[j][2] -= fforce[2];
tor[j][0] += rtor[0];
tor[j][1] += rtor[1];
tor[j][2] += rtor[2];
}
if (eflag) evdwl = factor_lj*one_eng;
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,
evdwl,0.0,fforce[0],fforce[1],fforce[2],
-r12[0],-r12[1],-r12[2]);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairGayBerne::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(form,n+1,n+1,"pair:form");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(shape1,n+1,3,"pair:shape1");
memory->create(shape2,n+1,3,"pair:shape2");
memory->create(well,n+1,3,"pair:well");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
lshape = new double[n+1];
setwell = new int[n+1];
for (int i = 1; i <= n; i++) setwell[i] = 0;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairGayBerne::settings(int narg, char **arg)
{
- if (narg != 4) error->all("Illegal pair_style command");
+ if (narg != 4) error->all(FLERR,"Illegal pair_style command");
gamma = force->numeric(arg[0]);
upsilon = force->numeric(arg[1])/2.0;
mu = force->numeric(arg[2]);
cut_global = force->numeric(arg[3]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairGayBerne::coeff(int narg, char **arg)
{
if (narg < 10 || narg > 11)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double eia_one = force->numeric(arg[4]);
double eib_one = force->numeric(arg[5]);
double eic_one = force->numeric(arg[6]);
double eja_one = force->numeric(arg[7]);
double ejb_one = force->numeric(arg[8]);
double ejc_one = force->numeric(arg[9]);
double cut_one = cut_global;
if (narg == 11) cut_one = force->numeric(arg[10]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut[i][j] = cut_one;
if (eia_one != 0.0 || eib_one != 0.0 || eic_one != 0.0) {
well[i][0] = pow(eia_one,-1.0/mu);
well[i][1] = pow(eib_one,-1.0/mu);
well[i][2] = pow(eic_one,-1.0/mu);
if (eia_one == eib_one && eib_one == eic_one) setwell[i] = 2;
else setwell[i] = 1;
}
if (eja_one != 0.0 || ejb_one != 0.0 || ejc_one != 0.0) {
well[j][0] = pow(eja_one,-1.0/mu);
well[j][1] = pow(ejb_one,-1.0/mu);
well[j][2] = pow(ejc_one,-1.0/mu);
if (eja_one == ejb_one && ejb_one == ejc_one) setwell[j] = 2;
else setwell[j] = 1;
}
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairGayBerne::init_style()
{
neighbor->request(this);
// per-type shape precalculations
// require that atom shapes are identical within each type
// if shape = 0 for point particle, set shape = 1 as required by Gay-Berne
for (int i = 1; i <= atom->ntypes; i++) {
if (!atom->shape_consistency(i,shape1[i][0],shape1[i][1],shape1[i][2]))
- error->all("Pair gayberne requires atoms with same type have same shape");
+ error->all(FLERR,"Pair gayberne requires atoms with same type have same shape");
if (shape1[i][0] == 0.0)
shape1[i][0] = shape1[i][1] = shape1[i][2] = 1.0;
shape2[i][0] = shape1[i][0]*shape1[i][0];
shape2[i][1] = shape1[i][1]*shape1[i][1];
shape2[i][2] = shape1[i][2]*shape1[i][2];
lshape[i] = (shape1[i][0]*shape1[i][1]+shape1[i][2]*shape1[i][2]) *
sqrt(shape1[i][0]*shape1[i][1]);
}
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairGayBerne::init_one(int i, int j)
{
if (setwell[i] == 0 || setwell[j] == 0)
- error->all("Pair gayberne epsilon a,b,c coeffs are not all set");
+ error->all(FLERR,"Pair gayberne epsilon a,b,c coeffs are not all set");
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
int ishape = 0;
if (shape1[i][0] != shape1[i][1] ||
shape1[i][0] != shape1[i][2] ||
shape1[i][1] != shape1[i][2]) ishape = 1;
if (setwell[i] == 1) ishape = 1;
int jshape = 0;
if (shape1[j][0] != shape1[j][1] ||
shape1[j][0] != shape1[j][2] ||
shape1[j][1] != shape1[j][2]) jshape = 1;
if (setwell[j] == 1) jshape = 1;
if (ishape == 0 && jshape == 0)
form[i][i] = form[j][j] = form[i][j] = form[j][i] = SPHERE_SPHERE;
else if (ishape == 0) {
form[i][i] = SPHERE_SPHERE; form[j][j] = ELLIPSE_ELLIPSE;
form[i][j] = SPHERE_ELLIPSE; form[j][i] = ELLIPSE_SPHERE;
} else if (jshape == 0) {
form[j][j] = SPHERE_SPHERE; form[i][i] = ELLIPSE_ELLIPSE;
form[j][i] = SPHERE_ELLIPSE; form[i][j] = ELLIPSE_SPHERE;
} else
form[i][i] = form[j][j] = form[i][j] = form[j][i] = ELLIPSE_ELLIPSE;
epsilon[j][i] = epsilon[i][j];
sigma[j][i] = sigma[i][j];
cut[j][i] = cut[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairGayBerne::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++) {
fwrite(&setwell[i],sizeof(int),1,fp);
if (setwell[i]) fwrite(&well[i][0],sizeof(double),3,fp);
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairGayBerne::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++) {
if (me == 0) fread(&setwell[i],sizeof(int),1,fp);
MPI_Bcast(&setwell[i],1,MPI_INT,0,world);
if (setwell[i]) {
if (me == 0) fread(&well[i][0],sizeof(double),3,fp);
MPI_Bcast(&well[i][0],3,MPI_DOUBLE,0,world);
}
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairGayBerne::write_restart_settings(FILE *fp)
{
fwrite(&gamma,sizeof(double),1,fp);
fwrite(&upsilon,sizeof(double),1,fp);
fwrite(&mu,sizeof(double),1,fp);
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairGayBerne::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&gamma,sizeof(double),1,fp);
fread(&upsilon,sizeof(double),1,fp);
fread(&mu,sizeof(double),1,fp);
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&gamma,1,MPI_DOUBLE,0,world);
MPI_Bcast(&upsilon,1,MPI_DOUBLE,0,world);
MPI_Bcast(&mu,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
compute analytic energy, force (fforce), and torque (ttor & rtor)
based on rotation matrices a and precomputed matrices b and g
if newton is off, rtor is not calculated for ghost atoms
------------------------------------------------------------------------- */
double PairGayBerne::gayberne_analytic(const int i,const int j,double a1[3][3],
double a2[3][3], double b1[3][3],
double b2[3][3], double g1[3][3],
double g2[3][3], double *r12,
const double rsq, double *fforce,
double *ttor, double *rtor)
{
double tempv[3], tempv2[3];
double temp[3][3];
double temp1,temp2,temp3;
int *type = atom->type;
int newton_pair = force->newton_pair;
int nlocal = atom->nlocal;
double r12hat[3];
MathExtra::normalize3(r12,r12hat);
double r = sqrt(rsq);
// compute distance of closest approach
double g12[3][3];
MathExtra::plus3(g1,g2,g12);
double kappa[3];
int ierror = MathExtra::mldivide3(g12,r12,kappa);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
// tempv = G12^-1*r12hat
tempv[0] = kappa[0]/r;
tempv[1] = kappa[1]/r;
tempv[2] = kappa[2]/r;
double sigma12 = MathExtra::dot3(r12hat,tempv);
sigma12 = pow(0.5*sigma12,-0.5);
double h12 = r-sigma12;
// energy
// compute u_r
double varrho = sigma[type[i]][type[j]]/(h12+gamma*sigma[type[i]][type[j]]);
double varrho6 = pow(varrho,6.0);
double varrho12 = varrho6*varrho6;
double u_r = 4.0*epsilon[type[i]][type[j]]*(varrho12-varrho6);
// compute eta_12
double eta = 2.0*lshape[type[i]]*lshape[type[j]];
double det_g12 = MathExtra::det3(g12);
eta = pow(eta/det_g12,upsilon);
// compute chi_12
double b12[3][3];
double iota[3];
MathExtra::plus3(b1,b2,b12);
ierror = MathExtra::mldivide3(b12,r12,iota);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
// tempv = G12^-1*r12hat
tempv[0] = iota[0]/r;
tempv[1] = iota[1]/r;
tempv[2] = iota[2]/r;
double chi = MathExtra::dot3(r12hat,tempv);
chi = pow(chi*2.0,mu);
// force
// compute dUr/dr
temp1 = (2.0*varrho12*varrho-varrho6*varrho)/sigma[type[i]][type[j]];
temp1 = temp1*24.0*epsilon[type[i]][type[j]];
double u_slj = temp1*pow(sigma12,3.0)/2.0;
double dUr[3];
temp2 = MathExtra::dot3(kappa,r12hat);
double uslj_rsq = u_slj/rsq;
dUr[0] = temp1*r12hat[0]+uslj_rsq*(kappa[0]-temp2*r12hat[0]);
dUr[1] = temp1*r12hat[1]+uslj_rsq*(kappa[1]-temp2*r12hat[1]);
dUr[2] = temp1*r12hat[2]+uslj_rsq*(kappa[2]-temp2*r12hat[2]);
// compute dChi_12/dr
double dchi[3];
temp1 = MathExtra::dot3(iota,r12hat);
temp2 = -4.0/rsq*mu*pow(chi,(mu-1.0)/mu);
dchi[0] = temp2*(iota[0]-temp1*r12hat[0]);
dchi[1] = temp2*(iota[1]-temp1*r12hat[1]);
dchi[2] = temp2*(iota[2]-temp1*r12hat[2]);
temp1 = -eta*u_r;
temp2 = eta*chi;
fforce[0] = temp1*dchi[0]-temp2*dUr[0];
fforce[1] = temp1*dchi[1]-temp2*dUr[1];
fforce[2] = temp1*dchi[2]-temp2*dUr[2];
// torque for particle 1 and 2
// compute dUr
tempv[0] = -uslj_rsq*kappa[0];
tempv[1] = -uslj_rsq*kappa[1];
tempv[2] = -uslj_rsq*kappa[2];
MathExtra::vecmat(kappa,g1,tempv2);
MathExtra::cross3(tempv,tempv2,dUr);
double dUr2[3];
if (newton_pair || j < nlocal) {
MathExtra::vecmat(kappa,g2,tempv2);
MathExtra::cross3(tempv,tempv2,dUr2);
}
// compute d_chi
MathExtra::vecmat(iota,b1,tempv);
MathExtra::cross3(tempv,iota,dchi);
temp1 = -4.0/rsq;
dchi[0] *= temp1;
dchi[1] *= temp1;
dchi[2] *= temp1;
double dchi2[3];
if (newton_pair || j < nlocal) {
MathExtra::vecmat(iota,b2,tempv);
MathExtra::cross3(tempv,iota,dchi2);
dchi2[0] *= temp1;
dchi2[1] *= temp1;
dchi2[2] *= temp1;
}
// compute d_eta
double deta[3];
deta[0] = deta[1] = deta[2] = 0.0;
compute_eta_torque(g12,a1,shape2[type[i]],temp);
temp1 = -eta*upsilon;
for (int m = 0; m < 3; m++) {
for (int y = 0; y < 3; y++) tempv[y] = temp1*temp[m][y];
MathExtra::cross3(a1[m],tempv,tempv2);
deta[0] += tempv2[0];
deta[1] += tempv2[1];
deta[2] += tempv2[2];
}
// compute d_eta for particle 2
double deta2[3];
if (newton_pair || j < nlocal) {
deta2[0] = deta2[1] = deta2[2] = 0.0;
compute_eta_torque(g12,a2,shape2[type[j]],temp);
for (int m = 0; m < 3; m++) {
for (int y = 0; y < 3; y++) tempv[y] = temp1*temp[m][y];
MathExtra::cross3(a2[m],tempv,tempv2);
deta2[0] += tempv2[0];
deta2[1] += tempv2[1];
deta2[2] += tempv2[2];
}
}
// torque
temp1 = u_r*eta;
temp2 = u_r*chi;
temp3 = chi*eta;
ttor[0] = (temp1*dchi[0]+temp2*deta[0]+temp3*dUr[0]) * -1.0;
ttor[1] = (temp1*dchi[1]+temp2*deta[1]+temp3*dUr[1]) * -1.0;
ttor[2] = (temp1*dchi[2]+temp2*deta[2]+temp3*dUr[2]) * -1.0;
if (newton_pair || j < nlocal) {
rtor[0] = (temp1*dchi2[0]+temp2*deta2[0]+temp3*dUr2[0]) * -1.0;
rtor[1] = (temp1*dchi2[1]+temp2*deta2[1]+temp3*dUr2[1]) * -1.0;
rtor[2] = (temp1*dchi2[2]+temp2*deta2[2]+temp3*dUr2[2]) * -1.0;
}
return temp1*chi;
}
/* ----------------------------------------------------------------------
compute analytic energy, force (fforce), and torque (ttor)
between ellipsoid and lj particle
------------------------------------------------------------------------- */
double PairGayBerne::gayberne_lj(const int i,const int j,double a1[3][3],
double b1[3][3],double g1[3][3],
double *r12,const double rsq,double *fforce,
double *ttor)
{
double tempv[3], tempv2[3];
double temp[3][3];
double temp1,temp2,temp3;
int *type = atom->type;
double r12hat[3];
MathExtra::normalize3(r12,r12hat);
double r = sqrt(rsq);
// compute distance of closest approach
double g12[3][3];
g12[0][0] = g1[0][0]+shape2[type[j]][0];
g12[1][1] = g1[1][1]+shape2[type[j]][0];
g12[2][2] = g1[2][2]+shape2[type[j]][0];
g12[0][1] = g1[0][1]; g12[1][0] = g1[1][0];
g12[0][2] = g1[0][2]; g12[2][0] = g1[2][0];
g12[1][2] = g1[1][2]; g12[2][1] = g1[2][1];
double kappa[3];
int ierror = MathExtra::mldivide3(g12,r12,kappa);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
// tempv = G12^-1*r12hat
tempv[0] = kappa[0]/r;
tempv[1] = kappa[1]/r;
tempv[2] = kappa[2]/r;
double sigma12 = MathExtra::dot3(r12hat,tempv);
sigma12 = pow(0.5*sigma12,-0.5);
double h12 = r-sigma12;
// energy
// compute u_r
double varrho = sigma[type[i]][type[j]]/(h12+gamma*sigma[type[i]][type[j]]);
double varrho6 = pow(varrho,6.0);
double varrho12 = varrho6*varrho6;
double u_r = 4.0*epsilon[type[i]][type[j]]*(varrho12-varrho6);
// compute eta_12
double eta = 2.0*lshape[type[i]]*lshape[type[j]];
double det_g12 = MathExtra::det3(g12);
eta = pow(eta/det_g12,upsilon);
// compute chi_12
double b12[3][3];
double iota[3];
b12[0][0] = b1[0][0] + well[type[j]][0];
b12[1][1] = b1[1][1] + well[type[j]][0];
b12[2][2] = b1[2][2] + well[type[j]][0];
b12[0][1] = b1[0][1]; b12[1][0] = b1[1][0];
b12[0][2] = b1[0][2]; b12[2][0] = b1[2][0];
b12[1][2] = b1[1][2]; b12[2][1] = b1[2][1];
ierror = MathExtra::mldivide3(b12,r12,iota);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
// tempv = G12^-1*r12hat
tempv[0] = iota[0]/r;
tempv[1] = iota[1]/r;
tempv[2] = iota[2]/r;
double chi = MathExtra::dot3(r12hat,tempv);
chi = pow(chi*2.0,mu);
// force
// compute dUr/dr
temp1 = (2.0*varrho12*varrho-varrho6*varrho)/sigma[type[i]][type[j]];
temp1 = temp1*24.0*epsilon[type[i]][type[j]];
double u_slj = temp1*pow(sigma12,3.0)/2.0;
double dUr[3];
temp2 = MathExtra::dot3(kappa,r12hat);
double uslj_rsq = u_slj/rsq;
dUr[0] = temp1*r12hat[0]+uslj_rsq*(kappa[0]-temp2*r12hat[0]);
dUr[1] = temp1*r12hat[1]+uslj_rsq*(kappa[1]-temp2*r12hat[1]);
dUr[2] = temp1*r12hat[2]+uslj_rsq*(kappa[2]-temp2*r12hat[2]);
// compute dChi_12/dr
double dchi[3];
temp1 = MathExtra::dot3(iota,r12hat);
temp2 = -4.0/rsq*mu*pow(chi,(mu-1.0)/mu);
dchi[0] = temp2*(iota[0]-temp1*r12hat[0]);
dchi[1] = temp2*(iota[1]-temp1*r12hat[1]);
dchi[2] = temp2*(iota[2]-temp1*r12hat[2]);
temp1 = -eta*u_r;
temp2 = eta*chi;
fforce[0] = temp1*dchi[0]-temp2*dUr[0];
fforce[1] = temp1*dchi[1]-temp2*dUr[1];
fforce[2] = temp1*dchi[2]-temp2*dUr[2];
// torque for particle 1 and 2
// compute dUr
tempv[0] = -uslj_rsq*kappa[0];
tempv[1] = -uslj_rsq*kappa[1];
tempv[2] = -uslj_rsq*kappa[2];
MathExtra::vecmat(kappa,g1,tempv2);
MathExtra::cross3(tempv,tempv2,dUr);
// compute d_chi
MathExtra::vecmat(iota,b1,tempv);
MathExtra::cross3(tempv,iota,dchi);
temp1 = -4.0/rsq;
dchi[0] *= temp1;
dchi[1] *= temp1;
dchi[2] *= temp1;
// compute d_eta
double deta[3];
deta[0] = deta[1] = deta[2] = 0.0;
compute_eta_torque(g12,a1,shape2[type[i]],temp);
temp1 = -eta*upsilon;
for (int m = 0; m < 3; m++) {
for (int y = 0; y < 3; y++) tempv[y] = temp1*temp[m][y];
MathExtra::cross3(a1[m],tempv,tempv2);
deta[0] += tempv2[0];
deta[1] += tempv2[1];
deta[2] += tempv2[2];
}
// torque
temp1 = u_r*eta;
temp2 = u_r*chi;
temp3 = chi*eta;
ttor[0] = (temp1*dchi[0]+temp2*deta[0]+temp3*dUr[0]) * -1.0;
ttor[1] = (temp1*dchi[1]+temp2*deta[1]+temp3*dUr[1]) * -1.0;
ttor[2] = (temp1*dchi[2]+temp2*deta[2]+temp3*dUr[2]) * -1.0;
return temp1*chi;
}
/* ----------------------------------------------------------------------
torque contribution from eta
computes trace in the last doc equation for the torque derivative
code comes from symbolic solver dump
m is g12, m2 is a_i, s is the shape for the particle
------------------------------------------------------------------------- */
void PairGayBerne::compute_eta_torque(double m[3][3], double m2[3][3],
double *s, double ans[3][3])
{
double den = m[1][0]*m[0][2]*m[2][1]-m[0][0]*m[1][2]*m[2][1]-
m[0][2]*m[2][0]*m[1][1]+m[0][1]*m[2][0]*m[1][2]-
m[1][0]*m[0][1]*m[2][2]+m[0][0]*m[1][1]*m[2][2];
ans[0][0] = s[0]*(m[1][2]*m[0][1]*m2[0][2]+2.0*m[1][1]*m[2][2]*m2[0][0]-
m[1][1]*m2[0][2]*m[0][2]-2.0*m[1][2]*m2[0][0]*m[2][1]+
m2[0][1]*m[0][2]*m[2][1]-m2[0][1]*m[0][1]*m[2][2]-
m[1][0]*m[2][2]*m2[0][1]+m[2][0]*m[1][2]*m2[0][1]+
m[1][0]*m2[0][2]*m[2][1]-m2[0][2]*m[2][0]*m[1][1])/den;
ans[0][1] = s[0]*(m[0][2]*m2[0][0]*m[2][1]-m[2][2]*m2[0][0]*m[0][1]+
2.0*m[0][0]*m[2][2]*m2[0][1]-m[0][0]*m2[0][2]*m[1][2]-
2.0*m[2][0]*m[0][2]*m2[0][1]+m2[0][2]*m[1][0]*m[0][2]-
m[2][2]*m[1][0]*m2[0][0]+m[2][0]*m2[0][0]*m[1][2]+
m[2][0]*m2[0][2]*m[0][1]-m2[0][2]*m[0][0]*m[2][1])/den;
ans[0][2] = s[0]*(m[0][1]*m[1][2]*m2[0][0]-m[0][2]*m2[0][0]*m[1][1]-
m[0][0]*m[1][2]*m2[0][1]+m[1][0]*m[0][2]*m2[0][1]-
m2[0][1]*m[0][0]*m[2][1]-m[2][0]*m[1][1]*m2[0][0]+
2.0*m[1][1]*m[0][0]*m2[0][2]-2.0*m[1][0]*m2[0][2]*m[0][1]+
m[1][0]*m[2][1]*m2[0][0]+m[2][0]*m2[0][1]*m[0][1])/den;
ans[1][0] = s[1]*(-m[1][1]*m2[1][2]*m[0][2]+2.0*m[1][1]*m[2][2]*m2[1][0]+
m[1][2]*m[0][1]*m2[1][2]-2.0*m[1][2]*m2[1][0]*m[2][1]+
m2[1][1]*m[0][2]*m[2][1]-m2[1][1]*m[0][1]*m[2][2]-
m[1][0]*m[2][2]*m2[1][1]+m[2][0]*m[1][2]*m2[1][1]-
m2[1][2]*m[2][0]*m[1][1]+m[1][0]*m2[1][2]*m[2][1])/den;
ans[1][1] = s[1]*(m[0][2]*m2[1][0]*m[2][1]-m[0][1]*m[2][2]*m2[1][0]+
2.0*m[2][2]*m[0][0]*m2[1][1]-m2[1][2]*m[0][0]*m[1][2]-
2.0*m[2][0]*m2[1][1]*m[0][2]-m[1][0]*m[2][2]*m2[1][0]+
m[2][0]*m[1][2]*m2[1][0]+m[1][0]*m2[1][2]*m[0][2]-
m[0][0]*m2[1][2]*m[2][1]+m2[1][2]*m[0][1]*m[2][0])/den;
ans[1][2] = s[1]*(m[0][1]*m[1][2]*m2[1][0]-m[0][2]*m2[1][0]*m[1][1]-
m[0][0]*m[1][2]*m2[1][1]+m[1][0]*m[0][2]*m2[1][1]+
2.0*m[1][1]*m[0][0]*m2[1][2]-m[0][0]*m2[1][1]*m[2][1]+
m[0][1]*m[2][0]*m2[1][1]-m2[1][0]*m[2][0]*m[1][1]-
2.0*m[1][0]*m[0][1]*m2[1][2]+m[1][0]*m2[1][0]*m[2][1])/den;
ans[2][0] = s[2]*(-m[1][1]*m[0][2]*m2[2][2]+m[0][1]*m[1][2]*m2[2][2]+
2.0*m[1][1]*m2[2][0]*m[2][2]-m[0][1]*m2[2][1]*m[2][2]+
m[0][2]*m[2][1]*m2[2][1]-2.0*m2[2][0]*m[2][1]*m[1][2]-
m[1][0]*m2[2][1]*m[2][2]+m[1][2]*m[2][0]*m2[2][1]-
m[1][1]*m[2][0]*m2[2][2]+m[2][1]*m[1][0]*m2[2][2])/den;
ans[2][1] = s[2]*-(m[0][1]*m[2][2]*m2[2][0]-m[0][2]*m2[2][0]*m[2][1]-
2.0*m2[2][1]*m[0][0]*m[2][2]+m[1][2]*m2[2][2]*m[0][0]+
2.0*m2[2][1]*m[0][2]*m[2][0]+m[1][0]*m2[2][0]*m[2][2]-
m[1][0]*m[0][2]*m2[2][2]-m[1][2]*m[2][0]*m2[2][0]+
m[0][0]*m2[2][2]*m[2][1]-m2[2][2]*m[0][1]*m[2][0])/den;
ans[2][2] = s[2]*(m[0][1]*m[1][2]*m2[2][0]-m[0][2]*m2[2][0]*m[1][1]-
m[0][0]*m[1][2]*m2[2][1]+m[1][0]*m[0][2]*m2[2][1]-
m[1][1]*m[2][0]*m2[2][0]-m[2][1]*m2[2][1]*m[0][0]+
2.0*m[1][1]*m2[2][2]*m[0][0]+m[2][1]*m[1][0]*m2[2][0]+
m[2][0]*m[0][1]*m2[2][1]-2.0*m2[2][2]*m[1][0]*m[0][1])/den;
}
diff --git a/src/ASPHERE/pair_resquared.cpp b/src/ASPHERE/pair_resquared.cpp
index 41d964a4e..20457226d 100755
--- a/src/ASPHERE/pair_resquared.cpp
+++ b/src/ASPHERE/pair_resquared.cpp
@@ -1,993 +1,990 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_resquared.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
using namespace LAMMPS_NS;
enum{SPHERE_SPHERE,SPHERE_ELLIPSE,ELLIPSE_SPHERE,ELLIPSE_ELLIPSE};
/* ---------------------------------------------------------------------- */
PairRESquared::PairRESquared(LAMMPS *lmp) : Pair(lmp),
b_alpha(45.0/56.0),
cr60(pow(60.0,1.0/3.0))
{
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Pair resquared requires atom style ellipsoid");
+ if (!avec) error->all(FLERR,"Pair resquared requires atom style ellipsoid");
single_enable = 0;
cr60 = pow(60.0,1.0/3.0);
b_alpha = 45.0/56.0;
solv_f_a = 3.0/(16.0*atan(1.0)*-36.0);
solv_f_r = 3.0/(16.0*atan(1.0)*2025.0);
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairRESquared::~PairRESquared()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(form);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(shape1);
memory->destroy(shape2);
memory->destroy(well);
memory->destroy(cut);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
delete [] lshape;
delete [] setwell;
}
}
/* ---------------------------------------------------------------------- */
void PairRESquared::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double evdwl,one_eng,rsq,r2inv,r6inv,forcelj,factor_lj;
double fforce[3],ttor[3],rtor[3],r12[3];
int *ilist,*jlist,*numneigh,**firstneigh;
RE2Vars wi,wj;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double **tor = atom->torque;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
// not a LJ sphere
if (lshape[itype] != 0.0) precompute_i(i,wi);
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
// r12 = center to center vector
r12[0] = x[j][0]-x[i][0];
r12[1] = x[j][1]-x[i][1];
r12[2] = x[j][2]-x[i][2];
rsq = MathExtra::dot3(r12,r12);
jtype = type[j];
// compute if less than cutoff
if (rsq < cutsq[itype][jtype]) {
switch (form[itype][jtype]) {
case SPHERE_SPHERE:
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
forcelj *= -r2inv;
if (eflag) one_eng =
r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) -
offset[itype][jtype];
fforce[0] = r12[0]*forcelj;
fforce[1] = r12[1]*forcelj;
fforce[2] = r12[2]*forcelj;
break;
case SPHERE_ELLIPSE:
precompute_i(j,wj);
if (newton_pair || j < nlocal) {
one_eng = resquared_lj(j,i,wj,r12,rsq,fforce,rtor,true);
tor[j][0] += rtor[0]*factor_lj;
tor[j][1] += rtor[1]*factor_lj;
tor[j][2] += rtor[2]*factor_lj;
} else
one_eng = resquared_lj(j,i,wj,r12,rsq,fforce,rtor,false);
break;
case ELLIPSE_SPHERE:
one_eng = resquared_lj(i,j,wi,r12,rsq,fforce,ttor,true);
tor[i][0] += ttor[0]*factor_lj;
tor[i][1] += ttor[1]*factor_lj;
tor[i][2] += ttor[2]*factor_lj;
break;
default:
precompute_i(j,wj);
one_eng = resquared_analytic(i,j,wi,wj,r12,rsq,fforce,ttor,rtor);
tor[i][0] += ttor[0]*factor_lj;
tor[i][1] += ttor[1]*factor_lj;
tor[i][2] += ttor[2]*factor_lj;
if (newton_pair || j < nlocal) {
tor[j][0] += rtor[0]*factor_lj;
tor[j][1] += rtor[1]*factor_lj;
tor[j][2] += rtor[2]*factor_lj;
}
break;
}
fforce[0] *= factor_lj;
fforce[1] *= factor_lj;
fforce[2] *= factor_lj;
f[i][0] += fforce[0];
f[i][1] += fforce[1];
f[i][2] += fforce[2];
if (newton_pair || j < nlocal) {
f[j][0] -= fforce[0];
f[j][1] -= fforce[1];
f[j][2] -= fforce[2];
}
if (eflag) evdwl = factor_lj*one_eng;
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,
evdwl,0.0,fforce[0],fforce[1],fforce[2],
-r12[0],-r12[1],-r12[2]);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairRESquared::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(form,n+1,n+1,"pair:form");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(shape1,n+1,3,"pair:shape1");
memory->create(shape2,n+1,3,"pair:shape2");
memory->create(well,n+1,3,"pair:well");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
lshape = new double[n+1];
setwell = new int[n+1];
for (int i = 1; i <= n; i++) setwell[i] = 0;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairRESquared::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairRESquared::coeff(int narg, char **arg)
{
if (narg < 10 || narg > 11)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double eia_one = force->numeric(arg[4]);
double eib_one = force->numeric(arg[5]);
double eic_one = force->numeric(arg[6]);
double eja_one = force->numeric(arg[7]);
double ejb_one = force->numeric(arg[8]);
double ejc_one = force->numeric(arg[9]);
double cut_one = cut_global;
if (narg == 11) cut_one = force->numeric(arg[10]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut[i][j] = cut_one;
if (eia_one != 0.0 || eib_one != 0.0 || eic_one != 0.0) {
well[i][0] = eia_one;
well[i][1] = eib_one;
well[i][2] = eic_one;
if (eia_one == 1.0 && eib_one == 1.0 && eic_one == 1.0) setwell[i] = 2;
else setwell[i] = 1;
}
if (eja_one != 0.0 || ejb_one != 0.0 || ejc_one != 0.0) {
well[j][0] = eja_one;
well[j][1] = ejb_one;
well[j][2] = ejc_one;
if (eja_one == 1.0 && ejb_one == 1.0 && ejc_one == 1.0) setwell[j] = 2;
else setwell[j] = 1;
}
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairRESquared::init_style()
{
neighbor->request(this);
// per-type shape precalculations
// require that atom shapes are identical within each type
for (int i = 1; i <= atom->ntypes; i++) {
if (!atom->shape_consistency(i,shape1[i][0],shape1[i][1],shape1[i][2]))
- error->all("Pair gayberne requires atoms with same type have same shape");
+ error->all(FLERR,"Pair gayberne requires atoms with same type have same shape");
if (setwell[i]) {
shape2[i][0] = shape1[i][0]*shape1[i][0];
shape2[i][1] = shape1[i][1]*shape1[i][1];
shape2[i][2] = shape1[i][2]*shape1[i][2];
lshape[i] = shape1[i][0]*shape1[i][1]*shape1[i][2];
}
}
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairRESquared::init_one(int i, int j)
{
if (setwell[i] == 0 || setwell[j] == 0)
- error->all("Pair resquared epsilon a,b,c coeffs are not all set");
+ error->all(FLERR,"Pair resquared epsilon a,b,c coeffs are not all set");
int ishape = 0;
if (shape1[i][0] != 0.0 && shape1[i][1] != 0.0 && shape1[i][2] != 0.0)
ishape = 1;
int jshape = 0;
if (shape1[j][0] != 0.0 && shape1[j][1] != 0.0 && shape1[j][2] != 0.0)
jshape = 1;
if (ishape == 0 && jshape == 0) {
form[i][j] = SPHERE_SPHERE;
form[j][i] = SPHERE_SPHERE;
} else if (ishape == 0) {
form[i][j] = SPHERE_ELLIPSE;
form[j][i] = ELLIPSE_SPHERE;
} else if (jshape == 0) {
form[i][j] = ELLIPSE_SPHERE;
form[j][i] = SPHERE_ELLIPSE;
} else {
form[i][j] = ELLIPSE_ELLIPSE;
form[j][i] = ELLIPSE_ELLIPSE;
}
// allow mixing only for LJ spheres
if (setflag[i][j] == 0) {
if (setflag[j][i] == 0) {
if (ishape == 0 && jshape == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
} else
- error->all("Pair resquared epsilon and sigma coeffs are not all set");
+ error->all(FLERR,"Pair resquared epsilon and sigma coeffs are not all set");
}
epsilon[i][j] = epsilon[j][i];
sigma[i][j] = sigma[j][i];
cut[i][j] = cut[j][i];
}
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
epsilon[j][i] = epsilon[i][j];
sigma[j][i] = sigma[i][j];
cut[j][i] = cut[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairRESquared::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++) {
fwrite(&setwell[i],sizeof(int),1,fp);
if (setwell[i]) fwrite(&well[i][0],sizeof(double),3,fp);
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairRESquared::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++) {
if (me == 0) fread(&setwell[i],sizeof(int),1,fp);
MPI_Bcast(&setwell[i],1,MPI_INT,0,world);
if (setwell[i]) {
if (me == 0) fread(&well[i][0],sizeof(double),3,fp);
MPI_Bcast(&well[i][0],3,MPI_DOUBLE,0,world);
}
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairRESquared::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairRESquared::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
Precompute per-particle temporaries for RE-squared calculation
------------------------------------------------------------------------- */
void PairRESquared::precompute_i(const int i,RE2Vars &ws)
{
double aTs[3][3]; // A1'*S1^2
int *ellipsoid = atom->ellipsoid;
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
MathExtra::quat_to_mat_trans(bonus[ellipsoid[i]].quat,ws.A);
MathExtra::transpose_diag3(ws.A,well[atom->type[i]],ws.aTe);
MathExtra::transpose_diag3(ws.A,shape2[atom->type[i]],aTs);
MathExtra::diag_times3(shape2[atom->type[i]],ws.A,ws.sa);
MathExtra::times3(aTs,ws.A,ws.gamma);
MathExtra::rotation_generator_x(ws.A,ws.lA[0]);
MathExtra::rotation_generator_y(ws.A,ws.lA[1]);
MathExtra::rotation_generator_z(ws.A,ws.lA[2]);
for (int i=0; i<3; i++) {
MathExtra::times3(aTs,ws.lA[i],ws.lAtwo[i]);
MathExtra::transpose_times3(ws.lA[i],ws.sa,ws.lAsa[i]);
MathExtra::plus3(ws.lAsa[i],ws.lAtwo[i],ws.lAsa[i]);
}
}
/* ----------------------------------------------------------------------
Compute the derivative of the determinant of m, using m and the
derivative of m (m2)
------------------------------------------------------------------------- */
double PairRESquared::det_prime(const double m[3][3], const double m2[3][3])
{
double ans;
ans = m2[0][0]*m[1][1]*m[2][2] - m2[0][0]*m[1][2]*m[2][1] -
m[1][0]*m2[0][1]*m[2][2] + m[1][0]*m2[0][2]*m[2][1] +
m[2][0]*m2[0][1]*m[1][2] - m[2][0]*m2[0][2]*m[1][1] +
m[0][0]*m2[1][1]*m[2][2] - m[0][0]*m2[1][2]*m[2][1] -
m2[1][0]*m[0][1]*m[2][2] + m2[1][0]*m[0][2]*m[2][1] +
m[2][0]*m[0][1]*m2[1][2] - m[2][0]*m[0][2]*m2[1][1] +
m[0][0]*m[1][1]*m2[2][2] - m[0][0]*m[1][2]*m2[2][1] -
m[1][0]*m[0][1]*m2[2][2] + m[1][0]*m[0][2]*m2[2][1] +
m2[2][0]*m[0][1]*m[1][2] - m2[2][0]*m[0][2]*m[1][1];
return ans;
}
/* ----------------------------------------------------------------------
Compute the energy, force, torque for a pair (INTEGRATED-INTEGRATED)
------------------------------------------------------------------------- */
double PairRESquared::resquared_analytic(const int i, const int j,
const RE2Vars &wi, const RE2Vars &wj,
const double *r, const double rsq,
double *fforce, double *ttor,
double *rtor)
{
int *type = atom->type;
// pair computations for energy, force, torque
double z1[3],z2[3]; // A1*rhat # don't need to store
double v1[3],v2[3]; // inv(S1^2)*z1 # don't need to store
double sigma1,sigma2; // 1/sqrt(z1'*v1)
double sigma1p2,sigma2p2; // sigma1^2
double rnorm; // L2 norm of r
double rhat[3]; // r/rnorm
double s[3]; // inv(gamma1+gamma2)*rhat
double sigma12; // 1/sqrt(0.5*s'*rhat)
double H12[3][3]; // gamma1/sigma1+gamma2/sigma2
double dH; // det(H12)
double lambda; // dS1/sigma1p2+dS2/sigma2p2
double nu; // sqrt(dH/(sigma1+sigma2))
double w[3]; // inv(A1'*E1*A1+A2'*E2*A2)*rhat
double h12; // rnorm-sigma12;
double eta; // lambda/nu
double chi; // 2*rhat'*w
double sprod; // dS1*dS2
double sigh; // sigma/h12
double tprod; // eta*chi*sigh
double Ua,Ur; // attractive/repulsive parts of potential
// pair computations for force, torque
double sec; // sigma*eta*chi
double sigma1p3, sigma2p3; // sigma1^3
double vsigma1[3], vsigma2[3]; // sigma1^3*v1;
double sigma12p3; // sigma12^3
double gsigma1[3][3], gsigma2[3][3]; // -gamma1/sigma1^2
double tsig1sig2; // eta/(2*(sigma1+sigma2))
double tdH; // eta/(2*dH)
double teta1,teta2; // 2*eta/lambda*dS1/sigma1p3
double fourw[3]; // 4*w;
double spr[3]; // 0.5*sigma12^3*s
double hsec; // h12+[3,b_alpha]*sec
double dspu; // 1/h12 - 1/hsec + temp
double pbsu; // 3*sigma/hsec
double dspr; // 7/h12-1/hsec+temp
double pbsr; // b_alpha*sigma/hsec;
double u[3]; // (-rhat(i)*rhat+eye(:,i))/rnorm
double u1[3],u2[3]; // A1*u
double dsigma1,dsigma2; // u1'*vsigma1 (force) p'*vsigma1 (tor)
double dH12[3][3]; // dsigma1*gsigma1 + dsigma2*gsigma2
double ddH; // derivative of det(H12)
double deta,dchi,dh12; // derivatives of eta,chi,h12
double dUr,dUa; // derivatives of Ua,Ur
// pair computations for torque
double fwae[3]; // -fourw'*aTe
double p[3]; // lA*rhat
rnorm = sqrt(rsq);
rhat[0] = r[0]/rnorm;
rhat[1] = r[1]/rnorm;
rhat[2] = r[2]/rnorm;
// energy
double temp[3][3];
MathExtra::plus3(wi.gamma,wj.gamma,temp);
int ierror = MathExtra::mldivide3(temp,rhat,s);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
sigma12 = 1.0/sqrt(0.5*MathExtra::dot3(s,rhat));
MathExtra::matvec(wi.A,rhat,z1);
MathExtra::matvec(wj.A,rhat,z2);
v1[0] = z1[0]/shape2[type[i]][0];
v1[1] = z1[1]/shape2[type[i]][1];
v1[2] = z1[2]/shape2[type[i]][2];
v2[0] = z2[0]/shape2[type[j]][0];
v2[1] = z2[1]/shape2[type[j]][1];
v2[2] = z2[2]/shape2[type[j]][2];
sigma1 = 1.0/sqrt(MathExtra::dot3(z1,v1));
sigma2 = 1.0/sqrt(MathExtra::dot3(z2,v2));
H12[0][0] = wi.gamma[0][0]/sigma1+wj.gamma[0][0]/sigma2;
H12[0][1] = wi.gamma[0][1]/sigma1+wj.gamma[0][1]/sigma2;
H12[0][2] = wi.gamma[0][2]/sigma1+wj.gamma[0][2]/sigma2;
H12[1][0] = wi.gamma[1][0]/sigma1+wj.gamma[1][0]/sigma2;
H12[1][1] = wi.gamma[1][1]/sigma1+wj.gamma[1][1]/sigma2;
H12[1][2] = wi.gamma[1][2]/sigma1+wj.gamma[1][2]/sigma2;
H12[2][0] = wi.gamma[2][0]/sigma1+wj.gamma[2][0]/sigma2;
H12[2][1] = wi.gamma[2][1]/sigma1+wj.gamma[2][1]/sigma2;
H12[2][2] = wi.gamma[2][2]/sigma1+wj.gamma[2][2]/sigma2;
dH=MathExtra::det3(H12);
sigma1p2 = sigma1*sigma1;
sigma2p2 = sigma2*sigma2;
lambda = lshape[type[i]]/sigma1p2 + lshape[type[j]]/sigma2p2;
nu = sqrt(dH/(sigma1+sigma2));
MathExtra::times3(wi.aTe,wi.A,temp);
double temp2[3][3];
MathExtra::times3(wj.aTe,wj.A,temp2);
MathExtra::plus3(temp,temp2,temp);
ierror = MathExtra::mldivide3(temp,rhat,w);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
h12 = rnorm-sigma12;
eta = lambda/nu;
chi = 2.0*MathExtra::dot3(rhat,w);
sprod = lshape[type[i]] * lshape[type[j]];
sigh = sigma[type[i]][type[j]]/h12;
tprod = eta*chi*sigh;
double stemp = h12/2.0;
Ua = (shape1[type[i]][0]+stemp)*(shape1[type[i]][1]+stemp)*
(shape1[type[i]][2]+stemp)*(shape1[type[j]][0]+stemp)*
(shape1[type[j]][1]+stemp)*(shape1[type[j]][2]+stemp);
Ua = (1.0+3.0*tprod)*sprod/Ua;
Ua = epsilon[type[i]][type[j]]*Ua/-36.0;
stemp = h12/cr60;
Ur = (shape1[type[i]][0]+stemp)*(shape1[type[i]][1]+stemp)*
(shape1[type[i]][2]+stemp)*(shape1[type[j]][0]+stemp)*
(shape1[type[j]][1]+stemp)*(shape1[type[j]][2]+stemp);
Ur = (1.0+b_alpha*tprod)*sprod/Ur;
Ur = epsilon[type[i]][type[j]]*Ur*pow(sigh,6.0)/2025.0;
// force
sec = sigma[type[i]][type[j]]*eta*chi;
sigma12p3 = pow(sigma12,3.0);
sigma1p3 = sigma1p2*sigma1;
sigma2p3 = sigma2p2*sigma2;
vsigma1[0] = -sigma1p3*v1[0];
vsigma1[1] = -sigma1p3*v1[1];
vsigma1[2] = -sigma1p3*v1[2];
vsigma2[0] = -sigma2p3*v2[0];
vsigma2[1] = -sigma2p3*v2[1];
vsigma2[2] = -sigma2p3*v2[2];
gsigma1[0][0] = -wi.gamma[0][0]/sigma1p2;
gsigma1[0][1] = -wi.gamma[0][1]/sigma1p2;
gsigma1[0][2] = -wi.gamma[0][2]/sigma1p2;
gsigma1[1][0] = -wi.gamma[1][0]/sigma1p2;
gsigma1[1][1] = -wi.gamma[1][1]/sigma1p2;
gsigma1[1][2] = -wi.gamma[1][2]/sigma1p2;
gsigma1[2][0] = -wi.gamma[2][0]/sigma1p2;
gsigma1[2][1] = -wi.gamma[2][1]/sigma1p2;
gsigma1[2][2] = -wi.gamma[2][2]/sigma1p2;
gsigma2[0][0] = -wj.gamma[0][0]/sigma2p2;
gsigma2[0][1] = -wj.gamma[0][1]/sigma2p2;
gsigma2[0][2] = -wj.gamma[0][2]/sigma2p2;
gsigma2[1][0] = -wj.gamma[1][0]/sigma2p2;
gsigma2[1][1] = -wj.gamma[1][1]/sigma2p2;
gsigma2[1][2] = -wj.gamma[1][2]/sigma2p2;
gsigma2[2][0] = -wj.gamma[2][0]/sigma2p2;
gsigma2[2][1] = -wj.gamma[2][1]/sigma2p2;
gsigma2[2][2] = -wj.gamma[2][2]/sigma2p2;
tsig1sig2 = eta/(2.0*(sigma1+sigma2));
tdH = eta/(2.0*dH);
teta1 = 2.0*eta/lambda;
teta2 = teta1*lshape[type[j]]/sigma2p3;
teta1 = teta1*lshape[type[i]]/sigma1p3;
fourw[0] = 4.0*w[0];
fourw[1] = 4.0*w[1];
fourw[2] = 4.0*w[2];
spr[0] = 0.5*sigma12p3*s[0];
spr[1] = 0.5*sigma12p3*s[1];
spr[2] = 0.5*sigma12p3*s[2];
stemp = 1.0/(shape1[type[i]][0]*2.0+h12)+
1.0/(shape1[type[i]][1]*2.0+h12)+
1.0/(shape1[type[i]][2]*2.0+h12)+
1.0/(shape1[type[j]][0]*2.0+h12)+
1.0/(shape1[type[j]][1]*2.0+h12)+
1.0/(shape1[type[j]][2]*2.0+h12);
hsec = h12+3.0*sec;
dspu = 1.0/h12-1.0/hsec+stemp;
pbsu = 3.0*sigma[type[i]][type[j]]/hsec;
stemp = 1.0/(shape1[type[i]][0]*cr60+h12)+
1.0/(shape1[type[i]][1]*cr60+h12)+
1.0/(shape1[type[i]][2]*cr60+h12)+
1.0/(shape1[type[j]][0]*cr60+h12)+
1.0/(shape1[type[j]][1]*cr60+h12)+
1.0/(shape1[type[j]][2]*cr60+h12);
hsec = h12+b_alpha*sec;
dspr = 7.0/h12-1.0/hsec+stemp;
pbsr = b_alpha*sigma[type[i]][type[j]]/hsec;
for (int i=0; i<3; i++) {
u[0] = -rhat[i]*rhat[0];
u[1] = -rhat[i]*rhat[1];
u[2] = -rhat[i]*rhat[2];
u[i] += 1.0;
u[0] /= rnorm;
u[1] /= rnorm;
u[2] /= rnorm;
MathExtra::matvec(wi.A,u,u1);
MathExtra::matvec(wj.A,u,u2);
dsigma1=MathExtra::dot3(u1,vsigma1);
dsigma2=MathExtra::dot3(u2,vsigma2);
dH12[0][0] = dsigma1*gsigma1[0][0]+dsigma2*gsigma2[0][0];
dH12[0][1] = dsigma1*gsigma1[0][1]+dsigma2*gsigma2[0][1];
dH12[0][2] = dsigma1*gsigma1[0][2]+dsigma2*gsigma2[0][2];
dH12[1][0] = dsigma1*gsigma1[1][0]+dsigma2*gsigma2[1][0];
dH12[1][1] = dsigma1*gsigma1[1][1]+dsigma2*gsigma2[1][1];
dH12[1][2] = dsigma1*gsigma1[1][2]+dsigma2*gsigma2[1][2];
dH12[2][0] = dsigma1*gsigma1[2][0]+dsigma2*gsigma2[2][0];
dH12[2][1] = dsigma1*gsigma1[2][1]+dsigma2*gsigma2[2][1];
dH12[2][2] = dsigma1*gsigma1[2][2]+dsigma2*gsigma2[2][2];
ddH = det_prime(H12,dH12);
deta = (dsigma1+dsigma2)*tsig1sig2;
deta -= ddH*tdH;
deta -= dsigma1*teta1+dsigma2*teta2;
dchi = MathExtra::dot3(u,fourw);
dh12 = rhat[i]+MathExtra::dot3(u,spr);
dUa = pbsu*(eta*dchi+deta*chi)-dh12*dspu;
dUr = pbsr*(eta*dchi+deta*chi)-dh12*dspr;
fforce[i]=dUr*Ur+dUa*Ua;
}
// torque on i
MathExtra::vecmat(fourw,wi.aTe,fwae);
for (int i=0; i<3; i++) {
MathExtra::matvec(wi.lA[i],rhat,p);
dsigma1 = MathExtra::dot3(p,vsigma1);
dH12[0][0] = wi.lAsa[i][0][0]/sigma1+dsigma1*gsigma1[0][0];
dH12[0][1] = wi.lAsa[i][0][1]/sigma1+dsigma1*gsigma1[0][1];
dH12[0][2] = wi.lAsa[i][0][2]/sigma1+dsigma1*gsigma1[0][2];
dH12[1][0] = wi.lAsa[i][1][0]/sigma1+dsigma1*gsigma1[1][0];
dH12[1][1] = wi.lAsa[i][1][1]/sigma1+dsigma1*gsigma1[1][1];
dH12[1][2] = wi.lAsa[i][1][2]/sigma1+dsigma1*gsigma1[1][2];
dH12[2][0] = wi.lAsa[i][2][0]/sigma1+dsigma1*gsigma1[2][0];
dH12[2][1] = wi.lAsa[i][2][1]/sigma1+dsigma1*gsigma1[2][1];
dH12[2][2] = wi.lAsa[i][2][2]/sigma1+dsigma1*gsigma1[2][2];
ddH = det_prime(H12,dH12);
deta = tsig1sig2*dsigma1-tdH*ddH;
deta -= teta1*dsigma1;
double tempv[3];
MathExtra::matvec(wi.lA[i],w,tempv);
dchi = -MathExtra::dot3(fwae,tempv);
MathExtra::matvec(wi.lAtwo[i],spr,tempv);
dh12 = -MathExtra::dot3(s,tempv);
dUa = pbsu*(eta*dchi + deta*chi)-dh12*dspu;
dUr = pbsr*(eta*dchi + deta*chi)-dh12*dspr;
ttor[i] = -(dUa*Ua+dUr*Ur);
}
// torque on j
if (!(force->newton_pair || j < atom->nlocal))
return Ua+Ur;
MathExtra::vecmat(fourw,wj.aTe,fwae);
for (int i=0; i<3; i++) {
MathExtra::matvec(wj.lA[i],rhat,p);
dsigma2 = MathExtra::dot3(p,vsigma2);
dH12[0][0] = wj.lAsa[i][0][0]/sigma2+dsigma2*gsigma2[0][0];
dH12[0][1] = wj.lAsa[i][0][1]/sigma2+dsigma2*gsigma2[0][1];
dH12[0][2] = wj.lAsa[i][0][2]/sigma2+dsigma2*gsigma2[0][2];
dH12[1][0] = wj.lAsa[i][1][0]/sigma2+dsigma2*gsigma2[1][0];
dH12[1][1] = wj.lAsa[i][1][1]/sigma2+dsigma2*gsigma2[1][1];
dH12[1][2] = wj.lAsa[i][1][2]/sigma2+dsigma2*gsigma2[1][2];
dH12[2][0] = wj.lAsa[i][2][0]/sigma2+dsigma2*gsigma2[2][0];
dH12[2][1] = wj.lAsa[i][2][1]/sigma2+dsigma2*gsigma2[2][1];
dH12[2][2] = wj.lAsa[i][2][2]/sigma2+dsigma2*gsigma2[2][2];
ddH = det_prime(H12,dH12);
deta = tsig1sig2*dsigma2-tdH*ddH;
deta -= teta2*dsigma2;
double tempv[3];
MathExtra::matvec(wj.lA[i],w,tempv);
dchi = -MathExtra::dot3(fwae,tempv);
MathExtra::matvec(wj.lAtwo[i],spr,tempv);
dh12 = -MathExtra::dot3(s,tempv);
dUa = pbsu*(eta*dchi + deta*chi)-dh12*dspu;
dUr = pbsr*(eta*dchi + deta*chi)-dh12*dspr;
rtor[i] = -(dUa*Ua+dUr*Ur);
}
return Ua+Ur;
}
/* ----------------------------------------------------------------------
Compute the energy, force, torque for a pair (INTEGRATED-LJ)
------------------------------------------------------------------------- */
double PairRESquared::resquared_lj(const int i, const int j,
const RE2Vars &wi, const double *r,
const double rsq, double *fforce,
double *ttor, bool calc_torque)
{
int *type = atom->type;
// pair computations for energy, force, torque
double rnorm; // L2 norm of r
double rhat[3]; // r/rnorm
double s[3]; // inv(gamma1)*rhat
double sigma12; // 1/sqrt(0.5*s'*rhat)
double w[3]; // inv(A1'*E1*A1+I)*rhat
double h12; // rnorm-sigma12;
double chi; // 2*rhat'*w
double sigh; // sigma/h12
double tprod; // chi*sigh
double Ua,Ur; // attractive/repulsive parts of potential
// pair computations for force, torque
double sec; // sigma*chi
double sigma12p3; // sigma12^3
double fourw[3]; // 4*w;
double spr[3]; // 0.5*sigma12^3*s
double hsec; // h12+[3,b_alpha]*sec
double dspu; // 1/h12 - 1/hsec + temp
double pbsu; // 3*sigma/hsec
double dspr; // 7/h12-1/hsec+temp
double pbsr; // b_alpha*sigma/hsec;
double u[3]; // (-rhat(i)*rhat+eye(:,i))/rnorm
double dchi,dh12; // derivatives of chi,h12
double dUr,dUa; // derivatives of Ua,Ur
double h12p3; // h12^3
// pair computations for torque
double fwae[3]; // -fourw'*aTe
double p[3]; // lA*rhat
// distance of closest approach correction
double aTs[3][3]; // A1'*S1^2
double gamma[3][3]; // A1'*S1^2*A
double lAtwo[3][3][3]; // A1'*S1^2*wi.lA
double scorrect[3];
double half_sigma=sigma[type[i]][type[j]] / 2.0;
scorrect[0] = shape1[type[i]][0]+half_sigma;
scorrect[1] = shape1[type[i]][1]+half_sigma;
scorrect[2] = shape1[type[i]][2]+half_sigma;
scorrect[0] = scorrect[0] * scorrect[0] / 2.0;
scorrect[1] = scorrect[1] * scorrect[1] / 2.0;
scorrect[2] = scorrect[2] * scorrect[2] / 2.0;
MathExtra::transpose_diag3(wi.A,scorrect,aTs);
MathExtra::times3(aTs,wi.A,gamma);
for (int ii=0; ii<3; ii++)
MathExtra::times3(aTs,wi.lA[ii],lAtwo[ii]);
rnorm=sqrt(rsq);
rhat[0] = r[0]/rnorm;
rhat[1] = r[1]/rnorm;
rhat[2] = r[2]/rnorm;
// energy
int ierror = MathExtra::mldivide3(gamma,rhat,s);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
sigma12 = 1.0/sqrt(0.5*MathExtra::dot3(s,rhat));
double temp[3][3];
MathExtra::times3(wi.aTe,wi.A,temp);
temp[0][0] += 1.0;
temp[1][1] += 1.0;
temp[2][2] += 1.0;
ierror = MathExtra::mldivide3(temp,rhat,w);
- if (ierror) error->all("Bad matrix inversion in mldivide3");
+ if (ierror) error->all(FLERR,"Bad matrix inversion in mldivide3");
h12 = rnorm-sigma12;
chi = 2.0*MathExtra::dot3(rhat,w);
sigh = sigma[type[i]][type[j]]/h12;
tprod = chi*sigh;
h12p3 = pow(h12,3.0);
double sigmap3 = pow(sigma[type[i]][type[j]],3.0);
double stemp = h12/2.0;
Ua = (shape1[type[i]][0]+stemp)*(shape1[type[i]][1]+stemp)*
(shape1[type[i]][2]+stemp)*h12p3/8.0;
Ua = (1.0+3.0*tprod)*lshape[type[i]]/Ua;
Ua = epsilon[type[i]][type[j]]*Ua*sigmap3*solv_f_a;
stemp = h12/cr60;
Ur = (shape1[type[i]][0]+stemp)*(shape1[type[i]][1]+stemp)*
(shape1[type[i]][2]+stemp)*h12p3/60.0;
Ur = (1.0+b_alpha*tprod)*lshape[type[i]]/Ur;
Ur = epsilon[type[i]][type[j]]*Ur*sigmap3*pow(sigh,6.0)*solv_f_r;
// force
sec = sigma[type[i]][type[j]]*chi;
sigma12p3 = pow(sigma12,3.0);
fourw[0] = 4.0*w[0];
fourw[1] = 4.0*w[1];
fourw[2] = 4.0*w[2];
spr[0] = 0.5*sigma12p3*s[0];
spr[1] = 0.5*sigma12p3*s[1];
spr[2] = 0.5*sigma12p3*s[2];
stemp = 1.0/(shape1[type[i]][0]*2.0+h12)+
1.0/(shape1[type[i]][1]*2.0+h12)+
1.0/(shape1[type[i]][2]*2.0+h12)+
3.0/h12;
hsec = h12+3.0*sec;
dspu = 1.0/h12-1.0/hsec+stemp;
pbsu = 3.0*sigma[type[i]][type[j]]/hsec;
stemp = 1.0/(shape1[type[i]][0]*cr60+h12)+
1.0/(shape1[type[i]][1]*cr60+h12)+
1.0/(shape1[type[i]][2]*cr60+h12)+
3.0/h12;
hsec = h12+b_alpha*sec;
dspr = 7.0/h12-1.0/hsec+stemp;
pbsr = b_alpha*sigma[type[i]][type[j]]/hsec;
for (int i=0; i<3; i++) {
u[0] = -rhat[i]*rhat[0];
u[1] = -rhat[i]*rhat[1];
u[2] = -rhat[i]*rhat[2];
u[i] += 1.0;
u[0] /= rnorm;
u[1] /= rnorm;
u[2] /= rnorm;
dchi = MathExtra::dot3(u,fourw);
dh12 = rhat[i]+MathExtra::dot3(u,spr);
dUa = pbsu*dchi-dh12*dspu;
dUr = pbsr*dchi-dh12*dspr;
fforce[i]=dUr*Ur+dUa*Ua;
}
// torque on i
if (calc_torque) {
MathExtra::vecmat(fourw,wi.aTe,fwae);
for (int i=0; i<3; i++) {
MathExtra::matvec(wi.lA[i],rhat,p);
double tempv[3];
MathExtra::matvec(wi.lA[i],w,tempv);
dchi = -MathExtra::dot3(fwae,tempv);
MathExtra::matvec(lAtwo[i],spr,tempv);
dh12 = -MathExtra::dot3(s,tempv);
dUa = pbsu*dchi-dh12*dspu;
dUr = pbsr*dchi-dh12*dspr;
ttor[i] = -(dUa*Ua+dUr*Ur);
}
}
return Ua+Ur;
}
diff --git a/src/CLASS2/angle_class2.cpp b/src/CLASS2/angle_class2.cpp
index ed9f16285..ca69cca5b 100644
--- a/src/CLASS2/angle_class2.cpp
+++ b/src/CLASS2/angle_class2.cpp
@@ -1,446 +1,446 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Eric Simon (Cray)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "angle_class2.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleClass2::AngleClass2(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleClass2::~AngleClass2()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(setflag_a);
memory->destroy(setflag_bb);
memory->destroy(setflag_ba);
memory->destroy(theta0);
memory->destroy(k2);
memory->destroy(k3);
memory->destroy(k4);
memory->destroy(bb_k);
memory->destroy(bb_r1);
memory->destroy(bb_r2);
memory->destroy(ba_k1);
memory->destroy(ba_k2);
memory->destroy(ba_r1);
memory->destroy(ba_r2);
}
}
/* ---------------------------------------------------------------------- */
void AngleClass2::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3];
double dtheta,dtheta2,dtheta3,dtheta4,de_angle;
double dr1,dr2,tk1,tk2,aa1,aa2,aa11,aa12,aa21,aa22;
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22,b1,b2;
double vx11,vx12,vy11,vy12,vz11,vz12,vx21,vx22,vy21,vy22,vz21,vz22;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
s = 1.0/s;
// force & energy for angle term
dtheta = acos(c) - theta0[type];
dtheta2 = dtheta*dtheta;
dtheta3 = dtheta2*dtheta;
dtheta4 = dtheta3*dtheta;
de_angle = 2.0*k2[type]*dtheta + 3.0*k3[type]*dtheta2 +
4.0*k4[type]*dtheta3;
a = -de_angle*s;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
if (eflag) eangle = k2[type]*dtheta2 + k3[type]*dtheta3 + k4[type]*dtheta4;
// force & energy for bond-bond term
dr1 = r1 - bb_r1[type];
dr2 = r2 - bb_r2[type];
tk1 = bb_k[type] * dr1;
tk2 = bb_k[type] * dr2;
f1[0] -= delx1*tk2/r1;
f1[1] -= dely1*tk2/r1;
f1[2] -= delz1*tk2/r1;
f3[0] -= delx2*tk1/r2;
f3[1] -= dely2*tk1/r2;
f3[2] -= delz2*tk1/r2;
if (eflag) eangle += bb_k[type]*dr1*dr2;
// force & energy for bond-angle term
aa1 = s * dr1 * ba_k1[type];
aa2 = s * dr2 * ba_k2[type];
aa11 = aa1 * c / rsq1;
aa12 = -aa1 / (r1 * r2);
aa21 = aa2 * c / rsq1;
aa22 = -aa2 / (r1 * r2);
vx11 = (aa11 * delx1) + (aa12 * delx2);
vx12 = (aa21 * delx1) + (aa22 * delx2);
vy11 = (aa11 * dely1) + (aa12 * dely2);
vy12 = (aa21 * dely1) + (aa22 * dely2);
vz11 = (aa11 * delz1) + (aa12 * delz2);
vz12 = (aa21 * delz1) + (aa22 * delz2);
aa11 = aa1 * c / rsq2;
aa21 = aa2 * c / rsq2;
vx21 = (aa11 * delx2) + (aa12 * delx1);
vx22 = (aa21 * delx2) + (aa22 * delx1);
vy21 = (aa11 * dely2) + (aa12 * dely1);
vy22 = (aa21 * dely2) + (aa22 * dely1);
vz21 = (aa11 * delz2) + (aa12 * delz1);
vz22 = (aa21 * delz2) + (aa22 * delz1);
b1 = ba_k1[type] * dtheta / r1;
b2 = ba_k2[type] * dtheta / r2;
f1[0] -= vx11 + b1*delx1 + vx12;
f1[1] -= vy11 + b1*dely1 + vy12;
f1[2] -= vz11 + b1*delz1 + vz12;
f3[0] -= vx21 + b2*delx2 + vx22;
f3[1] -= vy21 + b2*dely2 + vy22;
f3[2] -= vz21 + b2*delz2 + vz22;
if (eflag) eangle += ba_k1[type]*dr1*dtheta + ba_k2[type]*dr2*dtheta;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleClass2::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(theta0,n+1,"angle:theta0");
memory->create(k2,n+1,"angle:k2");
memory->create(k3,n+1,"angle:k3");
memory->create(k4,n+1,"angle:k4");
memory->create(bb_k,n+1,"angle:bb_k");
memory->create(bb_r1,n+1,"angle:bb_r1");
memory->create(bb_r2,n+1,"angle:bb_r2");
memory->create(ba_k1,n+1,"angle:ba_k1");
memory->create(ba_k2,n+1,"angle:ba_k2");
memory->create(ba_r1,n+1,"angle:ba_r1");
memory->create(ba_r2,n+1,"angle:ba_r2");
memory->create(setflag,n+1,"angle:setflag");
memory->create(setflag_a,n+1,"angle:setflag_a");
memory->create(setflag_bb,n+1,"angle:setflag_bb");
memory->create(setflag_ba,n+1,"angle:setflag_ba");
for (int i = 1; i <= n; i++)
setflag[i] = setflag_a[i] = setflag_bb[i] = setflag_ba[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
arg1 = "bb" -> BondBond coeffs
arg1 = "ba" -> BondAngle coeffs
else -> Angle coeffs
------------------------------------------------------------------------- */
void AngleClass2::coeff(int narg, char **arg)
{
- if (narg < 2) error->all("Incorrect args for angle coefficients");
+ if (narg < 2) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
int count = 0;
if (strcmp(arg[1],"bb") == 0) {
- if (narg != 5) error->all("Incorrect args for angle coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for angle coefficients");
double bb_k_one = force->numeric(arg[2]);
double bb_r1_one = force->numeric(arg[3]);
double bb_r2_one = force->numeric(arg[4]);
for (int i = ilo; i <= ihi; i++) {
bb_k[i] = bb_k_one;
bb_r1[i] = bb_r1_one;
bb_r2[i] = bb_r2_one;
setflag_bb[i] = 1;
count++;
}
} else if (strcmp(arg[1],"ba") == 0) {
- if (narg != 6) error->all("Incorrect args for angle coefficients");
+ if (narg != 6) error->all(FLERR,"Incorrect args for angle coefficients");
double ba_k1_one = force->numeric(arg[2]);
double ba_k2_one = force->numeric(arg[3]);
double ba_r1_one = force->numeric(arg[4]);
double ba_r2_one = force->numeric(arg[5]);
for (int i = ilo; i <= ihi; i++) {
ba_k1[i] = ba_k1_one;
ba_k2[i] = ba_k2_one;
ba_r1[i] = ba_r1_one;
ba_r2[i] = ba_r2_one;
setflag_ba[i] = 1;
count++;
}
} else {
- if (narg != 5) error->all("Incorrect args for angle coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for angle coefficients");
double theta0_one = force->numeric(arg[1]);
double k2_one = force->numeric(arg[2]);
double k3_one = force->numeric(arg[3]);
double k4_one = force->numeric(arg[4]);
// convert theta0 from degrees to radians
for (int i = ilo; i <= ihi; i++) {
theta0[i] = theta0_one/180.0 * PI;
k2[i] = k2_one;
k3[i] = k3_one;
k4[i] = k4_one;
setflag_a[i] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
for (int i = ilo; i <= ihi; i++)
if (setflag_a[i] == 1 && setflag_bb[i] == 1 && setflag_ba[i] == 1)
setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleClass2::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleClass2::write_restart(FILE *fp)
{
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
fwrite(&k2[1],sizeof(double),atom->nangletypes,fp);
fwrite(&k3[1],sizeof(double),atom->nangletypes,fp);
fwrite(&k4[1],sizeof(double),atom->nangletypes,fp);
fwrite(&bb_k[1],sizeof(double),atom->nangletypes,fp);
fwrite(&bb_r1[1],sizeof(double),atom->nangletypes,fp);
fwrite(&bb_r2[1],sizeof(double),atom->nangletypes,fp);
fwrite(&ba_k1[1],sizeof(double),atom->nangletypes,fp);
fwrite(&ba_k2[1],sizeof(double),atom->nangletypes,fp);
fwrite(&ba_r1[1],sizeof(double),atom->nangletypes,fp);
fwrite(&ba_r2[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleClass2::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
fread(&k2[1],sizeof(double),atom->nangletypes,fp);
fread(&k3[1],sizeof(double),atom->nangletypes,fp);
fread(&k4[1],sizeof(double),atom->nangletypes,fp);
fread(&bb_k[1],sizeof(double),atom->nangletypes,fp);
fread(&bb_r1[1],sizeof(double),atom->nangletypes,fp);
fread(&bb_r2[1],sizeof(double),atom->nangletypes,fp);
fread(&ba_k1[1],sizeof(double),atom->nangletypes,fp);
fread(&ba_k2[1],sizeof(double),atom->nangletypes,fp);
fread(&ba_r1[1],sizeof(double),atom->nangletypes,fp);
fread(&ba_r2[1],sizeof(double),atom->nangletypes,fp);
}
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k2[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k3[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k4[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&bb_k[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&bb_r1[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&bb_r2[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ba_k1[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ba_k2[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ba_r1[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ba_r2[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleClass2::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
s = 1.0/s;
double dtheta = acos(c) - theta0[type];
double dtheta2 = dtheta*dtheta;
double dtheta3 = dtheta2*dtheta;
double dtheta4 = dtheta3*dtheta;
double energy = k2[type]*dtheta2 + k3[type]*dtheta3 + k4[type]*dtheta4;
double dr1 = r1 - bb_r1[type];
double dr2 = r2 - bb_r2[type];
energy += bb_k[type]*dr1*dr2;
energy += ba_k1[type]*dr1*dtheta + ba_k2[type]*dr2*dtheta;
return energy;
}
diff --git a/src/CLASS2/bond_class2.cpp b/src/CLASS2/bond_class2.cpp
index 39e797ad9..f18d687fe 100644
--- a/src/CLASS2/bond_class2.cpp
+++ b/src/CLASS2/bond_class2.cpp
@@ -1,209 +1,209 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Eric Simon (Cray)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "bond_class2.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondClass2::BondClass2(LAMMPS *lmp) : Bond(lmp) {}
/* ---------------------------------------------------------------------- */
BondClass2::~BondClass2()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(r0);
memory->destroy(k2);
memory->destroy(k3);
memory->destroy(k4);
}
}
/* ---------------------------------------------------------------------- */
void BondClass2::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r,dr,dr2,dr3,dr4,de_bond;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
dr = r - r0[type];
dr2 = dr*dr;
dr3 = dr2*dr;
dr4 = dr3*dr;
// force & energy
de_bond = 2.0*k2[type]*dr + 3.0*k3[type]*dr2 + 4.0*k4[type]*dr3;
if (r > 0.0) fbond = -de_bond/r;
else fbond = 0.0;
if (eflag) ebond = k2[type]*dr2 + k3[type]*dr3 + k4[type]*dr4;
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondClass2::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(r0,n+1,"bond:r0");
memory->create(k2,n+1,"bond:k2");
memory->create(k3,n+1,"bond:k3");
memory->create(k4,n+1,"bond:k4");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs from one line in input script or data file
------------------------------------------------------------------------- */
void BondClass2::coeff(int narg, char **arg)
{
- if (narg != 5) error->all("Incorrect args for bond coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double r0_one = force->numeric(arg[1]);
double k2_one = force->numeric(arg[2]);
double k3_one = force->numeric(arg[3]);
double k4_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
r0[i] = r0_one;
k2[i] = k2_one;
k3[i] = k3_one;
k4[i] = k4_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondClass2::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondClass2::write_restart(FILE *fp)
{
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&k2[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&k3[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&k4[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondClass2::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
fread(&k2[1],sizeof(double),atom->nbondtypes,fp);
fread(&k3[1],sizeof(double),atom->nbondtypes,fp);
fread(&k4[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k2[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k3[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k4[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondClass2::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
double dr = r - r0[type];
double dr2 = dr*dr;
double dr3 = dr2*dr;
double dr4 = dr3*dr;
return (k2[type]*dr2 + k3[type]*dr3 + k4[type]*dr4);
}
diff --git a/src/CLASS2/dihedral_class2.cpp b/src/CLASS2/dihedral_class2.cpp
index 695333a56..d6e31696d 100644
--- a/src/CLASS2/dihedral_class2.cpp
+++ b/src/CLASS2/dihedral_class2.cpp
@@ -1,911 +1,908 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Eric Simon (Cray)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "dihedral_class2.h"
#include "atom.h"
#include "neighbor.h"
#include "update.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define TOLERANCE 0.05
#define SMALL 0.0000001
/* ---------------------------------------------------------------------- */
DihedralClass2::DihedralClass2(LAMMPS *lmp) : Dihedral(lmp)
{
PI = 4.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
DihedralClass2::~DihedralClass2()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(setflag_d);
memory->destroy(setflag_mbt);
memory->destroy(setflag_ebt);
memory->destroy(setflag_at);
memory->destroy(setflag_aat);
memory->destroy(setflag_bb13t);
memory->destroy(k1);
memory->destroy(k2);
memory->destroy(k3);
memory->destroy(phi1);
memory->destroy(phi2);
memory->destroy(phi3);
memory->destroy(mbt_f1);
memory->destroy(mbt_f2);
memory->destroy(mbt_f3);
memory->destroy(mbt_r0);
memory->destroy(ebt_f1_1);
memory->destroy(ebt_f2_1);
memory->destroy(ebt_f3_1);
memory->destroy(ebt_r0_1);
memory->destroy(ebt_f1_2);
memory->destroy(ebt_f2_2);
memory->destroy(ebt_f3_2);
memory->destroy(ebt_r0_2);
memory->destroy(at_f1_1);
memory->destroy(at_f2_1);
memory->destroy(at_f3_1);
memory->destroy(at_theta0_1);
memory->destroy(at_f1_2);
memory->destroy(at_f2_2);
memory->destroy(at_f3_2);
memory->destroy(at_theta0_2);
memory->destroy(aat_k);
memory->destroy(aat_theta0_1);
memory->destroy(aat_theta0_2);
memory->destroy(bb13t_k);
memory->destroy(bb13t_r10);
memory->destroy(bb13t_r30);
}
}
/* ---------------------------------------------------------------------- */
void DihedralClass2::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,i,j,k,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double edihedral;
double r1mag2,r1,r2mag2,r2,r3mag2,r3;
double sb1,rb1,sb2,rb2,sb3,rb3,c0,r12c1;
double r12c2,costh12,costh13,costh23,sc1,sc2,s1,s2,c;
double cosphi,phi,sinphi,a11,a22,a33,a12,a13,a23,sx1,sx2;
double sx12,sy1,sy2,sy12,sz1,sz2,sz12,dphi1,dphi2,dphi3;
double de_dihedral,t1,t2,t3,t4,cos2phi,cos3phi,bt1,bt2;
double bt3,sumbte,db,sumbtf,at1,at2,at3,da,da1,da2,r1_0;
double r3_0,dr1,dr2,tk1,tk2,s12,sin2;
double dcosphidr[4][3],dphidr[4][3],dbonddr[3][4][3],dthetadr[2][4][3];
double fabcd[4][3];
edihedral = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **dihedrallist = neighbor->dihedrallist;
int ndihedrallist = neighbor->ndihedrallist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < ndihedrallist; n++) {
i1 = dihedrallist[n][0];
i2 = dihedrallist[n][1];
i3 = dihedrallist[n][2];
i4 = dihedrallist[n][3];
type = dihedrallist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// distances
r1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
r1 = sqrt(r1mag2);
r2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
r2 = sqrt(r2mag2);
r3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
r3 = sqrt(r3mag2);
sb1 = 1.0/r1mag2;
rb1 = 1.0/r1;
sb2 = 1.0/r2mag2;
rb2 = 1.0/r2;
sb3 = 1.0/r3mag2;
rb3 = 1.0/r3;
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
// angles
r12c1 = rb1*rb2;
r12c2 = rb2*rb3;
costh12 = (vb1x*vb2x + vb1y*vb2y + vb1z*vb2z) * r12c1;
costh13 = c0;
costh23 = (vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z) * r12c2;
// cos and sin of 2 angles and final c
sin2 = MAX(1.0 - costh12*costh12,0.0);
sc1 = sqrt(sin2);
if (sc1 < SMALL) sc1 = SMALL;
sc1 = 1.0/sc1;
sin2 = MAX(1.0 - costh23*costh23,0.0);
sc2 = sqrt(sin2);
if (sc2 < SMALL) sc2 = SMALL;
sc2 = 1.0/sc2;
s1 = sc1 * sc1;
s2 = sc2 * sc2;
s12 = sc1 * sc2;
c = (c0 + costh12*costh23) * s12;
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
cosphi = c;
phi = acos(c);
sinphi = sqrt(1.0 - c*c);
sinphi = MAX(sinphi,SMALL);
a11 = -c*sb1*s1;
a22 = sb2 * (2.0*costh13*s12 - c*(s1+s2));
a33 = -c*sb3*s2;
a12 = r12c1 * (costh12*c*s1 + costh23*s12);
a13 = rb1*rb3*s12;
a23 = r12c2 * (-costh23*c*s2 - costh12*s12);
sx1 = a11*vb1x + a12*vb2x + a13*vb3x;
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
sx12 = a13*vb1x + a23*vb2x + a33*vb3x;
sy1 = a11*vb1y + a12*vb2y + a13*vb3y;
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
sy12 = a13*vb1y + a23*vb2y + a33*vb3y;
sz1 = a11*vb1z + a12*vb2z + a13*vb3z;
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
sz12 = a13*vb1z + a23*vb2z + a33*vb3z;
// set up d(cos(phi))/d(r) and dphi/dr arrays
dcosphidr[0][0] = -sx1;
dcosphidr[0][1] = -sy1;
dcosphidr[0][2] = -sz1;
dcosphidr[1][0] = sx2 + sx1;
dcosphidr[1][1] = sy2 + sy1;
dcosphidr[1][2] = sz2 + sz1;
dcosphidr[2][0] = sx12 - sx2;
dcosphidr[2][1] = sy12 - sy2;
dcosphidr[2][2] = sz12 - sz2;
dcosphidr[3][0] = -sx12;
dcosphidr[3][1] = -sy12;
dcosphidr[3][2] = -sz12;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
dphidr[i][j] = -dcosphidr[i][j] / sinphi;
// energy
dphi1 = phi - phi1[type];
dphi2 = 2.0*phi - phi2[type];
dphi3 = 3.0*phi - phi3[type];
if (eflag) edihedral = k1[type]*(1.0 - cos(dphi1)) +
k2[type]*(1.0 - cos(dphi2)) +
k3[type]*(1.0 - cos(dphi3));
de_dihedral = k1[type]*sin(dphi1) + 2.0*k2[type]*sin(dphi2) +
3.0*k3[type]*sin(dphi3);
// torsion forces on all 4 atoms
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] = de_dihedral*dphidr[i][j];
// set up d(bond)/d(r) array
// dbonddr(i,j,k) = bond i, atom j, coordinate k
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
for (k = 0; k < 3; k++)
dbonddr[i][j][k] = 0.0;
// bond1
dbonddr[0][0][0] = vb1x / r1;
dbonddr[0][0][1] = vb1y / r1;
dbonddr[0][0][2] = vb1z / r1;
dbonddr[0][1][0] = -vb1x / r1;
dbonddr[0][1][1] = -vb1y / r1;
dbonddr[0][1][2] = -vb1z / r1;
// bond2
dbonddr[1][1][0] = vb2x / r2;
dbonddr[1][1][1] = vb2y / r2;
dbonddr[1][1][2] = vb2z / r2;
dbonddr[1][2][0] = -vb2x / r2;
dbonddr[1][2][1] = -vb2y / r2;
dbonddr[1][2][2] = -vb2z / r2;
// bond3
dbonddr[2][2][0] = vb3x / r3;
dbonddr[2][2][1] = vb3y / r3;
dbonddr[2][2][2] = vb3z / r3;
dbonddr[2][3][0] = -vb3x / r3;
dbonddr[2][3][1] = -vb3y / r3;
dbonddr[2][3][2] = -vb3z / r3;
// set up d(theta)/d(r) array
// dthetadr(i,j,k) = angle i, atom j, coordinate k
for (i = 0; i < 2; i++)
for (j = 0; j < 4; j++)
for (k = 0; k < 3; k++)
dthetadr[i][j][k] = 0.0;
t1 = costh12 / r1mag2;
t2 = costh23 / r2mag2;
t3 = costh12 / r2mag2;
t4 = costh23 / r3mag2;
// angle12
dthetadr[0][0][0] = sc1 * ((t1 * vb1x) - (vb2x * r12c1));
dthetadr[0][0][1] = sc1 * ((t1 * vb1y) - (vb2y * r12c1));
dthetadr[0][0][2] = sc1 * ((t1 * vb1z) - (vb2z * r12c1));
dthetadr[0][1][0] = sc1 * ((-t1 * vb1x) + (vb2x * r12c1) +
(-t3 * vb2x) + (vb1x * r12c1));
dthetadr[0][1][1] = sc1 * ((-t1 * vb1y) + (vb2y * r12c1) +
(-t3 * vb2y) + (vb1y * r12c1));
dthetadr[0][1][2] = sc1 * ((-t1 * vb1z) + (vb2z * r12c1) +
(-t3 * vb2z) + (vb1z * r12c1));
dthetadr[0][2][0] = sc1 * ((t3 * vb2x) - (vb1x * r12c1));
dthetadr[0][2][1] = sc1 * ((t3 * vb2y) - (vb1y * r12c1));
dthetadr[0][2][2] = sc1 * ((t3 * vb2z) - (vb1z * r12c1));
// angle23
dthetadr[1][1][0] = sc2 * ((t2 * vb2x) + (vb3x * r12c2));
dthetadr[1][1][1] = sc2 * ((t2 * vb2y) + (vb3y * r12c2));
dthetadr[1][1][2] = sc2 * ((t2 * vb2z) + (vb3z * r12c2));
dthetadr[1][2][0] = sc2 * ((-t2 * vb2x) - (vb3x * r12c2) +
(t4 * vb3x) + (vb2x * r12c2));
dthetadr[1][2][1] = sc2 * ((-t2 * vb2y) - (vb3y * r12c2) +
(t4 * vb3y) + (vb2y * r12c2));
dthetadr[1][2][2] = sc2 * ((-t2 * vb2z) - (vb3z * r12c2) +
(t4 * vb3z) + (vb2z * r12c2));
dthetadr[1][3][0] = -sc2 * ((t4 * vb3x) + (vb2x * r12c2));
dthetadr[1][3][1] = -sc2 * ((t4 * vb3y) + (vb2y * r12c2));
dthetadr[1][3][2] = -sc2 * ((t4 * vb3z) + (vb2z * r12c2));
// mid-bond/torsion coupling
// energy on bond2 (middle bond)
cos2phi = cos(2.0*phi);
cos3phi = cos(3.0*phi);
bt1 = mbt_f1[type] * cosphi;
bt2 = mbt_f2[type] * cos2phi;
bt3 = mbt_f3[type] * cos3phi;
sumbte = bt1 + bt2 + bt3;
db = r2 - mbt_r0[type];
if (eflag) edihedral += db * sumbte;
// force on bond2
bt1 = -mbt_f1[type] * sinphi;
bt2 = -2.0 * mbt_f2[type] * sin(2.0*phi);
bt3 = -3.0 * mbt_f3[type] * sin(3.0*phi);
sumbtf = bt1 + bt2 + bt3;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] += db*sumbtf*dphidr[i][j] + sumbte*dbonddr[1][i][j];
// end-bond/torsion coupling
// energy on bond1 (first bond)
bt1 = ebt_f1_1[type] * cosphi;
bt2 = ebt_f2_1[type] * cos2phi;
bt3 = ebt_f3_1[type] * cos3phi;
sumbte = bt1 + bt2 + bt3;
db = r1 - ebt_r0_1[type];
if (eflag) edihedral += db * (bt1+bt2+bt3);
// force on bond1
bt1 = ebt_f1_1[type] * sinphi;
bt2 = 2.0 * ebt_f2_1[type] * sin(2.0*phi);
bt3 = 3.0 * ebt_f3_1[type] * sin(3.0*phi);
sumbtf = bt1 + bt2 + bt3;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] -= db*sumbtf*dphidr[i][j] + sumbte*dbonddr[0][i][j];
// end-bond/torsion coupling
// energy on bond3 (last bond)
bt1 = ebt_f1_2[type] * cosphi;
bt2 = ebt_f2_2[type] * cos2phi;
bt3 = ebt_f3_2[type] * cos3phi;
sumbte = bt1 + bt2 + bt3;
db = r3 - ebt_r0_2[type];
if (eflag) edihedral += db * (bt1+bt2+bt3);
// force on bond3
bt1 = -ebt_f1_2[type] * sinphi;
bt2 = -2.0 * ebt_f2_2[type] * sin(2.0*phi);
bt3 = -3.0 * ebt_f3_2[type] * sin(3.0*phi);
sumbtf = bt1 + bt2 + bt3;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] += db*sumbtf*dphidr[i][j] + sumbte*dbonddr[2][i][j];
// angle/torsion coupling
// energy on angle1
at1 = at_f1_1[type] * cosphi;
at2 = at_f2_1[type] * cos2phi;
at3 = at_f3_1[type] * cos3phi;
sumbte = at1 + at2 + at3;
da = acos(costh12) - at_theta0_1[type];
if (eflag) edihedral += da * (at1+at2+at3);
// force on angle1
bt1 = at_f1_1[type] * sinphi;
bt2 = 2.0 * at_f2_1[type] * sin(2.0*phi);
bt3 = 3.0 * at_f3_1[type] * sin(3.0*phi);
sumbtf = bt1 + bt2 + bt3;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] -= da*sumbtf*dphidr[i][j] + sumbte*dthetadr[0][i][j];
// energy on angle2
at1 = at_f1_2[type] * cosphi;
at2 = at_f2_2[type] * cos2phi;
at3 = at_f3_2[type] * cos3phi;
sumbte = at1 + at2 + at3;
da = acos(costh23) - at_theta0_2[type];
if (eflag) edihedral += da * (at1+at2+at3);
// force on angle2
bt1 = -at_f1_2[type] * sinphi;
bt2 = -2.0 * at_f2_2[type] * sin(2.0*phi);
bt3 = -3.0 * at_f3_2[type] * sin(3.0*phi);
sumbtf = bt1 + bt2 + bt3;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] += da*sumbtf*dphidr[i][j] + sumbte*dthetadr[1][i][j];
// angle/angle/torsion coupling
da1 = acos(costh12) - aat_theta0_1[type];
da2 = acos(costh23) - aat_theta0_2[type];
if (eflag) edihedral += aat_k[type]*da1*da2*cosphi;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] -= aat_k[type] *
(cosphi * (da2*dthetadr[0][i][j] - da1*dthetadr[1][i][j]) +
sinphi * da1*da2*dphidr[i][j]);
// bond1/bond3 coupling
if (fabs(bb13t_k[type]) > SMALL) {
r1_0 = bb13t_r10[type];
r3_0 = bb13t_r30[type];
dr1 = r1 - r1_0;
dr2 = r3 - r3_0;
tk1 = -bb13t_k[type] * dr1 / r3;
tk2 = -bb13t_k[type] * dr2 / r1;
if (eflag) edihedral += bb13t_k[type]*dr1*dr2;
fabcd[0][0] += tk2 * vb1x;
fabcd[0][1] += tk2 * vb1y;
fabcd[0][2] += tk2 * vb1z;
fabcd[1][0] -= tk2 * vb1x;
fabcd[1][1] -= tk2 * vb1y;
fabcd[1][2] -= tk2 * vb1z;
fabcd[2][0] -= tk1 * vb3x;
fabcd[2][1] -= tk1 * vb3y;
fabcd[2][2] -= tk1 * vb3z;
fabcd[3][0] += tk1 * vb3x;
fabcd[3][1] += tk1 * vb3y;
fabcd[3][2] += tk1 * vb3z;
}
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += fabcd[0][0];
f[i1][1] += fabcd[0][1];
f[i1][2] += fabcd[0][2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += fabcd[1][0];
f[i2][1] += fabcd[1][1];
f[i2][2] += fabcd[1][2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += fabcd[2][0];
f[i3][1] += fabcd[2][1];
f[i3][2] += fabcd[2][2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += fabcd[3][0];
f[i4][1] += fabcd[3][1];
f[i4][2] += fabcd[3][2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,
fabcd[0],fabcd[2],fabcd[3],
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void DihedralClass2::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(k1,n+1,"dihedral:k1");
memory->create(k2,n+1,"dihedral:k2");
memory->create(k3,n+1,"dihedral:k3");
memory->create(phi1,n+1,"dihedral:phi1");
memory->create(phi2,n+1,"dihedral:phi2");
memory->create(phi3,n+1,"dihedral:phi3");
memory->create(mbt_f1,n+1,"dihedral:mbt_f1");
memory->create(mbt_f2,n+1,"dihedral:mbt_f2");
memory->create(mbt_f3,n+1,"dihedral:mbt_f3");
memory->create(mbt_r0,n+1,"dihedral:mbt_r0");
memory->create(ebt_f1_1,n+1,"dihedral:ebt_f1_1");
memory->create(ebt_f2_1,n+1,"dihedral:ebt_f2_1");
memory->create(ebt_f3_1,n+1,"dihedral:ebt_f3_1");
memory->create(ebt_r0_1,n+1,"dihedral:ebt_r0_1");
memory->create(ebt_f1_2,n+1,"dihedral:ebt_f1_2");
memory->create(ebt_f2_2,n+1,"dihedral:ebt_f2_2");
memory->create(ebt_f3_2,n+1,"dihedral:ebt_f3_2");
memory->create(ebt_r0_2,n+1,"dihedral:ebt_r0_2");
memory->create(at_f1_1,n+1,"dihedral:at_f1_1");
memory->create(at_f2_1,n+1,"dihedral:at_f2_1");
memory->create(at_f3_1,n+1,"dihedral:at_f3_1");
memory->create(at_theta0_1,n+1,"dihedral:at_theta0_1");
memory->create(at_f1_2,n+1,"dihedral:at_f1_2");
memory->create(at_f2_2,n+1,"dihedral:at_f2_2");
memory->create(at_f3_2,n+1,"dihedral:at_f3_2");
memory->create(at_theta0_2,n+1,"dihedral:at_theta0_2");
memory->create(aat_k,n+1,"dihedral:aat_k");
memory->create(aat_theta0_1,n+1,"dihedral:aat_theta0_1");
memory->create(aat_theta0_2,n+1,"dihedral:aat_theta0_2");
memory->create(bb13t_k,n+1,"dihedral:bb13t_k");
memory->create(bb13t_r10,n+1,"dihedral:bb13t_r10");
memory->create(bb13t_r30,n+1,"dihedral:bb13t_r30");
memory->create(setflag,n+1,"dihedral:setflag");
memory->create(setflag_d,n+1,"dihedral:setflag_d");
memory->create(setflag_mbt,n+1,"dihedral:setflag_mbt");
memory->create(setflag_ebt,n+1,"dihedral:setflag_ebt");
memory->create(setflag_at,n+1,"dihedral:setflag_at");
memory->create(setflag_aat,n+1,"dihedral:setflag_aat");
memory->create(setflag_bb13t,n+1,"dihedral:setflag_bb13t");
for (int i = 1; i <= n; i++)
setflag[i] = setflag_d[i] = setflag_mbt[i] = setflag_ebt[i] =
setflag_at[i] = setflag_aat[i] = setflag_bb13t[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
arg1 = "mbt" -> MiddleBondTorsion coeffs
arg1 = "ebt" -> EndBondTorsion coeffs
arg1 = "at" -> AngleTorsion coeffs
arg1 = "aat" -> AngleAngleTorsion coeffs
arg1 = "bb13" -> BondBond13Torsion coeffs
arg1 -> Dihedral coeffs
------------------------------------------------------------------------- */
void DihedralClass2::coeff(int narg, char **arg)
{
- if (narg < 2) error->all("Invalid coeffs for this dihedral style");
+ if (narg < 2) error->all(FLERR,"Invalid coeffs for this dihedral style");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
int count = 0;
if (strcmp(arg[1],"mbt") == 0) {
- if (narg != 6) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 6) error->all(FLERR,"Incorrect args for dihedral coefficients");
double f1_one = force->numeric(arg[2]);
double f2_one = force->numeric(arg[3]);
double f3_one = force->numeric(arg[4]);
double r0_one = force->numeric(arg[5]);
for (int i = ilo; i <= ihi; i++) {
mbt_f1[i] = f1_one;
mbt_f2[i] = f2_one;
mbt_f3[i] = f3_one;
mbt_r0[i] = r0_one;
setflag_mbt[i] = 1;
count++;
}
} else if (strcmp(arg[1],"ebt") == 0) {
- if (narg != 10) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 10) error->all(FLERR,"Incorrect args for dihedral coefficients");
double f1_1_one = force->numeric(arg[2]);
double f2_1_one = force->numeric(arg[3]);
double f3_1_one = force->numeric(arg[4]);
double f1_2_one = force->numeric(arg[5]);
double f2_2_one = force->numeric(arg[6]);
double f3_2_one = force->numeric(arg[7]);
double r0_1_one = force->numeric(arg[8]);
double r0_2_one = force->numeric(arg[9]);
for (int i = ilo; i <= ihi; i++) {
ebt_f1_1[i] = f1_1_one;
ebt_f2_1[i] = f2_1_one;
ebt_f3_1[i] = f3_1_one;
ebt_f1_2[i] = f1_2_one;
ebt_f2_2[i] = f2_2_one;
ebt_f3_2[i] = f3_2_one;
ebt_r0_1[i] = r0_1_one;
ebt_r0_2[i] = r0_2_one;
setflag_ebt[i] = 1;
count++;
}
} else if (strcmp(arg[1],"at") == 0) {
- if (narg != 10) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 10) error->all(FLERR,"Incorrect args for dihedral coefficients");
double f1_1_one = force->numeric(arg[2]);
double f2_1_one = force->numeric(arg[3]);
double f3_1_one = force->numeric(arg[4]);
double f1_2_one = force->numeric(arg[5]);
double f2_2_one = force->numeric(arg[6]);
double f3_2_one = force->numeric(arg[7]);
double theta0_1_one = force->numeric(arg[8]);
double theta0_2_one = force->numeric(arg[9]);
// convert theta0's from degrees to radians
for (int i = ilo; i <= ihi; i++) {
at_f1_1[i] = f1_1_one;
at_f2_1[i] = f2_1_one;
at_f3_1[i] = f3_1_one;
at_f1_2[i] = f1_2_one;
at_f2_2[i] = f2_2_one;
at_f3_2[i] = f3_2_one;
at_theta0_1[i] = theta0_1_one/180.0 * PI;
at_theta0_2[i] = theta0_2_one/180.0 * PI;
setflag_at[i] = 1;
count++;
}
} else if (strcmp(arg[1],"aat") == 0) {
- if (narg != 5) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for dihedral coefficients");
double k_one = force->numeric(arg[2]);
double theta0_1_one = force->numeric(arg[3]);
double theta0_2_one = force->numeric(arg[4]);
// convert theta0's from degrees to radians
for (int i = ilo; i <= ihi; i++) {
aat_k[i] = k_one;
aat_theta0_1[i] = theta0_1_one/180.0 * PI;
aat_theta0_2[i] = theta0_2_one/180.0 * PI;
setflag_aat[i] = 1;
count++;
}
} else if (strcmp(arg[1],"bb13") == 0) {
- if (narg != 5) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for dihedral coefficients");
double k_one = force->numeric(arg[2]);
double r10_one = force->numeric(arg[3]);
double r30_one = force->numeric(arg[4]);
for (int i = ilo; i <= ihi; i++) {
bb13t_k[i] = k_one;
bb13t_r10[i] = r10_one;
bb13t_r30[i] = r30_one;
setflag_bb13t[i] = 1;
count++;
}
} else {
- if (narg != 7) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 7) error->all(FLERR,"Incorrect args for dihedral coefficients");
double k1_one = force->numeric(arg[1]);
double phi1_one = force->numeric(arg[2]);
double k2_one = force->numeric(arg[3]);
double phi2_one = force->numeric(arg[4]);
double k3_one = force->numeric(arg[5]);
double phi3_one = force->numeric(arg[6]);
// convert phi's from degrees to radians
for (int i = ilo; i <= ihi; i++) {
k1[i] = k1_one;
phi1[i] = phi1_one/180.0 * PI;
k2[i] = k2_one;
phi2[i] = phi2_one/180.0 * PI;
k3[i] = k3_one;
phi3[i] = phi3_one/180.0 * PI;
setflag_d[i] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for dihedral coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
for (int i = ilo; i <= ihi; i++)
if (setflag_d[i] == 1 && setflag_mbt[i] == 1 && setflag_ebt[i] == 1 &&
setflag_at[i] == 1 && setflag_aat[i] == 1 && setflag_bb13t[i] == 1)
setflag[i] = 1;
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralClass2::write_restart(FILE *fp)
{
fwrite(&k1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&k2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&k3[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&phi1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&phi2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&phi3[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&mbt_f1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&mbt_f2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&mbt_f3[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&mbt_r0[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_f1_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_f2_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_f3_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_r0_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_f1_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_f2_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_f3_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&ebt_r0_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_f1_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_f2_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_f3_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_theta0_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_f1_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_f2_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_f3_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&at_theta0_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&aat_k[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&aat_theta0_1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&aat_theta0_2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&bb13t_k[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&bb13t_r10[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&bb13t_r30[1],sizeof(double),atom->ndihedraltypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralClass2::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&k2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&k3[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&phi1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&phi2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&phi3[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&mbt_f1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&mbt_f2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&mbt_f3[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&mbt_r0[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_f1_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_f2_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_f3_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_r0_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_f1_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_f2_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_f3_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&ebt_r0_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_f1_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_f2_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_f3_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_theta0_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_f1_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_f2_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_f3_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&at_theta0_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&aat_k[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&aat_theta0_1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&aat_theta0_2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&bb13t_k[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&bb13t_r10[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&bb13t_r30[1],sizeof(double),atom->ndihedraltypes,fp);
}
MPI_Bcast(&k1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k3[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&phi1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&phi2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&phi3[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&mbt_f1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&mbt_f2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&mbt_f3[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&mbt_r0[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_f1_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_f2_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_f3_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_r0_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_f1_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_f2_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_f3_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ebt_r0_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_f1_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_f2_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_f3_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_theta0_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_f1_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_f2_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_f3_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&at_theta0_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aat_k[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aat_theta0_1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aat_theta0_2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&bb13t_k[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&bb13t_r10[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&bb13t_r30[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
}
diff --git a/src/CLASS2/improper_class2.cpp b/src/CLASS2/improper_class2.cpp
index 152c29bfa..7329870ae 100644
--- a/src/CLASS2/improper_class2.cpp
+++ b/src/CLASS2/improper_class2.cpp
@@ -1,845 +1,845 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Eric Simon (Cray)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "improper_class2.h"
#include "atom.h"
#include "neighbor.h"
#include "update.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
ImproperClass2::ImproperClass2(LAMMPS *lmp) : Improper(lmp)
{
PI = 4.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
ImproperClass2::~ImproperClass2()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(setflag_i);
memory->destroy(setflag_aa);
memory->destroy(k0);
memory->destroy(chi0);
memory->destroy(aa_k1);
memory->destroy(aa_k2);
memory->destroy(aa_k3);
memory->destroy(aa_theta0_1);
memory->destroy(aa_theta0_2);
memory->destroy(aa_theta0_3);
}
}
/* ---------------------------------------------------------------------- */
void ImproperClass2::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,i,j,k,n,type;
double eimproper;
double delr[3][3],rmag[3],rinvmag[3],rmag2[3];
double theta[3],costheta[3],sintheta[3];
double cossqtheta[3],sinsqtheta[3],invstheta[3];
double rABxrCB[3],rDBxrAB[3],rCBxrDB[3];
double ddelr[3][4],dr[3][4][3],dinvr[3][4][3];
double dthetadr[3][4][3],dinvsth[3][4][3];
double dinv3r[4][3],dinvs3r[3][4][3];
double drCBxrDB[3],rCBxdrDB[3],drDBxrAB[3],rDBxdrAB[3];
double drABxrCB[3],rABxdrCB[3];
double dot1,dot2,dd[3];
double fdot[3][4][3],ftmp,invs3r[3],inv3r;
double t,tt1,tt3,sc1;
double dotCBDBAB,dotDBABCB,dotABCBDB;
double chi,deltachi,d2chi,cossin2;
double drAB[3][4][3],drCB[3][4][3],drDB[3][4][3];
double dchi[3][4][3],dtotalchi[4][3];
double schiABCD,chiABCD,schiCBDA,chiCBDA,schiDBAC,chiDBAC;
double fabcd[4][3];
eimproper = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
for (k = 0; k < 3; k++) {
dthetadr[i][j][k] = 0.0;
drAB[i][j][k] = 0.0;
drCB[i][j][k] = 0.0;
drDB[i][j][k] = 0.0;
}
double **x = atom->x;
double **f = atom->f;
int **improperlist = neighbor->improperlist;
int nimproperlist = neighbor->nimproperlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nimproperlist; n++) {
i1 = improperlist[n][0];
i2 = improperlist[n][1];
i3 = improperlist[n][2];
i4 = improperlist[n][3];
type = improperlist[n][4];
if (k0[type] == 0.0) continue;
// difference vectors
delr[0][0] = x[i1][0] - x[i2][0];
delr[0][1] = x[i1][1] - x[i2][1];
delr[0][2] = x[i1][2] - x[i2][2];
domain->minimum_image(delr[0]);
delr[1][0] = x[i3][0] - x[i2][0];
delr[1][1] = x[i3][1] - x[i2][1];
delr[1][2] = x[i3][2] - x[i2][2];
domain->minimum_image(delr[1]);
delr[2][0] = x[i4][0] - x[i2][0];
delr[2][1] = x[i4][1] - x[i2][1];
delr[2][2] = x[i4][2] - x[i2][2];
domain->minimum_image(delr[2]);
// bond lengths and associated values
for (i = 0; i < 3; i++) {
rmag2[i] = delr[i][0]*delr[i][0] + delr[i][1]*delr[i][1] +
delr[i][2]*delr[i][2];
rmag[i] = sqrt(rmag2[i]);
rinvmag[i] = 1.0/rmag[i];
}
// angle ABC, CBD, ABD
costheta[0] = (delr[0][0]*delr[1][0] + delr[0][1]*delr[1][1] +
delr[0][2]*delr[1][2]) / (rmag[0]*rmag[1]);
costheta[1] = (delr[1][0]*delr[2][0] + delr[1][1]*delr[2][1] +
delr[1][2]*delr[2][2]) / (rmag[1]*rmag[2]);
costheta[2] = (delr[0][0]*delr[2][0] + delr[0][1]*delr[2][1] +
delr[0][2]*delr[2][2]) / (rmag[0]*rmag[2]);
// angle error check
for (i = 0; i < 3; i++) {
if (costheta[i] == -1.0) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,
"Improper problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
}
for (i = 0; i < 3; i++) {
if (costheta[i] > 1.0) costheta[i] = 1.0;
if (costheta[i] < -1.0) costheta[i] = -1.0;
theta[i] = acos(costheta[i]);
cossqtheta[i] = costheta[i]*costheta[i];
sintheta[i] = sin(theta[i]);
invstheta[i] = 1.0/sintheta[i];
sinsqtheta[i] = sintheta[i]*sintheta[i];
}
// cross & dot products
cross(delr[0],delr[1],rABxrCB);
cross(delr[2],delr[0],rDBxrAB);
cross(delr[1],delr[2],rCBxrDB);
dotCBDBAB = dot(rCBxrDB,delr[0]);
dotDBABCB = dot(rDBxrAB,delr[1]);
dotABCBDB = dot(rABxrCB,delr[2]);
t = rmag[0] * rmag[1] * rmag[2];
inv3r = 1.0/t;
invs3r[0] = invstheta[1] * inv3r;
invs3r[1] = invstheta[2] * inv3r;
invs3r[2] = invstheta[0] * inv3r;
// chi ABCD, CBDA, DBAC
// final chi is average of three
schiABCD = dotCBDBAB * invs3r[0];
chiABCD = asin(schiABCD);
schiCBDA = dotDBABCB * invs3r[1];
chiCBDA = asin(schiCBDA);
schiDBAC = dotABCBDB * invs3r[2];
chiDBAC = asin(schiDBAC);
chi = (chiABCD + chiCBDA + chiDBAC) / 3.0;
deltachi = chi - chi0[type];
d2chi = deltachi * deltachi;
// energy
if (eflag) eimproper = k0[type]*d2chi;
// forces
// define d(delr)
// i = bond AB/CB/DB, j = atom A/B/C/D
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
ddelr[i][j] = 0.0;
ddelr[0][0] = 1.0;
ddelr[0][1] = -1.0;
ddelr[1][1] = -1.0;
ddelr[1][2] = 1.0;
ddelr[2][1] = -1.0;
ddelr[2][3] = 1.0;
// compute d(|r|)/dr and d(1/|r|)/dr for each direction, bond and atom
// define d(r) for each r
// i = bond AB/CB/DB, j = atom A/B/C/D, k = X/Y/Z
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
for (k = 0; k < 3; k++) {
dr[i][j][k] = delr[i][k] * ddelr[i][j] / rmag[i];
dinvr[i][j][k] = -dr[i][j][k] / rmag2[i];
}
// compute d(1 / (|r_AB| * |r_CB| * |r_DB|) / dr
// i = atom A/B/C/D, j = X/Y/Z
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
dinv3r[i][j] = rinvmag[1] * (rinvmag[2] * dinvr[0][i][j] +
rinvmag[0] * dinvr[2][i][j]) +
rinvmag[2] * rinvmag[0] * dinvr[1][i][j];
// compute d(theta)/d(r) for 3 angles
// angleABC
tt1 = costheta[0] / rmag2[0];
tt3 = costheta[0] / rmag2[1];
sc1 = 1.0 / sqrt(1.0 - cossqtheta[0]);
dthetadr[0][0][0] = sc1 * ((tt1 * delr[0][0]) -
(delr[1][0] * rinvmag[0] * rinvmag[1]));
dthetadr[0][0][1] = sc1 * ((tt1 * delr[0][1]) -
(delr[1][1] * rinvmag[0] * rinvmag[1]));
dthetadr[0][0][2] = sc1 * ((tt1 * delr[0][2]) -
(delr[1][2] * rinvmag[0] * rinvmag[1]));
dthetadr[0][1][0] = -sc1 * ((tt1 * delr[0][0]) -
(delr[1][0] * rinvmag[0] * rinvmag[1]) +
(tt3 * delr[1][0]) -
(delr[0][0] * rinvmag[0] * rinvmag[1]));
dthetadr[0][1][1] = -sc1 * ((tt1 * delr[0][1]) -
(delr[1][1] * rinvmag[0] * rinvmag[1]) +
(tt3 * delr[1][1]) -
(delr[0][1] * rinvmag[0] * rinvmag[1]));
dthetadr[0][1][2] = -sc1 * ((tt1 * delr[0][2]) -
(delr[1][2] * rinvmag[0] * rinvmag[1]) +
(tt3 * delr[1][2]) -
(delr[0][2] * rinvmag[0] * rinvmag[1]));
dthetadr[0][2][0] = sc1 * ((tt3 * delr[1][0]) -
(delr[0][0] * rinvmag[0] * rinvmag[1]));
dthetadr[0][2][1] = sc1 * ((tt3 * delr[1][1]) -
(delr[0][1] * rinvmag[0] * rinvmag[1]));
dthetadr[0][2][2] = sc1 * ((tt3 * delr[1][2]) -
(delr[0][2] * rinvmag[0] * rinvmag[1]));
// angleCBD
tt1 = costheta[1] / rmag2[1];
tt3 = costheta[1] / rmag2[2];
sc1 = 1.0 / sqrt(1.0 - cossqtheta[1]);
dthetadr[1][2][0] = sc1 * ((tt1 * delr[1][0]) -
(delr[2][0] * rinvmag[1] * rinvmag[2]));
dthetadr[1][2][1] = sc1 * ((tt1 * delr[1][1]) -
(delr[2][1] * rinvmag[1] * rinvmag[2]));
dthetadr[1][2][2] = sc1 * ((tt1 * delr[1][2]) -
(delr[2][2] * rinvmag[1] * rinvmag[2]));
dthetadr[1][1][0] = -sc1 * ((tt1 * delr[1][0]) -
(delr[2][0] * rinvmag[1] * rinvmag[2]) +
(tt3 * delr[2][0]) -
(delr[1][0] * rinvmag[2] * rinvmag[1]));
dthetadr[1][1][1] = -sc1 * ((tt1 * delr[1][1]) -
(delr[2][1] * rinvmag[1] * rinvmag[2]) +
(tt3 * delr[2][1]) -
(delr[1][1] * rinvmag[2] * rinvmag[1]));
dthetadr[1][1][2] = -sc1 * ((tt1 * delr[1][2]) -
(delr[2][2] * rinvmag[1] * rinvmag[2]) +
(tt3 * delr[2][2]) -
(delr[1][2] * rinvmag[2] * rinvmag[1]));
dthetadr[1][3][0] = sc1 * ((tt3 * delr[2][0]) -
(delr[1][0] * rinvmag[2] * rinvmag[1]));
dthetadr[1][3][1] = sc1 * ((tt3 * delr[2][1]) -
(delr[1][1] * rinvmag[2] * rinvmag[1]));
dthetadr[1][3][2] = sc1 * ((tt3 * delr[2][2]) -
(delr[1][2] * rinvmag[2] * rinvmag[1]));
// angleABD
tt1 = costheta[2] / rmag2[0];
tt3 = costheta[2] / rmag2[2];
sc1 = 1.0 / sqrt(1.0 - cossqtheta[2]);
dthetadr[2][0][0] = sc1 * ((tt1 * delr[0][0]) -
(delr[2][0] * rinvmag[0] * rinvmag[2]));
dthetadr[2][0][1] = sc1 * ((tt1 * delr[0][1]) -
(delr[2][1] * rinvmag[0] * rinvmag[2]));
dthetadr[2][0][2] = sc1 * ((tt1 * delr[0][2]) -
(delr[2][2] * rinvmag[0] * rinvmag[2]));
dthetadr[2][1][0] = -sc1 * ((tt1 * delr[0][0]) -
(delr[2][0] * rinvmag[0] * rinvmag[2]) +
(tt3 * delr[2][0]) -
(delr[0][0] * rinvmag[2] * rinvmag[0]));
dthetadr[2][1][1] = -sc1 * ((tt1 * delr[0][1]) -
(delr[2][1] * rinvmag[0] * rinvmag[2]) +
(tt3 * delr[2][1]) -
(delr[0][1] * rinvmag[2] * rinvmag[0]));
dthetadr[2][1][2] = -sc1 * ((tt1 * delr[0][2]) -
(delr[2][2] * rinvmag[0] * rinvmag[2]) +
(tt3 * delr[2][2]) -
(delr[0][2] * rinvmag[2] * rinvmag[0]));
dthetadr[2][3][0] = sc1 * ((tt3 * delr[2][0]) -
(delr[0][0] * rinvmag[2] * rinvmag[0]));
dthetadr[2][3][1] = sc1 * ((tt3 * delr[2][1]) -
(delr[0][1] * rinvmag[2] * rinvmag[0]));
dthetadr[2][3][2] = sc1 * ((tt3 * delr[2][2]) -
(delr[0][2] * rinvmag[2] * rinvmag[0]));
// compute d( 1 / sin(theta))/dr
// i = angle, j = atom, k = direction
for (i = 0; i < 3; i++) {
cossin2 = -costheta[i] / sinsqtheta[i];
for (j = 0; j < 4; j++)
for (k = 0; k < 3; k++)
dinvsth[i][j][k] = cossin2 * dthetadr[i][j][k];
}
// compute d(1 / sin(theta) * |r_AB| * |r_CB| * |r_DB|)/dr
// i = angle, j = atom
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++) {
dinvs3r[0][i][j] = (invstheta[1] * dinv3r[i][j]) +
(inv3r * dinvsth[1][i][j]);
dinvs3r[1][i][j] = (invstheta[2] * dinv3r[i][j]) +
(inv3r * dinvsth[2][i][j]);
dinvs3r[2][i][j] = (invstheta[0] * dinv3r[i][j]) +
(inv3r * dinvsth[0][i][j]);
}
// drCB(i,j,k), etc
// i = vector X'/Y'/Z', j = atom A/B/C/D, k = direction X/Y/Z
for (i = 0; i < 3; i++) {
drCB[i][1][i] = -1.0;
drAB[i][1][i] = -1.0;
drDB[i][1][i] = -1.0;
drDB[i][3][i] = 1.0;
drCB[i][2][i] = 1.0;
drAB[i][0][i] = 1.0;
}
// d((r_CB x r_DB) dot r_AB)
// r_CB x d(r_DB)
// d(r_CB) x r_DB
// (r_CB x d(r_DB)) + (d(r_CB) x r_DB)
// (r_CB x d(r_DB)) + (d(r_CB) x r_DB) dot r_AB
// d(r_AB) dot (r_CB x r_DB)
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++) {
cross(delr[1],drDB[i][j],rCBxdrDB);
cross(drCB[i][j],delr[2],drCBxrDB);
for (k = 0; k < 3; k++) dd[k] = rCBxdrDB[k] + drCBxrDB[k];
dot1 = dot(dd,delr[0]);
dot2 = dot(rCBxrDB,drAB[i][j]);
fdot[0][j][i] = dot1 + dot2;
}
// d((r_DB x r_AB) dot r_CB)
// r_DB x d(r_AB)
// d(r_DB) x r_AB
// (r_DB x d(r_AB)) + (d(r_DB) x r_AB)
// (r_DB x d(r_AB)) + (d(r_DB) x r_AB) dot r_CB
// d(r_CB) dot (r_DB x r_AB)
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++) {
cross(delr[2],drAB[i][j],rDBxdrAB);
cross(drDB[i][j],delr[0],drDBxrAB);
for (k = 0; k < 3; k++) dd[k] = rDBxdrAB[k] + drDBxrAB[k];
dot1 = dot(dd,delr[1]);
dot2 = dot(rDBxrAB,drCB[i][j]);
fdot[1][j][i] = dot1 + dot2;
}
// d((r_AB x r_CB) dot r_DB)
// r_AB x d(r_CB)
// d(r_AB) x r_CB
// (r_AB x d(r_CB)) + (d(r_AB) x r_CB)
// (r_AB x d(r_CB)) + (d(r_AB) x r_CB) dot r_DB
// d(r_DB) dot (r_AB x r_CB)
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++) {
cross(delr[0],drCB[i][j],rABxdrCB);
cross(drAB[i][j],delr[1],drABxrCB);
for (k = 0; k < 3; k++) dd[k] = rABxdrCB[k] + drABxrCB[k];
dot1 = dot(dd,delr[2]);
dot2 = dot(rABxrCB,drDB[i][j]);
fdot[2][j][i] = dot1 + dot2;
}
// force on each atom
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++) {
ftmp = (fdot[0][i][j] * invs3r[0]) +
(dinvs3r[0][i][j] * dotCBDBAB);
dchi[0][i][j] = ftmp / cos(chiABCD);
ftmp = (fdot[1][i][j] * invs3r[1]) +
(dinvs3r[1][i][j] * dotDBABCB);
dchi[1][i][j] = ftmp / cos(chiCBDA);
ftmp = (fdot[2][i][j] * invs3r[2]) +
(dinvs3r[2][i][j] * dotABCBDB);
dchi[2][i][j] = ftmp / cos(chiDBAC);
dtotalchi[i][j] = (dchi[0][i][j]+dchi[1][i][j]+dchi[2][i][j]) / 3.0;
}
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] = -2.0*k0[type] * deltachi*dtotalchi[i][j];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += fabcd[0][0];
f[i1][1] += fabcd[0][1];
f[i1][2] += fabcd[0][2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += fabcd[1][0];
f[i2][1] += fabcd[1][1];
f[i2][2] += fabcd[1][2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += fabcd[2][0];
f[i3][1] += fabcd[2][1];
f[i3][2] += fabcd[2][2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += fabcd[3][0];
f[i4][1] += fabcd[3][1];
f[i4][2] += fabcd[3][2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,eimproper,
fabcd[0],fabcd[2],fabcd[3],
delr[0][0],delr[0][1],delr[0][2],
delr[1][0],delr[1][1],delr[1][2],
delr[2][0]-delr[1][0],delr[2][1]-delr[1][1],
delr[2][2]-delr[1][2]);
}
// compute angle-angle interactions
angleangle(eflag,vflag);
}
/* ---------------------------------------------------------------------- */
void ImproperClass2::allocate()
{
allocated = 1;
int n = atom->nimpropertypes;
memory->create(k0,n+1,"improper:k0");
memory->create(chi0,n+1,"improper:chi0");
memory->create(aa_k1,n+1,"improper:aa_k1");
memory->create(aa_k2,n+1,"improper:aa_k2");
memory->create(aa_k3,n+1,"improper:aa_k3");
memory->create(aa_theta0_1,n+1,"improper:aa_theta0_1");
memory->create(aa_theta0_2,n+1,"improper:aa_theta0_2");
memory->create(aa_theta0_3,n+1,"improper:aa_theta0_3");
memory->create(setflag,n+1,"improper:setflag");
memory->create(setflag_i,n+1,"improper:setflag_i");
memory->create(setflag_aa,n+1,"improper:setflag_aa");
for (int i = 1; i <= n; i++)
setflag[i] = setflag_i[i] = setflag_aa[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
arg1 = "aa" -> AngleAngle coeffs
else arg1 -> improper coeffs
------------------------------------------------------------------------- */
void ImproperClass2::coeff(int narg, char **arg)
{
- if (narg < 2) error->all("Incorrect args for improper coefficients");
+ if (narg < 2) error->all(FLERR,"Incorrect args for improper coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
int count = 0;
if (strcmp(arg[1],"aa") == 0) {
- if (narg != 8) error->all("Incorrect args for improper coefficients");
+ if (narg != 8) error->all(FLERR,"Incorrect args for improper coefficients");
double k1_one = force->numeric(arg[2]);
double k2_one = force->numeric(arg[3]);
double k3_one = force->numeric(arg[4]);
double theta0_1_one = force->numeric(arg[5]);
double theta0_2_one = force->numeric(arg[6]);
double theta0_3_one = force->numeric(arg[7]);
// convert theta0's from degrees to radians
for (int i = ilo; i <= ihi; i++) {
aa_k1[i] = k1_one;
aa_k2[i] = k2_one;
aa_k3[i] = k3_one;
aa_theta0_1[i] = theta0_1_one/180.0 * PI;
aa_theta0_2[i] = theta0_2_one/180.0 * PI;
aa_theta0_3[i] = theta0_3_one/180.0 * PI;
setflag_aa[i] = 1;
count++;
}
} else {
- if (narg != 3) error->all("Incorrect args for improper coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for improper coefficients");
double k0_one = force->numeric(arg[1]);
double chi0_one = force->numeric(arg[2]);
// convert chi0 from degrees to radians
for (int i = ilo; i <= ihi; i++) {
k0[i] = k0_one;
chi0[i] = chi0_one/180.0 * PI;
setflag_i[i] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for improper coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for improper coefficients");
for (int i = ilo; i <= ihi; i++)
if (setflag_i[i] == 1 && setflag_aa[i] == 1) setflag[i] = 1;
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void ImproperClass2::write_restart(FILE *fp)
{
fwrite(&k0[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&chi0[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&aa_k1[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&aa_k2[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&aa_k3[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&aa_theta0_1[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&aa_theta0_2[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&aa_theta0_3[1],sizeof(double),atom->nimpropertypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void ImproperClass2::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k0[1],sizeof(double),atom->nimpropertypes,fp);
fread(&chi0[1],sizeof(double),atom->nimpropertypes,fp);
fread(&aa_k1[1],sizeof(double),atom->nimpropertypes,fp);
fread(&aa_k2[1],sizeof(double),atom->nimpropertypes,fp);
fread(&aa_k3[1],sizeof(double),atom->nimpropertypes,fp);
fread(&aa_theta0_1[1],sizeof(double),atom->nimpropertypes,fp);
fread(&aa_theta0_2[1],sizeof(double),atom->nimpropertypes,fp);
fread(&aa_theta0_3[1],sizeof(double),atom->nimpropertypes,fp);
}
MPI_Bcast(&k0[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&chi0[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aa_k1[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aa_k2[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aa_k3[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aa_theta0_1[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aa_theta0_2[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&aa_theta0_3[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
}
/* ----------------------------------------------------------------------
angle-angle interactions within improper
------------------------------------------------------------------------- */
void ImproperClass2::angleangle(int eflag, int vflag)
{
int i1,i2,i3,i4,i,j,k,n,type;
double eimproper;
double delxAB,delyAB,delzAB,rABmag2,rAB;
double delxBC,delyBC,delzBC,rBCmag2,rBC;
double delxBD,delyBD,delzBD,rBDmag2,rBD;
double costhABC,thetaABC,costhABD;
double thetaABD,costhCBD,thetaCBD,dthABC,dthCBD,dthABD;
double sc1,t1,t3,r12;
double dthetadr[3][4][3],fabcd[4][3];
double **x = atom->x;
double **f = atom->f;
int **improperlist = neighbor->improperlist;
int nimproperlist = neighbor->nimproperlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nimproperlist; n++) {
i1 = improperlist[n][0];
i2 = improperlist[n][1];
i3 = improperlist[n][2];
i4 = improperlist[n][3];
type = improperlist[n][4];
// difference vectors
delxAB = x[i1][0] - x[i2][0];
delyAB = x[i1][1] - x[i2][1];
delzAB = x[i1][2] - x[i2][2];
domain->minimum_image(delxAB,delyAB,delzAB);
delxBC = x[i3][0] - x[i2][0];
delyBC = x[i3][1] - x[i2][1];
delzBC = x[i3][2] - x[i2][2];
domain->minimum_image(delxBC,delyBC,delzBC);
delxBD = x[i4][0] - x[i2][0];
delyBD = x[i4][1] - x[i2][1];
delzBD = x[i4][2] - x[i2][2];
domain->minimum_image(delxBD,delyBD,delzBD);
// bond lengths
rABmag2 = delxAB*delxAB + delyAB*delyAB + delzAB*delzAB;
rAB = sqrt(rABmag2);
rBCmag2 = delxBC*delxBC + delyBC*delyBC + delzBC*delzBC;
rBC = sqrt(rBCmag2);
rBDmag2 = delxBD*delxBD + delyBD*delyBD + delzBD*delzBD;
rBD = sqrt(rBDmag2);
// angle ABC, ABD, CBD
costhABC = (delxAB*delxBC + delyAB*delyBC + delzAB*delzBC) / (rAB * rBC);
if (costhABC > 1.0) costhABC = 1.0;
if (costhABC < -1.0) costhABC = -1.0;
thetaABC = acos(costhABC);
costhABD = (delxAB*delxBD + delyAB*delyBD + delzAB*delzBD) / (rAB * rBD);
if (costhABD > 1.0) costhABD = 1.0;
if (costhABD < -1.0) costhABD = -1.0;
thetaABD = acos(costhABD);
costhCBD = (delxBC*delxBD + delyBC*delyBD + delzBC*delzBD) /(rBC * rBD);
if (costhCBD > 1.0) costhCBD = 1.0;
if (costhCBD < -1.0) costhCBD = -1.0;
thetaCBD = acos(costhCBD);
dthABC = thetaABC - aa_theta0_1[type];
dthABD = thetaABD - aa_theta0_2[type];
dthCBD = thetaCBD - aa_theta0_3[type];
// energy
if (eflag) eimproper = aa_k2[type] * dthABC * dthABD +
aa_k1[type] * dthABC * dthCBD +
aa_k3[type] * dthABD * dthCBD;
// d(theta)/d(r) array
// angle i, atom j, coordinate k
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
for (k = 0; k < 3; k++)
dthetadr[i][j][k] = 0.0;
// angle ABC
sc1 = sqrt(1.0/(1.0 - costhABC*costhABC));
t1 = costhABC / rABmag2;
t3 = costhABC / rBCmag2;
r12 = 1.0 / (rAB * rBC);
dthetadr[0][0][0] = sc1 * ((t1 * delxAB) - (delxBC * r12));
dthetadr[0][0][1] = sc1 * ((t1 * delyAB) - (delyBC * r12));
dthetadr[0][0][2] = sc1 * ((t1 * delzAB) - (delzBC * r12));
dthetadr[0][1][0] = sc1 * ((-t1 * delxAB) + (delxBC * r12) +
(-t3 * delxBC) + (delxAB * r12));
dthetadr[0][1][1] = sc1 * ((-t1 * delyAB) + (delyBC * r12) +
(-t3 * delyBC) + (delyAB * r12));
dthetadr[0][1][2] = sc1 * ((-t1 * delzAB) + (delzBC * r12) +
(-t3 * delzBC) + (delzAB * r12));
dthetadr[0][2][0] = sc1 * ((t3 * delxBC) - (delxAB * r12));
dthetadr[0][2][1] = sc1 * ((t3 * delyBC) - (delyAB * r12));
dthetadr[0][2][2] = sc1 * ((t3 * delzBC) - (delzAB * r12));
// angle CBD
sc1 = sqrt(1.0/(1.0 - costhCBD*costhCBD));
t1 = costhCBD / rBCmag2;
t3 = costhCBD / rBDmag2;
r12 = 1.0 / (rBC * rBD);
dthetadr[1][2][0] = sc1 * ((t1 * delxBC) - (delxBD * r12));
dthetadr[1][2][1] = sc1 * ((t1 * delyBC) - (delyBD * r12));
dthetadr[1][2][2] = sc1 * ((t1 * delzBC) - (delzBD * r12));
dthetadr[1][1][0] = sc1 * ((-t1 * delxBC) + (delxBD * r12) +
(-t3 * delxBD) + (delxBC * r12));
dthetadr[1][1][1] = sc1 * ((-t1 * delyBC) + (delyBD * r12) +
(-t3 * delyBD) + (delyBC * r12));
dthetadr[1][1][2] = sc1 * ((-t1 * delzBC) + (delzBD * r12) +
(-t3 * delzBD) + (delzBC * r12));
dthetadr[1][3][0] = sc1 * ((t3 * delxBD) - (delxBC * r12));
dthetadr[1][3][1] = sc1 * ((t3 * delyBD) - (delyBC * r12));
dthetadr[1][3][2] = sc1 * ((t3 * delzBD) - (delzBC * r12));
// angle ABD
sc1 = sqrt(1.0/(1.0 - costhABD*costhABD));
t1 = costhABD / rABmag2;
t3 = costhABD / rBDmag2;
r12 = 1.0 / (rAB * rBD);
dthetadr[2][0][0] = sc1 * ((t1 * delxAB) - (delxBD * r12));
dthetadr[2][0][1] = sc1 * ((t1 * delyAB) - (delyBD * r12));
dthetadr[2][0][2] = sc1 * ((t1 * delzAB) - (delzBD * r12));
dthetadr[2][1][0] = sc1 * ((-t1 * delxAB) + (delxBD * r12) +
(-t3 * delxBD) + (delxAB * r12));
dthetadr[2][1][1] = sc1 * ((-t1 * delyAB) + (delyBD * r12) +
(-t3 * delyBD) + (delyAB * r12));
dthetadr[2][1][2] = sc1 * ((-t1 * delzAB) + (delzBD * r12) +
(-t3 * delzBD) + (delzAB * r12));
dthetadr[2][3][0] = sc1 * ((t3 * delxBD) - (delxAB * r12));
dthetadr[2][3][1] = sc1 * ((t3 * delyBD) - (delyAB * r12));
dthetadr[2][3][2] = sc1 * ((t3 * delzBD) - (delzAB * r12));
// angleangle forces
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
fabcd[i][j] = -
((aa_k1[type] *
(dthABC*dthetadr[1][i][j] + dthCBD*dthetadr[0][i][j])) +
(aa_k2[type] *
(dthABC*dthetadr[2][i][j] + dthABD*dthetadr[0][i][j])) +
(aa_k3[type] *
(dthABD*dthetadr[1][i][j] + dthCBD*dthetadr[2][i][j])));
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += fabcd[0][0];
f[i1][1] += fabcd[0][1];
f[i1][2] += fabcd[0][2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += fabcd[1][0];
f[i2][1] += fabcd[1][1];
f[i2][2] += fabcd[1][2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += fabcd[2][0];
f[i3][1] += fabcd[2][1];
f[i3][2] += fabcd[2][2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += fabcd[3][0];
f[i4][1] += fabcd[3][1];
f[i4][2] += fabcd[3][2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,eimproper,
fabcd[0],fabcd[2],fabcd[3],
delxAB,delyAB,delzAB,delxBC,delyBC,delzBC,delxBD,delyBD,delzBD);
}
}
/* ----------------------------------------------------------------------
cross product: c = a x b
------------------------------------------------------------------------- */
void ImproperClass2::cross(double *a, double *b, double *c)
{
c[0] = a[1]*b[2] - a[2]*b[1];
c[1] = a[2]*b[0] - a[0]*b[2];
c[2] = a[0]*b[1] - a[1]*b[0];
}
/* ----------------------------------------------------------------------
dot product of a dot b
------------------------------------------------------------------------- */
double ImproperClass2::dot(double *a, double *b)
{
return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
}
diff --git a/src/CLASS2/pair_lj_class2.cpp b/src/CLASS2/pair_lj_class2.cpp
index c77443081..aba3715cc 100644
--- a/src/CLASS2/pair_lj_class2.cpp
+++ b/src/CLASS2/pair_lj_class2.cpp
@@ -1,368 +1,365 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_class2.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJClass2::PairLJClass2(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJClass2::~PairLJClass2()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,rinv,r2inv,r3inv,r6inv,forcelj,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
rinv = sqrt(r2inv);
r3inv = r2inv*rinv;
r6inv = r3inv*r3inv;
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJClass2::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJClass2::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJClass2::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_one = cut_global;
if (narg == 5) cut_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJClass2::init_one(int i, int j)
{
// always mix epsilon,sigma via sixthpower rules
// mix distance via user-defined rule
if (setflag[i][j] == 0) {
epsilon[i][j] = 2.0 * sqrt(epsilon[i][i]*epsilon[j][j]) *
pow(sigma[i][i],3.0) * pow(sigma[j][j],3.0) /
(pow(sigma[i][i],6.0) + pow(sigma[j][j],6.0));
sigma[i][j] =
pow((0.5 * (pow(sigma[i][i],6.0) + pow(sigma[j][j],6.0))),1.0/6.0);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
lj1[i][j] = 18.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj2[i][j] = 18.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 2.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj4[i][j] = 3.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut[i][j];
offset[i][j] = epsilon[i][j] * (2.0*pow(ratio,9.0) - 3.0*pow(ratio,6.0));
} else offset[i][j] = 0.0;
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig3 = sigma[i][j]*sigma[i][j]*sigma[i][j];
double sig6 = sig3*sig3;
double rc3 = cut[i][j]*cut[i][j]*cut[i][j];
double rc6 = rc3*rc3;
etail_ij = 2.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig3 - 3.0*rc3) / (3.0*rc6);
ptail_ij = 2.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig3 - 2.0*rc3) / rc6;
}
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJClass2::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJClass2::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJClass2::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJClass2::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJClass2::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,rinv,r3inv,r6inv,forcelj,philj;
r2inv = 1.0/rsq;
rinv = sqrt(r2inv);
r3inv = r2inv*rinv;
r6inv = r3inv*r3inv;
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fforce = factor_lj*forcelj*r2inv;
philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
return factor_lj*philj;
}
diff --git a/src/CLASS2/pair_lj_class2_coul_cut.cpp b/src/CLASS2/pair_lj_class2_coul_cut.cpp
index c7107077d..b6dc7d801 100644
--- a/src/CLASS2/pair_lj_class2_coul_cut.cpp
+++ b/src/CLASS2/pair_lj_class2_coul_cut.cpp
@@ -1,441 +1,438 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_class2_coul_cut.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJClass2CoulCut::PairLJClass2CoulCut(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJClass2CoulCut::~PairLJClass2CoulCut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulCut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,rinv,r2inv,r3inv,r6inv,forcecoul,forcelj;
double factor_coul,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype])
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
rinv = sqrt(r2inv);
r3inv = r2inv*rinv;
r6inv = r3inv*r3inv;
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq[itype][jtype])
ecoul = factor_coul * qqrd2e * qtmp*q[j]*sqrt(r2inv);
else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"pair:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"pair:cut_coulsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::settings(int narg, char **arg)
{
- if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul_global = cut_lj_global;
else cut_coul_global = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_lj[i][j] = cut_lj_global;
cut_coul[i][j] = cut_coul_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_lj_one = cut_lj_global;
double cut_coul_one = cut_coul_global;
if (narg >= 5) cut_coul_one = cut_lj_one = force->numeric(arg[4]);
if (narg == 6) cut_coul_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_lj[i][j] = cut_lj_one;
cut_coul[i][j] = cut_coul_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/class2/coul/cut requires atom attribute q");
+ error->all(FLERR,"Pair style lj/class2/coul/cut requires atom attribute q");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJClass2CoulCut::init_one(int i, int j)
{
// always mix epsilon,sigma via sixthpower rules
// mix distance via user-defined rule
if (setflag[i][j] == 0) {
epsilon[i][j] = 2.0 * sqrt(epsilon[i][i]*epsilon[j][j]) *
pow(sigma[i][i],3.0) * pow(sigma[j][j],3.0) /
(pow(sigma[i][i],6.0) + pow(sigma[j][j],6.0));
sigma[i][j] =
pow((0.5 * (pow(sigma[i][i],6.0) + pow(sigma[j][j],6.0))),1.0/6.0);
cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]);
cut_coul[i][j] = mix_distance(cut_coul[i][i],cut_coul[j][j]);
}
double cut = MAX(cut_lj[i][j],cut_coul[i][j]);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
cut_coulsq[i][j] = cut_coul[i][j] * cut_coul[i][j];
lj1[i][j] = 18.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj2[i][j] = 18.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 2.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj4[i][j] = 3.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut_lj[i][j];
offset[i][j] = epsilon[i][j] * (2.0*pow(ratio,9.0) - 3.0*pow(ratio,6.0));
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
cut_coulsq[j][i] = cut_coulsq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig3 = sigma[i][j]*sigma[i][j]*sigma[i][j];
double sig6 = sig3*sig3;
double rc3 = cut_lj[i][j]*cut_lj[i][j]*cut_lj[i][j];
double rc6 = rc3*rc3;
etail_ij = 2.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig3 - 3.0*rc3) / (3.0*rc6);
ptail_ij = 2.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig3 - 2.0*rc3) / rc6;
}
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
fwrite(&cut_coul[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
fread(&cut_coul[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJClass2CoulCut::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJClass2CoulCut::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,rinv,r3inv,r6inv,forcecoul,forcelj,phicoul,philj;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype])
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
rinv = sqrt(r2inv);
r3inv = r2inv*rinv;
r6inv = r3inv*r3inv;
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq[itype][jtype]) {
phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
eng += factor_coul*phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
eng += factor_lj*philj;
}
return eng;
}
diff --git a/src/CLASS2/pair_lj_class2_coul_long.cpp b/src/CLASS2/pair_lj_class2_coul_long.cpp
index 280dacad0..b9423c472 100644
--- a/src/CLASS2/pair_lj_class2_coul_long.cpp
+++ b/src/CLASS2/pair_lj_class2_coul_long.cpp
@@ -1,470 +1,467 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_class2_coul_long.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJClass2CoulLong::PairLJClass2CoulLong(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJClass2CoulLong::~PairLJClass2CoulLong()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulLong::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r,rinv,r2inv,r3inv,r6inv,forcecoul,forcelj;
double grij,expm2,prefactor,t,erfc;
double factor_coul,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
rinv = sqrt(r2inv);
r3inv = r2inv*rinv;
r6inv = r3inv*r3inv;
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
ecoul = prefactor*erfc;
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::settings(int narg, char **arg)
{
- if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul = cut_lj_global;
else cut_coul = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_lj_one = cut_lj_global;
if (narg == 5) cut_lj_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_lj[i][j] = cut_lj_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/class2/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/class2/coul/long requires atom attribute q");
neighbor->request(this);
cut_coulsq = cut_coul * cut_coul;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJClass2CoulLong::init_one(int i, int j)
{
// always mix epsilon,sigma via sixthpower rules
// mix distance via user-defined rule
if (setflag[i][j] == 0) {
epsilon[i][j] = 2.0 * sqrt(epsilon[i][i]*epsilon[j][j]) *
pow(sigma[i][i],3.0) * pow(sigma[j][j],3.0) /
(pow(sigma[i][i],6.0) + pow(sigma[j][j],6.0));
sigma[i][j] =
pow((0.5 * (pow(sigma[i][i],6.0) + pow(sigma[j][j],6.0))),1.0/6.0);
cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]);
}
double cut = MAX(cut_lj[i][j],cut_coul);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
lj1[i][j] = 18.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj2[i][j] = 18.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 2.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj4[i][j] = 3.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut_lj[i][j];
offset[i][j] = epsilon[i][j] * (2.0*pow(ratio,9.0) - 3.0*pow(ratio,6.0));
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig3 = sigma[i][j]*sigma[i][j]*sigma[i][j];
double sig6 = sig3*sig3;
double rc3 = cut_lj[i][j]*cut_lj[i][j]*cut_lj[i][j];
double rc6 = rc3*rc3;
etail_ij = 2.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig3 - 3.0*rc3) / (3.0*rc6);
ptail_ij = 2.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig3 - 2.0*rc3) / rc6;
}
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJClass2CoulLong::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJClass2CoulLong::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r,rinv,r3inv,r6inv,grij,expm2,t,erfc,prefactor;
double forcecoul,forcelj,phicoul,philj;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
rinv = sqrt(r2inv);
r3inv = r2inv*rinv;
r6inv = r3inv*r3inv;
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fforce = (forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq) {
phicoul = prefactor*erfc;
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
eng += phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
eng += factor_lj*philj;
}
return eng;
}
/* ---------------------------------------------------------------------- */
void *PairLJClass2CoulLong::extract(char *str, int &dim)
{
dim = 0;
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul;
return NULL;
}
diff --git a/src/COLLOID/fix_wall_colloid.cpp b/src/COLLOID/fix_wall_colloid.cpp
index 7627fca70..e4267358c 100644
--- a/src/COLLOID/fix_wall_colloid.cpp
+++ b/src/COLLOID/fix_wall_colloid.cpp
@@ -1,158 +1,158 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Jeremy Lechman (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "fix_wall_colloid.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixWallColloid::FixWallColloid(LAMMPS *lmp, int narg, char **arg) :
FixWall(lmp, narg, arg) {}
/* ---------------------------------------------------------------------- */
void FixWallColloid::init()
{
if (!atom->sphere_flag)
- error->all("Fix wall/colloid requires atom style sphere");
+ error->all(FLERR,"Fix wall/colloid requires atom style sphere");
// insure all particles in group are extended particles
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int flag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (radius[i] == 0.0) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
- if (flagall) error->all("Fix wall/colloid requires extended particles");
+ if (flagall) error->all(FLERR,"Fix wall/colloid requires extended particles");
FixWall::init();
}
/* ---------------------------------------------------------------------- */
void FixWallColloid::precompute(int m)
{
coeff1[m] = 4.0/315.0 * epsilon[m] * pow(sigma[m],6.0);
coeff2[m] = 2.0/3.0 * epsilon[m];
coeff3[m] = epsilon[m] * pow(sigma[m],6.0)/7560.0;
coeff4[m] = epsilon[m]/6.0;
}
/* ----------------------------------------------------------------------
interaction of all particles in group with a wall
m = index of wall coeffs
which = xlo,xhi,ylo,yhi,zlo,zhi
error if any finite-size particle is touching or penetrating wall
------------------------------------------------------------------------- */
void FixWallColloid::wall_particle(int m, int which, double coord)
{
double delta,delta2,rinv,r2inv,r4inv,r8inv,fwall;
double r2,rinv2,r2inv2,r4inv2;
double r3,rinv3,r2inv3,r4inv3,r6inv3;
double rad,rad2,rad4,rad8,diam,new_coeff2;
double eoffset;
double **x = atom->x;
double **f = atom->f;
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int dim = which / 2;
int side = which % 2;
if (side == 0) side = -1;
int onflag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (side < 0) delta = x[i][dim] - coord;
else delta = coord - x[i][dim];
if (delta >= cutoff[m]) continue;
rad = radius[i];
if (rad >= delta) {
onflag = 1;
continue;
}
new_coeff2 = coeff2[m]*rad*rad*rad;
diam = 2.0*rad;
rad2 = rad*rad;
rad4 = rad2*rad2;
rad8 = rad4*rad4;
delta2 = rad2 - delta*delta;
rinv = 1.0/delta2;
r2inv = rinv*rinv;
r4inv = r2inv*r2inv;
r8inv = r4inv*r4inv;
fwall = side * (coeff1[m]*(rad8*rad + 27.0*rad4*rad2*rad*pow(delta,2.0)
+ 63.0*rad4*rad*pow(delta,4.0)
+ 21.0*rad2*rad*pow(delta,6.0))*r8inv -
new_coeff2*r2inv);
f[i][dim] -= fwall;
r2 = rad - delta;
rinv2 = 1.0/r2;
r2inv2 = rinv2*rinv2;
r4inv2 = r2inv2*r2inv2;
r3 = delta + rad;
rinv3 = 1.0/r3;
r2inv3 = rinv3*rinv3;
r4inv3 = r2inv3*r2inv3;
r6inv3 = r4inv3*r2inv3;
ewall[0] += coeff3[m]*((-3.5*diam+delta)*r4inv2*r2inv2*rinv2
+ (3.5*diam+delta)*r4inv3*r2inv3*rinv3) -
coeff4[m]*((diam*delta-r2*r3*(log(-r2)-log(r3)))*
(-rinv2)*rinv3);
// offset depends on particle size
r2 = rad - cutoff[m];
rinv2 = 1.0/r2;
r2inv2 = rinv2*rinv2;
r4inv2 = r2inv2*r2inv2;
r3 = cutoff[m] + rad;
rinv3 = 1.0/r3;
r2inv3 = rinv3*rinv3;
r4inv3 = r2inv3*r2inv3;
r6inv3 = r4inv3*r2inv3;
eoffset = coeff3[m]*((-3.5*diam+cutoff[m])*r4inv2*r2inv2*rinv2
+ (3.5*diam+cutoff[m])*r4inv3*r2inv3*rinv3) -
coeff4[m]*((diam*cutoff[m]-r2*r3*(log(-r2)-log(r3)))*
(-rinv2)*rinv3);
ewall[0] -= eoffset;
ewall[m+1] += fwall;
}
- if (onflag) error->one("Particle on or inside fix wall surface");
+ if (onflag) error->one(FLERR,"Particle on or inside fix wall surface");
}
diff --git a/src/COLLOID/pair_colloid.cpp b/src/COLLOID/pair_colloid.cpp
index db0c612ae..1965e98ac 100644
--- a/src/COLLOID/pair_colloid.cpp
+++ b/src/COLLOID/pair_colloid.cpp
@@ -1,521 +1,518 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_colloid.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
enum{SMALL_SMALL,SMALL_LARGE,LARGE_LARGE};
/* ---------------------------------------------------------------------- */
PairColloid::PairColloid(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairColloid::~PairColloid()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(form);
memory->destroy(a12);
memory->destroy(sigma);
memory->destroy(d1);
memory->destroy(d2);
memory->destroy(a1);
memory->destroy(a2);
memory->destroy(diameter);
memory->destroy(cut);
memory->destroy(offset);
memory->destroy(sigma3);
memory->destroy(sigma6);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
}
}
/* ---------------------------------------------------------------------- */
void PairColloid::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,forcelj,factor_lj;
double r2inv,r6inv,c1,c2,fR,dUR,dUA;
double K[9],h[4],g[4];
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq >= cutsq[itype][jtype]) continue;
switch (form[itype][jtype]) {
case SMALL_SMALL:
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
if (eflag) evdwl = r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) -
offset[itype][jtype];
break;
case SMALL_LARGE:
c2 = a2[itype][jtype];
K[1] = c2*c2;
K[2] = rsq;
K[0] = K[1] - rsq;
K[4] = rsq*rsq;
K[3] = K[1] - K[2];
K[3] *= K[3]*K[3];
K[6] = K[3]*K[3];
fR = sigma3[itype][jtype]*a12[itype][jtype]*c2*K[1]/K[3];
fpair = 4.0/15.0*fR*factor_lj *
(2.0*(K[1]+K[2]) * (K[1]*(5.0*K[1]+22.0*K[2])+5.0*K[4]) *
sigma6[itype][jtype]/K[6]-5.0) / K[0];
if (eflag)
evdwl = 2.0/9.0*fR *
(1.0-(K[1]*(K[1]*(K[1]/3.0+3.0*K[2])+4.2*K[4])+K[2]*K[4]) *
sigma6[itype][jtype]/K[6]) - offset[itype][jtype];
- if (rsq <= K[1]) error->one("Overlapping small/large in pair colloid");
+ if (rsq <= K[1]) error->one(FLERR,"Overlapping small/large in pair colloid");
break;
case LARGE_LARGE:
r = sqrt(rsq);
c1 = a1[itype][jtype];
c2 = a2[itype][jtype];
K[0] = c1*c2;
K[1] = c1+c2;
K[2] = c1-c2;
K[3] = K[1]+r;
K[4] = K[1]-r;
K[5] = K[2]+r;
K[6] = K[2]-r;
K[7] = 1.0/(K[3]*K[4]);
K[8] = 1.0/(K[5]*K[6]);
g[0] = pow(K[3],-7.0);
g[1] = pow(K[4],-7.0);
g[2] = pow(K[5],-7.0);
g[3] = pow(K[6],-7.0);
h[0] = ((K[3]+5.0*K[1])*K[3]+30.0*K[0])*g[0];
h[1] = ((K[4]+5.0*K[1])*K[4]+30.0*K[0])*g[1];
h[2] = ((K[5]+5.0*K[2])*K[5]-30.0*K[0])*g[2];
h[3] = ((K[6]+5.0*K[2])*K[6]-30.0*K[0])*g[3];
g[0] *= 42.0*K[0]/K[3]+6.0*K[1]+K[3];
g[1] *= 42.0*K[0]/K[4]+6.0*K[1]+K[4];
g[2] *= -42.0*K[0]/K[5]+6.0*K[2]+K[5];
g[3] *= -42.0*K[0]/K[6]+6.0*K[2]+K[6];
fR = a12[itype][jtype]*sigma6[itype][jtype]/r/37800.0;
evdwl = fR * (h[0]-h[1]-h[2]+h[3]);
dUR = evdwl/r + 5.0*fR*(g[0]+g[1]-g[2]-g[3]);
dUA = -a12[itype][jtype]/3.0*r*((2.0*K[0]*K[7]+1.0)*K[7] +
(2.0*K[0]*K[8]-1.0)*K[8]);
fpair = factor_lj * (dUR+dUA)/r;
if (eflag)
evdwl += a12[itype][jtype]/6.0 *
(2.0*K[0]*(K[7]+K[8])-log(K[8]/K[7])) - offset[itype][jtype];
- if (r <= K[1]) error->one("Overlapping large/large in pair colloid");
+ if (r <= K[1]) error->one(FLERR,"Overlapping large/large in pair colloid");
break;
}
if (eflag) evdwl *= factor_lj;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairColloid::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(form,n+1,n+1,"pair:form");
memory->create(a12,n+1,n+1,"pair:a12");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(d1,n+1,n+1,"pair:d1");
memory->create(d2,n+1,n+1,"pair:d2");
memory->create(a1,n+1,n+1,"pair:a1");
memory->create(a2,n+1,n+1,"pair:a2");
memory->create(diameter,n+1,n+1,"pair:diameter");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(offset,n+1,n+1,"pair:offset");
memory->create(sigma3,n+1,n+1,"pair:sigma3");
memory->create(sigma6,n+1,n+1,"pair:sigma6");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairColloid::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairColloid::coeff(int narg, char **arg)
{
- if (narg < 6 || narg > 7) error->all("Incorrect args for pair coefficients");
+ if (narg < 6 || narg > 7) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a12_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double d1_one = force->numeric(arg[4]);
double d2_one = force->numeric(arg[5]);
double cut_one = cut_global;
if (narg == 7) cut_one = force->numeric(arg[6]);
if (d1_one < 0.0 || d2_one < 0.0)
- error->all("Invalid d1 or d2 value for pair colloid coeff");
+ error->all(FLERR,"Invalid d1 or d2 value for pair colloid coeff");
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a12[i][j] = a12_one;
sigma[i][j] = sigma_one;
if (i == j && d1_one != d2_one)
- error->all("Invalid d1 or d2 value for pair colloid coeff");
+ error->all(FLERR,"Invalid d1 or d2 value for pair colloid coeff");
d1[i][j] = d1_one;
d2[i][j] = d2_one;
diameter[i][j] = 0.5*(d1_one+d2_one);
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairColloid::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
a12[i][j] = mix_energy(a12[i][i],a12[j][j],sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
d1[i][j] = mix_distance(d1[i][i],d1[j][j]);
d2[i][j] = mix_distance(d2[i][i],d2[j][j]);
diameter[i][j] = 0.5 * (d1[i][j] + d2[i][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
sigma3[i][j] = sigma[i][j]*sigma[i][j]*sigma[i][j];
sigma6[i][j] = sigma3[i][j]*sigma3[i][j];
if (d1[i][j] == 0.0 && d2[i][j] == 0.0) form[i][j] = SMALL_SMALL;
else if (d1[i][j] == 0.0 || d2[i][j] == 0.0) form[i][j] = SMALL_LARGE;
else form[i][j] = LARGE_LARGE;
// for SMALL_SMALL, a1/a2 do not need to be set
// for SMALL_LARGE, a1 does not need to be set, a2 = radius for i,j and j,i
// for LARGE_LARGE, a1/a2 are radii, swap them for j,i
if (form[i][j] == SMALL_LARGE) {
if (d1[i][j] > 0.0) a2[i][j] = 0.5*d1[i][j];
else a2[i][j] = 0.5*d2[i][j];
a2[j][i] = a2[i][j];
} else if (form[i][j] == LARGE_LARGE) {
a2[j][i] = a1[i][j] = 0.5*d1[i][j];
a1[j][i] = a2[i][j] = 0.5*d2[i][j];
}
form[j][i] = form[i][j];
a12[j][i] = a12[i][j];
sigma[j][i] = sigma[i][j];
sigma3[j][i] = sigma3[i][j];
sigma6[j][i] = sigma6[i][j];
diameter[j][i] = diameter[i][j];
cut[j][i] = cut[i][j];
double epsilon = a12[i][j]/144.0;
lj1[j][i] = lj1[i][j] = 48.0 * epsilon * sigma6[i][j] * sigma6[i][j];
lj2[j][i] = lj2[i][j] = 24.0 * epsilon * sigma6[i][j];
lj3[j][i] = lj3[i][j] = 4.0 * epsilon * sigma6[i][j] * sigma6[i][j];
lj4[j][i] = lj4[i][j] = 4.0 * epsilon * sigma6[i][j];
offset[j][i] = offset[i][j] = 0.0;
if (offset_flag) {
double tmp;
offset[j][i] = offset[i][j] =
single(0,0,i,j,cut[i][j]*cut[i][j],0.0,1.0,tmp);
}
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairColloid::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a12[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&d1[i][j],sizeof(double),1,fp);
fwrite(&d2[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairColloid::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (comm->me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (comm->me == 0) {
fread(&a12[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&d1[i][j],sizeof(double),1,fp);
fread(&d2[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a12[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&d1[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&d2[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairColloid::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairColloid::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairColloid::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double K[9],h[4],g[4];
double r,r2inv,r6inv,forcelj,c1,c2,phi,fR,dUR,dUA;
switch (form[itype][jtype]) {
case SMALL_SMALL:
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fforce = factor_lj*forcelj*r2inv;
phi = r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) -
offset[itype][jtype];
break;
case SMALL_LARGE:
c2 = a2[itype][jtype];
K[1] = c2*c2;
K[2] = rsq;
K[0] = K[1] - rsq;
K[4] = rsq*rsq;
K[3] = K[1] - K[2];
K[3] *= K[3]*K[3];
K[6] = K[3]*K[3];
fR = sigma3[itype][jtype]*a12[itype][jtype]*c2*K[1]/K[3];
fforce = 4.0/15.0*fR*factor_lj *
(2.0*(K[1]+K[2])*(K[1]*(5.0*K[1]+22.0*K[2])+5.0*K[4]) *
sigma6[itype][jtype]/K[6] - 5.0)/K[0];
phi = 2.0/9.0*fR *
(1.0-(K[1]*(K[1]*(K[1]/3.0+3.0*K[2])+4.2*K[4])+K[2]*K[4]) *
sigma6[itype][jtype]/K[6]) - offset[itype][jtype];
break;
case LARGE_LARGE:
r = sqrt(rsq);
c1 = a1[itype][jtype];
c2 = a2[itype][jtype];
K[0] = c1*c2;
K[1] = c1+c2;
K[2] = c1-c2;
K[3] = K[1]+r;
K[4] = K[1]-r;
K[5] = K[2]+r;
K[6] = K[2]-r;
K[7] = 1.0/(K[3]*K[4]);
K[8] = 1.0/(K[5]*K[6]);
g[0] = pow(K[3],-7.0);
g[1] = pow(K[4],-7.0);
g[2] = pow(K[5],-7.0);
g[3] = pow(K[6],-7.0);
h[0] = ((K[3]+5.0*K[1])*K[3]+30.0*K[0])*g[0];
h[1] = ((K[4]+5.0*K[1])*K[4]+30.0*K[0])*g[1];
h[2] = ((K[5]+5.0*K[2])*K[5]-30.0*K[0])*g[2];
h[3] = ((K[6]+5.0*K[2])*K[6]-30.0*K[0])*g[3];
g[0] *= 42.0*K[0]/K[3]+6.0*K[1]+K[3];
g[1] *= 42.0*K[0]/K[4]+6.0*K[1]+K[4];
g[2] *= -42.0*K[0]/K[5]+6.0*K[2]+K[5];
g[3] *= -42.0*K[0]/K[6]+6.0*K[2]+K[6];
fR = a12[itype][jtype]*sigma6[itype][jtype]/r/37800.0;
phi = fR * (h[0]-h[1]-h[2]+h[3]);
dUR = phi/r + 5.0*fR*(g[0]+g[1]-g[2]-g[3]);
dUA = -a12[itype][jtype]/3.0*r*((2.0*K[0]*K[7]+1.0)*K[7] +
(2.0*K[0]*K[8]-1.0)*K[8]);
fforce = factor_lj*(dUR+dUA)/r;
phi += a12[itype][jtype]/6.0*(2.0*K[0]*(K[7]+K[8])-log(K[8]/K[7])) -
offset[itype][jtype];
break;
}
return factor_lj*phi;
}
diff --git a/src/COLLOID/pair_lubricate.cpp b/src/COLLOID/pair_lubricate.cpp
index 4975c4f7e..5eb072b93 100644
--- a/src/COLLOID/pair_lubricate.cpp
+++ b/src/COLLOID/pair_lubricate.cpp
@@ -1,525 +1,522 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Randy Schunk (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lubricate.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "update.h"
#include "memory.h"
#include "random_mars.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLubricate::PairLubricate(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
random = NULL;
}
/* ---------------------------------------------------------------------- */
PairLubricate::~PairLubricate()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(cut_inner);
}
delete random;
}
/* ---------------------------------------------------------------------- */
void PairLubricate::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fpair,fx,fy,fz,tx,ty,tz;
double rsq,r,h_sep,radi,tfmag;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3;
double vt1,vt2,vt3,w1,w2,w3,v_shear1,v_shear2,v_shear3;
double omega_t_1,omega_t_2,omega_t_3;
double n_cross_omega_t_1,n_cross_omega_t_2,n_cross_omega_t_3;
double wr1,wr2,wr3,wnnr,wn1,wn2,wn3;
double P_dot_wrel_1,P_dot_wrel_2,P_dot_wrel_3;
double a_squeeze,a_shear,a_pump,a_twist;
int *ilist,*jlist,*numneigh,**firstneigh;
double PI = 4.0*atan(1.0);
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *radius = atom->radius;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
double vxmu2f = force->vxmu2f;
double prethermostat = sqrt(2.0 * force->boltz * t_target / update->dt);
prethermostat *= sqrt(force->vxmu2f/force->ftm2v/force->mvv2e);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
a_squeeze = a_shear = a_pump = a_twist = 0.0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
radi = radius[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
// relative translational velocity
vr1 = v[i][0] - v[j][0];
vr2 = v[i][1] - v[j][1];
vr3 = v[i][2] - v[j][2];
// normal component N.(v1-v2) = nn.(v1-v2)
vnnr = vr1*delx + vr2*dely + vr3*delz;
vnnr /= r;
vn1 = delx*vnnr / r;
vn2 = dely*vnnr / r;
vn3 = delz*vnnr / r;
// tangential component -P.(v1-v2)
// P = (I - nn) where n is vector between centers
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// additive rotational velocity = omega_1 + omega_2
w1 = omega[i][0] + omega[j][0];
w2 = omega[i][1] + omega[j][1];
w3 = omega[i][2] + omega[j][2];
// relative velocities n X P . (v1-v2) = n X (I-nn) . (v1-v2)
v_shear1 = (dely*vt3 - delz*vt2) / r;
v_shear2 = -(delx*vt3 - delz*vt1) / r;
v_shear3 = (delx*vt2 - dely*vt1) / r;
// relative rotation rate P.(omega1 + omega2)
omega_t_1 = w1 - delx*(delx*w1) / rsq;
omega_t_2 = w2 - dely*(dely*w2) / rsq;
omega_t_3 = w3 - delz*(delz*w3) / rsq;
// n X omega_t
n_cross_omega_t_1 = (dely*omega_t_3 - delz*omega_t_2) / r;
n_cross_omega_t_2 = -(delx*omega_t_3 - delz*omega_t_1) / r;
n_cross_omega_t_3 = (delx*omega_t_2 - dely*omega_t_1) / r;
// N.(w1-w2) and P.(w1-w2)
wr1 = omega[i][0] - omega[j][0];
wr2 = omega[i][1] - omega[j][1];
wr3 = omega[i][2] - omega[j][2];
wnnr = wr1*delx + wr2*dely + wr3*delz;
wn1 = delx*wnnr / rsq;
wn2 = dely*wnnr / rsq;
wn3 = delz*wnnr / rsq;
P_dot_wrel_1 = wr1 - delx*(delx*wr1)/rsq;
P_dot_wrel_2 = wr2 - dely*(dely*wr2)/rsq;
P_dot_wrel_3 = wr3 - delz*(delz*wr3)/rsq;
// compute components of pair-hydro
h_sep = r - 2.0*radi;
if (flag1)
a_squeeze = (3.0*PI*mu*2.0*radi/2.0) * (2.0*radi/4.0/h_sep);
if (flag2)
a_shear = (PI*mu*2.*radi/2.0) *
log(2.0*radi/2.0/h_sep)*(2.0*radi+h_sep)*(2.0*radi+h_sep)/4.0;
if (flag3)
a_pump = (PI*mu*pow(2.0*radi,4)/8.0) *
((3.0/20.0) * log(2.0*radi/2.0/h_sep) +
(63.0/250.0) * (h_sep/2.0/radi) * log(2.0*radi/2.0/h_sep));
if (flag4)
a_twist = (PI*mu*pow(2.0*radi,4)/4.0) *
(h_sep/2.0/radi) * log(2.0/(2.0*h_sep));
if (h_sep >= cut_inner[itype][jtype]) {
fx = -a_squeeze*vn1 - a_shear*(2.0/r)*(2.0/r)*vt1 +
(2.0/r)*a_shear*n_cross_omega_t_1;
fy = -a_squeeze*vn2 - a_shear*(2.0/r)*(2.0/r)*vt2 +
(2.0/r)*a_shear*n_cross_omega_t_2;
fz = -a_squeeze*vn3 - a_shear*(2.0/r)*(2.0/r)*vt3 +
(2.0/r)*a_shear*n_cross_omega_t_3;
fx *= vxmu2f;
fy *= vxmu2f;
fz *= vxmu2f;
// add in thermostat force
tfmag = prethermostat*sqrt(a_squeeze)*(random->uniform()-0.5);
fx -= tfmag * delx/r;
fy -= tfmag * dely/r;
fz -= tfmag * delz/r;
tx = -(2.0/r)*a_shear*v_shear1 - a_shear*omega_t_1 -
a_pump*P_dot_wrel_1 - a_twist*wn1;
ty = -(2.0/r)*a_shear*v_shear2 - a_shear*omega_t_2 -
a_pump*P_dot_wrel_2 - a_twist*wn2;
tz = -(2.0/r)*a_shear*v_shear3 - a_shear*omega_t_3 -
a_pump*P_dot_wrel_3 - a_twist*wn3;
torque[i][0] += vxmu2f * tx;
torque[i][1] += vxmu2f * ty;
torque[i][2] += vxmu2f * tz;
} else {
a_squeeze = (3.0*PI*mu*2.0*radi/2.0) *
(2.0*radi/4.0/cut_inner[itype][jtype]);
fpair = -a_squeeze*vnnr;
fpair *= vxmu2f;
// add in thermostat force
fpair -= prethermostat*sqrt(a_squeeze)*(random->uniform()-0.5);
fx = fpair * delx/r;
fy = fpair * dely/r;
fz = fpair * delz/r;
}
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
if (newton_pair || j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
if (h_sep >= cut_inner[itype][jtype]) {
tx = -(2.0/r)*a_shear*v_shear1 - a_shear*omega_t_1 +
a_pump*P_dot_wrel_1 + a_twist*wn1;
ty = -(2.0/r)*a_shear*v_shear2 - a_shear*omega_t_2 +
a_pump*P_dot_wrel_2 + a_twist*wn2;
tz = -(2.0/r)*a_shear*v_shear3 - a_shear*omega_t_3 +
a_pump*P_dot_wrel_3 + a_twist*wn3;
torque[j][0] += vxmu2f * tx;
torque[j][1] += vxmu2f * ty;
torque[j][2] += vxmu2f * tz;
}
}
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,
0.0,0.0,fx,fy,fz,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLubricate::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(cut_inner,n+1,n+1,"pair:cut_inner");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLubricate::settings(int narg, char **arg)
{
- if (narg != 9) error->all("Illegal pair_style command");
+ if (narg != 9) error->all(FLERR,"Illegal pair_style command");
mu = force->numeric(arg[0]);
flag1 = force->inumeric(arg[1]);
flag2 = force->inumeric(arg[2]);
flag3 = force->inumeric(arg[3]);
flag4 = force->inumeric(arg[4]);
cut_inner_global = force->numeric(arg[5]);
cut_global = force->numeric(arg[6]);
t_target = force->numeric(arg[7]);
seed = force->inumeric(arg[8]);
// initialize Marsaglia RNG with processor-unique seed
- if (seed <= 0) error->all("Illegal pair_style command");
+ if (seed <= 0) error->all(FLERR,"Illegal pair_style command");
delete random;
random = new RanMars(lmp,seed + comm->me);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_inner[i][j] = cut_inner_global;
cut[i][j] = cut_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLubricate::coeff(int narg, char **arg)
{
if (narg != 2 && narg != 4)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double cut_inner_one = cut_inner_global;
double cut_one = cut_global;
if (narg == 4) {
cut_inner_one = force->numeric(arg[2]);
cut_one = force->numeric(arg[3]);
}
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
cut_inner[i][j] = cut_inner_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLubricate::init_style()
{
if (!atom->sphere_flag)
- error->all("Pair lubricate requires atom style sphere");
+ error->all(FLERR,"Pair lubricate requires atom style sphere");
if (comm->ghost_velocity == 0)
- error->all("Pair lubricate requires ghost atoms store velocity");
+ error->all(FLERR,"Pair lubricate requires ghost atoms store velocity");
neighbor->request(this);
// require that atom radii are identical within each type
// require monodisperse system with same radii for all types
double rad,radtype;
for (int i = 1; i <= atom->ntypes; i++) {
if (!atom->radius_consistency(i,radtype))
- error->all("Pair lubricate requires monodisperse particles");
+ error->all(FLERR,"Pair lubricate requires monodisperse particles");
if (i > 1 && radtype != rad)
- error->all("Pair lubricate requires monodisperse particles");
+ error->all(FLERR,"Pair lubricate requires monodisperse particles");
rad = radtype;
}
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLubricate::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
cut_inner[i][j] = mix_distance(cut_inner[i][i],cut_inner[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
cut_inner[j][i] = cut_inner[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLubricate::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&cut_inner[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLubricate::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&cut_inner[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&cut_inner[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLubricate::write_restart_settings(FILE *fp)
{
fwrite(&mu,sizeof(double),1,fp);
fwrite(&flag1,sizeof(int),1,fp);
fwrite(&flag2,sizeof(int),1,fp);
fwrite(&flag3,sizeof(int),1,fp);
fwrite(&flag4,sizeof(int),1,fp);
fwrite(&cut_inner_global,sizeof(double),1,fp);
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&t_target,sizeof(double),1,fp);
fwrite(&seed,sizeof(int),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLubricate::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&mu,sizeof(double),1,fp);
fread(&flag1,sizeof(int),1,fp);
fread(&flag2,sizeof(int),1,fp);
fread(&flag3,sizeof(int),1,fp);
fread(&flag4,sizeof(int),1,fp);
fread(&cut_inner_global,sizeof(double),1,fp);
fread(&cut_global,sizeof(double),1,fp);
fread(&t_target, sizeof(double),1,fp);
fread(&seed, sizeof(int),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&mu,1,MPI_DOUBLE,0,world);
MPI_Bcast(&flag1,1,MPI_INT,0,world);
MPI_Bcast(&flag2,1,MPI_INT,0,world);
MPI_Bcast(&flag3,1,MPI_INT,0,world);
MPI_Bcast(&flag4,1,MPI_INT,0,world);
MPI_Bcast(&cut_inner_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&t_target,1,MPI_DOUBLE,0,world);
MPI_Bcast(&seed,1,MPI_INT,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
// additional setup based on restart parameters
delete random;
random = new RanMars(lmp,seed + comm->me);
}
/* ---------------------------------------------------------------------- */
void *PairLubricate::extract(char *str, int &dim)
{
dim = 0;
if (strcmp(str,"mu") == 0) return (void *) &mu;
return NULL;
}
diff --git a/src/COLLOID/pair_yukawa_colloid.cpp b/src/COLLOID/pair_yukawa_colloid.cpp
index 10ef11638..ca68a56c9 100644
--- a/src/COLLOID/pair_yukawa_colloid.cpp
+++ b/src/COLLOID/pair_yukawa_colloid.cpp
@@ -1,177 +1,177 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Randy Schunk (Sandia)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_yukawa_colloid.h"
#include "atom.h"
#include "atom_vec.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairYukawaColloid::PairYukawaColloid(LAMMPS *lmp) : PairYukawa(lmp) {}
/* ---------------------------------------------------------------------- */
void PairYukawaColloid::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair,radi,radj;
double rsq,r2inv,r,rinv,screening,forceyukawa,factor;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *radius = atom->radius;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
radi = radius[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
radj = radius[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*(r-(radi+radj)));
forceyukawa = a[itype][jtype] * screening;
fpair = factor*forceyukawa * rinv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = a[itype][jtype]/kappa * screening - offset[itype][jtype];
evdwl *= factor;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairYukawaColloid::init_style()
{
if (!atom->sphere_flag)
- error->all("Pair yukawa/colloid requires atom style sphere");
+ error->all(FLERR,"Pair yukawa/colloid requires atom style sphere");
neighbor->request(this);
// require that atom radii are identical within each type
for (int i = 1; i <= atom->ntypes; i++)
if (!atom->radius_consistency(i,rad[i]))
- error->all("Pair yukawa/colloid requires atoms with same type "
+ error->all(FLERR,"Pair yukawa/colloid requires atoms with same type "
"have same radius");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairYukawaColloid::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
a[i][j] = mix_energy(a[i][i],a[j][j],1.0,1.0);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
if (offset_flag) {
double screening = exp(-kappa * (cut[i][j] - (rad[i]+rad[j])));
offset[i][j] = a[i][j]/kappa * screening;
} else offset[i][j] = 0.0;
a[j][i] = a[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ---------------------------------------------------------------------- */
double PairYukawaColloid::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r,rinv,screening,forceyukawa,phi;
r2inv = 1.0/rsq;
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*(r-(rad[itype]+rad[jtype])));
forceyukawa = a[itype][jtype] * screening;
fforce = factor_lj*forceyukawa * rinv;
phi = a[itype][jtype]/kappa * screening - offset[itype][jtype];
return factor_lj*phi;
}
diff --git a/src/DIPOLE/atom_vec_dipole.cpp b/src/DIPOLE/atom_vec_dipole.cpp
index cde9b0c80..64ec41d58 100644
--- a/src/DIPOLE/atom_vec_dipole.cpp
+++ b/src/DIPOLE/atom_vec_dipole.cpp
@@ -1,831 +1,831 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "atom_vec_dipole.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecDipole::AtomVecDipole(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 0;
mass_type = 1;
comm_x_only = 0;
comm_f_only = 1;
size_forward = 6;
size_reverse = 3;
size_border = 11;
size_velocity = 3;
size_data_atom = 9;
size_data_vel = 7;
xcol_data = 4;
atom->q_flag = atom->mu_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecDipole::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
q = memory->grow(atom->q,nmax,"atom:q");
mu = memory->grow(atom->mu,nmax,4,"atom:mu");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecDipole::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
q = atom->q; mu = atom->mu;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecDipole::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
q[j] = q[i];
mu[j][0] = mu[i][0];
mu[j][1] = mu[i][1];
mu[j][2] = mu[i][2];
mu[j][3] = mu[i][3];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::pack_comm_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecDipole::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
mu[i][0] = buf[m++];
mu[i][1] = buf[m++];
mu[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecDipole::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
mu[i][0] = buf[m++];
mu[i][1] = buf[m++];
mu[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::unpack_comm_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
mu[i][0] = buf[m++];
mu[i][1] = buf[m++];
mu[i][2] = buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecDipole::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = mu[j][3];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = mu[j][3];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = mu[j][3];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = mu[j][3];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = mu[j][3];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = q[j];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = mu[j][3];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecDipole::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
mu[i][0] = buf[m++];
mu[i][1] = buf[m++];
mu[i][2] = buf[m++];
mu[i][3] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecDipole::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
mu[i][0] = buf[m++];
mu[i][1] = buf[m++];
mu[i][2] = buf[m++];
mu[i][3] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
q[i] = buf[m++];
mu[i][0] = buf[m++];
mu[i][1] = buf[m++];
mu[i][2] = buf[m++];
mu[i][3] = buf[m++];
}
return m;
}
/* ----------------------------------------------------------------------
pack all atom quantities for shipping to another proc
xyz must be 1st 3 values, so that comm::exchange can test on them
------------------------------------------------------------------------- */
int AtomVecDipole::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = q[i];
buf[m++] = mu[i][0];
buf[m++] = mu[i][1];
buf[m++] = mu[i][2];
buf[m++] = mu[i][3];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecDipole::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
q[nlocal] = buf[m++];
mu[nlocal][0] = buf[m++];
mu[nlocal][1] = buf[m++];
mu[nlocal][2] = buf[m++];
mu[nlocal][3] = buf[m++];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecDipole::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 15 * nlocal;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecDipole::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = q[i];
buf[m++] = mu[i][0];
buf[m++] = mu[i][1];
buf[m++] = mu[i][2];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecDipole::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
q[nlocal] = buf[m++];
mu[nlocal][0] = buf[m++];
mu[nlocal][1] = buf[m++];
mu[nlocal][2] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecDipole::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
q[nlocal] = 0.0;
mu[nlocal][0] = 0.0;
mu[nlocal][1] = 0.0;
mu[nlocal][2] = 0.0;
mu[nlocal][3] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecDipole::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
q[nlocal] = atof(values[2]);
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mu[nlocal][0] = atof(values[6]);
mu[nlocal][1] = atof(values[7]);
mu[nlocal][2] = atof(values[8]);
mu[nlocal][3] = sqrt(mu[nlocal][0]*mu[nlocal][0] +
mu[nlocal][1]*mu[nlocal][1] +
mu[nlocal][2]*mu[nlocal][2]);
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecDipole::data_atom_hybrid(int nlocal, char **values)
{
q[nlocal] = atof(values[0]);
mu[nlocal][0] = atof(values[1]);
mu[nlocal][1] = atof(values[2]);
mu[nlocal][2] = atof(values[3]);
mu[nlocal][3] = sqrt(mu[nlocal][0]*mu[nlocal][0] +
mu[nlocal][1]*mu[nlocal][1] +
mu[nlocal][2]*mu[nlocal][2]);
return 4;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecDipole::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("q")) bytes += memory->usage(q,nmax);
if (atom->memcheck("mu")) bytes += memory->usage(mu,nmax,4);
return bytes;
}
diff --git a/src/DIPOLE/pair_dipole_cut.cpp b/src/DIPOLE/pair_dipole_cut.cpp
index 3f9e79332..f443854b9 100644
--- a/src/DIPOLE/pair_dipole_cut.cpp
+++ b/src/DIPOLE/pair_dipole_cut.cpp
@@ -1,484 +1,481 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_dipole_cut.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairDipoleCut::PairDipoleCut(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
}
/* ---------------------------------------------------------------------- */
PairDipoleCut::~PairDipoleCut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairDipoleCut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fx,fy,fz;
double rsq,rinv,r2inv,r6inv,r3inv,r5inv,r7inv;
double forcecoulx,forcecouly,forcecoulz,crossx,crossy,crossz;
double tixcoul,tiycoul,tizcoul,tjxcoul,tjycoul,tjzcoul;
double fq,pdotp,pidotr,pjdotr,pre1,pre2,pre3,pre4;
double forcelj,factor_coul,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
double **mu = atom->mu;
double **torque = atom->torque;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
rinv = sqrt(r2inv);
// atom can have both a charge and dipole
// i,j = charge-charge, dipole-dipole, dipole-charge, or charge-dipole
forcecoulx = forcecouly = forcecoulz = 0.0;
tixcoul = tiycoul = tizcoul = 0.0;
tjxcoul = tjycoul = tjzcoul = 0.0;
if (rsq < cut_coulsq[itype][jtype]) {
if (qtmp != 0.0 && q[j] != 0.0) {
r3inv = r2inv*rinv;
pre1 = qtmp*q[j]*r3inv;
forcecoulx += pre1*delx;
forcecouly += pre1*dely;
forcecoulz += pre1*delz;
}
if (mu[i][3] > 0.0 && mu[j][3] > 0.0) {
r3inv = r2inv*rinv;
r5inv = r3inv*r2inv;
r7inv = r5inv*r2inv;
pdotp = mu[i][0]*mu[j][0] + mu[i][1]*mu[j][1] + mu[i][2]*mu[j][2];
pidotr = mu[i][0]*delx + mu[i][1]*dely + mu[i][2]*delz;
pjdotr = mu[j][0]*delx + mu[j][1]*dely + mu[j][2]*delz;
pre1 = 3.0*r5inv*pdotp - 15.0*r7inv*pidotr*pjdotr;
pre2 = 3.0*r5inv*pjdotr;
pre3 = 3.0*r5inv*pidotr;
pre4 = -1.0*r3inv;
forcecoulx += pre1*delx + pre2*mu[i][0] + pre3*mu[j][0];
forcecouly += pre1*dely + pre2*mu[i][1] + pre3*mu[j][1];
forcecoulz += pre1*delz + pre2*mu[i][2] + pre3*mu[j][2];
crossx = pre4 * (mu[i][1]*mu[j][2] - mu[i][2]*mu[j][1]);
crossy = pre4 * (mu[i][2]*mu[j][0] - mu[i][0]*mu[j][2]);
crossz = pre4 * (mu[i][0]*mu[j][1] - mu[i][1]*mu[j][0]);
tixcoul += crossx + pre2 * (mu[i][1]*delz - mu[i][2]*dely);
tiycoul += crossy + pre2 * (mu[i][2]*delx - mu[i][0]*delz);
tizcoul += crossz + pre2 * (mu[i][0]*dely - mu[i][1]*delx);
tjxcoul += -crossx + pre3 * (mu[j][1]*delz - mu[j][2]*dely);
tjycoul += -crossy + pre3 * (mu[j][2]*delx - mu[j][0]*delz);
tjzcoul += -crossz + pre3 * (mu[j][0]*dely - mu[j][1]*delx);
}
if (mu[i][3] > 0.0 && q[j] != 0.0) {
r3inv = r2inv*rinv;
r5inv = r3inv*r2inv;
pidotr = mu[i][0]*delx + mu[i][1]*dely + mu[i][2]*delz;
pre1 = 3.0*q[j]*r5inv * pidotr;
pre2 = q[j]*r3inv;
forcecoulx += pre2*mu[i][0] - pre1*delx;
forcecouly += pre2*mu[i][1] - pre1*dely;
forcecoulz += pre2*mu[i][2] - pre1*delz;
tixcoul += pre2 * (mu[i][1]*delz - mu[i][2]*dely);
tiycoul += pre2 * (mu[i][2]*delx - mu[i][0]*delz);
tizcoul += pre2 * (mu[i][0]*dely - mu[i][1]*delx);
}
if (mu[j][3] > 0.0 && qtmp != 0.0) {
r3inv = r2inv*rinv;
r5inv = r3inv*r2inv;
pjdotr = mu[j][0]*delx + mu[j][1]*dely + mu[j][2]*delz;
pre1 = 3.0*qtmp*r5inv * pjdotr;
pre2 = qtmp*r3inv;
forcecoulx += pre1*delx - pre2*mu[j][0];
forcecouly += pre1*dely - pre2*mu[j][1];
forcecoulz += pre1*delz - pre2*mu[j][2];
tjxcoul += -pre2 * (mu[j][1]*delz - mu[j][2]*dely);
tjycoul += -pre2 * (mu[j][2]*delx - mu[j][0]*delz);
tjzcoul += -pre2 * (mu[j][0]*dely - mu[j][1]*delx);
}
}
// LJ interaction
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
forcelj *= factor_lj * r2inv;
} else forcelj = 0.0;
// total force
fq = factor_coul*qqrd2e;
fx = fq*forcecoulx + delx*forcelj;
fy = fq*forcecouly + dely*forcelj;
fz = fq*forcecoulz + delz*forcelj;
// force & torque accumulation
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
torque[i][0] += fq*tixcoul;
torque[i][1] += fq*tiycoul;
torque[i][2] += fq*tizcoul;
if (newton_pair || j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
torque[j][0] += fq*tjxcoul;
torque[j][1] += fq*tjycoul;
torque[j][2] += fq*tjzcoul;
}
if (eflag) {
if (rsq < cut_coulsq[itype][jtype]) {
ecoul = qtmp*q[j]*rinv;
if (mu[i][3] > 0.0 && mu[j][3] > 0.0)
ecoul += r3inv*pdotp - 3.0*r5inv*pidotr*pjdotr;
if (mu[i][3] > 0.0 && q[j] != 0.0)
ecoul += -q[j]*r3inv*pidotr;
if (mu[j][3] > 0.0 && qtmp != 0.0)
ecoul += qtmp*r3inv*pjdotr;
ecoul *= factor_coul*qqrd2e;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,
evdwl,ecoul,fx,fy,fz,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairDipoleCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"pair:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"pair:cut_coulsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairDipoleCut::settings(int narg, char **arg)
{
if (narg < 1 || narg > 2)
- error->all("Incorrect args in pair_style command");
+ error->all(FLERR,"Incorrect args in pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul_global = cut_lj_global;
else cut_coul_global = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_lj[i][j] = cut_lj_global;
cut_coul[i][j] = cut_coul_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairDipoleCut::coeff(int narg, char **arg)
{
if (narg < 4 || narg > 6)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_lj_one = cut_lj_global;
double cut_coul_one = cut_coul_global;
if (narg >= 5) cut_coul_one = cut_lj_one = force->numeric(arg[4]);
if (narg == 6) cut_coul_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_lj[i][j] = cut_lj_one;
cut_coul[i][j] = cut_coul_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairDipoleCut::init_style()
{
if (!atom->q_flag || !atom->mu_flag || !atom->torque_flag)
- error->all("Pair dipole/cut requires atom attributes q, mu, torque");
+ error->all(FLERR,"Pair dipole/cut requires atom attributes q, mu, torque");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairDipoleCut::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]);
cut_coul[i][j] = mix_distance(cut_coul[i][i],cut_coul[j][j]);
}
double cut = MAX(cut_lj[i][j],cut_coul[i][j]);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
cut_coulsq[i][j] = cut_coul[i][j] * cut_coul[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut_lj[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
cut_coulsq[j][i] = cut_coulsq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDipoleCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
fwrite(&cut_coul[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDipoleCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
fread(&cut_coul[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDipoleCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDipoleCut::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
diff --git a/src/GPU/fix_gpu.cpp b/src/GPU/fix_gpu.cpp
index cdcaaa845..a44498670 100644
--- a/src/GPU/fix_gpu.cpp
+++ b/src/GPU/fix_gpu.cpp
@@ -1,181 +1,181 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "fix_gpu.h"
#include "atom.h"
#include "force.h"
#include "pair.h"
#include "respa.h"
#include "input.h"
#include "error.h"
#include "timer.h"
#include "modify.h"
#include "domain.h"
#include "universe.h"
#include "gpu_extra.h"
using namespace LAMMPS_NS;
enum{GPU_FORCE, GPU_NEIGH};
extern int lmp_init_device(MPI_Comm world, MPI_Comm replica,
const int first_gpu, const int last_gpu,
const int gpu_mode, const double particle_split,
const int nthreads, const int t_per_atom);
extern void lmp_clear_device();
extern double lmp_gpu_forces(double **f, double **tor, double *eatom,
double **vatom, double *virial, double &ecoul);
/* ---------------------------------------------------------------------- */
FixGPU::FixGPU(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (lmp->cuda) error->all("Cannot use fix GPU with USER-CUDA mode enabled");
+ if (lmp->cuda) error->all(FLERR,"Cannot use fix GPU with USER-CUDA mode enabled");
- if (narg < 7) error->all("Illegal fix GPU command");
- if (strcmp(arg[1],"all") != 0) error->all("Illegal fix GPU command");
+ if (narg < 7) error->all(FLERR,"Illegal fix GPU command");
+ if (strcmp(arg[1],"all") != 0) error->all(FLERR,"Illegal fix GPU command");
int first_gpu, last_gpu;
if (strcmp(arg[3],"force") == 0)
_gpu_mode = GPU_FORCE;
else if (strcmp(arg[3],"force/neigh") == 0) {
_gpu_mode = GPU_NEIGH;
if (domain->triclinic)
- error->all("Cannot use force/neigh with triclinic box");
+ error->all(FLERR,"Cannot use force/neigh with triclinic box");
} else
- error->all("Illegal fix GPU command");
+ error->all(FLERR,"Illegal fix GPU command");
first_gpu = atoi(arg[4]);
last_gpu = atoi(arg[5]);
_particle_split = force->numeric(arg[6]);
if (_particle_split==0 || _particle_split>1)
- error->all("Illegal fix GPU command");
+ error->all(FLERR,"Illegal fix GPU command");
int nthreads = 1;
int threads_per_atom = -1;
if (narg == 9) {
if (strcmp(arg[7],"threads_per_atom") == 0)
threads_per_atom = atoi(arg[8]);
else if (strcmp(arg[7],"nthreads") == 0)
nthreads = atoi(arg[8]);
else
- error->all("Illegal fix GPU command");
+ error->all(FLERR,"Illegal fix GPU command");
} else if (narg != 7)
- error->all("Illegal fix GPU command");
+ error->all(FLERR,"Illegal fix GPU command");
if (nthreads < 1)
- error->all("Illegal fix GPU command");
+ error->all(FLERR,"Illegal fix GPU command");
#ifndef _OPENMP
if (nthreads > 1)
- error->all("No OpenMP support compiled in");
+ error->all(FLERR,"No OpenMP support compiled in");
#endif
int gpu_flag = lmp_init_device(universe->uworld, world, first_gpu, last_gpu,
_gpu_mode, _particle_split, nthreads,
threads_per_atom);
GPU_EXTRA::check_flag(gpu_flag,error,world);
}
/* ---------------------------------------------------------------------- */
FixGPU::~FixGPU()
{
lmp_clear_device();
}
/* ---------------------------------------------------------------------- */
int FixGPU::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixGPU::init()
{
// Can only have 1 gpu fix that must be the first fix for a run
if ((void*)modify->fix[0] != (void*)this)
- error->all("GPU is not the first fix for this run");
+ error->all(FLERR,"GPU is not the first fix for this run");
// Hybrid cannot be used with force/neigh option
if (_gpu_mode == GPU_NEIGH)
if (force->pair_match("hybrid",1) != NULL ||
force->pair_match("hybrid/overlay",1) != NULL)
- error->all("Cannot use pair hybrid with GPU neighbor builds");
+ error->all(FLERR,"Cannot use pair hybrid with GPU neighbor builds");
if (_particle_split < 0)
if (force->pair_match("hybrid",1) != NULL ||
force->pair_match("hybrid/overlay",1) != NULL)
- error->all("Fix GPU split must be positive for hybrid pair styles");
+ error->all(FLERR,"Fix GPU split must be positive for hybrid pair styles");
}
/* ---------------------------------------------------------------------- */
void FixGPU::setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixGPU::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixGPU::post_force(int vflag)
{
timer->stamp();
double lvirial[6];
for (int i = 0; i < 6; i++) lvirial[i] = 0.0;
double my_eng = lmp_gpu_forces(atom->f, atom->torque, force->pair->eatom,
force->pair->vatom, lvirial,
force->pair->eng_coul);
force->pair->eng_vdwl += my_eng;
force->pair->virial[0] += lvirial[0];
force->pair->virial[1] += lvirial[1];
force->pair->virial[2] += lvirial[2];
force->pair->virial[3] += lvirial[3];
force->pair->virial[4] += lvirial[4];
force->pair->virial[5] += lvirial[5];
if (force->pair->vflag_fdotr) force->pair->virial_fdotr_compute();
timer->stamp(TIME_PAIR);
}
/* ---------------------------------------------------------------------- */
void FixGPU::min_post_force(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
double FixGPU::memory_usage()
{
double bytes = 0.0;
// Memory usage currently returned by pair routine
return bytes;
}
diff --git a/src/GPU/gpu_extra.h b/src/GPU/gpu_extra.h
index 9fa2d83a1..d9bbb7eaa 100644
--- a/src/GPU/gpu_extra.h
+++ b/src/GPU/gpu_extra.h
@@ -1,47 +1,49 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (ORNL)
------------------------------------------------------------------------- */
#ifndef LMP_GPU_EXTRA_H
#define LMP_GPU_EXTRA_H
#include "error.h"
namespace GPU_EXTRA {
inline void check_flag(int error_flag, LAMMPS_NS::Error *error,
MPI_Comm &world) {
int all_success;
MPI_Allreduce(&error_flag, &all_success, 1, MPI_INT, MPI_MIN, world);
if (all_success != 0) {
if (all_success == -1)
- error->all("Accelerated style in input script but no fix gpu");
+ error->all(FLERR,"Accelerated style in input script but no fix gpu");
else if (all_success == -2)
- error->all("Could not find/initialize a specified accelerator device");
+ error->all(FLERR,
+ "Could not find/initialize a specified accelerator device");
else if (all_success == -3)
- error->all("Insufficient memory on accelerator");
+ error->all(FLERR,"Insufficient memory on accelerator");
else if (all_success == -4)
- error->all("GPU library not compiled for this accelerator");
+ error->all(FLERR,"GPU library not compiled for this accelerator");
else if (all_success == -5)
- error->all("Double precision is not supported on this accelerator");
+ error->all(FLERR,
+ "Double precision is not supported on this accelerator");
else
- error->all("Unknown error in GPU library");
+ error->all(FLERR,"Unknown error in GPU library");
}
}
}
#endif
diff --git a/src/GPU/pair_cg_cmm_coul_long_gpu.cpp b/src/GPU/pair_cg_cmm_coul_long_gpu.cpp
index d19b2d651..27aedd419 100644
--- a/src/GPU/pair_cg_cmm_coul_long_gpu.cpp
+++ b/src/GPU/pair_cg_cmm_coul_long_gpu.cpp
@@ -1,340 +1,337 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_cg_cmm_coul_long_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "kspace.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
// External functions from cuda library for atom decomposition
int cmml_gpu_init(const int ntypes, double **cutsq, int **cg_type,
double **host_lj1, double **host_lj2, double **host_lj3,
double **host_lj4, double **offset, double *special_lj,
const int nlocal, const int nall, const int max_nbors,
const int maxspecial, const double cell_size, int &gpu_mode,
FILE *screen, double **host_cut_ljsq, double host_cut_coulsq,
double *host_special_coul, const double qqrd2e,
const double g_ewald);
void cmml_gpu_clear();
int ** cmml_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum, const double cpu_time,
bool &success, double *host_q, double *boxlo,
double *prd);
void cmml_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double *host_q,
const int nlocal, double *boxlo, double *prd);
double cmml_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairCGCMMCoulLongGPU::PairCGCMMCoulLongGPU(LAMMPS *lmp) : PairCGCMMCoulLong(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairCGCMMCoulLongGPU::~PairCGCMMCoulLongGPU()
{
cmml_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLongGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = cmml_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, atom->q, domain->boxlo,
domain->prd);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
cmml_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success, atom->q,
atom->nlocal, domain->boxlo, domain->prd);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairCGCMMCoulLongGPU::init_style()
{
cut_respa = NULL;
if (!atom->q_flag)
- error->all("Pair style cg/cmm/coul/long/gpu requires atom attribute q");
+ error->all(FLERR,"Pair style cg/cmm/coul/long/gpu requires atom attribute q");
if (force->newton_pair)
- error->all("Cannot use newton pair with cg/cmm/coul/long/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with cg/cmm/coul/long/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = cmml_gpu_init(atom->ntypes+1, cutsq, cg_type, lj1, lj2, lj3,
lj4, offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen, cut_ljsq,
cut_coulsq_global, force->special_coul,
force->qqrd2e, g_ewald);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulLongGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + cmml_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLongGPU::cpu_compute(int start, int inum, int eflag,
int vflag, int *ilist, int *numneigh,
int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
int *jlist;
double rsq;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
const double delx = xtmp - x[j][0];
const double dely = ytmp - x[j][1];
const double delz = ztmp - x[j][2];
const double rsq = delx*delx + dely*dely + delz*delz;
const int jtype = type[j];
double evdwl = 0.0;
double ecoul = 0.0;
double fpair = 0.0;
if (rsq < cutsq[itype][jtype]) {
const double r2inv = 1.0/rsq;
const int cgt=cg_type[itype][jtype];
double forcelj = 0.0;
double forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
forcelj=factor_lj;
if (eflag) evdwl=factor_lj;
if (cgt == CG_LJ12_4) {
const double r4inv=r2inv*r2inv;
forcelj *= r4inv*(lj1[itype][jtype]*r4inv*r4inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r4inv*(lj3[itype][jtype]*r4inv*r4inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else if (cgt == CG_LJ9_6) {
const double r3inv = r2inv*sqrt(r2inv);
const double r6inv = r3inv*r3inv;
forcelj *= r6inv*(lj1[itype][jtype]*r3inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r3inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else {
const double r6inv = r2inv*r2inv*r2inv;
forcelj *= r6inv*(lj1[itype][jtype]*r6inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r6inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
}
}
if (rsq < cut_coulsq_global) {
if (!ncoultablebits || rsq <= tabinnersq) {
const double r = sqrt(rsq);
const double grij = g_ewald * r;
const double expm2 = exp(-grij*grij);
const double t = 1.0 / (1.0 + EWALD_P*grij);
const double erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
const double prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (eflag) ecoul = prefactor*erfc;
if (factor_coul < 1.0) {
forcecoul -= (1.0-factor_coul)*prefactor;
if (eflag) ecoul -= (1.0-factor_coul)*prefactor;
}
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
int itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
const double fraction = (rsq_lookup.f - rtable[itable]) *
drtable[itable];
const double table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (eflag) {
const double table2 = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table2;
}
if (factor_coul < 1.0) {
const double table2 = ctable[itable] + fraction*dctable[itable];
const double prefactor = qtmp*q[j] * table2;
forcecoul -= (1.0-factor_coul)*prefactor;
if (eflag) ecoul -= (1.0-factor_coul)*prefactor;
}
}
}
fpair = (forcecoul + forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (evflag) ev_tally_full(i,evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_cg_cmm_coul_msm.cpp b/src/GPU/pair_cg_cmm_coul_msm.cpp
index d1e9b2277..5321945eb 100644
--- a/src/GPU/pair_cg_cmm_coul_msm.cpp
+++ b/src/GPU/pair_cg_cmm_coul_msm.cpp
@@ -1,292 +1,290 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
CMM coarse grained MD potentials. Coulomb with MSM version.
Contributing author: Mike Brown <brownw@ornl.gov>
------------------------------------------------------------------------- */
+#include "string.h"
#include "pair_cg_cmm_coul_msm.h"
#include "memory.h"
#include "atom.h"
#include "force.h"
#include "kspace.h"
-#include "string.h"
+using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
enum {C3=0,C4=1};
-using namespace LAMMPS_NS;
-
/* ---------------------------------------------------------------------- */
PairCGCMMCoulMSM::PairCGCMMCoulMSM(LAMMPS *lmp) : PairCMMCommon(lmp)
{
respa_enable = 0;
single_enable = 0;
}
/* ---------------------------------------------------------------------- */
PairCGCMMCoulMSM::~PairCGCMMCoulMSM()
{
if (allocated_coul) {
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
allocated_coul=0;
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulMSM::allocate()
{
PairCMMCommon::allocate();
allocated_coul = 1;
int n = atom->ntypes;
memory->create(cut_lj,n+1,n+1,"paircg:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"paircg:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"paircg:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"paircg:cut_coulsq");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairCGCMMCoulMSM::settings(int narg, char **arg)
{
// strip off smoothing type and send args to parent
- if (narg < 1) error->all("Illegal pair_style command");
+ if (narg < 1) error->all(FLERR,"Illegal pair_style command");
if (strcmp(arg[0],"C3") == 0)
_smooth = C3;
else if (strcmp(arg[0],"C4") == 0)
_smooth = C4;
- else error->all("Illegal pair_style command");
+ else error->all(FLERR,"Illegal pair_style command");
PairCMMCommon::settings(narg-1,&arg[1]);
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulMSM::init_style()
{
if (!atom->q_flag)
- error->all("Pair style cg/cut/coul/msm requires atom attribute q");
+ error->all(FLERR,"Pair style cg/cut/coul/msm requires atom attribute q");
PairCMMCommon::init_style();
_ia=-1.0/cut_coul_global;
_ia2=_ia*_ia;
_ia3=_ia2*_ia;
cut_respa = NULL;
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulMSM::init_one(int i, int j)
{
double mycut = PairCMMCommon::init_one(i,j);
return mycut;
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulMSM::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
int *ilist,*jlist,*numneigh,**firstneigh;
double rsq;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
const double delx = xtmp - x[j][0];
const double dely = ytmp - x[j][1];
const double delz = ztmp - x[j][2];
const double rsq = delx*delx + dely*dely + delz*delz;
const int jtype = type[j];
double evdwl = 0.0;
double ecoul = 0.0;
double fpair = 0.0;
if (rsq < cutsq[itype][jtype]) {
const double r2inv = 1.0/rsq;
const int cgt=cg_type[itype][jtype];
double forcelj = 0.0;
double forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
forcelj=factor_lj;
if (eflag) evdwl=factor_lj;
if (cgt == CG_LJ12_4) {
const double r4inv=r2inv*r2inv;
forcelj *= r4inv*(lj1[itype][jtype]*r4inv*r4inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r4inv*(lj3[itype][jtype]*r4inv*r4inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else if (cgt == CG_LJ9_6) {
const double r3inv = r2inv*sqrt(r2inv);
const double r6inv = r3inv*r3inv;
forcelj *= r6inv*(lj1[itype][jtype]*r3inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r3inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else {
const double r6inv = r2inv*r2inv*r2inv;
forcelj *= r6inv*(lj1[itype][jtype]*r6inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r6inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
}
}
if (rsq < cut_coulsq_global) {
const double ir = 1.0/sqrt(rsq);
const double prefactor = qqrd2e * qtmp*q[j];
const double r2_ia2 = rsq*_ia2;
const double r4_ia4 = r2_ia2*r2_ia2;
if (_smooth==C3) {
forcecoul = prefactor*(_ia3*(-4.375+5.25*r2_ia2-1.875*r4_ia4)-
ir/rsq);
if (eflag)
ecoul = prefactor*(ir+_ia*(2.1875-2.1875*r2_ia2+
1.3125*r4_ia4-0.3125*r2_ia2*r4_ia4));
} else {
const double r6_ia6 = r2_ia2*r4_ia4;
forcecoul = prefactor*(_ia3*(-6.5625+11.8125*r2_ia2-8.4375*r4_ia4+
2.1875*r6_ia6)-ir/rsq);
if (eflag)
ecoul = prefactor*(ir+_ia*(2.4609375-3.28125*r2_ia2+
2.953125*r4_ia4-1.40625*r6_ia6+
0.2734375*r4_ia4*r4_ia4));
}
if (factor_coul < 1.0) {
forcecoul -= (1.0-factor_coul)*prefactor*ir;
if (eflag) ecoul -= (1.0-factor_coul)*prefactor*ir;
}
}
fpair = forcecoul + forcelj * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulMSM::write_restart(FILE *fp)
{
write_restart_settings(fp);
PairCMMCommon::write_restart(fp);
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulMSM::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
PairCMMCommon::read_restart(fp);
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulMSM::memory_usage()
{
double bytes=PairCMMCommon::memory_usage();
int n = atom->ntypes;
// cut_coul/cut_coulsq/cut_ljsq
bytes += (n+1)*(n+1)*sizeof(double)*4;
return bytes;
}
/* ---------------------------------------------------------------------- */
void *PairCGCMMCoulMSM::extract(char *str)
{
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul_global;
return NULL;
}
/* ---------------------------------------------------------------------- */
diff --git a/src/GPU/pair_cg_cmm_coul_msm_gpu.cpp b/src/GPU/pair_cg_cmm_coul_msm_gpu.cpp
index d946b739d..0d079304f 100644
--- a/src/GPU/pair_cg_cmm_coul_msm_gpu.cpp
+++ b/src/GPU/pair_cg_cmm_coul_msm_gpu.cpp
@@ -1,309 +1,307 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_cg_cmm_coul_msm_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "kspace.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-enum {C3=0,C4=1};
-
// External functions from cuda library for atom decomposition
int cmmm_gpu_init(const int ntypes, double **cutsq, int **cg_type,
double **host_lj1, double **host_lj2, double **host_lj3,
double **host_lj4, double **offset, double *special_lj,
const int nlocal, const int nall, const int max_nbors,
const int maxspecial, const double cell_size, int &gpu_mode,
FILE *screen, double **host_cut_ljsq, double host_cut_coulsq,
double *host_special_coul, const double qqrd2e,
const int smooth);
void cmmm_gpu_clear();
int ** cmmm_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum, const double cpu_time,
bool &success, double *host_q, double *boxlo,
double *prd);
void cmmm_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double *host_q,
const int nlocal, double *boxlo, double *prd);
double cmmm_gpu_bytes();
using namespace LAMMPS_NS;
+enum {C3=0,C4=1};
+
/* ---------------------------------------------------------------------- */
PairCGCMMCoulMSMGPU::PairCGCMMCoulMSMGPU(LAMMPS *lmp) : PairCGCMMCoulMSM(lmp),
gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairCGCMMCoulMSMGPU::~PairCGCMMCoulMSMGPU()
{
cmmm_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulMSMGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = cmmm_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, atom->q, domain->boxlo,
domain->prd);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
cmmm_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success, atom->q,
atom->nlocal, domain->boxlo, domain->prd);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairCGCMMCoulMSMGPU::init_style()
{
PairCGCMMCoulMSM::init_style();
if (force->newton_pair)
- error->all("Cannot use newton pair with cg/cmm/coul/msm/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with cg/cmm/coul/msm/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = cmmm_gpu_init(atom->ntypes+1, cutsq, cg_type, lj1, lj2, lj3,
lj4, offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen, cut_ljsq,
cut_coulsq_global, force->special_coul,
force->qqrd2e,_smooth);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulMSMGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + cmmm_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulMSMGPU::cpu_compute(int start, int inum, int eflag,
int vflag, int *ilist, int *numneigh,
int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
int *jlist;
double rsq;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
const double delx = xtmp - x[j][0];
const double dely = ytmp - x[j][1];
const double delz = ztmp - x[j][2];
const double rsq = delx*delx + dely*dely + delz*delz;
const int jtype = type[j];
double evdwl = 0.0;
double ecoul = 0.0;
double fpair = 0.0;
if (rsq < cutsq[itype][jtype]) {
const double r2inv = 1.0/rsq;
const int cgt=cg_type[itype][jtype];
double forcelj = 0.0;
double forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
forcelj=factor_lj;
if (eflag) evdwl=factor_lj;
if (cgt == CG_LJ12_4) {
const double r4inv=r2inv*r2inv;
forcelj *= r4inv*(lj1[itype][jtype]*r4inv*r4inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r4inv*(lj3[itype][jtype]*r4inv*r4inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else if (cgt == CG_LJ9_6) {
const double r3inv = r2inv*sqrt(r2inv);
const double r6inv = r3inv*r3inv;
forcelj *= r6inv*(lj1[itype][jtype]*r3inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r3inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else {
const double r6inv = r2inv*r2inv*r2inv;
forcelj *= r6inv*(lj1[itype][jtype]*r6inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r6inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
}
}
if (rsq < cut_coulsq_global) {
const double ir = 1.0/sqrt(rsq);
const double prefactor = qqrd2e * qtmp*q[j];
const double r2_ia2 = rsq*_ia2;
const double r4_ia4 = r2_ia2*r2_ia2;
if (_smooth==C3) {
forcecoul = prefactor*(_ia3*(-4.375+5.25*r2_ia2-1.875*r4_ia4)-
ir/rsq);
if (eflag)
ecoul = prefactor*(ir+_ia*(2.1875-2.1875*r2_ia2+
1.3125*r4_ia4-0.3125*r2_ia2*r4_ia4));
} else {
const double r6_ia6 = r2_ia2*r4_ia4;
forcecoul = prefactor*(_ia3*(-6.5625+11.8125*r2_ia2-8.4375*r4_ia4+
2.1875*r6_ia6)-ir/rsq);
if (eflag)
ecoul = prefactor*(ir+_ia*(2.4609375-3.28125*r2_ia2+
2.953125*r4_ia4-1.40625*r6_ia6+
0.2734375*r4_ia4*r4_ia4));
}
if (factor_coul < 1.0) {
forcecoul -= (1.0-factor_coul)*prefactor*ir;
if (eflag) ecoul -= (1.0-factor_coul)*prefactor*ir;
}
}
fpair = forcecoul + forcelj * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (evflag) ev_tally_full(i,evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_cg_cmm_gpu.cpp b/src/GPU/pair_cg_cmm_gpu.cpp
index e756d7d0e..9fd28666f 100644
--- a/src/GPU/pair_cg_cmm_gpu.cpp
+++ b/src/GPU/pair_cg_cmm_gpu.cpp
@@ -1,256 +1,253 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_cg_cmm_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int cmm_gpu_init(const int ntypes, double **cutsq, int **cg_types,
double **host_lj1, double **host_lj2, double **host_lj3,
double **host_lj4, double **offset, double *special_lj,
const int nlocal, const int nall, const int max_nbors,
const int maxspecial, const double cell_size, int &gpu_mode,
FILE *screen);
void cmm_gpu_clear();
int ** cmm_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum,
const double cpu_time, bool &success);
void cmm_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success);
double cmm_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairCGCMMGPU::PairCGCMMGPU(LAMMPS *lmp) : PairCGCMM(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairCGCMMGPU::~PairCGCMMGPU()
{
cmm_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = cmm_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
cmm_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairCGCMMGPU::init_style()
{
cut_respa = NULL;
if (force->newton_pair)
- error->all("Cannot use newton pair with cg/cmm/gpu pair style");
+ error->all("FLERR,Cannot use newton pair with cg/cmm/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = cmm_gpu_init(atom->ntypes+1,cutsq,cg_type,lj1,lj2,lj3,lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairCGCMMGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + cmm_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
int *jlist;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
const int cgt=cg_type[itype][jtype];
r2inv = 1.0/rsq;
fpair = factor_lj;
if (eflag) evdwl = factor_lj;
if (cgt == CG_LJ12_4) {
const double r4inv = r2inv*r2inv;
fpair *= r4inv*(lj1[itype][jtype]*r4inv*r4inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r4inv*(lj3[itype][jtype]*r4inv*r4inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else if (cgt == CG_LJ9_6) {
const double r3inv = r2inv*sqrt(r2inv);
const double r6inv = r3inv*r3inv;
fpair *= r6inv*(lj1[itype][jtype]*r3inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r3inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
} else {
const double r6inv = r2inv*r2inv*r2inv;
fpair *= r6inv*(lj1[itype][jtype]*r6inv
- lj2[itype][jtype]);
if (eflag) {
evdwl *= r6inv*(lj3[itype][jtype]*r6inv
- lj4[itype][jtype]) - offset[itype][jtype];
}
}
fpair *= r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (evflag) ev_tally_full(i,evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_coul_long_gpu.cpp b/src/GPU/pair_coul_long_gpu.cpp
index 468821dce..8502e8ae5 100644
--- a/src/GPU/pair_coul_long_gpu.cpp
+++ b/src/GPU/pair_coul_long_gpu.cpp
@@ -1,282 +1,279 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_coul_long_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "kspace.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
// External functions from cuda library for atom decomposition
int cl_gpu_init(const int nlocal, const int nall, const int max_nbors,
const int maxspecial, const double cell_size, int &gpu_mode,
FILE *screen, double host_cut_coulsq, double *host_special_coul,
const double qqrd2e, const double g_ewald);
void cl_gpu_clear();
int ** cl_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag,
int **nspecial, int **special, const bool eflag,
const bool vflag, const bool eatom, const bool vatom,
int &host_start, int **ilist, int **jnum,
const double cpu_time, bool &success, double *host_q,
double *boxlo, double *prd);
void cl_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double *host_q,
const int nlocal, double *boxlo, double *prd);
double cl_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairCoulLongGPU::PairCoulLongGPU(LAMMPS *lmp) :
PairCoulLong(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairCoulLongGPU::~PairCoulLongGPU()
{
cl_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairCoulLongGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = cl_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, atom->q, domain->boxlo,
domain->prd);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
cl_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success, atom->q,
atom->nlocal, domain->boxlo, domain->prd);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairCoulLongGPU::init_style()
{
cut_respa = NULL;
if (!atom->q_flag)
- error->all("Pair style coul/long/gpu requires atom attribute q");
+ error->all(FLERR,"Pair style coul/long/gpu requires atom attribute q");
if (force->newton_pair)
- error->all("Cannot use newton pair with coul/long/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with coul/long/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double cell_size = sqrt(cut_coul) + neighbor->skin;
cut_coulsq = cut_coul * cut_coul;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = cl_gpu_init(atom->nlocal, atom->nlocal+atom->nghost, 300,
maxspecial, cell_size, gpu_mode, screen, cut_coulsq,
force->special_coul, force->qqrd2e, g_ewald);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairCoulLongGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + cl_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairCoulLongGPU::cpu_compute(int start, int inum, int eflag,
int vflag, int *ilist, int *numneigh,
int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
int *jlist;
double rsq;
evdwl = ecoul = 0.0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
double *special_coul = force->special_coul;
double qqrd2e = force->qqrd2e;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
fpair = forcecoul * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
}
if (evflag) ev_tally_full(i,0.0,ecoul,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_gayberne_gpu.cpp b/src/GPU/pair_gayberne_gpu.cpp
index c137f0f67..eb9fd0094 100644
--- a/src/GPU/pair_gayberne_gpu.cpp
+++ b/src/GPU/pair_gayberne_gpu.cpp
@@ -1,344 +1,341 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_gayberne_gpu.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec.h"
#include "atom_vec_ellipsoid.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "domain.h"
#include "update.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int gb_gpu_init(const int ntypes, const double gamma, const double upsilon,
const double mu, double **shape, double **well, double **cutsq,
double **sigma, double **epsilon, double *host_lshape,
int **form, double **host_lj1, double **host_lj2,
double **host_lj3, double **host_lj4, double **offset,
double *special_lj, const int nlocal, const int nall,
const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen);
void gb_gpu_clear();
int ** gb_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial, int **special,
const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum, const double cpu_time,
bool &success, double **host_quat);
int * gb_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double **host_quat);
double gb_gpu_bytes();
using namespace LAMMPS_NS;
enum{SPHERE_SPHERE,SPHERE_ELLIPSE,ELLIPSE_SPHERE,ELLIPSE_ELLIPSE};
/* ---------------------------------------------------------------------- */
PairGayBerneGPU::PairGayBerneGPU(LAMMPS *lmp) : PairGayBerne(lmp),
gpu_mode(GPU_PAIR)
{
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
if (!avec)
- error->all("Pair gayberne requires atom style ellipsoid");
+ error->all(FLERR,"Pair gayberne requires atom style ellipsoid");
quat_nmax = 0;
quat = NULL;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairGayBerneGPU::~PairGayBerneGPU()
{
gb_gpu_clear();
cpu_time = 0.0;
memory->destroy(quat);
}
/* ---------------------------------------------------------------------- */
void PairGayBerneGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (nall > quat_nmax) {
quat_nmax = static_cast<int>(1.1 * nall);
memory->grow(quat, quat_nmax, 4, "pair:quat");
}
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
for (int i=0; i<nall; i++) {
int qi = ellipsoid[i];
if (qi > -1) {
quat[i][0] = bonus[qi].quat[0];
quat[i][1] = bonus[qi].quat[1];
quat[i][2] = bonus[qi].quat[2];
quat[i][3] = bonus[qi].quat[3];
}
}
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = gb_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, quat);
} else {
inum = list->inum;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
ilist = gb_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
list->ilist, numneigh, firstneigh, eflag, vflag,
eflag_atom, vflag_atom, host_start,
cpu_time, success, quat);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start < inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairGayBerneGPU::init_style()
{
if (force->newton_pair)
- error->all("Cannot use newton pair with gayberne/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with gayberne/gpu pair style");
if (!atom->ellipsoid_flag)
- error->all("Pair gayberne/gpu requires atom style ellipsoid");
+ error->all(FLERR,"Pair gayberne/gpu requires atom style ellipsoid");
// per-type shape precalculations
// require that atom shapes are identical within each type
// if shape = 0 for point particle, set shape = 1 as required by Gay-Berne
for (int i = 1; i <= atom->ntypes; i++) {
if (!atom->shape_consistency(i,shape1[i][0],shape1[i][1],shape1[i][2]))
- error->all("Pair gayberne/gpu requires atoms with same type have same shape");
+ error->all(FLERR,"Pair gayberne/gpu requires atoms with same type have same shape");
if (shape1[i][0] == 0.0)
shape1[i][0] = shape1[i][1] = shape1[i][2] = 1.0;
shape2[i][0] = shape1[i][0]*shape1[i][0];
shape2[i][1] = shape1[i][1]*shape1[i][1];
shape2[i][2] = shape1[i][2]*shape1[i][2];
lshape[i] = (shape1[i][0]*shape1[i][1]+shape1[i][2]*shape1[i][2]) *
sqrt(shape1[i][0]*shape1[i][1]);
}
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = gb_gpu_init(atom->ntypes+1, gamma, upsilon, mu,
shape2, well, cutsq, sigma, epsilon, lshape, form,
lj1, lj2, lj3, lj4, offset, force->special_lj,
atom->nlocal, atom->nlocal+atom->nghost, 300,
maxspecial, cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
quat_nmax = static_cast<int>(1.1 * (atom->nlocal + atom->nghost));
memory->grow(quat, quat_nmax, 4, "pair:quat");
}
/* ---------------------------------------------------------------------- */
double PairGayBerneGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + memory->usage(quat,quat_nmax)+gb_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairGayBerneGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double evdwl,one_eng,rsq,r2inv,r6inv,forcelj,factor_lj;
double fforce[3],ttor[3],rtor[3],r12[3];
double a1[3][3],b1[3][3],g1[3][3],a2[3][3],b2[3][3],g2[3][3],temp[3][3];
int *jlist;
double *iquat,*jquat;
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
double **x = atom->x;
double **f = atom->f;
double **tor = atom->torque;
int *type = atom->type;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
if (form[itype][itype] == ELLIPSE_ELLIPSE) {
iquat = bonus[ellipsoid[i]].quat;
MathExtra::quat_to_mat_trans(iquat,a1);
MathExtra::diag_times3(well[itype],a1,temp);
MathExtra::transpose_times3(a1,temp,b1);
MathExtra::diag_times3(shape2[itype],a1,temp);
MathExtra::transpose_times3(a1,temp,g1);
}
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
// r12 = center to center vector
r12[0] = x[j][0]-x[i][0];
r12[1] = x[j][1]-x[i][1];
r12[2] = x[j][2]-x[i][2];
rsq = MathExtra::dot3(r12,r12);
jtype = type[j];
// compute if less than cutoff
if (rsq < cutsq[itype][jtype]) {
switch (form[itype][jtype]) {
case SPHERE_SPHERE:
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
forcelj *= -r2inv;
if (eflag) one_eng =
r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) -
offset[itype][jtype];
fforce[0] = r12[0]*forcelj;
fforce[1] = r12[1]*forcelj;
fforce[2] = r12[2]*forcelj;
ttor[0] = ttor[1] = ttor[2] = 0.0;
rtor[0] = rtor[1] = rtor[2] = 0.0;
break;
case SPHERE_ELLIPSE:
jquat = bonus[ellipsoid[j]].quat;
MathExtra::quat_to_mat_trans(jquat,a2);
MathExtra::diag_times3(well[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,b2);
MathExtra::diag_times3(shape2[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,g2);
one_eng = gayberne_lj(j,i,a2,b2,g2,r12,rsq,fforce,rtor);
ttor[0] = ttor[1] = ttor[2] = 0.0;
break;
case ELLIPSE_SPHERE:
one_eng = gayberne_lj(i,j,a1,b1,g1,r12,rsq,fforce,ttor);
rtor[0] = rtor[1] = rtor[2] = 0.0;
break;
default:
jquat = bonus[ellipsoid[j]].quat;
MathExtra::quat_to_mat_trans(jquat,a2);
MathExtra::diag_times3(well[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,b2);
MathExtra::diag_times3(shape2[jtype],a2,temp);
MathExtra::transpose_times3(a2,temp,g2);
one_eng = gayberne_analytic(i,j,a1,a2,b1,b2,g1,g2,r12,rsq,
fforce,ttor,rtor);
break;
}
fforce[0] *= factor_lj;
fforce[1] *= factor_lj;
fforce[2] *= factor_lj;
ttor[0] *= factor_lj;
ttor[1] *= factor_lj;
ttor[2] *= factor_lj;
f[i][0] += fforce[0];
f[i][1] += fforce[1];
f[i][2] += fforce[2];
tor[i][0] += ttor[0];
tor[i][1] += ttor[1];
tor[i][2] += ttor[2];
if (eflag) evdwl = factor_lj*one_eng;
if (evflag) ev_tally_xyz_full(i,evdwl,0.0,fforce[0],fforce[1],fforce[2],
-r12[0],-r12[1],-r12[2]);
}
}
}
}
diff --git a/src/GPU/pair_lj96_cut_gpu.cpp b/src/GPU/pair_lj96_cut_gpu.cpp
index ce51b12a7..f09e4636f 100644
--- a/src/GPU/pair_lj96_cut_gpu.cpp
+++ b/src/GPU/pair_lj96_cut_gpu.cpp
@@ -1,232 +1,229 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj96_cut_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int lj96_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen);
void lj96_gpu_clear();
int ** lj96_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum,
const double cpu_time, bool &success);
void lj96_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success);
double lj96_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJ96CutGPU::PairLJ96CutGPU(LAMMPS *lmp) : PairLJ96Cut(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJ96CutGPU::~PairLJ96CutGPU()
{
lj96_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJ96CutGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = lj96_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
lj96_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJ96CutGPU::init_style()
{
cut_respa = NULL;
if (force->newton_pair)
- error->all("Cannot use newton pair with lj96/cut/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj96/cut/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = lj96_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJ96CutGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + lj96_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJ96CutGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj;
int *jlist;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally_full(i,evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_lj_charmm_coul_long_gpu.cpp b/src/GPU/pair_lj_charmm_coul_long_gpu.cpp
index fa48db0d9..a1a30bfb1 100644
--- a/src/GPU/pair_lj_charmm_coul_long_gpu.cpp
+++ b/src/GPU/pair_lj_charmm_coul_long_gpu.cpp
@@ -1,343 +1,340 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_charmm_coul_long_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "kspace.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
// External functions from cuda library for atom decomposition
int crml_gpu_init(const int ntypes, double cut_bothsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen,
double host_cut_ljsq, double host_cut_coulsq,
double *host_special_coul, const double qqrd2e,
const double g_ewald, const double cut_lj_innersq,
const double denom_lj, double **epsilon, double **sigma,
const bool mix_arithmetic);
void crml_gpu_clear();
int ** crml_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag,
int **nspecial, int **special, const bool eflag,
const bool vflag, const bool eatom, const bool vatom,
int &host_start, int **ilist, int **jnum,
const double cpu_time, bool &success, double *host_q,
double *boxlo, double *prd);
void crml_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double *host_q,
const int nlocal, double *boxlo, double *prd);
double crml_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulLongGPU::PairLJCharmmCoulLongGPU(LAMMPS *lmp) :
PairLJCharmmCoulLong(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJCharmmCoulLongGPU::~PairLJCharmmCoulLongGPU()
{
crml_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLongGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = crml_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, atom->q, domain->boxlo,
domain->prd);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
crml_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success, atom->q,
atom->nlocal, domain->boxlo, domain->prd);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCharmmCoulLongGPU::init_style()
{
cut_respa = NULL;
if (!atom->q_flag)
- error->all("Pair style lj/charmm/coul/long/gpu requires atom attribute q");
+ error->all(FLERR,"Pair style lj/charmm/coul/long/gpu requires atom attribute q");
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/charmm/coul/long/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/charmm/coul/long/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0))
cut = init_one(i,j);
}
}
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) *
(cut_ljsq-cut_lj_innersq);
double cell_size = sqrt(cut_bothsq) + neighbor->skin;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
bool arithmetic = true;
for (int i = 1; i < atom->ntypes + 1; i++)
for (int j = i + 1; j < atom->ntypes + 1; j++) {
if (epsilon[i][j] != sqrt(epsilon[i][i] * epsilon[j][j]))
arithmetic = false;
if (sigma[i][j] != 0.5 * (sigma[i][i] + sigma[j][j]))
arithmetic = false;
}
int success = crml_gpu_init(atom->ntypes+1, cut_bothsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen, cut_ljsq,
cut_coulsq, force->special_coul, force->qqrd2e,
g_ewald, cut_lj_innersq,denom_lj,epsilon,sigma,
arithmetic);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJCharmmCoulLongGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + crml_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLongGPU::cpu_compute(int start, int inum, int eflag,
int vflag, int *ilist,
int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
double philj,switch1,switch2;
int *jlist;
double rsq;
evdwl = ecoul = 0.0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_bothsq) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
evdwl *= switch1;
}
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally_full(i,evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_lj_class2_coul_long_gpu.cpp b/src/GPU/pair_lj_class2_coul_long_gpu.cpp
index 2c7ea4153..568cec2bf 100644
--- a/src/GPU/pair_lj_class2_coul_long_gpu.cpp
+++ b/src/GPU/pair_lj_class2_coul_long_gpu.cpp
@@ -1,289 +1,286 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_class2_coul_long_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "kspace.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
// External functions from cuda library for atom decomposition
int c2cl_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen,
double **host_cut_ljsq, double host_cut_coulsq,
double *host_special_coul, const double qqrd2e,
const double g_ewald);
void c2cl_gpu_clear();
int ** c2cl_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag,
int **nspecial, int **special, const bool eflag,
const bool vflag, const bool eatom, const bool vatom,
int &host_start, int **ilist, int **jnum,
const double cpu_time, bool &success, double *host_q,
double *boxlo, double *prd);
void c2cl_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double *host_q,
const int nlocal, double *boxlo, double *prd);
double c2cl_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJClass2CoulLongGPU::PairLJClass2CoulLongGPU(LAMMPS *lmp) :
PairLJClass2CoulLong(lmp), gpu_mode(GPU_PAIR)
{
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJClass2CoulLongGPU::~PairLJClass2CoulLongGPU()
{
c2cl_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulLongGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = c2cl_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, atom->q, domain->boxlo,
domain->prd);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
c2cl_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success, atom->q,
atom->nlocal, domain->boxlo, domain->prd);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJClass2CoulLongGPU::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/class2/coul/long/gpu requires atom attribute q");
+ error->all(FLERR,"Pair style lj/class2/coul/long/gpu requires atom attribute q");
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/class2/coul/long/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/class2/coul/long/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
cut_coulsq = cut_coul * cut_coul;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = c2cl_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen, cut_ljsq, cut_coulsq,
force->special_coul, force->qqrd2e, g_ewald);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJClass2CoulLongGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + c2cl_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulLongGPU::cpu_compute(int start, int inum, int eflag,
int vflag, int *ilist, int *numneigh,
int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r,rinv,r2inv,r3inv,r6inv,forcecoul,forcelj;
double grij,expm2,prefactor,t,erfc;
double factor_coul,factor_lj;
int *jlist;
evdwl = ecoul = 0.0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
rinv = sqrt(r2inv);
r3inv = r2inv*rinv;
r6inv = r3inv*r3inv;
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
if (rsq < cut_coulsq) {
ecoul = prefactor*erfc;
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally_full(i,evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_lj_class2_gpu.cpp b/src/GPU/pair_lj_class2_gpu.cpp
index c45fb5bfd..349c043cd 100644
--- a/src/GPU/pair_lj_class2_gpu.cpp
+++ b/src/GPU/pair_lj_class2_gpu.cpp
@@ -1,229 +1,226 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_class2_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int lj96_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen);
void lj96_gpu_clear();
int ** lj96_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum,
const double cpu_time, bool &success);
void lj96_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success);
double lj96_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJClass2GPU::PairLJClass2GPU(LAMMPS *lmp) : PairLJClass2(lmp), gpu_mode(GPU_PAIR)
{
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJClass2GPU::~PairLJClass2GPU()
{
lj96_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJClass2GPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = lj96_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
lj96_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJClass2GPU::init_style()
{
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/class2/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/class2/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = lj96_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJClass2GPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + lj96_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJClass2GPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj;
int *jlist;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally_full(i,evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_lj_cut_coul_cut_gpu.cpp b/src/GPU/pair_lj_cut_coul_cut_gpu.cpp
index cd19e81ca..66dbbed46 100644
--- a/src/GPU/pair_lj_cut_coul_cut_gpu.cpp
+++ b/src/GPU/pair_lj_cut_coul_cut_gpu.cpp
@@ -1,261 +1,258 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_cut_coul_cut_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int ljc_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen,
double **host_cut_ljsq, double **host_cut_coulsq,
double *host_special_coul, const double qqrd2e);
void ljc_gpu_clear();
int ** ljc_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum, const double cpu_time,
bool &success, double *host_q, double *boxlo,
double *prd);
void ljc_gpu_compute(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
int *ilist, int *numj, int **firstneigh,
const bool eflag, const bool vflag, const bool eatom,
const bool vatom, int &host_start, const double cpu_time,
bool &success, double *host_q, const int nlocal,
double *boxlo, double *prd);
double ljc_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJCutCoulCutGPU::PairLJCutCoulCutGPU(LAMMPS *lmp) : PairLJCutCoulCut(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJCutCoulCutGPU::~PairLJCutCoulCutGPU()
{
ljc_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulCutGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = ljc_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, atom->q, domain->boxlo,
domain->prd);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
ljc_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success, atom->q,
atom->nlocal, domain->boxlo, domain->prd);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCutCoulCutGPU::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/cut/gpu requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/cut/gpu requires atom attribute q");
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/cut/coul/cut/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/cut/coul/cut/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = ljc_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen, cut_ljsq, cut_coulsq,
force->special_coul, force->qqrd2e);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJCutCoulCutGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + ljc_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulCutGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh,
int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
int *jlist;
evdwl = ecoul = 0.0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype])
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
if (rsq < cut_coulsq[itype][jtype])
ecoul = factor_coul * qqrd2e * qtmp*q[j]*sqrt(r2inv);
else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally_full(i,evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_lj_cut_coul_long_gpu.cpp b/src/GPU/pair_lj_cut_coul_long_gpu.cpp
index 2b3a915f0..80c792627 100644
--- a/src/GPU/pair_lj_cut_coul_long_gpu.cpp
+++ b/src/GPU/pair_lj_cut_coul_long_gpu.cpp
@@ -1,316 +1,313 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_cut_coul_long_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "kspace.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
// External functions from cuda library for atom decomposition
int ljcl_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen,
double **host_cut_ljsq, double host_cut_coulsq,
double *host_special_coul, const double qqrd2e,
const double g_ewald);
void ljcl_gpu_clear();
int ** ljcl_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag,
int **nspecial, int **special, const bool eflag,
const bool vflag, const bool eatom, const bool vatom,
int &host_start, int **ilist, int **jnum,
const double cpu_time, bool &success, double *host_q,
double *boxlo, double *prd);
void ljcl_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double *host_q,
const int nlocal, double *boxlo, double *prd);
double ljcl_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJCutCoulLongGPU::PairLJCutCoulLongGPU(LAMMPS *lmp) :
PairLJCutCoulLong(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJCutCoulLongGPU::~PairLJCutCoulLongGPU()
{
ljcl_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLongGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = ljcl_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, atom->q, domain->boxlo,
domain->prd);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
ljcl_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success, atom->q,
atom->nlocal, domain->boxlo, domain->prd);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCutCoulLongGPU::init_style()
{
cut_respa = NULL;
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/long/gpu requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/long/gpu requires atom attribute q");
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/cut/could/cut/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/cut/could/cut/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
cut_coulsq = cut_coul * cut_coul;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = ljcl_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen, cut_ljsq, cut_coulsq,
force->special_coul, force->qqrd2e, g_ewald);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJCutCoulLongGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + ljcl_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLongGPU::cpu_compute(int start, int inum, int eflag,
int vflag, int *ilist, int *numneigh,
int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
int *jlist;
double rsq;
evdwl = ecoul = 0.0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally_full(i,evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_lj_cut_gpu.cpp b/src/GPU/pair_lj_cut_gpu.cpp
index 63a908d3e..198328274 100644
--- a/src/GPU/pair_lj_cut_gpu.cpp
+++ b/src/GPU/pair_lj_cut_gpu.cpp
@@ -1,230 +1,227 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_cut_gpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int ljl_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen);
void ljl_gpu_clear();
int ** ljl_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum,
const double cpu_time, bool &success);
void ljl_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success);
double ljl_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJCutGPU::PairLJCutGPU(LAMMPS *lmp) : PairLJCut(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJCutGPU::~PairLJCutGPU()
{
ljl_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJCutGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = ljl_gpu_compute_n(neighbor->ago, inum, nall,
atom->x, atom->type, domain->sublo,
domain->subhi, atom->tag, atom->nspecial,
atom->special, eflag, vflag, eflag_atom,
vflag_atom, host_start,
&ilist, &numneigh, cpu_time, success);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
ljl_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCutGPU::init_style()
{
cut_respa = NULL;
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/cut/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/cut/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = ljl_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJCutGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + ljl_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJCutGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh) {
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
int *jlist;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally_full(i,evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_lj_cut_tgpu.cpp b/src/GPU/pair_lj_cut_tgpu.cpp
index 043cf0e5b..7b9aa9af0 100644
--- a/src/GPU/pair_lj_cut_tgpu.cpp
+++ b/src/GPU/pair_lj_cut_tgpu.cpp
@@ -1,252 +1,249 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_cut_tgpu.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int ljl_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen);
void ljl_gpu_clear();
int ** ljl_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum,
const double cpu_time, bool &success);
void ljl_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success);
double ljl_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJCutTGPU::PairLJCutTGPU(LAMMPS *lmp) : PairLJCut(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
omp = new PairOMPGPU(lmp);
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJCutTGPU::~PairLJCutTGPU()
{
ljl_gpu_clear();
delete omp;
}
/* ---------------------------------------------------------------------- */
void PairLJCutTGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) {
ev_setup(eflag,vflag);
omp->ev_setup_thr(eflag,vflag,eflag_either,eflag_global,eflag_atom,
vflag_either,vflag_global,vflag_atom);
} else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = ljl_gpu_compute_n(neighbor->ago, inum, nall,
atom->x, atom->type, domain->sublo,
domain->subhi, atom->tag, atom->nspecial,
atom->special, eflag, vflag, eflag_atom,
vflag_atom, host_start, &ilist, &numneigh,
cpu_time, success);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
ljl_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
#ifdef _OPENMP
#pragma omp parallel default(shared)
#endif
{
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
}
if (evflag) omp->ev_reduce_thr(*this);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCutTGPU::init_style()
{
omp->init_style();
cut_respa = NULL;
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/cut/tgpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/cut/tgpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = ljl_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJCutTGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + ljl_gpu_bytes()+omp->memory_usage();
}
/* ---------------------------------------------------------------------- */
void PairLJCutTGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
int *jlist;
double **x = atom->x;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
int iifrom, iito, tid;
double **f = omp->loop_setup_thr_full(atom->f,iifrom,iito,tid,start,inum,
nall);
for (ii = iifrom; ii < iito; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
#ifdef _OPENMP
if (evflag) omp->ev_tally_full_thr(i,evdwl,0.0,fpair,delx,dely,delz,
tid);
#else
if (evflag) ev_tally_full(i,evdwl,0.0,fpair,delx,dely,delz);
#endif
}
}
}
}
diff --git a/src/GPU/pair_lj_expand_gpu.cpp b/src/GPU/pair_lj_expand_gpu.cpp
index f45429a9d..b610e02bc 100644
--- a/src/GPU/pair_lj_expand_gpu.cpp
+++ b/src/GPU/pair_lj_expand_gpu.cpp
@@ -1,234 +1,231 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Inderaj Bains (NVIDIA), ibains@nvidia.com
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_expand_gpu.h"
#include "lmptype.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int lje_gpu_init(const int ntypes, double **cutsq, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double **shift, double *special_lj,
const int nlocal, const int nall, const int max_nbors,
const int maxspecial, const double cell_size, int &gpu_mode,
FILE *screen);
void lje_gpu_clear();
int ** lje_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum,
const double cpu_time, bool &success);
void lje_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success);
double lje_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJExpandGPU::PairLJExpandGPU(LAMMPS *lmp) : PairLJExpand(lmp), gpu_mode(GPU_PAIR)
{
respa_enable = 0;
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJExpandGPU::~PairLJExpandGPU()
{
lje_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairLJExpandGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = lje_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
lje_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJExpandGPU::init_style()
{
if (force->newton_pair)
- error->all("Cannot use newton pair with lj/expand/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with lj/expand/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = lje_gpu_init(atom->ntypes+1, cutsq, lj1, lj2, lj3, lj4,
offset, shift, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairLJExpandGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + lje_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairLJExpandGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
double r,rshift,rshiftsq;
int *jlist;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
rshift = r - shift[itype][jtype];
rshiftsq = rshift*rshift;
r2inv = 1.0/rshiftsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj/rshift/r;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally_full(i,evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_morse_gpu.cpp b/src/GPU/pair_morse_gpu.cpp
index ae5fcdfe6..8ede76217 100644
--- a/src/GPU/pair_morse_gpu.cpp
+++ b/src/GPU/pair_morse_gpu.cpp
@@ -1,228 +1,225 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_morse_gpu.h"
#include "lmptype.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int mor_gpu_init(const int ntypes, double **cutsq, double **host_morse1,
double **host_r0, double **host_alpha, double **host_d0,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen);
void mor_gpu_clear();
int ** mor_gpu_compute_n(const int ago, const int inum,
const int nall, double **host_x, int *host_type,
double *sublo, double *subhi, int *tag, int **nspecial,
int **special, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum,
const double cpu_time, bool &success);
void mor_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success);
double mor_gpu_bytes();
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairMorseGPU::PairMorseGPU(LAMMPS *lmp) : PairMorse(lmp), gpu_mode(GPU_PAIR)
{
cpu_time = 0.0;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairMorseGPU::~PairMorseGPU()
{
mor_gpu_clear();
}
/* ---------------------------------------------------------------------- */
void PairMorseGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = mor_gpu_compute_n(neighbor->ago, inum, nall,
atom->x, atom->type, domain->sublo,
domain->subhi, atom->tag, atom->nspecial,
atom->special, eflag, vflag, eflag_atom,
vflag_atom, host_start, &ilist, &numneigh,
cpu_time, success);
} else {
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
mor_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
ilist, numneigh, firstneigh, eflag, vflag, eflag_atom,
vflag_atom, host_start, cpu_time, success);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start<inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairMorseGPU::init_style()
{
if (force->newton_pair)
- error->all("Cannot use newton pair with morse/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with morse/gpu pair style");
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = mor_gpu_init(atom->ntypes+1, cutsq, morse1, r0, alpha, d0,
offset, force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
}
/* ---------------------------------------------------------------------- */
double PairMorseGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + mor_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairMorseGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,dr,dexp,factor_lj;
int *jlist;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
dr = r - r0[itype][jtype];
dexp = exp(-alpha[itype][jtype] * dr);
fpair = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (eflag) {
evdwl = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally_full(i,evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
diff --git a/src/GPU/pair_resquared_gpu.cpp b/src/GPU/pair_resquared_gpu.cpp
index 69b606039..f50d1feda 100644
--- a/src/GPU/pair_resquared_gpu.cpp
+++ b/src/GPU/pair_resquared_gpu.cpp
@@ -1,319 +1,316 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_resquared_gpu.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec.h"
#include "atom_vec_ellipsoid.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "integrate.h"
#include "memory.h"
#include "error.h"
#include "neigh_request.h"
#include "universe.h"
#include "domain.h"
#include "update.h"
#include "string.h"
#include "gpu_extra.h"
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
int re_gpu_init(const int ntypes, double **shape, double **well,
double **cutsq, double **sigma, double **epsilon,
int **form, double **host_lj1,
double **host_lj2, double **host_lj3, double **host_lj4,
double **offset, double *special_lj, const int nlocal,
const int nall, const int max_nbors, const int maxspecial,
const double cell_size, int &gpu_mode, FILE *screen);
void re_gpu_clear();
int ** re_gpu_compute_n(const int ago, const int inum, const int nall,
double **host_x, int *host_type, double *sublo,
double *subhi, int *tag, int **nspecial, int **special,
const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
int **ilist, int **jnum, const double cpu_time,
bool &success, double **host_quat);
int * re_gpu_compute(const int ago, const int inum, const int nall,
double **host_x, int *host_type, int *ilist, int *numj,
int **firstneigh, const bool eflag, const bool vflag,
const bool eatom, const bool vatom, int &host_start,
const double cpu_time, bool &success, double **host_quat);
double re_gpu_bytes();
using namespace LAMMPS_NS;
enum{SPHERE_SPHERE,SPHERE_ELLIPSE,ELLIPSE_SPHERE,ELLIPSE_ELLIPSE};
/* ---------------------------------------------------------------------- */
PairRESquaredGPU::PairRESquaredGPU(LAMMPS *lmp) : PairRESquared(lmp),
gpu_mode(GPU_PAIR)
{
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
if (!avec)
- error->all("Pair gayberne requires atom style ellipsoid");
+ error->all(FLERR,"Pair gayberne requires atom style ellipsoid");
quat_nmax = 0;
quat = NULL;
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairRESquaredGPU::~PairRESquaredGPU()
{
re_gpu_clear();
cpu_time = 0.0;
memory->destroy(quat);
}
/* ---------------------------------------------------------------------- */
void PairRESquaredGPU::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int nall = atom->nlocal + atom->nghost;
int inum, host_start;
bool success = true;
int *ilist, *numneigh, **firstneigh;
if (nall > quat_nmax) {
quat_nmax = static_cast<int>(1.1 * nall);
memory->grow(quat, quat_nmax, 4, "pair:quat");
}
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
for (int i=0; i<nall; i++) {
int qi = ellipsoid[i];
if (qi > -1) {
quat[i][0] = bonus[qi].quat[0];
quat[i][1] = bonus[qi].quat[1];
quat[i][2] = bonus[qi].quat[2];
quat[i][3] = bonus[qi].quat[3];
}
}
if (gpu_mode == GPU_NEIGH) {
inum = atom->nlocal;
firstneigh = re_gpu_compute_n(neighbor->ago, inum, nall, atom->x,
atom->type, domain->sublo, domain->subhi,
atom->tag, atom->nspecial, atom->special,
eflag, vflag, eflag_atom, vflag_atom,
host_start, &ilist, &numneigh, cpu_time,
success, quat);
} else {
inum = list->inum;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
ilist = re_gpu_compute(neighbor->ago, inum, nall, atom->x, atom->type,
list->ilist, numneigh, firstneigh, eflag, vflag,
eflag_atom, vflag_atom, host_start,
cpu_time, success, quat);
}
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (host_start < inum) {
cpu_time = MPI_Wtime();
cpu_compute(host_start, inum, eflag, vflag, ilist, numneigh, firstneigh);
cpu_time = MPI_Wtime() - cpu_time;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairRESquaredGPU::init_style()
{
if (force->newton_pair)
- error->all("Cannot use newton pair with resquared/gpu pair style");
+ error->all(FLERR,"Cannot use newton pair with resquared/gpu pair style");
if (!atom->ellipsoid_flag)
- error->all("Pair resquared/gpu requires atom style ellipsoid");
+ error->all(FLERR,"Pair resquared/gpu requires atom style ellipsoid");
// per-type shape precalculations
// require that atom shapes are identical within each type
// if shape = 0 for point particle, set shape = 1 as required by Gay-Berne
for (int i = 1; i <= atom->ntypes; i++) {
if (!atom->shape_consistency(i,shape1[i][0],shape1[i][1],shape1[i][2]))
- error->all("Pair resquared/gpu requires atoms with same type have same shape");
+ error->all(FLERR,"Pair resquared/gpu requires atoms with same type have same shape");
if (setwell[i]) {
shape2[i][0] = shape1[i][0]*shape1[i][0];
shape2[i][1] = shape1[i][1]*shape1[i][1];
shape2[i][2] = shape1[i][2]*shape1[i][2];
lshape[i] = shape1[i][0]*shape1[i][1]*shape1[i][2];
}
}
// Repeat cutsq calculation because done after call to init_style
double maxcut = -1.0;
double cut;
for (int i = 1; i <= atom->ntypes; i++) {
for (int j = i; j <= atom->ntypes; j++) {
if (setflag[i][j] != 0 || (setflag[i][i] != 0 && setflag[j][j] != 0)) {
cut = init_one(i,j);
cut *= cut;
if (cut > maxcut)
maxcut = cut;
cutsq[i][j] = cutsq[j][i] = cut;
} else
cutsq[i][j] = cutsq[j][i] = 0.0;
}
}
double cell_size = sqrt(maxcut) + neighbor->skin;
int maxspecial=0;
if (atom->molecular)
maxspecial=atom->maxspecial;
int success = re_gpu_init(atom->ntypes+1, shape1, well, cutsq, sigma,
epsilon, form, lj1, lj2, lj3, lj4, offset,
force->special_lj, atom->nlocal,
atom->nlocal+atom->nghost, 300, maxspecial,
cell_size, gpu_mode, screen);
GPU_EXTRA::check_flag(success,error,world);
if (gpu_mode != GPU_NEIGH) {
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
quat_nmax = static_cast<int>(1.1 * (atom->nlocal + atom->nghost));
memory->grow(quat, quat_nmax, 4, "pair:quat");
}
/* ---------------------------------------------------------------------- */
double PairRESquaredGPU::memory_usage()
{
double bytes = Pair::memory_usage();
return bytes + memory->usage(quat,quat_nmax)+re_gpu_bytes();
}
/* ---------------------------------------------------------------------- */
void PairRESquaredGPU::cpu_compute(int start, int inum, int eflag, int vflag,
int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jj,jnum,itype,jtype;
double evdwl,one_eng,rsq,r2inv,r6inv,forcelj,factor_lj;
double fforce[3],ttor[3],rtor[3],r12[3];
int *jlist;
RE2Vars wi,wj;
double **x = atom->x;
double **f = atom->f;
double **tor = atom->torque;
int *type = atom->type;
double *special_lj = force->special_lj;
// loop over neighbors of my atoms
for (ii = start; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
// not a LJ sphere
if (lshape[itype] != 0.0) precompute_i(i,wi);
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
// r12 = center to center vector
r12[0] = x[j][0]-x[i][0];
r12[1] = x[j][1]-x[i][1];
r12[2] = x[j][2]-x[i][2];
rsq = MathExtra::dot3(r12,r12);
jtype = type[j];
// compute if less than cutoff
if (rsq < cutsq[itype][jtype]) {
switch (form[itype][jtype]) {
case SPHERE_SPHERE:
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
forcelj *= -r2inv;
if (eflag) one_eng =
r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) -
offset[itype][jtype];
fforce[0] = r12[0]*forcelj;
fforce[1] = r12[1]*forcelj;
fforce[2] = r12[2]*forcelj;
break;
case SPHERE_ELLIPSE:
precompute_i(j,wj);
one_eng = resquared_lj(j,i,wj,r12,rsq,fforce,rtor,false);
break;
case ELLIPSE_SPHERE:
one_eng = resquared_lj(i,j,wi,r12,rsq,fforce,ttor,true);
tor[i][0] += ttor[0]*factor_lj;
tor[i][1] += ttor[1]*factor_lj;
tor[i][2] += ttor[2]*factor_lj;
break;
default:
precompute_i(j,wj);
one_eng = resquared_analytic(i,j,wi,wj,r12,rsq,fforce,ttor,rtor);
tor[i][0] += ttor[0]*factor_lj;
tor[i][1] += ttor[1]*factor_lj;
tor[i][2] += ttor[2]*factor_lj;
break;
}
fforce[0] *= factor_lj;
fforce[1] *= factor_lj;
fforce[2] *= factor_lj;
f[i][0] += fforce[0];
f[i][1] += fforce[1];
f[i][2] += fforce[2];
if (eflag) evdwl = factor_lj*one_eng;
if (evflag) ev_tally_xyz_full(i,evdwl,0.0,fforce[0],fforce[1],
fforce[2],-r12[0],-r12[1],-r12[2]);
}
}
}
}
diff --git a/src/GPU/pppm_gpu.cpp b/src/GPU/pppm_gpu.cpp
index f9a929a30..044d018c2 100644
--- a/src/GPU/pppm_gpu.cpp
+++ b/src/GPU/pppm_gpu.cpp
@@ -1,844 +1,841 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Mike Brown (ORNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "pppm_gpu.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "domain.h"
#include "fft3d_wrap.h"
#include "remap_wrap.h"
#include "memory.h"
#include "error.h"
#include "gpu_extra.h"
using namespace LAMMPS_NS;
#define MAXORDER 7
#define OFFSET 16384
#define SMALL 0.00001
#define LARGE 10000.0
#define EPS_HOC 1.0e-7
#ifdef FFT_SINGLE
#define ZEROF 0.0f
#define ONEF 1.0f
#else
#define ZEROF 0.0
#define ONEF 1.0
#endif
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
// External functions from cuda library for atom decomposition
#ifdef FFT_SINGLE
#define PPPM_GPU_API(api) pppm_gpu_ ## api ## _f
#else
#define PPPM_GPU_API(api) pppm_gpu_ ## api ## _d
#endif
FFT_SCALAR* PPPM_GPU_API(init)(const int nlocal, const int nall, FILE *screen,
const int order, const int nxlo_out,
const int nylo_out, const int nzlo_out,
const int nxhi_out, const int nyhi_out,
const int nzhi_out, FFT_SCALAR **rho_coeff,
FFT_SCALAR **_vd_brick, const double slab_volfactor,
const int nx_pppm, const int ny_pppm,
const int nz_pppm, int &success);
void PPPM_GPU_API(clear)(const double poisson_time);
int PPPM_GPU_API(spread)(const int ago, const int nlocal, const int nall,
double **host_x, int *host_type, bool &success,
double *host_q, double *boxlo, const double delxinv,
const double delyinv, const double delzinv);
void PPPM_GPU_API(interp)(const FFT_SCALAR qqrd2e_scale);
double PPPM_GPU_API(bytes)();
/* ---------------------------------------------------------------------- */
PPPMGPU::PPPMGPU(LAMMPS *lmp, int narg, char **arg) : PPPM(lmp, narg, arg)
{
- if (narg != 1) error->all("Illegal kspace_style pppm/gpu command");
+ if (narg != 1) error->all(FLERR,"Illegal kspace_style pppm/gpu command");
density_brick_gpu = vd_brick = NULL;
}
/* ----------------------------------------------------------------------
free all memory
------------------------------------------------------------------------- */
PPPMGPU::~PPPMGPU()
{
PPPM_GPU_API(clear)(poisson_time);
}
/* ----------------------------------------------------------------------
called once before run
------------------------------------------------------------------------- */
void PPPMGPU::init()
{
PPPM::init();
// GPU precision specific init.
if (order>8)
- error->all("Cannot use order greater than 8 with pppm/gpu.");
+ error->all(FLERR,"Cannot use order greater than 8 with pppm/gpu.");
PPPM_GPU_API(clear)(poisson_time);
int success;
FFT_SCALAR *data, *h_brick;
h_brick = PPPM_GPU_API(init)(atom->nlocal, atom->nlocal+atom->nghost, screen,
order, nxlo_out, nylo_out, nzlo_out, nxhi_out,
nyhi_out, nzhi_out, rho_coeff, &data,
slab_volfactor,nx_pppm,ny_pppm,nz_pppm,success);
GPU_EXTRA::check_flag(success,error,world);
density_brick_gpu =
create_3d_offset(nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:density_brick_gpu",h_brick,1);
vd_brick =
create_3d_offset(nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vd_brick",data,4);
poisson_time=0;
}
/* ----------------------------------------------------------------------
compute the PPPMGPU long-range force, energy, virial
------------------------------------------------------------------------- */
void PPPMGPU::compute(int eflag, int vflag)
{
bool success = true;
int flag=PPPM_GPU_API(spread)(neighbor->ago, atom->nlocal, atom->nlocal +
atom->nghost, atom->x, atom->type, success,
atom->q, domain->boxlo, delxinv, delyinv,
delzinv);
if (!success)
- error->one("Out of memory on GPGPU");
+ error->one(FLERR,"Out of memory on GPGPU");
if (flag != 0)
- error->one("Out of range atoms - cannot compute PPPM");
+ error->one(FLERR,"Out of range atoms - cannot compute PPPM");
int i;
// convert atoms from box to lamda coords
if (triclinic == 0) boxlo = domain->boxlo;
else {
boxlo = domain->boxlo_lamda;
domain->x2lamda(atom->nlocal);
}
energy = 0.0;
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
double t3=MPI_Wtime();
// all procs communicate density values from their ghost cells
// to fully sum contribution in their 3d bricks
// remap from 3d decomposition to FFT decomposition
brick2fft();
// compute potential gradient on my FFT grid and
// portion of e_long on this proc's FFT grid
// return gradients (electric fields) in 3d brick decomposition
poisson(eflag,vflag);
// all procs communicate E-field values to fill ghost cells
// surrounding their 3d bricks
fillbrick();
poisson_time+=MPI_Wtime()-t3;
// calculate the force on my particles
FFT_SCALAR qqrd2e_scale=qqrd2e*scale;
PPPM_GPU_API(interp)(qqrd2e_scale);
// sum energy across procs and add in volume-dependent term
if (eflag) {
double energy_all;
MPI_Allreduce(&energy,&energy_all,1,MPI_DOUBLE,MPI_SUM,world);
energy = energy_all;
energy *= 0.5*volume;
energy -= g_ewald*qsqsum/1.772453851 +
0.5*PI*qsum*qsum / (g_ewald*g_ewald*volume);
energy *= qqrd2e*scale;
}
// sum virial across procs
if (vflag) {
double virial_all[6];
MPI_Allreduce(virial,virial_all,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) virial[i] = 0.5*qqrd2e*scale*volume*virial_all[i];
}
// 2d slab correction
if (slabflag) slabcorr(eflag);
// convert atoms back from lamda to box coords
if (triclinic) domain->lamda2x(atom->nlocal);
}
/* ----------------------------------------------------------------------
allocate memory that depends on # of K-vectors and order
------------------------------------------------------------------------- */
void PPPMGPU::allocate()
{
memory->create(density_fft,nfft_both,"pppm:density_fft");
memory->create(greensfn,nfft_both,"pppm:greensfn");
memory->create(work1,2*nfft_both,"pppm:work1");
memory->create(work2,2*nfft_both,"pppm:work2");
memory->create(vg,nfft_both,6,"pppm:vg");
memory->create1d_offset(fkx,nxlo_fft,nxhi_fft,"pppm:fkx");
memory->create1d_offset(fky,nylo_fft,nyhi_fft,"pppm:fky");
memory->create1d_offset(fkz,nzlo_fft,nzhi_fft,"pppm:fkz");
memory->create(buf1,nbuf,"pppm:buf1");
memory->create(buf2,nbuf,"pppm:buf2");
// summation coeffs
memory->create(gf_b,order,"pppm:gf_b");
memory->create2d_offset(rho1d,3,-order/2,order/2,"pppm:rho1d");
memory->create2d_offset(rho_coeff,order,(1-order)/2,order/2,"pppm:rho_coeff");
// create 2 FFTs and a Remap
// 1st FFT keeps data in FFT decompostion
// 2nd FFT returns data in 3d brick decomposition
// remap takes data from 3d brick to FFT decomposition
int tmp;
fft1 = new FFT3d(lmp,world,nx_pppm,ny_pppm,nz_pppm,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
0,0,&tmp);
fft2 = new FFT3d(lmp,world,nx_pppm,ny_pppm,nz_pppm,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in,
0,0,&tmp);
remap = new Remap(lmp,world,
nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
1,0,0,FFT_PRECISION);
}
/* ----------------------------------------------------------------------
deallocate memory that depends on # of K-vectors and order
------------------------------------------------------------------------- */
void PPPMGPU::deallocate()
{
destroy_3d_offset(density_brick_gpu,nzlo_out,nylo_out);
destroy_3d_offset(vd_brick,nzlo_out,nylo_out);
memory->destroy(density_fft);
memory->destroy(greensfn);
memory->destroy(work1);
memory->destroy(work2);
memory->destroy(vg);
memory->destroy1d_offset(fkx,nxlo_fft);
memory->destroy1d_offset(fky,nylo_fft);
memory->destroy1d_offset(fkz,nzlo_fft);
memory->destroy(buf1);
memory->destroy(buf2);
memory->destroy(gf_b);
memory->destroy2d_offset(rho1d,-order/2);
memory->destroy2d_offset(rho_coeff,(1-order)/2);
delete fft1;
delete fft2;
delete remap;
}
/* ----------------------------------------------------------------------
ghost-swap to accumulate full density in brick decomposition
remap density from 3d brick decomposition to FFT decomposition
------------------------------------------------------------------------- */
void PPPMGPU::brick2fft()
{
int i,n,ix,iy,iz;
MPI_Request request;
MPI_Status status;
// pack my ghosts for +x processor
// pass data to self or +x processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxhi_in+1; ix <= nxhi_out; ix++)
buf1[n++] = density_brick_gpu[iz][iy][ix];
if (comm->procneigh[0][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxlo_in; ix < nxlo_in+nxlo_ghost; ix++)
density_brick_gpu[iz][iy][ix] += buf2[n++];
// pack my ghosts for -x processor
// pass data to self or -x processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxlo_out; ix < nxlo_in; ix++)
buf1[n++] = density_brick_gpu[iz][iy][ix];
if (comm->procneigh[0][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxhi_in-nxhi_ghost+1; ix <= nxhi_in; ix++)
density_brick_gpu[iz][iy][ix] += buf2[n++];
// pack my ghosts for +y processor
// pass data to self or +y processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in+1; iy <= nyhi_out; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick_gpu[iz][iy][ix];
if (comm->procneigh[1][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy < nylo_in+nylo_ghost; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick_gpu[iz][iy][ix] += buf2[n++];
// pack my ghosts for -y processor
// pass data to self or -y processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy < nylo_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick_gpu[iz][iy][ix];
if (comm->procneigh[1][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in-nyhi_ghost+1; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick_gpu[iz][iy][ix] += buf2[n++];
// pack my ghosts for +z processor
// pass data to self or +z processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzhi_in+1; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick_gpu[iz][iy][ix];
if (comm->procneigh[2][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_in; iz < nzlo_in+nzlo_ghost; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick_gpu[iz][iy][ix] += buf2[n++];
// pack my ghosts for -z processor
// pass data to self or -z processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz < nzlo_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick_gpu[iz][iy][ix];
if (comm->procneigh[2][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzhi_in-nzhi_ghost+1; iz <= nzhi_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick_gpu[iz][iy][ix] += buf2[n++];
// remap from 3d brick decomposition to FFT decomposition
// copy grabs inner portion of density from 3d brick
// remap could be done as pre-stage of FFT,
// but this works optimally on only double values, not complex values
n = 0;
for (iz = nzlo_in; iz <= nzhi_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_fft[n++] = density_brick_gpu[iz][iy][ix];
remap->perform(density_fft,density_fft,work1);
}
/* ----------------------------------------------------------------------
ghost-swap to fill ghost cells of my brick with field values
------------------------------------------------------------------------- */
void PPPMGPU::fillbrick()
{
int i,n,ix,iy,iz;
MPI_Request request;
MPI_Status status;
// pack my real cells for +z processor
// pass data to self or +z processor
// unpack and sum recv data into my ghost cells
n = 0;
int x_lo = nxlo_in * 4;
int x_hi = nxhi_in * 4 + 1;
for (iz = nzhi_in-nzhi_ghost+1; iz <= nzhi_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
buf1[n++] = vd_brick[iz][iy][ix];
buf1[n++] = vd_brick[iz][iy][ix+1];
buf1[n++] = vd_brick[iz][iy][ix+2];
}
if (comm->procneigh[2][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz < nzlo_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
vd_brick[iz][iy][ix] = buf2[n++];
vd_brick[iz][iy][ix+1] = buf2[n++];
vd_brick[iz][iy][ix+2] = buf2[n++];
}
// pack my real cells for -z processor
// pass data to self or -z processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_in; iz < nzlo_in+nzlo_ghost; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
buf1[n++] = vd_brick[iz][iy][ix];
buf1[n++] = vd_brick[iz][iy][ix+1];
buf1[n++] = vd_brick[iz][iy][ix+2];
}
if (comm->procneigh[2][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzhi_in+1; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
vd_brick[iz][iy][ix] = buf2[n++];
vd_brick[iz][iy][ix+1] = buf2[n++];
vd_brick[iz][iy][ix+2] = buf2[n++];
}
// pack my real cells for +y processor
// pass data to self or +y processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in-nyhi_ghost+1; iy <= nyhi_in; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
buf1[n++] = vd_brick[iz][iy][ix];
buf1[n++] = vd_brick[iz][iy][ix+1];
buf1[n++] = vd_brick[iz][iy][ix+2];
}
if (comm->procneigh[1][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy < nylo_in; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
vd_brick[iz][iy][ix] = buf2[n++];
vd_brick[iz][iy][ix+1] = buf2[n++];
vd_brick[iz][iy][ix+2] = buf2[n++];
}
// pack my real cells for -y processor
// pass data to self or -y processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy < nylo_in+nylo_ghost; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
buf1[n++] = vd_brick[iz][iy][ix];
buf1[n++] = vd_brick[iz][iy][ix+1];
buf1[n++] = vd_brick[iz][iy][ix+2];
}
if (comm->procneigh[1][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in+1; iy <= nyhi_out; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
vd_brick[iz][iy][ix] = buf2[n++];
vd_brick[iz][iy][ix+1] = buf2[n++];
vd_brick[iz][iy][ix+2] = buf2[n++];
}
// pack my real cells for +x processor
// pass data to self or +x processor
// unpack and sum recv data into my ghost cells
n = 0;
x_lo = (nxhi_in-nxhi_ghost+1) * 4;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
buf1[n++] = vd_brick[iz][iy][ix];
buf1[n++] = vd_brick[iz][iy][ix+1];
buf1[n++] = vd_brick[iz][iy][ix+2];
}
if (comm->procneigh[0][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
x_lo = nxlo_out * 4;
x_hi = nxlo_in * 4;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
vd_brick[iz][iy][ix] = buf2[n++];
vd_brick[iz][iy][ix+1] = buf2[n++];
vd_brick[iz][iy][ix+2] = buf2[n++];
}
// pack my real cells for -x processor
// pass data to self or -x processor
// unpack and sum recv data into my ghost cells
n = 0;
x_lo = x_hi;
x_hi = (nxlo_in+nxlo_ghost) * 4;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
buf1[n++] = vd_brick[iz][iy][ix];
buf1[n++] = vd_brick[iz][iy][ix+1];
buf1[n++] = vd_brick[iz][iy][ix+2];
}
if (comm->procneigh[0][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
x_lo = (nxhi_in + 1) * 4;
x_hi = nxhi_out * 4 + 1;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = x_lo; ix < x_hi; ix+=4) {
vd_brick[iz][iy][ix] = buf2[n++];
vd_brick[iz][iy][ix+1] = buf2[n++];
vd_brick[iz][iy][ix+2] = buf2[n++];
}
}
/* ----------------------------------------------------------------------
FFT-based Poisson solver
------------------------------------------------------------------------- */
void PPPMGPU::poisson(int eflag, int vflag)
{
int i,j,k,n;
double eng;
// transform charge density (r -> k)
n = 0;
for (i = 0; i < nfft; i++) {
work1[n++] = density_fft[i];
work1[n++] = ZEROF;
}
fft1->compute(work1,work1,1);
// if requested, compute energy and virial contribution
double scaleinv = 1.0/(nx_pppm*ny_pppm*nz_pppm);
double s2 = scaleinv*scaleinv;
if (eflag || vflag) {
if (vflag) {
n = 0;
for (i = 0; i < nfft; i++) {
eng = s2 * greensfn[i] * (work1[n]*work1[n] + work1[n+1]*work1[n+1]);
for (j = 0; j < 6; j++) virial[j] += eng*vg[i][j];
energy += eng;
n += 2;
}
} else {
n = 0;
for (i = 0; i < nfft; i++) {
energy +=
s2 * greensfn[i] * (work1[n]*work1[n] + work1[n+1]*work1[n+1]);
n += 2;
}
}
}
// scale by 1/total-grid-pts to get rho(k)
// multiply by Green's function to get V(k)
n = 0;
for (i = 0; i < nfft; i++) {
work1[n++] *= scaleinv * greensfn[i];
work1[n++] *= scaleinv * greensfn[i];
}
// compute gradients of V(r) in each of 3 dims by transformimg -ik*V(k)
// FFT leaves data in 3d brick decomposition
// copy it into inner portion of vdx,vdy,vdz arrays
// x direction gradient
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++)
for (j = nylo_fft; j <= nyhi_fft; j++)
for (i = nxlo_fft; i <= nxhi_fft; i++) {
work2[n] = fkx[i]*work1[n+1];
work2[n+1] = -fkx[i]*work1[n];
n += 2;
}
fft2->compute(work2,work2,-1);
n = 0;
int x_hi = nxhi_in * 4 + 3;
for (k = nzlo_in; k <= nzhi_in; k++)
for (j = nylo_in; j <= nyhi_in; j++)
for (i = nxlo_in * 4; i < x_hi; i+=4) {
vd_brick[k][j][i] = work2[n];
n += 2;
}
// y direction gradient
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++)
for (j = nylo_fft; j <= nyhi_fft; j++)
for (i = nxlo_fft; i <= nxhi_fft; i++) {
work2[n] = fky[j]*work1[n+1];
work2[n+1] = -fky[j]*work1[n];
n += 2;
}
fft2->compute(work2,work2,-1);
n = 0;
for (k = nzlo_in; k <= nzhi_in; k++)
for (j = nylo_in; j <= nyhi_in; j++)
for (i = nxlo_in * 4 + 1; i < x_hi; i+=4) {
vd_brick[k][j][i] = work2[n];
n += 2;
}
// z direction gradient
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++)
for (j = nylo_fft; j <= nyhi_fft; j++)
for (i = nxlo_fft; i <= nxhi_fft; i++) {
work2[n] = fkz[k]*work1[n+1];
work2[n+1] = -fkz[k]*work1[n];
n += 2;
}
fft2->compute(work2,work2,-1);
n = 0;
for (k = nzlo_in; k <= nzhi_in; k++)
for (j = nylo_in; j <= nyhi_in; j++)
for (i = nxlo_in * 4 + 2; i < x_hi; i+=4) {
vd_brick[k][j][i] = work2[n];
n += 2;
}
}
/* ----------------------------------------------------------------------
Create array using offsets from pinned memory allocation
------------------------------------------------------------------------- */
FFT_SCALAR ***PPPMGPU::create_3d_offset(int n1lo, int n1hi, int n2lo, int n2hi,
int n3lo, int n3hi, const char *name,
FFT_SCALAR *data, int vec_length)
{
int i,j;
int n1 = n1hi - n1lo + 1;
int n2 = n2hi - n2lo + 1;
int n3 = n3hi - n3lo + 1;
FFT_SCALAR **plane = (FFT_SCALAR **)memory->smalloc(n1*n2*sizeof(FFT_SCALAR *),name);
FFT_SCALAR ***array = (FFT_SCALAR ***)memory->smalloc(n1*sizeof(FFT_SCALAR **),name);
int n = 0;
for (i = 0; i < n1; i++) {
array[i] = &plane[i*n2];
for (j = 0; j < n2; j++) {
plane[i*n2+j] = &data[n];
n += n3*vec_length;
}
}
for (i = 0; i < n1*n2; i++) array[0][i] -= n3lo*vec_length;
for (i = 0; i < n1; i++) array[i] -= n2lo;
return array-n1lo;
}
/* ----------------------------------------------------------------------
3d memory offsets
------------------------------------------------------------------------- */
void PPPMGPU::destroy_3d_offset(FFT_SCALAR ***array, int n1_offset,
int n2_offset)
{
if (array == NULL) return;
memory->sfree(&array[n1_offset][n2_offset]);
memory->sfree(array + n1_offset);
}
/* ----------------------------------------------------------------------
memory usage of local arrays
------------------------------------------------------------------------- */
double PPPMGPU::memory_usage()
{
double bytes = nmax*3 * sizeof(double);
int nbrick = (nxhi_out-nxlo_out+1) * (nyhi_out-nylo_out+1) *
(nzhi_out-nzlo_out+1);
bytes += 4 * nbrick * sizeof(FFT_SCALAR);
bytes += 6 * nfft_both * sizeof(double);
bytes += nfft_both * sizeof(double);
bytes += nfft_both*5 * sizeof(FFT_SCALAR);
bytes += 2 * nbuf * sizeof(double);
return bytes + PPPM_GPU_API(bytes)();
}
diff --git a/src/GRANULAR/fix_freeze.cpp b/src/GRANULAR/fix_freeze.cpp
index 997337a67..848574e5f 100644
--- a/src/GRANULAR/fix_freeze.cpp
+++ b/src/GRANULAR/fix_freeze.cpp
@@ -1,130 +1,130 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_freeze.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "comm.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixFreeze::FixFreeze(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal fix freeze command");
+ if (narg != 3) error->all(FLERR,"Illegal fix freeze command");
if (!atom->torque_flag)
- error->all("Fix freeze requires atom attribute torque");
+ error->all(FLERR,"Fix freeze requires atom attribute torque");
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extvector = 1;
force_flag = 0;
foriginal[0] = foriginal[1] = foriginal[2] = 0.0;
}
/* ---------------------------------------------------------------------- */
int FixFreeze::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixFreeze::init()
{
// error if more than one freeze fix
// because accessed by pair style granular and fix gran/diag
int count = 0;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"freeze") == 0) count++;
- if (count > 1) error->all("More than one fix freeze");
+ if (count > 1) error->all(FLERR,"More than one fix freeze");
}
/* ---------------------------------------------------------------------- */
void FixFreeze::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
int nlevels_respa = ((Respa *) update->integrate)->nlevels;
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
}
}
/* ---------------------------------------------------------------------- */
void FixFreeze::post_force(int vflag)
{
double **f = atom->f;
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
foriginal[0] = foriginal[1] = foriginal[2] = 0.0;
force_flag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
foriginal[0] += f[i][0];
foriginal[1] += f[i][1];
foriginal[2] += f[i][2];
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
/* ---------------------------------------------------------------------- */
void FixFreeze::post_force_respa(int vflag, int ilevel, int iloop)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixFreeze::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,3,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[n];
}
diff --git a/src/GRANULAR/fix_pour.cpp b/src/GRANULAR/fix_pour.cpp
index 1248c05db..4dcf9fc3b 100644
--- a/src/GRANULAR/fix_pour.cpp
+++ b/src/GRANULAR/fix_pour.cpp
@@ -1,577 +1,577 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_pour.h"
#include "atom.h"
#include "atom_vec.h"
#include "force.h"
#include "update.h"
#include "comm.h"
#include "modify.h"
#include "fix_gravity.h"
#include "domain.h"
#include "region.h"
#include "region_block.h"
#include "region_cylinder.h"
#include "random_park.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define EPSILON 0.001
/* ---------------------------------------------------------------------- */
FixPour::FixPour(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix pour command");
+ if (narg < 6) error->all(FLERR,"Illegal fix pour command");
time_depend = 1;
if (!atom->radius_flag || !atom->rmass_flag)
- error->all("Fix pour requires atom attributes radius, rmass");
+ error->all(FLERR,"Fix pour requires atom attributes radius, rmass");
// required args
ninsert = atoi(arg[3]);
ntype = atoi(arg[4]);
seed = atoi(arg[5]);
- if (seed <= 0) error->all("Illegal fix pour command");
+ if (seed <= 0) error->all(FLERR,"Illegal fix pour command");
PI = 4.0*atan(1.0);
// option defaults
int iregion = -1;
radius_lo = radius_hi = 0.5;
density_lo = density_hi = 1.0;
volfrac = 0.25;
maxattempt = 50;
rate = 0.0;
vxlo = vxhi = vylo = vyhi = vy = vz = 0.0;
// optional args
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix pour command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix pour command");
iregion = domain->find_region(arg[iarg+1]);
- if (iregion == -1) error->all("Fix pour region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Fix pour region ID does not exist");
iarg += 2;
} else if (strcmp(arg[iarg],"diam") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix pour command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix pour command");
radius_lo = 0.5 * atof(arg[iarg+1]);
radius_hi = 0.5 * atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"dens") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix pour command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix pour command");
density_lo = atof(arg[iarg+1]);
density_hi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"vol") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix pour command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix pour command");
volfrac = atof(arg[iarg+1]);
maxattempt = atoi(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"rate") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix pour command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix pour command");
rate = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"vel") == 0) {
if (domain->dimension == 3) {
- if (iarg+6 > narg) error->all("Illegal fix pour command");
+ if (iarg+6 > narg) error->all(FLERR,"Illegal fix pour command");
vxlo = atof(arg[iarg+1]);
vxhi = atof(arg[iarg+2]);
vylo = atof(arg[iarg+3]);
vyhi = atof(arg[iarg+4]);
vz = atof(arg[iarg+5]);
iarg += 6;
} else {
- if (iarg+4 > narg) error->all("Illegal fix pour command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix pour command");
vxlo = atof(arg[iarg+1]);
vxhi = atof(arg[iarg+2]);
vy = atof(arg[iarg+3]);
vz = 0.0;
iarg += 4;
}
- } else error->all("Illegal fix pour command");
+ } else error->all(FLERR,"Illegal fix pour command");
}
// error checks on region and its extent being inside simulation box
- if (iregion == -1) error->all("Must specify a region in fix pour");
+ if (iregion == -1) error->all(FLERR,"Must specify a region in fix pour");
if (domain->regions[iregion]->bboxflag == 0)
- error->all("Fix pour region does not support a bounding box");
+ error->all(FLERR,"Fix pour region does not support a bounding box");
if (domain->regions[iregion]->dynamic_check())
- error->all("Fix pour region cannot be dynamic");
+ error->all(FLERR,"Fix pour region cannot be dynamic");
if (strcmp(domain->regions[iregion]->style,"block") == 0) {
region_style = 1;
xlo = ((RegBlock *) domain->regions[iregion])->xlo;
xhi = ((RegBlock *) domain->regions[iregion])->xhi;
ylo = ((RegBlock *) domain->regions[iregion])->ylo;
yhi = ((RegBlock *) domain->regions[iregion])->yhi;
zlo = ((RegBlock *) domain->regions[iregion])->zlo;
zhi = ((RegBlock *) domain->regions[iregion])->zhi;
if (xlo < domain->boxlo[0] || xhi > domain->boxhi[0] ||
ylo < domain->boxlo[1] || yhi > domain->boxhi[1] ||
zlo < domain->boxlo[2] || zhi > domain->boxhi[2])
- error->all("Insertion region extends outside simulation box");
+ error->all(FLERR,"Insertion region extends outside simulation box");
} else if (strcmp(domain->regions[iregion]->style,"cylinder") == 0) {
region_style = 2;
char axis = ((RegCylinder *) domain->regions[iregion])->axis;
xc = ((RegCylinder *) domain->regions[iregion])->c1;
yc = ((RegCylinder *) domain->regions[iregion])->c2;
rc = ((RegCylinder *) domain->regions[iregion])->radius;
zlo = ((RegCylinder *) domain->regions[iregion])->lo;
zhi = ((RegCylinder *) domain->regions[iregion])->hi;
if (axis != 'z')
- error->all("Must use a z-axis cylinder with fix pour");
+ error->all(FLERR,"Must use a z-axis cylinder with fix pour");
if (xc-rc < domain->boxlo[0] || xc+rc > domain->boxhi[0] ||
yc-rc < domain->boxlo[1] || yc+rc > domain->boxhi[1] ||
zlo < domain->boxlo[2] || zhi > domain->boxhi[2])
- error->all("Insertion region extends outside simulation box");
- } else error->all("Must use a block or cylinder region with fix pour");
+ error->all(FLERR,"Insertion region extends outside simulation box");
+ } else error->all(FLERR,"Must use a block or cylinder region with fix pour");
if (region_style == 2 && domain->dimension == 2)
- error->all("Must use a block region with fix pour for 2d simulations");
+ error->all(FLERR,"Must use a block region with fix pour for 2d simulations");
// random number generator, same for all procs
random = new RanPark(lmp,seed);
// allgather arrays
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
recvcounts = new int[nprocs];
displs = new int[nprocs];
// grav = gravity in distance/time^2 units
// assume grav = -magnitude at this point, enforce in init()
int ifix;
for (ifix = 0; ifix < modify->nfix; ifix++)
if (strcmp(modify->fix[ifix]->style,"gravity") == 0) break;
if (ifix == modify->nfix)
- error->all("No fix gravity defined for fix pour");
+ error->all(FLERR,"No fix gravity defined for fix pour");
grav = - ((FixGravity *) modify->fix[ifix])->magnitude * force->ftm2v;
// nfreq = timesteps between insertions
// should be time for a particle to fall from top of insertion region
// to bottom, taking into account that the region may be moving
// set these 2 eqs equal to each other, solve for smallest positive t
// x = zhi + vz*t + 1/2 grav t^2
// x = zlo + rate*t
// gives t = [-(vz-rate) - sqrt((vz-rate)^2 - 2*grav*(zhi-zlo))] / grav
// where zhi-zlo > 0, grav < 0, and vz & rate can be either > 0 or < 0
double v_relative,delta;
if (domain->dimension == 3) {
v_relative = vz - rate;
delta = zhi - zlo;
} else {
v_relative = vy - rate;
delta = yhi - ylo;
}
double t =
(-v_relative - sqrt(v_relative*v_relative - 2.0*grav*delta)) / grav;
nfreq = static_cast<int> (t/update->dt + 0.5);
// 1st insertion on next timestep
force_reneighbor = 1;
next_reneighbor = update->ntimestep + 1;
nfirst = next_reneighbor;
ninserted = 0;
// nper = # to insert each time
// depends on specified volume fraction
// volume = volume of insertion region
// volume_one = volume of inserted particle (with max possible radius)
// in 3d, insure dy >= 1, for quasi-2d simulations
double volume,volume_one;
if (domain->dimension == 3) {
if (region_style == 1) {
double dy = yhi - ylo;
if (dy < 1.0) dy = 1.0;
volume = (xhi-xlo) * dy * (zhi-zlo);
} else volume = PI*rc*rc * (zhi-zlo);
volume_one = 4.0/3.0 * PI * radius_hi*radius_hi*radius_hi;
} else {
volume = (xhi-xlo) * (yhi-ylo);
volume_one = PI * radius_hi*radius_hi;
}
nper = static_cast<int> (volfrac*volume/volume_one);
int nfinal = update->ntimestep + 1 + (ninsert-1)/nper * nfreq;
// print stats
if (me == 0) {
if (screen)
fprintf(screen,
"Particle insertion: %d every %d steps, %d by step %d\n",
nper,nfreq,ninsert,nfinal);
if (logfile)
fprintf(logfile,
"Particle insertion: %d every %d steps, %d by step %d\n",
nper,nfreq,ninsert,nfinal);
}
}
/* ---------------------------------------------------------------------- */
FixPour::~FixPour()
{
delete random;
delete [] recvcounts;
delete [] displs;
}
/* ---------------------------------------------------------------------- */
int FixPour::setmask()
{
int mask = 0;
mask |= PRE_EXCHANGE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPour::init()
{
- if (domain->triclinic) error->all("Cannot use fix pour with triclinic box");
+ if (domain->triclinic) error->all(FLERR,"Cannot use fix pour with triclinic box");
// insure gravity fix exists
// for 3d must point in -z, for 2d must point in -y
// else insertion cannot work
int ifix;
for (ifix = 0; ifix < modify->nfix; ifix++)
if (strcmp(modify->fix[ifix]->style,"gravity") == 0) break;
if (ifix == modify->nfix)
- error->all("No fix gravity defined for fix pour");
+ error->all(FLERR,"No fix gravity defined for fix pour");
double xgrav = ((FixGravity *) modify->fix[ifix])->xgrav;
double ygrav = ((FixGravity *) modify->fix[ifix])->ygrav;
double zgrav = ((FixGravity *) modify->fix[ifix])->zgrav;
if (domain->dimension == 3) {
if (fabs(xgrav) > EPSILON || fabs(ygrav) > EPSILON ||
fabs(zgrav+1.0) > EPSILON)
- error->all("Gravity must point in -z to use with fix pour in 3d");
+ error->all(FLERR,"Gravity must point in -z to use with fix pour in 3d");
} else {
if (fabs(xgrav) > EPSILON || fabs(ygrav+1.0) > EPSILON ||
fabs(zgrav) > EPSILON)
- error->all("Gravity must point in -y to use with fix pour in 2d");
+ error->all(FLERR,"Gravity must point in -y to use with fix pour in 2d");
}
double gnew = - ((FixGravity *) modify->fix[ifix])->magnitude * force->ftm2v;
if (gnew != grav)
- error->all("Gravity changed since fix pour was created");
+ error->all(FLERR,"Gravity changed since fix pour was created");
}
/* ----------------------------------------------------------------------
perform particle insertion
------------------------------------------------------------------------- */
void FixPour::pre_exchange()
{
int i;
// just return if should not be called on this timestep
if (next_reneighbor != update->ntimestep) return;
// nnew = # to insert this timestep
int nnew = nper;
if (ninserted + nnew > ninsert) nnew = ninsert - ninserted;
// lo/hi current = z (or y) bounds of insertion region this timestep
if (domain->dimension == 3) {
lo_current = zlo + (update->ntimestep - nfirst) * update->dt * rate;
hi_current = zhi + (update->ntimestep - nfirst) * update->dt * rate;
} else {
lo_current = ylo + (update->ntimestep - nfirst) * update->dt * rate;
hi_current = yhi + (update->ntimestep - nfirst) * update->dt * rate;
}
// ncount = # of my atoms that overlap the insertion region
// nprevious = total of ncount across all procs
int ncount = 0;
for (i = 0; i < atom->nlocal; i++)
if (overlap(i)) ncount++;
int nprevious;
MPI_Allreduce(&ncount,&nprevious,1,MPI_INT,MPI_SUM,world);
// xmine is for my atoms
// xnear is for atoms from all procs + atoms to be inserted
double **xmine,**xnear;
memory->create(xmine,ncount,4,"fix_pour:xmine");
memory->create(xnear,nprevious+nnew,4,"fix_pour:xnear");
int nnear = nprevious;
// setup for allgatherv
int n = 4*ncount;
MPI_Allgather(&n,1,MPI_INT,recvcounts,1,MPI_INT,world);
displs[0] = 0;
for (int iproc = 1; iproc < nprocs; iproc++)
displs[iproc] = displs[iproc-1] + recvcounts[iproc-1];
// load up xmine array
double **x = atom->x;
double *radius = atom->radius;
ncount = 0;
for (i = 0; i < atom->nlocal; i++)
if (overlap(i)) {
xmine[ncount][0] = x[i][0];
xmine[ncount][1] = x[i][1];
xmine[ncount][2] = x[i][2];
xmine[ncount][3] = radius[i];
ncount++;
}
// perform allgatherv to acquire list of nearby particles on all procs
double *ptr = NULL;
if (ncount) ptr = xmine[0];
MPI_Allgatherv(ptr,4*ncount,MPI_DOUBLE,
xnear[0],recvcounts,displs,MPI_DOUBLE,world);
// insert new atoms into xnear list, one by one
// check against all nearby atoms and previously inserted ones
// if there is an overlap then try again at same z (3d) or y (2d) coord
// else insert by adding to xnear list
// max = maximum # of insertion attempts for all particles
// h = height, biased to give uniform distribution in time of insertion
int success;
double coord[3],radtmp,delx,dely,delz,rsq,radsum,rn,h;
int attempt = 0;
int max = nnew * maxattempt;
int ntotal = nprevious+nnew;
while (nnear < ntotal) {
rn = random->uniform();
h = hi_current - rn*rn * (hi_current-lo_current);
radtmp = radius_lo + random->uniform() * (radius_hi-radius_lo);
success = 0;
while (attempt < max) {
attempt++;
xyz_random(h,coord);
for (i = 0; i < nnear; i++) {
delx = coord[0] - xnear[i][0];
dely = coord[1] - xnear[i][1];
delz = coord[2] - xnear[i][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radtmp + xnear[i][3];
if (rsq <= radsum*radsum) break;
}
if (i == nnear) {
success = 1;
break;
}
}
if (success) {
xnear[nnear][0] = coord[0];
xnear[nnear][1] = coord[1];
xnear[nnear][2] = coord[2];
xnear[nnear][3] = radtmp;
nnear++;
} else break;
}
// warn if not all insertions were performed
ninserted += nnear-nprevious;
if (nnear - nprevious < nnew && me == 0)
- error->warning("Less insertions than requested",0);
+ error->warning(FLERR,"Less insertions than requested",0);
// check if new atom is in my sub-box or above it if I'm highest proc
// if so, add to my list via create_atom()
// initialize info about the atom
// type, diameter, density set from fix parameters
// group mask set to "all" plus fix group
// z velocity set to what velocity would be if particle
// had fallen from top of insertion region
// this gives continuous stream of atoms
// solution for v from these 2 eqs, after eliminate t:
// v = vz + grav*t
// coord[2] = hi_current + vz*t + 1/2 grav t^2
// set npartner for new atom to 0 (assume not touching any others)
AtomVec *avec = atom->avec;
int j,m,flag;
double denstmp,vxtmp,vytmp,vztmp;
double *sublo = domain->sublo;
double *subhi = domain->subhi;
int nfix = modify->nfix;
Fix **fix = modify->fix;
for (i = nprevious; i < nnear; i++) {
coord[0] = xnear[i][0];
coord[1] = xnear[i][1];
coord[2] = xnear[i][2];
radtmp = xnear[i][3];
denstmp = density_lo + random->uniform() * (density_hi-density_lo);
if (domain->dimension == 3) {
vxtmp = vxlo + random->uniform() * (vxhi-vxlo);
vytmp = vylo + random->uniform() * (vyhi-vylo);
vztmp = -sqrt(vz*vz + 2.0*grav*(coord[2]-hi_current));
} else {
vxtmp = vxlo + random->uniform() * (vxhi-vxlo);
vytmp = -sqrt(vy*vy + 2.0*grav*(coord[1]-hi_current));
vztmp = 0.0;
}
flag = 0;
if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1] &&
coord[2] >= sublo[2] && coord[2] < subhi[2]) flag = 1;
else if (domain->dimension == 3 && coord[2] >= domain->boxhi[2] &&
comm->myloc[2] == comm->procgrid[2]-1 &&
coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1]) flag = 1;
else if (domain->dimension == 2 && coord[1] >= domain->boxhi[1] &&
comm->myloc[1] == comm->procgrid[1]-1 &&
coord[0] >= sublo[0] && coord[0] < subhi[0]) flag = 1;
if (flag) {
avec->create_atom(ntype,coord);
m = atom->nlocal - 1;
atom->type[m] = ntype;
atom->radius[m] = radtmp;
atom->rmass[m] = 4.0*PI/3.0 * radtmp*radtmp*radtmp * denstmp;
atom->mask[m] = 1 | groupbit;
atom->v[m][0] = vxtmp;
atom->v[m][1] = vytmp;
atom->v[m][2] = vztmp;
for (j = 0; j < nfix; j++)
if (fix[j]->create_attribute) fix[j]->set_arrays(m);
}
}
// reset global natoms
// set tag # of new particles beyond all previous atoms
// if global map exists, reset it now instead of waiting for comm
// since deleting atoms messes up ghosts
if (nnear - nprevious > 0) {
atom->natoms += nnear - nprevious;
if (atom->tag_enable) {
atom->tag_extend();
if (atom->map_style) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
}
}
// free local memory
memory->destroy(xmine);
memory->destroy(xnear);
// next timestep to insert
if (ninserted < ninsert) next_reneighbor += nfreq;
else next_reneighbor = 0;
}
/* ----------------------------------------------------------------------
check if particle i could overlap with a particle inserted into region
return 1 if yes, 0 if no
use maximum diameter for inserted particle
------------------------------------------------------------------------- */
int FixPour::overlap(int i)
{
double delta = radius_hi + atom->radius[i];
double **x = atom->x;
if (domain->dimension == 3) {
if (region_style == 1) {
if (x[i][0] < xlo-delta || x[i][0] > xhi+delta ||
x[i][1] < ylo-delta || x[i][1] > yhi+delta ||
x[i][2] < lo_current-delta || x[i][2] > hi_current+delta) return 0;
} else {
if (x[i][2] < lo_current-delta || x[i][2] > hi_current+delta) return 0;
double delx = x[i][0] - xc;
double dely = x[i][1] - yc;
double rsq = delx*delx + dely*dely;
double r = rc + delta;
if (rsq > r*r) return 0;
}
} else {
if (x[i][0] < xlo-delta || x[i][0] > xhi+delta ||
x[i][1] < lo_current-delta || x[i][1] > hi_current+delta) return 0;
}
return 1;
}
/* ---------------------------------------------------------------------- */
void FixPour::xyz_random(double h, double *coord)
{
if (domain->dimension == 3) {
if (region_style == 1) {
coord[0] = xlo + random->uniform() * (xhi-xlo);
coord[1] = ylo + random->uniform() * (yhi-ylo);
coord[2] = h;
} else {
double r1,r2;
while (1) {
r1 = random->uniform() - 0.5;
r2 = random->uniform() - 0.5;
if (r1*r1 + r2*r2 < 0.25) break;
}
coord[0] = xc + 2.0*r1*rc;
coord[1] = yc + 2.0*r2*rc;
coord[2] = h;
}
} else {
coord[0] = xlo + random->uniform() * (xhi-xlo);
coord[1] = h;
coord[2] = 0.0;
}
}
/* ---------------------------------------------------------------------- */
void FixPour::reset_dt()
{
- error->all("Cannot change timestep with fix pour");
+ error->all(FLERR,"Cannot change timestep with fix pour");
}
diff --git a/src/GRANULAR/fix_wall_gran.cpp b/src/GRANULAR/fix_wall_gran.cpp
index 975828339..a23f70c44 100644
--- a/src/GRANULAR/fix_wall_gran.cpp
+++ b/src/GRANULAR/fix_wall_gran.cpp
@@ -1,798 +1,795 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_wall_gran.h"
#include "atom.h"
#include "domain.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "modify.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{XPLANE,YPLANE,ZPLANE,ZCYLINDER}; // XYZ PLANE need to be 0,1,2
enum{HOOKE,HOOKE_HISTORY,HERTZ_HISTORY};
#define BIG 1.0e20
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixWallGran::FixWallGran(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 10) error->all("Illegal fix wall/gran command");
+ if (narg < 10) error->all(FLERR,"Illegal fix wall/gran command");
if (!atom->sphere_flag)
- error->all("Fix wall/gran requires atom style sphere");
+ error->all(FLERR,"Fix wall/gran requires atom style sphere");
restart_peratom = 1;
create_attribute = 1;
time_depend = 1;
// wall/particle coefficients
kn = atof(arg[3]);
if (strcmp(arg[4],"NULL") == 0) kt = kn * 2.0/7.0;
else kt = atof(arg[4]);
gamman = atof(arg[5]);
if (strcmp(arg[6],"NULL") == 0) gammat = 0.5 * gamman;
else gammat = atof(arg[6]);
xmu = atof(arg[7]);
int dampflag = atoi(arg[8]);
if (dampflag == 0) gammat = 0.0;
if (kn < 0.0 || kt < 0.0 || gamman < 0.0 || gammat < 0.0 ||
xmu < 0.0 || xmu > 1.0 || dampflag < 0 || dampflag > 1)
- error->all("Illegal fix wall/gran command");
+ error->all(FLERR,"Illegal fix wall/gran command");
// convert Kn and Kt from pressure units to force/distance^2 if Hertzian
if (force->pair_match("gran/hertz/history",1)) {
kn /= force->nktv2p;
kt /= force->nktv2p;
}
// wallstyle args
int iarg = 9;
if (strcmp(arg[iarg],"xplane") == 0) {
- if (narg < iarg+3) error->all("Illegal fix wall/gran command");
+ if (narg < iarg+3) error->all(FLERR,"Illegal fix wall/gran command");
wallstyle = XPLANE;
if (strcmp(arg[iarg+1],"NULL") == 0) lo = -BIG;
else lo = atof(arg[iarg+1]);
if (strcmp(arg[iarg+2],"NULL") == 0) hi = BIG;
else hi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"yplane") == 0) {
- if (narg < iarg+3) error->all("Illegal fix wall/gran command");
+ if (narg < iarg+3) error->all(FLERR,"Illegal fix wall/gran command");
wallstyle = YPLANE;
if (strcmp(arg[iarg+1],"NULL") == 0) lo = -BIG;
else lo = atof(arg[iarg+1]);
if (strcmp(arg[iarg+2],"NULL") == 0) hi = BIG;
else hi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"zplane") == 0) {
- if (narg < iarg+3) error->all("Illegal fix wall/gran command");
+ if (narg < iarg+3) error->all(FLERR,"Illegal fix wall/gran command");
wallstyle = ZPLANE;
if (strcmp(arg[iarg+1],"NULL") == 0) lo = -BIG;
else lo = atof(arg[iarg+1]);
if (strcmp(arg[iarg+2],"NULL") == 0) hi = BIG;
else hi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"zcylinder") == 0) {
- if (narg < iarg+2) error->all("Illegal fix wall/gran command");
+ if (narg < iarg+2) error->all(FLERR,"Illegal fix wall/gran command");
wallstyle = ZCYLINDER;
lo = hi = 0.0;
cylradius = atof(arg[iarg+1]);
iarg += 2;
}
// check for trailing keyword/values
wiggle = 0;
wshear = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"wiggle") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix wall/gran command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix wall/gran command");
if (strcmp(arg[iarg+1],"x") == 0) axis = 0;
else if (strcmp(arg[iarg+1],"y") == 0) axis = 1;
else if (strcmp(arg[iarg+1],"z") == 0) axis = 2;
- else error->all("Illegal fix wall/gran command");
+ else error->all(FLERR,"Illegal fix wall/gran command");
amplitude = atof(arg[iarg+2]);
period = atof(arg[iarg+3]);
wiggle = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"shear") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix wall/gran command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix wall/gran command");
if (strcmp(arg[iarg+1],"x") == 0) axis = 0;
else if (strcmp(arg[iarg+1],"y") == 0) axis = 1;
else if (strcmp(arg[iarg+1],"z") == 0) axis = 2;
- else error->all("Illegal fix wall/gran command");
+ else error->all(FLERR,"Illegal fix wall/gran command");
vshear = atof(arg[iarg+2]);
wshear = 1;
iarg += 3;
- } else error->all("Illegal fix wall/gran command");
+ } else error->all(FLERR,"Illegal fix wall/gran command");
}
if (wallstyle == XPLANE && domain->xperiodic)
- error->all("Cannot use wall in periodic dimension");
+ error->all(FLERR,"Cannot use wall in periodic dimension");
if (wallstyle == YPLANE && domain->yperiodic)
- error->all("Cannot use wall in periodic dimension");
+ error->all(FLERR,"Cannot use wall in periodic dimension");
if (wallstyle == ZPLANE && domain->zperiodic)
- error->all("Cannot use wall in periodic dimension");
+ error->all(FLERR,"Cannot use wall in periodic dimension");
if (wallstyle == ZCYLINDER && (domain->xperiodic || domain->yperiodic))
- error->all("Cannot use wall in periodic dimension");
+ error->all(FLERR,"Cannot use wall in periodic dimension");
- if (wiggle && wshear) error->all("Cannot wiggle and shear fix wall/gran");
+ if (wiggle && wshear) error->all(FLERR,"Cannot wiggle and shear fix wall/gran");
if (wiggle && wallstyle == ZCYLINDER && axis != 2)
- error->all("Invalid wiggle direction for fix wall/gran");
+ error->all(FLERR,"Invalid wiggle direction for fix wall/gran");
if (wshear && wallstyle == XPLANE && axis == 0)
- error->all("Invalid shear direction for fix wall/gran");
+ error->all(FLERR,"Invalid shear direction for fix wall/gran");
if (wshear && wallstyle == YPLANE && axis == 1)
- error->all("Invalid shear direction for fix wall/gran");
+ error->all(FLERR,"Invalid shear direction for fix wall/gran");
if (wshear && wallstyle == ZPLANE && axis == 2)
- error->all("Invalid shear direction for fix wall/gran");
+ error->all(FLERR,"Invalid shear direction for fix wall/gran");
// setup oscillations
if (wiggle) {
double PI = 4.0 * atan(1.0);
omega = 2.0*PI / period;
}
// perform initial allocation of atom-based arrays
// register with Atom class
shear = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
atom->add_callback(1);
// initialize as if particle is not touching wall
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
shear[i][0] = shear[i][1] = shear[i][2] = 0.0;
time_origin = update->ntimestep;
laststep = -1;
}
/* ---------------------------------------------------------------------- */
FixWallGran::~FixWallGran()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
atom->delete_callback(id,1);
// delete locally stored arrays
memory->destroy(shear);
}
/* ---------------------------------------------------------------------- */
int FixWallGran::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixWallGran::init()
{
dt = update->dt;
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
// set pairstyle from granular pair style
if (force->pair_match("gran/hooke",1))
pairstyle = HOOKE;
else if (force->pair_match("gran/hooke/history",1))
pairstyle = HOOKE_HISTORY;
else if (force->pair_match("gran/hertz/history",1))
pairstyle = HERTZ_HISTORY;
- else error->all("Fix wall/gran is incompatible with Pair style");
+ else error->all(FLERR,"Fix wall/gran is incompatible with Pair style");
}
/* ---------------------------------------------------------------------- */
void FixWallGran::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixWallGran::post_force(int vflag)
{
double vwall[3],dx,dy,dz,del1,del2,delxy,delr,rsq;
// set position of wall to initial settings and velocity to 0.0
// if wiggle or shear, set wall position and velocity accordingly
double wlo = lo;
double whi = hi;
vwall[0] = vwall[1] = vwall[2] = 0.0;
if (wiggle) {
double arg = omega * (update->ntimestep - time_origin) * dt;
if (wallstyle == axis) {
wlo = lo + amplitude - amplitude*cos(arg);
whi = hi + amplitude - amplitude*cos(arg);
}
vwall[axis] = amplitude*omega*sin(arg);
} else if (wshear) vwall[axis] = vshear;
// loop over all my atoms
// rsq = distance from wall
// dx,dy,dz = signed distance from wall
// for rotating cylinder, reset vwall based on particle position
// skip atom if not close enough to wall
// if wall was set to NULL, it's skipped since lo/hi are infinity
// compute force and torque on atom if close enough to wall
// via wall potential matched to pair potential
// set shear if pair potential stores history
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (update->ntimestep > laststep) shearupdate = 1;
else shearupdate = 0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dx = dy = dz = 0.0;
if (wallstyle == XPLANE) {
del1 = x[i][0] - wlo;
del2 = whi - x[i][0];
if (del1 < del2) dx = del1;
else dx = -del2;
} else if (wallstyle == YPLANE) {
del1 = x[i][1] - wlo;
del2 = whi - x[i][1];
if (del1 < del2) dy = del1;
else dy = -del2;
} else if (wallstyle == ZPLANE) {
del1 = x[i][2] - wlo;
del2 = whi - x[i][2];
if (del1 < del2) dz = del1;
else dz = -del2;
} else if (wallstyle == ZCYLINDER) {
delxy = sqrt(x[i][0]*x[i][0] + x[i][1]*x[i][1]);
delr = cylradius - delxy;
if (delr > radius[i]) dz = cylradius;
else {
dx = -delr/delxy * x[i][0];
dy = -delr/delxy * x[i][1];
if (wshear && axis != 2) {
vwall[0] = vshear * x[i][1]/delxy;
vwall[1] = -vshear * x[i][0]/delxy;
vwall[2] = 0.0;
}
}
}
rsq = dx*dx + dy*dy + dz*dz;
if (rsq > radius[i]*radius[i]) {
if (pairstyle != HOOKE) {
shear[i][0] = 0.0;
shear[i][1] = 0.0;
shear[i][2] = 0.0;
}
} else {
if (pairstyle == HOOKE)
hooke(rsq,dx,dy,dz,vwall,v[i],f[i],omega[i],torque[i],
radius[i],rmass[i]);
else if (pairstyle == HOOKE_HISTORY)
hooke_history(rsq,dx,dy,dz,vwall,v[i],f[i],omega[i],torque[i],
radius[i],rmass[i],shear[i]);
else if (pairstyle == HERTZ_HISTORY)
hertz_history(rsq,dx,dy,dz,vwall,v[i],f[i],omega[i],torque[i],
radius[i],rmass[i],shear[i]);
}
}
}
laststep = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void FixWallGran::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixWallGran::hooke(double rsq, double dx, double dy, double dz,
double *vwall, double *v,
double *f, double *omega, double *torque,
double radius, double mass)
{
double r,vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3,meff,damp,ccel,vtr1,vtr2,vtr3,vrel;
double fn,fs,ft,fs1,fs2,fs3,fx,fy,fz,tor1,tor2,tor3,rinv,rsqinv;
r = sqrt(rsq);
rinv = 1.0/r;
rsqinv = 1.0/rsq;
// relative translational velocity
vr1 = v[0] - vwall[0];
vr2 = v[1] - vwall[1];
vr3 = v[2] - vwall[2];
// normal component
vnnr = vr1*dx + vr2*dy + vr3*dz;
vn1 = dx*vnnr * rsqinv;
vn2 = dy*vnnr * rsqinv;
vn3 = dz*vnnr * rsqinv;
// tangential component
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// relative rotational velocity
wr1 = radius*omega[0] * rinv;
wr2 = radius*omega[1] * rinv;
wr3 = radius*omega[2] * rinv;
// normal forces = Hookian contact + normal velocity damping
meff = mass;
damp = meff*gamman*vnnr*rsqinv;
ccel = kn*(radius-r)*rinv - damp;
// relative velocities
vtr1 = vt1 - (dz*wr2-dy*wr3);
vtr2 = vt2 - (dx*wr3-dz*wr1);
vtr3 = vt3 - (dy*wr1-dx*wr2);
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
vrel = sqrt(vrel);
// force normalization
fn = xmu * fabs(ccel*r);
fs = meff*gammat*vrel;
if (vrel != 0.0) ft = MIN(fn,fs) / vrel;
else ft = 0.0;
// tangential force due to tangential velocity damping
fs1 = -ft*vtr1;
fs2 = -ft*vtr2;
fs3 = -ft*vtr3;
// forces & torques
fx = dx*ccel + fs1;
fy = dy*ccel + fs2;
fz = dz*ccel + fs3;
f[0] += fx;
f[1] += fy;
f[2] += fz;
tor1 = rinv * (dy*fs3 - dz*fs2);
tor2 = rinv * (dz*fs1 - dx*fs3);
tor3 = rinv * (dx*fs2 - dy*fs1);
torque[0] -= radius*tor1;
torque[1] -= radius*tor2;
torque[2] -= radius*tor3;
}
/* ---------------------------------------------------------------------- */
void FixWallGran::hooke_history(double rsq, double dx, double dy, double dz,
double *vwall, double *v,
double *f, double *omega, double *torque,
double radius, double mass, double *shear)
{
double r,vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3,meff,damp,ccel,vtr1,vtr2,vtr3,vrel;
double fn,fs,fs1,fs2,fs3,fx,fy,fz,tor1,tor2,tor3;
double shrmag,rsht,rinv,rsqinv;
r = sqrt(rsq);
rinv = 1.0/r;
rsqinv = 1.0/rsq;
// relative translational velocity
vr1 = v[0] - vwall[0];
vr2 = v[1] - vwall[1];
vr3 = v[2] - vwall[2];
// normal component
vnnr = vr1*dx + vr2*dy + vr3*dz;
vn1 = dx*vnnr * rsqinv;
vn2 = dy*vnnr * rsqinv;
vn3 = dz*vnnr * rsqinv;
// tangential component
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// relative rotational velocity
wr1 = radius*omega[0] * rinv;
wr2 = radius*omega[1] * rinv;
wr3 = radius*omega[2] * rinv;
// normal forces = Hookian contact + normal velocity damping
meff = mass;
damp = meff*gamman*vnnr*rsqinv;
ccel = kn*(radius-r)*rinv - damp;
// relative velocities
vtr1 = vt1 - (dz*wr2-dy*wr3);
vtr2 = vt2 - (dx*wr3-dz*wr1);
vtr3 = vt3 - (dy*wr1-dx*wr2);
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
vrel = sqrt(vrel);
// shear history effects
if (shearupdate) {
shear[0] += vtr1*dt;
shear[1] += vtr2*dt;
shear[2] += vtr3*dt;
}
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] + shear[2]*shear[2]);
// rotate shear displacements
rsht = shear[0]*dx + shear[1]*dy + shear[2]*dz;
rsht = rsht*rsqinv;
if (shearupdate) {
shear[0] -= rsht*dx;
shear[1] -= rsht*dy;
shear[2] -= rsht*dz;
}
// tangential forces = shear + tangential velocity damping
fs1 = - (kt*shear[0] + meff*gammat*vtr1);
fs2 = - (kt*shear[1] + meff*gammat*vtr2);
fs3 = - (kt*shear[2] + meff*gammat*vtr3);
// rescale frictional displacements and forces if needed
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
fn = xmu * fabs(ccel*r);
if (fs > fn) {
if (shrmag != 0.0) {
shear[0] = (fn/fs) * (shear[0] + meff*gammat*vtr1/kt) -
meff*gammat*vtr1/kt;
shear[1] = (fn/fs) * (shear[1] + meff*gammat*vtr2/kt) -
meff*gammat*vtr2/kt;
shear[2] = (fn/fs) * (shear[2] + meff*gammat*vtr3/kt) -
meff*gammat*vtr3/kt;
fs1 *= fn/fs ;
fs2 *= fn/fs;
fs3 *= fn/fs;
} else fs1 = fs2 = fs3 = 0.0;
}
// forces & torques
fx = dx*ccel + fs1;
fy = dy*ccel + fs2;
fz = dz*ccel + fs3;
f[0] += fx;
f[1] += fy;
f[2] += fz;
tor1 = rinv * (dy*fs3 - dz*fs2);
tor2 = rinv * (dz*fs1 - dx*fs3);
tor3 = rinv * (dx*fs2 - dy*fs1);
torque[0] -= radius*tor1;
torque[1] -= radius*tor2;
torque[2] -= radius*tor3;
}
/* ---------------------------------------------------------------------- */
void FixWallGran::hertz_history(double rsq, double dx, double dy, double dz,
double *vwall, double *v,
double *f, double *omega, double *torque,
double radius, double mass, double *shear)
{
double r,vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3,meff,damp,ccel,vtr1,vtr2,vtr3,vrel;
double fn,fs,fs1,fs2,fs3,fx,fy,fz,tor1,tor2,tor3;
double shrmag,rsht,polyhertz,rinv,rsqinv;
r = sqrt(rsq);
rinv = 1.0/r;
rsqinv = 1.0/rsq;
// relative translational velocity
vr1 = v[0] - vwall[0];
vr2 = v[1] - vwall[1];
vr3 = v[2] - vwall[2];
// normal component
vnnr = vr1*dx + vr2*dy + vr3*dz;
vn1 = dx*vnnr / rsq;
vn2 = dy*vnnr / rsq;
vn3 = dz*vnnr / rsq;
// tangential component
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// relative rotational velocity
wr1 = radius*omega[0] * rinv;
wr2 = radius*omega[1] * rinv;
wr3 = radius*omega[2] * rinv;
// normal forces = Hertzian contact + normal velocity damping
meff = mass;
damp = meff*gamman*vnnr*rsqinv;
ccel = kn*(radius-r)*rinv - damp;
polyhertz = sqrt((radius-r)*radius);
ccel *= polyhertz;
// relative velocities
vtr1 = vt1 - (dz*wr2-dy*wr3);
vtr2 = vt2 - (dx*wr3-dz*wr1);
vtr3 = vt3 - (dy*wr1-dx*wr2);
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
vrel = sqrt(vrel);
// shear history effects
if (shearupdate) {
shear[0] += vtr1*dt;
shear[1] += vtr2*dt;
shear[2] += vtr3*dt;
}
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] + shear[2]*shear[2]);
// rotate shear displacements
rsht = shear[0]*dx + shear[1]*dy + shear[2]*dz;
rsht = rsht*rsqinv;
if (shearupdate) {
shear[0] -= rsht*dx;
shear[1] -= rsht*dy;
shear[2] -= rsht*dz;
}
// tangential forces = shear + tangential velocity damping
fs1 = -polyhertz * (kt*shear[0] + meff*gammat*vtr1);
fs2 = -polyhertz * (kt*shear[1] + meff*gammat*vtr2);
fs3 = -polyhertz * (kt*shear[2] + meff*gammat*vtr3);
// rescale frictional displacements and forces if needed
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
fn = xmu * fabs(ccel*r);
if (fs > fn) {
if (shrmag != 0.0) {
shear[0] = (fn/fs) * (shear[0] + meff*gammat*vtr1/kt) -
meff*gammat*vtr1/kt;
shear[1] = (fn/fs) * (shear[1] + meff*gammat*vtr2/kt) -
meff*gammat*vtr2/kt;
shear[2] = (fn/fs) * (shear[2] + meff*gammat*vtr3/kt) -
meff*gammat*vtr3/kt;
fs1 *= fn/fs ;
fs2 *= fn/fs;
fs3 *= fn/fs;
} else fs1 = fs2 = fs3 = 0.0;
}
// forces & torques
fx = dx*ccel + fs1;
fy = dy*ccel + fs2;
fz = dz*ccel + fs3;
f[0] += fx;
f[1] += fy;
f[2] += fz;
tor1 = rinv * (dy*fs3 - dz*fs2);
tor2 = rinv * (dz*fs1 - dx*fs3);
tor3 = rinv * (dx*fs2 - dy*fs1);
torque[0] -= radius*tor1;
torque[1] -= radius*tor2;
torque[2] -= radius*tor3;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixWallGran::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int);
bytes += 3*nmax * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixWallGran::grow_arrays(int nmax)
{
memory->grow(shear,nmax,3,"fix_wall_gran:shear");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixWallGran::copy_arrays(int i, int j)
{
shear[j][0] = shear[i][0];
shear[j][1] = shear[i][1];
shear[j][2] = shear[i][2];
}
/* ----------------------------------------------------------------------
initialize one atom's array values, called when atom is created
------------------------------------------------------------------------- */
void FixWallGran::set_arrays(int i)
{
shear[i][0] = shear[i][1] = shear[i][2] = 0.0;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixWallGran::pack_exchange(int i, double *buf)
{
buf[0] = shear[i][0];
buf[1] = shear[i][1];
buf[2] = shear[i][2];
return 3;
}
/* ----------------------------------------------------------------------
unpack values into local atom-based arrays after exchange
------------------------------------------------------------------------- */
int FixWallGran::unpack_exchange(int nlocal, double *buf)
{
shear[nlocal][0] = buf[0];
shear[nlocal][1] = buf[1];
shear[nlocal][2] = buf[2];
return 3;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixWallGran::pack_restart(int i, double *buf)
{
int m = 0;
buf[m++] = 4;
buf[m++] = shear[i][0];
buf[m++] = shear[i][1];
buf[m++] = shear[i][2];
return m;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixWallGran::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
shear[nlocal][0] = extra[nlocal][m++];
shear[nlocal][1] = extra[nlocal][m++];
shear[nlocal][2] = extra[nlocal][m++];
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixWallGran::maxsize_restart()
{
return 4;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixWallGran::size_restart(int nlocal)
{
return 4;
}
/* ---------------------------------------------------------------------- */
void FixWallGran::reset_dt()
{
dt = update->dt;
}
diff --git a/src/GRANULAR/pair_gran_hertz_history.cpp b/src/GRANULAR/pair_gran_hertz_history.cpp
index 6c193e351..a418e9352 100644
--- a/src/GRANULAR/pair_gran_hertz_history.cpp
+++ b/src/GRANULAR/pair_gran_hertz_history.cpp
@@ -1,281 +1,278 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "pair_gran_hertz_history.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "neigh_list.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairGranHertzHistory::PairGranHertzHistory(LAMMPS *lmp) :
PairGranHookeHistory(lmp) {}
/* ---------------------------------------------------------------------- */
void PairGranHertzHistory::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz;
double radi,radj,radsum,rsq,r,rinv,rsqinv;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3;
double vtr1,vtr2,vtr3,vrel;
double meff,damp,ccel,tor1,tor2,tor3;
double fn,fs,fs1,fs2,fs3;
double shrmag,rsht,polyhertz;
int *ilist,*jlist,*numneigh,**firstneigh;
int *touch,**firsttouch;
double *shear,*allshear,**firstshear;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int shearupdate = 0;
if (update->ntimestep > laststep) shearupdate = 1;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *radius = atom->radius;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
firsttouch = list->listgranhistory->firstneigh;
firstshear = list->listgranhistory->firstdouble;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
touch = firsttouch[i];
allshear = firstshear[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radj = radius[j];
radsum = radi + radj;
if (rsq >= radsum*radsum) {
// unset non-touching neighbors
touch[jj] = 0;
shear = &allshear[3*jj];
shear[0] = 0.0;
shear[1] = 0.0;
shear[2] = 0.0;
} else {
r = sqrt(rsq);
rinv = 1.0/r;
rsqinv = 1.0/rsq;
// relative translational velocity
vr1 = v[i][0] - v[j][0];
vr2 = v[i][1] - v[j][1];
vr3 = v[i][2] - v[j][2];
// normal component
vnnr = vr1*delx + vr2*dely + vr3*delz;
vn1 = delx*vnnr * rsqinv;
vn2 = dely*vnnr * rsqinv;
vn3 = delz*vnnr * rsqinv;
// tangential component
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// relative rotational velocity
wr1 = (radi*omega[i][0] + radj*omega[j][0]) * rinv;
wr2 = (radi*omega[i][1] + radj*omega[j][1]) * rinv;
wr3 = (radi*omega[i][2] + radj*omega[j][2]) * rinv;
// normal force = Hertzian contact + normal velocity damping
if (rmass) {
meff = rmass[i]*rmass[j] / (rmass[i]+rmass[j]);
if (mask[i] & freeze_group_bit) meff = rmass[j];
if (mask[j] & freeze_group_bit) meff = rmass[i];
} else {
itype = type[i];
jtype = type[j];
meff = mass[itype]*mass[jtype] / (mass[itype]+mass[jtype]);
if (mask[i] & freeze_group_bit) meff = mass[jtype];
if (mask[j] & freeze_group_bit) meff = mass[itype];
}
damp = meff*gamman*vnnr*rsqinv;
ccel = kn*(radsum-r)*rinv - damp;
polyhertz = sqrt((radsum-r)*radi*radj / radsum);
ccel *= polyhertz;
// relative velocities
vtr1 = vt1 - (delz*wr2-dely*wr3);
vtr2 = vt2 - (delx*wr3-delz*wr1);
vtr3 = vt3 - (dely*wr1-delx*wr2);
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
vrel = sqrt(vrel);
// shear history effects
touch[jj] = 1;
shear = &allshear[3*jj];
if (shearupdate) {
shear[0] += vtr1*dt;
shear[1] += vtr2*dt;
shear[2] += vtr3*dt;
}
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
shear[2]*shear[2]);
// rotate shear displacements
rsht = shear[0]*delx + shear[1]*dely + shear[2]*delz;
rsht *= rsqinv;
if (shearupdate) {
shear[0] -= rsht*delx;
shear[1] -= rsht*dely;
shear[2] -= rsht*delz;
}
// tangential forces = shear + tangential velocity damping
fs1 = -polyhertz * (kt*shear[0] + meff*gammat*vtr1);
fs2 = -polyhertz * (kt*shear[1] + meff*gammat*vtr2);
fs3 = -polyhertz * (kt*shear[2] + meff*gammat*vtr3);
// rescale frictional displacements and forces if needed
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
fn = xmu * fabs(ccel*r);
if (fs > fn) {
if (shrmag != 0.0) {
shear[0] = (fn/fs) * (shear[0] + meff*gammat*vtr1/kt) -
meff*gammat*vtr1/kt;
shear[1] = (fn/fs) * (shear[1] + meff*gammat*vtr2/kt) -
meff*gammat*vtr2/kt;
shear[2] = (fn/fs) * (shear[2] + meff*gammat*vtr3/kt) -
meff*gammat*vtr3/kt;
fs1 *= fn/fs;
fs2 *= fn/fs;
fs3 *= fn/fs;
} else fs1 = fs2 = fs3 = 0.0;
}
// forces & torques
fx = delx*ccel + fs1;
fy = dely*ccel + fs2;
fz = delz*ccel + fs3;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
tor1 = rinv * (dely*fs3 - delz*fs2);
tor2 = rinv * (delz*fs1 - delx*fs3);
tor3 = rinv * (delx*fs2 - dely*fs1);
torque[i][0] -= radi*tor1;
torque[i][1] -= radi*tor2;
torque[i][2] -= radi*tor3;
if (j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
torque[j][0] -= radj*tor1;
torque[j][1] -= radj*tor2;
torque[j][2] -= radj*tor3;
}
if (evflag) ev_tally_xyz(i,j,nlocal,0,
0.0,0.0,fx,fy,fz,delx,dely,delz);
}
}
}
laststep = update->ntimestep;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairGranHertzHistory::settings(int narg, char **arg)
{
- if (narg != 6) error->all("Illegal pair_style command");
+ if (narg != 6) error->all(FLERR,"Illegal pair_style command");
kn = force->numeric(arg[0]);
if (strcmp(arg[1],"NULL") == 0) kt = kn * 2.0/7.0;
else kt = force->numeric(arg[1]);
gamman = force->numeric(arg[2]);
if (strcmp(arg[3],"NULL") == 0) gammat = 0.5 * gamman;
else gammat = force->numeric(arg[3]);
xmu = force->numeric(arg[4]);
dampflag = force->inumeric(arg[5]);
if (dampflag == 0) gammat = 0.0;
if (kn < 0.0 || kt < 0.0 || gamman < 0.0 || gammat < 0.0 ||
xmu < 0.0 || xmu > 1.0 || dampflag < 0 || dampflag > 1)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
// convert Kn and Kt from pressure units to force/distance^2
kn /= force->nktv2p;
kt /= force->nktv2p;
}
diff --git a/src/GRANULAR/pair_gran_hooke.cpp b/src/GRANULAR/pair_gran_hooke.cpp
index 542bbaa58..95651e760 100644
--- a/src/GRANULAR/pair_gran_hooke.cpp
+++ b/src/GRANULAR/pair_gran_hooke.cpp
@@ -1,196 +1,193 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "string.h"
#include "pair_gran_hooke.h"
#include "atom.h"
#include "force.h"
#include "neigh_list.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairGranHooke::PairGranHooke(LAMMPS *lmp) : PairGranHookeHistory(lmp)
{
no_virial_fdotr_compute = 0;
history = 0;
}
/* ---------------------------------------------------------------------- */
void PairGranHooke::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz;
double radi,radj,radsum,rsq,r,rinv,rsqinv;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3;
double vtr1,vtr2,vtr3,vrel;
double meff,damp,ccel,tor1,tor2,tor3;
double fn,fs,ft,fs1,fs2,fs3;
int *ilist,*jlist,*numneigh,**firstneigh;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *radius = atom->radius;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radj = radius[j];
radsum = radi + radj;
if (rsq < radsum*radsum) {
r = sqrt(rsq);
rinv = 1.0/r;
rsqinv = 1.0/rsq;
// relative translational velocity
vr1 = v[i][0] - v[j][0];
vr2 = v[i][1] - v[j][1];
vr3 = v[i][2] - v[j][2];
// normal component
vnnr = vr1*delx + vr2*dely + vr3*delz;
vn1 = delx*vnnr * rsqinv;
vn2 = dely*vnnr * rsqinv;
vn3 = delz*vnnr * rsqinv;
// tangential component
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// relative rotational velocity
wr1 = (radi*omega[i][0] + radj*omega[j][0]) * rinv;
wr2 = (radi*omega[i][1] + radj*omega[j][1]) * rinv;
wr3 = (radi*omega[i][2] + radj*omega[j][2]) * rinv;
// normal forces = Hookian contact + normal velocity damping
if (rmass) {
meff = rmass[i]*rmass[j] / (rmass[i]+rmass[j]);
if (mask[i] & freeze_group_bit) meff = rmass[j];
if (mask[j] & freeze_group_bit) meff = rmass[i];
} else {
itype = type[i];
jtype = type[j];
meff = mass[itype]*mass[jtype] / (mass[itype]+mass[jtype]);
if (mask[i] & freeze_group_bit) meff = mass[jtype];
if (mask[j] & freeze_group_bit) meff = mass[itype];
}
damp = meff*gamman*vnnr*rsqinv;
ccel = kn*(radsum-r)*rinv - damp;
// relative velocities
vtr1 = vt1 - (delz*wr2-dely*wr3);
vtr2 = vt2 - (delx*wr3-delz*wr1);
vtr3 = vt3 - (dely*wr1-delx*wr2);
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
vrel = sqrt(vrel);
// force normalization
fn = xmu * fabs(ccel*r);
fs = meff*gammat*vrel;
if (vrel != 0.0) ft = MIN(fn,fs) / vrel;
else ft = 0.0;
// tangential force due to tangential velocity damping
fs1 = -ft*vtr1;
fs2 = -ft*vtr2;
fs3 = -ft*vtr3;
// forces & torques
fx = delx*ccel + fs1;
fy = dely*ccel + fs2;
fz = delz*ccel + fs3;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
tor1 = rinv * (dely*fs3 - delz*fs2);
tor2 = rinv * (delz*fs1 - delx*fs3);
tor3 = rinv * (delx*fs2 - dely*fs1);
torque[i][0] -= radi*tor1;
torque[i][1] -= radi*tor2;
torque[i][2] -= radi*tor3;
if (newton_pair || j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
torque[j][0] -= radj*tor1;
torque[j][1] -= radj*tor2;
torque[j][2] -= radj*tor3;
}
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,
0.0,0.0,fx,fy,fz,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
diff --git a/src/GRANULAR/pair_gran_hooke_history.cpp b/src/GRANULAR/pair_gran_hooke_history.cpp
index 149fa696f..6ab64ee37 100644
--- a/src/GRANULAR/pair_gran_hooke_history.cpp
+++ b/src/GRANULAR/pair_gran_hooke_history.cpp
@@ -1,548 +1,545 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Leo Silbert (SNL), Gary Grest (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_gran_hooke_history.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "fix_pour.h"
#include "fix_shear_history.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairGranHookeHistory::PairGranHookeHistory(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
no_virial_fdotr_compute = 1;
history = 1;
fix_history = NULL;
laststep = -1;
}
/* ---------------------------------------------------------------------- */
PairGranHookeHistory::~PairGranHookeHistory()
{
if (fix_history) modify->delete_fix("SHEAR_HISTORY");
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] onerad_dynamic;
delete [] onerad_frozen;
delete [] maxrad_dynamic;
delete [] maxrad_frozen;
}
}
/* ---------------------------------------------------------------------- */
void PairGranHookeHistory::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fx,fy,fz;
double radi,radj,radsum,rsq,r,rinv,rsqinv;
double vr1,vr2,vr3,vnnr,vn1,vn2,vn3,vt1,vt2,vt3;
double wr1,wr2,wr3;
double vtr1,vtr2,vtr3,vrel;
double meff,damp,ccel,tor1,tor2,tor3;
double fn,fs,fs1,fs2,fs3;
double shrmag,rsht;
int *ilist,*jlist,*numneigh,**firstneigh;
int *touch,**firsttouch;
double *shear,*allshear,**firstshear;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int shearupdate = 0;
if (update->ntimestep > laststep) shearupdate = 1;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *radius = atom->radius;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
firsttouch = listgranhistory->firstneigh;
firstshear = listgranhistory->firstdouble;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
touch = firsttouch[i];
allshear = firstshear[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radj = radius[j];
radsum = radi + radj;
if (rsq >= radsum*radsum) {
// unset non-touching neighbors
touch[jj] = 0;
shear = &allshear[3*jj];
shear[0] = 0.0;
shear[1] = 0.0;
shear[2] = 0.0;
} else {
r = sqrt(rsq);
rinv = 1.0/r;
rsqinv = 1.0/rsq;
// relative translational velocity
vr1 = v[i][0] - v[j][0];
vr2 = v[i][1] - v[j][1];
vr3 = v[i][2] - v[j][2];
// normal component
vnnr = vr1*delx + vr2*dely + vr3*delz;
vn1 = delx*vnnr * rsqinv;
vn2 = dely*vnnr * rsqinv;
vn3 = delz*vnnr * rsqinv;
// tangential component
vt1 = vr1 - vn1;
vt2 = vr2 - vn2;
vt3 = vr3 - vn3;
// relative rotational velocity
wr1 = (radi*omega[i][0] + radj*omega[j][0]) * rinv;
wr2 = (radi*omega[i][1] + radj*omega[j][1]) * rinv;
wr3 = (radi*omega[i][2] + radj*omega[j][2]) * rinv;
// normal forces = Hookian contact + normal velocity damping
if (rmass) {
meff = rmass[i]*rmass[j] / (rmass[i]+rmass[j]);
if (mask[i] & freeze_group_bit) meff = rmass[j];
if (mask[j] & freeze_group_bit) meff = rmass[i];
} else {
itype = type[i];
jtype = type[j];
meff = mass[itype]*mass[jtype] / (mass[itype]+mass[jtype]);
if (mask[i] & freeze_group_bit) meff = mass[jtype];
if (mask[j] & freeze_group_bit) meff = mass[itype];
}
damp = meff*gamman*vnnr*rsqinv;
ccel = kn*(radsum-r)*rinv - damp;
// relative velocities
vtr1 = vt1 - (delz*wr2-dely*wr3);
vtr2 = vt2 - (delx*wr3-delz*wr1);
vtr3 = vt3 - (dely*wr1-delx*wr2);
vrel = vtr1*vtr1 + vtr2*vtr2 + vtr3*vtr3;
vrel = sqrt(vrel);
// shear history effects
touch[jj] = 1;
shear = &allshear[3*jj];
if (shearupdate) {
shear[0] += vtr1*dt;
shear[1] += vtr2*dt;
shear[2] += vtr3*dt;
}
shrmag = sqrt(shear[0]*shear[0] + shear[1]*shear[1] +
shear[2]*shear[2]);
// rotate shear displacements
rsht = shear[0]*delx + shear[1]*dely + shear[2]*delz;
rsht *= rsqinv;
if (shearupdate) {
shear[0] -= rsht*delx;
shear[1] -= rsht*dely;
shear[2] -= rsht*delz;
}
// tangential forces = shear + tangential velocity damping
fs1 = - (kt*shear[0] + meff*gammat*vtr1);
fs2 = - (kt*shear[1] + meff*gammat*vtr2);
fs3 = - (kt*shear[2] + meff*gammat*vtr3);
// rescale frictional displacements and forces if needed
fs = sqrt(fs1*fs1 + fs2*fs2 + fs3*fs3);
fn = xmu * fabs(ccel*r);
if (fs > fn) {
if (shrmag != 0.0) {
shear[0] = (fn/fs) * (shear[0] + meff*gammat*vtr1/kt) -
meff*gammat*vtr1/kt;
shear[1] = (fn/fs) * (shear[1] + meff*gammat*vtr2/kt) -
meff*gammat*vtr2/kt;
shear[2] = (fn/fs) * (shear[2] + meff*gammat*vtr3/kt) -
meff*gammat*vtr3/kt;
fs1 *= fn/fs;
fs2 *= fn/fs;
fs3 *= fn/fs;
} else fs1 = fs2 = fs3 = 0.0;
}
// forces & torques
fx = delx*ccel + fs1;
fy = dely*ccel + fs2;
fz = delz*ccel + fs3;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
tor1 = rinv * (dely*fs3 - delz*fs2);
tor2 = rinv * (delz*fs1 - delx*fs3);
tor3 = rinv * (delx*fs2 - dely*fs1);
torque[i][0] -= radi*tor1;
torque[i][1] -= radi*tor2;
torque[i][2] -= radi*tor3;
if (j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
torque[j][0] -= radj*tor1;
torque[j][1] -= radj*tor2;
torque[j][2] -= radj*tor3;
}
if (evflag) ev_tally_xyz(i,j,nlocal,0,
0.0,0.0,fx,fy,fz,delx,dely,delz);
}
}
}
laststep = update->ntimestep;
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairGranHookeHistory::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
onerad_dynamic = new double[n+1];
onerad_frozen = new double[n+1];
maxrad_dynamic = new double[n+1];
maxrad_frozen = new double[n+1];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairGranHookeHistory::settings(int narg, char **arg)
{
- if (narg != 6) error->all("Illegal pair_style command");
+ if (narg != 6) error->all(FLERR,"Illegal pair_style command");
kn = force->numeric(arg[0]);
if (strcmp(arg[1],"NULL") == 0) kt = kn * 2.0/7.0;
else kt = force->numeric(arg[1]);
gamman = force->numeric(arg[2]);
if (strcmp(arg[3],"NULL") == 0) gammat = 0.5 * gamman;
else gammat = force->numeric(arg[3]);
xmu = force->numeric(arg[4]);
dampflag = force->inumeric(arg[5]);
if (dampflag == 0) gammat = 0.0;
if (kn < 0.0 || kt < 0.0 || gamman < 0.0 || gammat < 0.0 ||
xmu < 0.0 || xmu > 1.0 || dampflag < 0 || dampflag > 1)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairGranHookeHistory::coeff(int narg, char **arg)
{
- if (narg > 2) error->all("Incorrect args for pair coefficients");
+ if (narg > 2) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairGranHookeHistory::init_style()
{
int i;
// error and warning checks
if (!atom->sphere_flag)
- error->all("Pair granular requires atom style sphere");
+ error->all(FLERR,"Pair granular requires atom style sphere");
if (comm->ghost_velocity == 0)
- error->all("Pair granular requires ghost atoms store velocity");
+ error->all(FLERR,"Pair granular requires ghost atoms store velocity");
// need a half neigh list and optionally a granular history neigh list
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->gran = 1;
if (history) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->granhistory = 1;
neighbor->requests[irequest]->dnum = 3;
}
dt = update->dt;
// if shear history is stored:
// check if newton flag is valid
// if first init, create Fix needed for storing shear history
if (history && force->newton_pair == 1)
- error->all("Pair granular with shear history requires newton pair off");
+ error->all(FLERR,"Pair granular with shear history requires newton pair off");
if (history && fix_history == NULL) {
char **fixarg = new char*[3];
fixarg[0] = (char *) "SHEAR_HISTORY";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "SHEAR_HISTORY";
modify->add_fix(3,fixarg);
delete [] fixarg;
fix_history = (FixShearHistory *) modify->fix[modify->nfix-1];
fix_history->pair = this;
}
// check for Fix freeze and set freeze_group_bit
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"freeze") == 0) break;
if (i < modify->nfix) freeze_group_bit = modify->fix[i]->groupbit;
else freeze_group_bit = 0;
// check for Fix pour and set pour_type and pour_maxdiam
int pour_type = 0;
double pour_maxrad = 0.0;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"pour") == 0) break;
if (i < modify->nfix) {
pour_type = ((FixPour *) modify->fix[i])->ntype;
pour_maxrad = ((FixPour *) modify->fix[i])->radius_hi;
}
// set maxrad_dynamic and maxrad_frozen for each type
// include future Fix pour particles as dynamic
for (i = 1; i <= atom->ntypes; i++)
onerad_dynamic[i] = onerad_frozen[i] = 0.0;
if (pour_type) onerad_dynamic[pour_type] = pour_maxrad;
double *radius = atom->radius;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (mask[i] & freeze_group_bit)
onerad_frozen[type[i]] = MAX(onerad_frozen[type[i]],radius[i]);
else
onerad_dynamic[type[i]] = MAX(onerad_dynamic[type[i]],radius[i]);
MPI_Allreduce(&onerad_dynamic[1],&maxrad_dynamic[1],atom->ntypes,
MPI_DOUBLE,MPI_MAX,world);
MPI_Allreduce(&onerad_frozen[1],&maxrad_frozen[1],atom->ntypes,
MPI_DOUBLE,MPI_MAX,world);
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
optional granular history list
------------------------------------------------------------------------- */
void PairGranHookeHistory::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listgranhistory = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairGranHookeHistory::init_one(int i, int j)
{
if (!allocated) allocate();
// cutoff = sum of max I,J radii for
// dynamic/dynamic & dynamic/frozen interactions, but not frozen/frozen
double cutoff = maxrad_dynamic[i]+maxrad_dynamic[j];
cutoff = MAX(cutoff,maxrad_frozen[i]+maxrad_dynamic[j]);
cutoff = MAX(cutoff,maxrad_dynamic[i]+maxrad_frozen[j]);
return cutoff;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairGranHookeHistory::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++)
fwrite(&setflag[i][j],sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairGranHookeHistory::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairGranHookeHistory::write_restart_settings(FILE *fp)
{
fwrite(&kn,sizeof(double),1,fp);
fwrite(&kt,sizeof(double),1,fp);
fwrite(&gamman,sizeof(double),1,fp);
fwrite(&gammat,sizeof(double),1,fp);
fwrite(&xmu,sizeof(double),1,fp);
fwrite(&dampflag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairGranHookeHistory::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&kn,sizeof(double),1,fp);
fread(&kt,sizeof(double),1,fp);
fread(&gamman,sizeof(double),1,fp);
fread(&gammat,sizeof(double),1,fp);
fread(&xmu,sizeof(double),1,fp);
fread(&dampflag,sizeof(int),1,fp);
}
MPI_Bcast(&kn,1,MPI_DOUBLE,0,world);
MPI_Bcast(&kt,1,MPI_DOUBLE,0,world);
MPI_Bcast(&gamman,1,MPI_DOUBLE,0,world);
MPI_Bcast(&gammat,1,MPI_DOUBLE,0,world);
MPI_Bcast(&xmu,1,MPI_DOUBLE,0,world);
MPI_Bcast(&dampflag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
void PairGranHookeHistory::reset_dt()
{
dt = update->dt;
}
diff --git a/src/KSPACE/ewald.cpp b/src/KSPACE/ewald.cpp
index ad7a5923e..5b6d46750 100644
--- a/src/KSPACE/ewald.cpp
+++ b/src/KSPACE/ewald.cpp
@@ -1,847 +1,844 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Roy Pollock (LLNL), Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "math.h"
#include "ewald.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.00001
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
Ewald::Ewald(LAMMPS *lmp, int narg, char **arg) : KSpace(lmp, narg, arg)
{
- if (narg != 1) error->all("Illegal kspace_style ewald command");
+ if (narg != 1) error->all(FLERR,"Illegal kspace_style ewald command");
precision = atof(arg[0]);
PI = 4.0*atan(1.0);
kmax = 0;
kxvecs = kyvecs = kzvecs = NULL;
ug = NULL;
eg = vg = NULL;
sfacrl = sfacim = sfacrl_all = sfacim_all = NULL;
nmax = 0;
ek = NULL;
cs = sn = NULL;
kcount = 0;
}
/* ----------------------------------------------------------------------
free all memory
------------------------------------------------------------------------- */
Ewald::~Ewald()
{
deallocate();
memory->destroy(ek);
memory->destroy3d_offset(cs,-kmax_created);
memory->destroy3d_offset(sn,-kmax_created);
}
/* ---------------------------------------------------------------------- */
void Ewald::init()
{
if (comm->me == 0) {
if (screen) fprintf(screen,"Ewald initialization ...\n");
if (logfile) fprintf(logfile,"Ewald initialization ...\n");
}
// error check
- if (domain->triclinic) error->all("Cannot use Ewald with triclinic box");
+ if (domain->triclinic) error->all(FLERR,"Cannot use Ewald with triclinic box");
if (domain->dimension == 2)
- error->all("Cannot use Ewald with 2d simulation");
+ error->all(FLERR,"Cannot use Ewald with 2d simulation");
- if (!atom->q_flag) error->all("Kspace style requires atom attribute q");
+ if (!atom->q_flag) error->all(FLERR,"Kspace style requires atom attribute q");
if (slabflag == 0 && domain->nonperiodic > 0)
- error->all("Cannot use nonperiodic boundaries with Ewald");
+ error->all(FLERR,"Cannot use nonperiodic boundaries with Ewald");
if (slabflag == 1) {
if (domain->xperiodic != 1 || domain->yperiodic != 1 ||
domain->boundary[2][0] != 1 || domain->boundary[2][1] != 1)
- error->all("Incorrect boundaries with slab Ewald");
+ error->all(FLERR,"Incorrect boundaries with slab Ewald");
}
// extract short-range Coulombic cutoff from pair style
qqrd2e = force->qqrd2e;
scale = 1.0;
if (force->pair == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
int itmp;
double *p_cutoff = (double *) force->pair->extract("cut_coul",itmp);
if (p_cutoff == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
double cutoff = *p_cutoff;
qsum = qsqsum = 0.0;
for (int i = 0; i < atom->nlocal; i++) {
qsum += atom->q[i];
qsqsum += atom->q[i]*atom->q[i];
}
double tmp;
MPI_Allreduce(&qsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
qsum = tmp;
MPI_Allreduce(&qsqsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
qsqsum = tmp;
if (qsqsum == 0.0)
- error->all("Cannot use kspace solver on system with no charge");
+ error->all(FLERR,"Cannot use kspace solver on system with no charge");
if (fabs(qsum) > SMALL && comm->me == 0) {
char str[128];
sprintf(str,"System is not charge neutral, net charge = %g",qsum);
- error->warning(str);
+ error->warning(FLERR,str);
}
// setup K-space resolution
if (!gewaldflag) g_ewald = (1.35 - 0.15*log(precision))/cutoff;
gsqmx = -4.0*g_ewald*g_ewald*log(precision);
if (comm->me == 0) {
if (screen) fprintf(screen," G vector = %g\n",g_ewald);
if (logfile) fprintf(logfile," G vector = %g\n",g_ewald);
}
// setup Ewald coefficients so can print stats
setup();
if (comm->me == 0) {
if (screen) fprintf(screen," vectors: actual 1d max = %d %d %d\n",
kcount,kmax,kmax3d);
if (logfile) fprintf(logfile," vectors: actual 1d max = %d %d %d\n",
kcount,kmax,kmax3d);
}
}
/* ----------------------------------------------------------------------
adjust Ewald coeffs, called initially and whenever volume has changed
------------------------------------------------------------------------- */
void Ewald::setup()
{
// volume-dependent factors
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
// adjustment of z dimension for 2d slab Ewald
// 3d Ewald just uses zprd since slab_volfactor = 1.0
double zprd_slab = zprd*slab_volfactor;
volume = xprd * yprd * zprd_slab;
unitk[0] = 2.0*PI/xprd;
unitk[1] = 2.0*PI/yprd;
unitk[2] = 2.0*PI/zprd_slab;
// determine kmax
// function of current box size, precision, G_ewald (short-range cutoff)
int nkxmx = static_cast<int> ((g_ewald*xprd/PI) * sqrt(-log(precision)));
int nkymx = static_cast<int> ((g_ewald*yprd/PI) * sqrt(-log(precision)));
int nkzmx =
static_cast<int> ((g_ewald*zprd_slab/PI) * sqrt(-log(precision)));
int kmax_old = kmax;
kmax = MAX(nkxmx,nkymx);
kmax = MAX(kmax,nkzmx);
kmax3d = 4*kmax*kmax*kmax + 6*kmax*kmax + 3*kmax;
// if size has grown, reallocate k-dependent and nlocal-dependent arrays
if (kmax > kmax_old) {
deallocate();
allocate();
memory->destroy(ek);
memory->destroy3d_offset(cs,-kmax_created);
memory->destroy3d_offset(sn,-kmax_created);
nmax = atom->nmax;
memory->create(ek,nmax,3,"ewald:ek");
memory->create3d_offset(cs,-kmax,kmax,3,nmax,"ewald:cs");
memory->create3d_offset(sn,-kmax,kmax,3,nmax,"ewald:sn");
kmax_created = kmax;
}
// pre-compute Ewald coefficients
coeffs();
}
/* ----------------------------------------------------------------------
compute the Ewald long-range force, energy, virial
------------------------------------------------------------------------- */
void Ewald::compute(int eflag, int vflag)
{
int i,k,n;
energy = 0.0;
if (vflag) for (n = 0; n < 6; n++) virial[n] = 0.0;
// extend size of per-atom arrays if necessary
if (atom->nlocal > nmax) {
memory->destroy(ek);
memory->destroy3d_offset(cs,-kmax_created);
memory->destroy3d_offset(sn,-kmax_created);
nmax = atom->nmax;
memory->create(ek,nmax,3,"ewald:ek");
memory->create3d_offset(cs,-kmax,kmax,3,nmax,"ewald:cs");
memory->create3d_offset(sn,-kmax,kmax,3,nmax,"ewald:sn");
kmax_created = kmax;
}
// partial structure factors on each processor
// total structure factor by summing over procs
eik_dot_r();
MPI_Allreduce(sfacrl,sfacrl_all,kcount,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(sfacim,sfacim_all,kcount,MPI_DOUBLE,MPI_SUM,world);
// K-space portion of electric field
// double loop over K-vectors and local atoms
double **f = atom->f;
double *q = atom->q;
int nlocal = atom->nlocal;
int kx,ky,kz;
double cypz,sypz,exprl,expim,partial;
for (i = 0; i < nlocal; i++) {
ek[i][0] = 0.0;
ek[i][1] = 0.0;
ek[i][2] = 0.0;
}
for (k = 0; k < kcount; k++) {
kx = kxvecs[k];
ky = kyvecs[k];
kz = kzvecs[k];
for (i = 0; i < nlocal; i++) {
cypz = cs[ky][1][i]*cs[kz][2][i] - sn[ky][1][i]*sn[kz][2][i];
sypz = sn[ky][1][i]*cs[kz][2][i] + cs[ky][1][i]*sn[kz][2][i];
exprl = cs[kx][0][i]*cypz - sn[kx][0][i]*sypz;
expim = sn[kx][0][i]*cypz + cs[kx][0][i]*sypz;
partial = expim*sfacrl_all[k] - exprl*sfacim_all[k];
ek[i][0] += partial*eg[k][0];
ek[i][1] += partial*eg[k][1];
ek[i][2] += partial*eg[k][2];
}
}
// convert E-field to force
for (i = 0; i < nlocal; i++) {
f[i][0] += qqrd2e*scale * q[i]*ek[i][0];
f[i][1] += qqrd2e*scale * q[i]*ek[i][1];
f[i][2] += qqrd2e*scale * q[i]*ek[i][2];
}
// energy if requested
if (eflag) {
for (k = 0; k < kcount; k++)
energy += ug[k] * (sfacrl_all[k]*sfacrl_all[k] +
sfacim_all[k]*sfacim_all[k]);
PI = 4.0*atan(1.0);
energy -= g_ewald*qsqsum/1.772453851 +
0.5*PI*qsum*qsum / (g_ewald*g_ewald*volume);
energy *= qqrd2e*scale;
}
// virial if requested
if (vflag) {
double uk;
for (k = 0; k < kcount; k++) {
uk = ug[k] * (sfacrl_all[k]*sfacrl_all[k] + sfacim_all[k]*sfacim_all[k]);
for (n = 0; n < 6; n++) virial[n] += uk*vg[k][n];
}
for (n = 0; n < 6; n++) virial[n] *= qqrd2e*scale;
}
if (slabflag) slabcorr(eflag);
}
/* ---------------------------------------------------------------------- */
void Ewald::eik_dot_r()
{
int i,k,l,m,n,ic;
double cstr1,sstr1,cstr2,sstr2,cstr3,sstr3,cstr4,sstr4;
double sqk,clpm,slpm;
double **x = atom->x;
double *q = atom->q;
int nlocal = atom->nlocal;
n = 0;
// (k,0,0), (0,l,0), (0,0,m)
for (ic = 0; ic < 3; ic++) {
sqk = unitk[ic]*unitk[ic];
if (sqk <= gsqmx) {
cstr1 = 0.0;
sstr1 = 0.0;
for (i = 0; i < nlocal; i++) {
cs[0][ic][i] = 1.0;
sn[0][ic][i] = 0.0;
cs[1][ic][i] = cos(unitk[ic]*x[i][ic]);
sn[1][ic][i] = sin(unitk[ic]*x[i][ic]);
cs[-1][ic][i] = cs[1][ic][i];
sn[-1][ic][i] = -sn[1][ic][i];
cstr1 += q[i]*cs[1][ic][i];
sstr1 += q[i]*sn[1][ic][i];
}
sfacrl[n] = cstr1;
sfacim[n++] = sstr1;
}
}
for (m = 2; m <= kmax; m++) {
for (ic = 0; ic < 3; ic++) {
sqk = m*unitk[ic] * m*unitk[ic];
if (sqk <= gsqmx) {
cstr1 = 0.0;
sstr1 = 0.0;
for (i = 0; i < nlocal; i++) {
cs[m][ic][i] = cs[m-1][ic][i]*cs[1][ic][i] -
sn[m-1][ic][i]*sn[1][ic][i];
sn[m][ic][i] = sn[m-1][ic][i]*cs[1][ic][i] +
cs[m-1][ic][i]*sn[1][ic][i];
cs[-m][ic][i] = cs[m][ic][i];
sn[-m][ic][i] = -sn[m][ic][i];
cstr1 += q[i]*cs[m][ic][i];
sstr1 += q[i]*sn[m][ic][i];
}
sfacrl[n] = cstr1;
sfacim[n++] = sstr1;
}
}
}
// 1 = (k,l,0), 2 = (k,-l,0)
for (k = 1; k <= kmax; k++) {
for (l = 1; l <= kmax; l++) {
sqk = (k*unitk[0] * k*unitk[0]) + (l*unitk[1] * l*unitk[1]);
if (sqk <= gsqmx) {
cstr1 = 0.0;
sstr1 = 0.0;
cstr2 = 0.0;
sstr2 = 0.0;
for (i = 0; i < nlocal; i++) {
cstr1 += q[i]*(cs[k][0][i]*cs[l][1][i] - sn[k][0][i]*sn[l][1][i]);
sstr1 += q[i]*(sn[k][0][i]*cs[l][1][i] + cs[k][0][i]*sn[l][1][i]);
cstr2 += q[i]*(cs[k][0][i]*cs[l][1][i] + sn[k][0][i]*sn[l][1][i]);
sstr2 += q[i]*(sn[k][0][i]*cs[l][1][i] - cs[k][0][i]*sn[l][1][i]);
}
sfacrl[n] = cstr1;
sfacim[n++] = sstr1;
sfacrl[n] = cstr2;
sfacim[n++] = sstr2;
}
}
}
// 1 = (0,l,m), 2 = (0,l,-m)
for (l = 1; l <= kmax; l++) {
for (m = 1; m <= kmax; m++) {
sqk = (l*unitk[1] * l*unitk[1]) + (m*unitk[2] * m*unitk[2]);
if (sqk <= gsqmx) {
cstr1 = 0.0;
sstr1 = 0.0;
cstr2 = 0.0;
sstr2 = 0.0;
for (i = 0; i < nlocal; i++) {
cstr1 += q[i]*(cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i]);
sstr1 += q[i]*(sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i]);
cstr2 += q[i]*(cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i]);
sstr2 += q[i]*(sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i]);
}
sfacrl[n] = cstr1;
sfacim[n++] = sstr1;
sfacrl[n] = cstr2;
sfacim[n++] = sstr2;
}
}
}
// 1 = (k,0,m), 2 = (k,0,-m)
for (k = 1; k <= kmax; k++) {
for (m = 1; m <= kmax; m++) {
sqk = (k*unitk[0] * k*unitk[0]) + (m*unitk[2] * m*unitk[2]);
if (sqk <= gsqmx) {
cstr1 = 0.0;
sstr1 = 0.0;
cstr2 = 0.0;
sstr2 = 0.0;
for (i = 0; i < nlocal; i++) {
cstr1 += q[i]*(cs[k][0][i]*cs[m][2][i] - sn[k][0][i]*sn[m][2][i]);
sstr1 += q[i]*(sn[k][0][i]*cs[m][2][i] + cs[k][0][i]*sn[m][2][i]);
cstr2 += q[i]*(cs[k][0][i]*cs[m][2][i] + sn[k][0][i]*sn[m][2][i]);
sstr2 += q[i]*(sn[k][0][i]*cs[m][2][i] - cs[k][0][i]*sn[m][2][i]);
}
sfacrl[n] = cstr1;
sfacim[n++] = sstr1;
sfacrl[n] = cstr2;
sfacim[n++] = sstr2;
}
}
}
// 1 = (k,l,m), 2 = (k,-l,m), 3 = (k,l,-m), 4 = (k,-l,-m)
for (k = 1; k <= kmax; k++) {
for (l = 1; l <= kmax; l++) {
for (m = 1; m <= kmax; m++) {
sqk = (k*unitk[0] * k*unitk[0]) + (l*unitk[1] * l*unitk[1]) +
(m*unitk[2] * m*unitk[2]);
if (sqk <= gsqmx) {
cstr1 = 0.0;
sstr1 = 0.0;
cstr2 = 0.0;
sstr2 = 0.0;
cstr3 = 0.0;
sstr3 = 0.0;
cstr4 = 0.0;
sstr4 = 0.0;
for (i = 0; i < nlocal; i++) {
clpm = cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i];
slpm = sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i];
cstr1 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
sstr1 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
clpm = cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i];
slpm = -sn[l][1][i]*cs[m][2][i] + cs[l][1][i]*sn[m][2][i];
cstr2 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
sstr2 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
clpm = cs[l][1][i]*cs[m][2][i] + sn[l][1][i]*sn[m][2][i];
slpm = sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i];
cstr3 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
sstr3 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
clpm = cs[l][1][i]*cs[m][2][i] - sn[l][1][i]*sn[m][2][i];
slpm = -sn[l][1][i]*cs[m][2][i] - cs[l][1][i]*sn[m][2][i];
cstr4 += q[i]*(cs[k][0][i]*clpm - sn[k][0][i]*slpm);
sstr4 += q[i]*(sn[k][0][i]*clpm + cs[k][0][i]*slpm);
}
sfacrl[n] = cstr1;
sfacim[n++] = sstr1;
sfacrl[n] = cstr2;
sfacim[n++] = sstr2;
sfacrl[n] = cstr3;
sfacim[n++] = sstr3;
sfacrl[n] = cstr4;
sfacim[n++] = sstr4;
}
}
}
}
}
/* ----------------------------------------------------------------------
pre-compute coefficients for each Ewald K-vector
------------------------------------------------------------------------- */
void Ewald::coeffs()
{
int k,l,m;
double sqk,vterm;
double unitkx = unitk[0];
double unitky = unitk[1];
double unitkz = unitk[2];
double g_ewald_sq_inv = 1.0 / (g_ewald*g_ewald);
double preu = 4.0*PI/volume;
kcount = 0;
// (k,0,0), (0,l,0), (0,0,m)
for (m = 1; m <= kmax; m++) {
sqk = (m*unitkx) * (m*unitkx);
if (sqk <= gsqmx) {
kxvecs[kcount] = m;
kyvecs[kcount] = 0;
kzvecs[kcount] = 0;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*m*ug[kcount];
eg[kcount][1] = 0.0;
eg[kcount][2] = 0.0;
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
vg[kcount][0] = 1.0 + vterm*(unitkx*m)*(unitkx*m);
vg[kcount][1] = 1.0;
vg[kcount][2] = 1.0;
vg[kcount][3] = 0.0;
vg[kcount][4] = 0.0;
vg[kcount][5] = 0.0;
kcount++;
}
sqk = (m*unitky) * (m*unitky);
if (sqk <= gsqmx) {
kxvecs[kcount] = 0;
kyvecs[kcount] = m;
kzvecs[kcount] = 0;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 0.0;
eg[kcount][1] = 2.0*unitky*m*ug[kcount];
eg[kcount][2] = 0.0;
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
vg[kcount][0] = 1.0;
vg[kcount][1] = 1.0 + vterm*(unitky*m)*(unitky*m);
vg[kcount][2] = 1.0;
vg[kcount][3] = 0.0;
vg[kcount][4] = 0.0;
vg[kcount][5] = 0.0;
kcount++;
}
sqk = (m*unitkz) * (m*unitkz);
if (sqk <= gsqmx) {
kxvecs[kcount] = 0;
kyvecs[kcount] = 0;
kzvecs[kcount] = m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 0.0;
eg[kcount][1] = 0.0;
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
vg[kcount][0] = 1.0;
vg[kcount][1] = 1.0;
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = 0.0;
vg[kcount][4] = 0.0;
vg[kcount][5] = 0.0;
kcount++;
}
}
// 1 = (k,l,0), 2 = (k,-l,0)
for (k = 1; k <= kmax; k++) {
for (l = 1; l <= kmax; l++) {
sqk = (unitkx*k) * (unitkx*k) + (unitky*l) * (unitky*l);
if (sqk <= gsqmx) {
kxvecs[kcount] = k;
kyvecs[kcount] = l;
kzvecs[kcount] = 0;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
eg[kcount][2] = 0.0;
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0;
vg[kcount][3] = vterm*unitkx*k*unitky*l;
vg[kcount][4] = 0.0;
vg[kcount][5] = 0.0;
kcount++;
kxvecs[kcount] = k;
kyvecs[kcount] = -l;
kzvecs[kcount] = 0;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = -2.0*unitky*l*ug[kcount];
eg[kcount][2] = 0.0;
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0;
vg[kcount][3] = -vterm*unitkx*k*unitky*l;
vg[kcount][4] = 0.0;
vg[kcount][5] = 0.0;
kcount++;;
}
}
}
// 1 = (0,l,m), 2 = (0,l,-m)
for (l = 1; l <= kmax; l++) {
for (m = 1; m <= kmax; m++) {
sqk = (unitky*l) * (unitky*l) + (unitkz*m) * (unitkz*m);
if (sqk <= gsqmx) {
kxvecs[kcount] = 0;
kyvecs[kcount] = l;
kzvecs[kcount] = m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 0.0;
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
vg[kcount][0] = 1.0;
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = 0.0;
vg[kcount][4] = 0.0;
vg[kcount][5] = vterm*unitky*l*unitkz*m;
kcount++;
kxvecs[kcount] = 0;
kyvecs[kcount] = l;
kzvecs[kcount] = -m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 0.0;
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
vg[kcount][0] = 1.0;
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = 0.0;
vg[kcount][4] = 0.0;
vg[kcount][5] = -vterm*unitky*l*unitkz*m;
kcount++;
}
}
}
// 1 = (k,0,m), 2 = (k,0,-m)
for (k = 1; k <= kmax; k++) {
for (m = 1; m <= kmax; m++) {
sqk = (unitkx*k) * (unitkx*k) + (unitkz*m) * (unitkz*m);
if (sqk <= gsqmx) {
kxvecs[kcount] = k;
kyvecs[kcount] = 0;
kzvecs[kcount] = m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = 0.0;
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0;
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = 0.0;
vg[kcount][4] = vterm*unitkx*k*unitkz*m;
vg[kcount][5] = 0.0;
kcount++;
kxvecs[kcount] = k;
kyvecs[kcount] = 0;
kzvecs[kcount] = -m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = 0.0;
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0;
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = 0.0;
vg[kcount][4] = -vterm*unitkx*k*unitkz*m;
vg[kcount][5] = 0.0;
kcount++;
}
}
}
// 1 = (k,l,m), 2 = (k,-l,m), 3 = (k,l,-m), 4 = (k,-l,-m)
for (k = 1; k <= kmax; k++) {
for (l = 1; l <= kmax; l++) {
for (m = 1; m <= kmax; m++) {
sqk = (unitkx*k) * (unitkx*k) + (unitky*l) * (unitky*l) +
(unitkz*m) * (unitkz*m);
if (sqk <= gsqmx) {
kxvecs[kcount] = k;
kyvecs[kcount] = l;
kzvecs[kcount] = m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
vterm = -2.0*(1.0/sqk + 0.25*g_ewald_sq_inv);
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = vterm*unitkx*k*unitky*l;
vg[kcount][4] = vterm*unitkx*k*unitkz*m;
vg[kcount][5] = vterm*unitky*l*unitkz*m;
kcount++;
kxvecs[kcount] = k;
kyvecs[kcount] = -l;
kzvecs[kcount] = m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = -2.0*unitky*l*ug[kcount];
eg[kcount][2] = 2.0*unitkz*m*ug[kcount];
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = -vterm*unitkx*k*unitky*l;
vg[kcount][4] = vterm*unitkx*k*unitkz*m;
vg[kcount][5] = -vterm*unitky*l*unitkz*m;
kcount++;
kxvecs[kcount] = k;
kyvecs[kcount] = l;
kzvecs[kcount] = -m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = 2.0*unitky*l*ug[kcount];
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = vterm*unitkx*k*unitky*l;
vg[kcount][4] = -vterm*unitkx*k*unitkz*m;
vg[kcount][5] = -vterm*unitky*l*unitkz*m;
kcount++;
kxvecs[kcount] = k;
kyvecs[kcount] = -l;
kzvecs[kcount] = -m;
ug[kcount] = preu*exp(-0.25*sqk*g_ewald_sq_inv)/sqk;
eg[kcount][0] = 2.0*unitkx*k*ug[kcount];
eg[kcount][1] = -2.0*unitky*l*ug[kcount];
eg[kcount][2] = -2.0*unitkz*m*ug[kcount];
vg[kcount][0] = 1.0 + vterm*(unitkx*k)*(unitkx*k);
vg[kcount][1] = 1.0 + vterm*(unitky*l)*(unitky*l);
vg[kcount][2] = 1.0 + vterm*(unitkz*m)*(unitkz*m);
vg[kcount][3] = -vterm*unitkx*k*unitky*l;
vg[kcount][4] = -vterm*unitkx*k*unitkz*m;
vg[kcount][5] = vterm*unitky*l*unitkz*m;
kcount++;;
}
}
}
}
}
/* ----------------------------------------------------------------------
allocate memory that depends on # of K-vectors
------------------------------------------------------------------------- */
void Ewald::allocate()
{
kxvecs = new int[kmax3d];
kyvecs = new int[kmax3d];
kzvecs = new int[kmax3d];
ug = new double[kmax3d];
memory->create(eg,kmax3d,3,"ewald:eg");
memory->create(vg,kmax3d,6,"ewald:vg");
sfacrl = new double[kmax3d];
sfacim = new double[kmax3d];
sfacrl_all = new double[kmax3d];
sfacim_all = new double[kmax3d];
}
/* ----------------------------------------------------------------------
deallocate memory that depends on # of K-vectors
------------------------------------------------------------------------- */
void Ewald::deallocate()
{
delete [] kxvecs;
delete [] kyvecs;
delete [] kzvecs;
delete [] ug;
memory->destroy(eg);
memory->destroy(vg);
delete [] sfacrl;
delete [] sfacim;
delete [] sfacrl_all;
delete [] sfacim_all;
}
/* ----------------------------------------------------------------------
Slab-geometry correction term to dampen inter-slab interactions between
periodically repeating slabs. Yields good approximation to 2-D Ewald if
adequate empty space is left between repeating slabs (J. Chem. Phys.
111, 3155). Slabs defined here to be parallel to the xy plane.
------------------------------------------------------------------------- */
void Ewald::slabcorr(int eflag)
{
// compute local contribution to global dipole moment
double *q = atom->q;
double **x = atom->x;
int nlocal = atom->nlocal;
double dipole = 0.0;
for (int i = 0; i < nlocal; i++) dipole += q[i]*x[i][2];
// sum local contributions to get global dipole moment
double dipole_all;
MPI_Allreduce(&dipole,&dipole_all,1,MPI_DOUBLE,MPI_SUM,world);
// compute corrections
double e_slabcorr = 2.0*PI*dipole_all*dipole_all/volume;
if (eflag) energy += qqrd2e*scale * e_slabcorr;
// add on force corrections
double ffact = -4.0*PI*dipole_all/volume;
double **f = atom->f;
for (int i = 0; i < nlocal; i++) f[i][2] += qqrd2e*scale * q[i]*ffact;
}
/* ----------------------------------------------------------------------
memory usage of local arrays
------------------------------------------------------------------------- */
double Ewald::memory_usage()
{
double bytes = 3 * kmax3d * sizeof(int);
bytes += (1 + 3 + 6) * kmax3d * sizeof(double);
bytes += 4 * kmax3d * sizeof(double);
bytes += nmax*3 * sizeof(double);
bytes += 2 * (2*kmax+1)*3*nmax * sizeof(double);
return bytes;
}
diff --git a/src/KSPACE/fft3d_wrap.cpp b/src/KSPACE/fft3d_wrap.cpp
index fa0d232a1..ef1298de4 100644
--- a/src/KSPACE/fft3d_wrap.cpp
+++ b/src/KSPACE/fft3d_wrap.cpp
@@ -1,55 +1,55 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "fft3d_wrap.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FFT3d::FFT3d(LAMMPS *lmp, MPI_Comm comm, int nfast, int nmid, int nslow,
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
int in_klo, int in_khi,
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
int out_klo, int out_khi,
int scaled, int permute, int *nbuf) : Pointers(lmp)
{
plan = fft_3d_create_plan(comm,nfast,nmid,nslow,
in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
out_ilo,out_ihi,out_jlo,out_jhi,out_klo,out_khi,
scaled,permute,nbuf);
- if (plan == NULL) error->one("Could not create 3d FFT plan");
+ if (plan == NULL) error->one(FLERR,"Could not create 3d FFT plan");
}
/* ---------------------------------------------------------------------- */
FFT3d::~FFT3d()
{
fft_3d_destroy_plan(plan);
}
/* ---------------------------------------------------------------------- */
void FFT3d::compute(FFT_SCALAR *in, FFT_SCALAR *out, int flag)
{
fft_3d((FFT_DATA *) in,(FFT_DATA *) out,flag,plan);
}
/* ---------------------------------------------------------------------- */
void FFT3d::timing1d(FFT_SCALAR *in, int nsize, int flag)
{
fft_1d_only((FFT_DATA *) in,nsize,flag,plan);
}
diff --git a/src/KSPACE/pair_born_coul_long.cpp b/src/KSPACE/pair_born_coul_long.cpp
index 05f075cc1..dca8532d3 100644
--- a/src/KSPACE/pair_born_coul_long.cpp
+++ b/src/KSPACE/pair_born_coul_long.cpp
@@ -1,499 +1,496 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Ahmed Ismail (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_born_coul_long.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairBornCoulLong::PairBornCoulLong(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairBornCoulLong::~PairBornCoulLong()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(a);
memory->destroy(rho);
memory->destroy(sigma);
memory->destroy(c);
memory->destroy(d);
memory->destroy(rhoinv);
memory->destroy(born1);
memory->destroy(born2);
memory->destroy(born3);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairBornCoulLong::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forceborn,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
double r,rexp;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r = sqrt(rsq);
if (rsq < cut_coulsq) {
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
rexp = exp((sigma[itype][jtype]-r)*rhoinv[itype][jtype]);
forceborn = born1[itype][jtype]*r*rexp - born2[itype][jtype]*r6inv
+ born3[itype][jtype]*r2inv*r6inv;
} else forceborn = 0.0;
fpair = (forcecoul + factor_lj*forceborn) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
ecoul = prefactor*erfc;
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = a[itype][jtype]*rexp - c[itype][jtype]*r6inv
+ d[itype][jtype]*r6inv*r2inv - offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairBornCoulLong::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(a,n+1,n+1,"pair:a");
memory->create(rho,n+1,n+1,"pair:rho");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(c,n+1,n+1,"pair:c");
memory->create(d,n+1,n+1,"pair:d");
memory->create(rhoinv,n+1,n+1,"pair:rhoinv");
memory->create(born1,n+1,n+1,"pair:born1");
memory->create(born2,n+1,n+1,"pair:born2");
memory->create(born3,n+1,n+1,"pair:born3");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairBornCoulLong::settings(int narg, char **arg)
{
- if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul = cut_lj_global;
else cut_coul = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairBornCoulLong::coeff(int narg, char **arg)
{
- if (narg < 7 || narg > 8) error->all("Incorrect args for pair coefficients");
+ if (narg < 7 || narg > 8) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a_one = force->numeric(arg[2]);
double rho_one = force->numeric(arg[3]);
double sigma_one = force->numeric(arg[4]);
- if (rho_one <= 0) error->all("Incorrect args for pair coefficients");
+ if (rho_one <= 0) error->all(FLERR,"Incorrect args for pair coefficients");
double c_one = force->numeric(arg[5]);
double d_one = force->numeric(arg[6]);
double cut_lj_one = cut_lj_global;
if (narg == 8) cut_lj_one = force->numeric(arg[7]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a[i][j] = a_one;
rho[i][j] = rho_one;
sigma[i][j] = sigma_one;
c[i][j] = c_one;
d[i][j] = d_one;
cut_lj[i][j] = cut_lj_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairBornCoulLong::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
double cut = MAX(cut_lj[i][j],cut_coul);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
rhoinv[i][j] = 1.0/rho[i][j];
born1[i][j] = a[i][j]/rho[i][j];
born2[i][j] = 6.0*c[i][j];
born3[i][j] = 8.0*d[i][j];
if (offset_flag) {
double rexp = exp(-cut_lj[i][j]*rhoinv[i][j]);
offset[i][j] = a[i][j]*rexp - c[i][j]/pow(cut_lj[i][j],6.0) +
d[i][j]/pow(cut_lj[i][j],8.0);
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
a[j][i] = a[i][j];
c[j][i] = c[i][j];
d[j][i] = d[i][j];
rhoinv[j][i] = rhoinv[i][j];
sigma[j][i] = sigma[i][j];
born1[j][i] = born1[i][j];
born2[j][i] = born2[i][j];
born3[j][i] = born3[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double rho1 = rho[i][j];
double rho2 = rho1*rho1;
double rho3 = rho2*rho1;
double rc = cut_lj[i][j];
double rc2 = rc*rc;
double rc3 = rc2*rc;
double rc5 = rc3*rc2;
etail_ij = 2.0*PI*all[0]*all[1] *
(a[i][j]*exp((sigma[i][j]-rc)/rho1)*rho1*
(rc2 + 2.0*rho1*rc + 2.0*rho2) -
c[i][j]/(3.0*rc3) + d[i][j]/(5.0*rc5));
ptail_ij = (-1/3.0)*2.0*PI*all[0]*all[1] *
(-a[i][j]*exp((sigma[i][j]-rc)/rho1) *
(rc3 + 3.0*rho1*rc2 + 6.0*rho2*rc + 6.0*rho3) +
2.0*c[i][j]/rc3 - 8.0*d[i][j]/(5.0*rc5));
}
return cut;
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairBornCoulLong::init_style()
{
if (!atom->q_flag)
- error->all("Pair style born/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style born/coul/long requires atom attribute q");
cut_coulsq = cut_coul * cut_coul;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
neighbor->request(this);
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBornCoulLong::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a[i][j],sizeof(double),1,fp);
fwrite(&rho[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&c[i][j],sizeof(double),1,fp);
fwrite(&d[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBornCoulLong::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a[i][j],sizeof(double),1,fp);
fread(&rho[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&c[i][j],sizeof(double),1,fp);
fread(&d[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&rho[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&c[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&d[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBornCoulLong::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBornCoulLong::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairBornCoulLong::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,rexp,grij,expm2,t,erfc,prefactor;
double forcecoul,forceborn,phicoul,phiborn;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
rexp = exp((sigma[itype][jtype]-r)*rhoinv[itype][jtype]);
forceborn = born1[itype][jtype]*r*rexp - born2[itype][jtype]*r6inv +
born3[itype][jtype]*r2inv*r6inv;
} else forceborn = 0.0;
fforce = (forcecoul + factor_lj*forceborn) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq) {
phicoul = prefactor*erfc;
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
eng += phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
phiborn = a[itype][jtype]*rexp - c[itype][jtype]*r6inv +
d[itype][jtype]*r2inv*r6inv - offset[itype][jtype];
eng += factor_lj*phiborn;
}
return eng;
}
/* ---------------------------------------------------------------------- */
void *PairBornCoulLong::extract(char *str, int &dim)
{
dim = 0;
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul;
return NULL;
}
diff --git a/src/KSPACE/pair_buck_coul_long.cpp b/src/KSPACE/pair_buck_coul_long.cpp
index 43e9f098a..813b3b025 100644
--- a/src/KSPACE/pair_buck_coul_long.cpp
+++ b/src/KSPACE/pair_buck_coul_long.cpp
@@ -1,469 +1,466 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_buck_coul_long.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairBuckCoulLong::PairBuckCoulLong(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairBuckCoulLong::~PairBuckCoulLong()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(a);
memory->destroy(rho);
memory->destroy(c);
memory->destroy(rhoinv);
memory->destroy(buck1);
memory->destroy(buck2);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulLong::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forcebuck,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
double r,rexp;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r = sqrt(rsq);
if (rsq < cut_coulsq) {
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
rexp = exp(-r*rhoinv[itype][jtype]);
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
} else forcebuck = 0.0;
fpair = (forcecoul + factor_lj*forcebuck) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
ecoul = prefactor*erfc;
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairBuckCoulLong::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(a,n+1,n+1,"pair:a");
memory->create(rho,n+1,n+1,"pair:rho");
memory->create(c,n+1,n+1,"pair:c");
memory->create(rhoinv,n+1,n+1,"pair:rhoinv");
memory->create(buck1,n+1,n+1,"pair:buck1");
memory->create(buck2,n+1,n+1,"pair:buck2");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairBuckCoulLong::settings(int narg, char **arg)
{
- if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul = cut_lj_global;
else cut_coul = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairBuckCoulLong::coeff(int narg, char **arg)
{
- if (narg < 5 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a_one = force->numeric(arg[2]);
double rho_one = force->numeric(arg[3]);
- if (rho_one <= 0) error->all("Incorrect args for pair coefficients");
+ if (rho_one <= 0) error->all(FLERR,"Incorrect args for pair coefficients");
double c_one = force->numeric(arg[4]);
double cut_lj_one = cut_lj_global;
if (narg == 6) cut_lj_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a[i][j] = a_one;
rho[i][j] = rho_one;
c[i][j] = c_one;
cut_lj[i][j] = cut_lj_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairBuckCoulLong::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
double cut = MAX(cut_lj[i][j],cut_coul);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
rhoinv[i][j] = 1.0/rho[i][j];
buck1[i][j] = a[i][j]/rho[i][j];
buck2[i][j] = 6.0*c[i][j];
if (offset_flag) {
double rexp = exp(-cut_lj[i][j]/rho[i][j]);
offset[i][j] = a[i][j]*rexp - c[i][j]/pow(cut_lj[i][j],6.0);
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
a[j][i] = a[i][j];
c[j][i] = c[i][j];
rhoinv[j][i] = rhoinv[i][j];
buck1[j][i] = buck1[i][j];
buck2[j][i] = buck2[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double rho1 = rho[i][j];
double rho2 = rho1*rho1;
double rho3 = rho2*rho1;
double rc = cut_lj[i][j];
double rc2 = rc*rc;
double rc3 = rc2*rc;
etail_ij = 2.0*PI*all[0]*all[1]*
(a[i][j]*exp(-rc/rho1)*rho1*(rc2 + 2.0*rho1*rc + 2.0*rho2) -
c[i][j]/(3.0*rc3));
ptail_ij = (-1/3.0)*2.0*PI*all[0]*all[1]*
(-a[i][j]*exp(-rc/rho1)*
(rc3 + 3.0*rho1*rc2 + 6.0*rho2*rc + 6.0*rho3) + 2.0*c[i][j]/rc3);
}
return cut;
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairBuckCoulLong::init_style()
{
if (!atom->q_flag)
- error->all("Pair style buck/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style buck/coul/long requires atom attribute q");
cut_coulsq = cut_coul * cut_coul;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
neighbor->request(this);
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuckCoulLong::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a[i][j],sizeof(double),1,fp);
fwrite(&rho[i][j],sizeof(double),1,fp);
fwrite(&c[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuckCoulLong::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a[i][j],sizeof(double),1,fp);
fread(&rho[i][j],sizeof(double),1,fp);
fread(&c[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&rho[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&c[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuckCoulLong::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuckCoulLong::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairBuckCoulLong::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,rexp,grij,expm2,t,erfc,prefactor;
double forcecoul,forcebuck,phicoul,phibuck;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
rexp = exp(-r*rhoinv[itype][jtype]);
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
} else forcebuck = 0.0;
fforce = (forcecoul + factor_lj*forcebuck) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq) {
phicoul = prefactor*erfc;
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
eng += phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
offset[itype][jtype];
eng += factor_lj*phibuck;
}
return eng;
}
/* ---------------------------------------------------------------------- */
void *PairBuckCoulLong::extract(char *str, int &dim)
{
dim = 0;
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul;
return NULL;
}
diff --git a/src/KSPACE/pair_coul_long.cpp b/src/KSPACE/pair_coul_long.cpp
index dee833cb6..6a3f70b35 100644
--- a/src/KSPACE/pair_coul_long.cpp
+++ b/src/KSPACE/pair_coul_long.cpp
@@ -1,573 +1,570 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_coul_long.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairCoulLong::PairCoulLong(LAMMPS *lmp) : Pair(lmp)
{
ftable = NULL;
}
/* ---------------------------------------------------------------------- */
PairCoulLong::~PairCoulLong()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(scale);
}
if (ftable) free_tables();
}
/* ---------------------------------------------------------------------- */
void PairCoulLong::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itable,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,ecoul,fpair;
double fraction,table;
double r,r2inv,forcecoul,factor_coul;
double grij,expm2,prefactor,t,erfc;
int *ilist,*jlist,*numneigh,**firstneigh;
double rsq;
ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cut_coulsq) {
r2inv = 1.0/rsq;
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * scale[itype][jtype] * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = scale[itype][jtype] * qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = scale[itype][jtype] * qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
fpair = forcecoul * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = scale[itype][jtype] * qtmp*q[j] * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
0.0,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairCoulLong::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(scale,n+1,n+1,"pair:scale");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairCoulLong::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_coul = force->numeric(arg[0]);
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairCoulLong::coeff(int narg, char **arg)
{
- if (narg != 2) error->all("Incorrect args for pair coefficients");
+ if (narg != 2) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
scale[i][j] = 1.0;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairCoulLong::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/long requires atom attribute q");
neighbor->request(this);
cut_coulsq = cut_coul * cut_coul;
// set & error check interior rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0) {
cut_respa = ((Respa *) update->integrate)->cutoff;
if (cut_coul < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
} else cut_respa = NULL;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairCoulLong::init_one(int i, int j)
{
scale[j][i] = scale[i][j];
return cut_coul;
}
/* ----------------------------------------------------------------------
setup force tables used in compute routines
------------------------------------------------------------------------- */
void PairCoulLong::init_tables()
{
int masklo,maskhi;
double r,grij,expm2,derfc,rsw;
double qqrd2e = force->qqrd2e;
tabinnersq = tabinner*tabinner;
init_bitmap(tabinner,cut_coul,ncoultablebits,
masklo,maskhi,ncoulmask,ncoulshiftbits);
int ntable = 1;
for (int i = 0; i < ncoultablebits; i++) ntable *= 2;
// linear lookup tables of length N = 2^ncoultablebits
// stored value = value at lower edge of bin
// d values = delta from lower edge to upper edge of bin
if (ftable) free_tables();
memory->create(rtable,ntable,"pair:rtable");
memory->create(ftable,ntable,"pair:ftable");
memory->create(ctable,ntable,"pair:ctable");
memory->create(etable,ntable,"pair:etable");
memory->create(drtable,ntable,"pair:drtable");
memory->create(dftable,ntable,"pair:dftable");
memory->create(dctable,ntable,"pair:dctable");
memory->create(detable,ntable,"pair:detable");
if (cut_respa == NULL) {
vtable = ptable = dvtable = dptable = NULL;
} else {
memory->create(vtable,ntable,"pair:vtable");
memory->create(ptable,ntable,"pair:ptable");
memory->create(dvtable,ntable,"pair:dvtable");
memory->create(dptable,ntable,"pair:dptable");
}
union_int_float_t rsq_lookup;
union_int_float_t minrsq_lookup;
int itablemin;
minrsq_lookup.i = 0 << ncoulshiftbits;
minrsq_lookup.i |= maskhi;
for (int i = 0; i < ntable; i++) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tabinnersq) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= maskhi;
}
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
etable[i] = qqrd2e/r * derfc;
} else {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
ctable[i] = 0.0;
etable[i] = qqrd2e/r * derfc;
ptable[i] = qqrd2e/r;
vtable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
ftable[i] += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
ctable[i] = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
}
}
}
minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f);
}
tabinnersq = minrsq_lookup.f;
int ntablem1 = ntable - 1;
for (int i = 0; i < ntablem1; i++) {
drtable[i] = 1.0/(rtable[i+1] - rtable[i]);
dftable[i] = ftable[i+1] - ftable[i];
dctable[i] = ctable[i+1] - ctable[i];
detable[i] = etable[i+1] - etable[i];
}
if (cut_respa) {
for (int i = 0; i < ntablem1; i++) {
dvtable[i] = vtable[i+1] - vtable[i];
dptable[i] = ptable[i+1] - ptable[i];
}
}
// get the delta values for the last table entries
// tables are connected periodically between 0 and ntablem1
drtable[ntablem1] = 1.0/(rtable[0] - rtable[ntablem1]);
dftable[ntablem1] = ftable[0] - ftable[ntablem1];
dctable[ntablem1] = ctable[0] - ctable[ntablem1];
detable[ntablem1] = etable[0] - etable[ntablem1];
if (cut_respa) {
dvtable[ntablem1] = vtable[0] - vtable[ntablem1];
dptable[ntablem1] = ptable[0] - ptable[ntablem1];
}
// get the correct delta values at itablemax
// smallest r is in bin itablemin
// largest r is in bin itablemax, which is itablemin-1,
// or ntablem1 if itablemin=0
// deltas at itablemax only needed if corresponding rsq < cut*cut
// if so, compute deltas between rsq and cut*cut
double f_tmp,c_tmp,e_tmp,p_tmp,v_tmp;
itablemin = minrsq_lookup.i & ncoulmask;
itablemin >>= ncoulshiftbits;
int itablemax = itablemin - 1;
if (itablemin == 0) itablemax = ntablem1;
rsq_lookup.i = itablemax << ncoulshiftbits;
rsq_lookup.i |= maskhi;
if (rsq_lookup.f < cut_coulsq) {
rsq_lookup.f = cut_coulsq;
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
e_tmp = qqrd2e/r * derfc;
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
c_tmp = 0.0;
e_tmp = qqrd2e/r * derfc;
p_tmp = qqrd2e/r;
v_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
f_tmp += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
c_tmp = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
}
}
}
drtable[itablemax] = 1.0/(rsq_lookup.f - rtable[itablemax]);
dftable[itablemax] = f_tmp - ftable[itablemax];
dctable[itablemax] = c_tmp - ctable[itablemax];
detable[itablemax] = e_tmp - etable[itablemax];
if (cut_respa) {
dvtable[itablemax] = v_tmp - vtable[itablemax];
dptable[itablemax] = p_tmp - ptable[itablemax];
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairCoulLong::write_restart(FILE *fp)
{
write_restart_settings(fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairCoulLong::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairCoulLong::write_restart_settings(FILE *fp)
{
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairCoulLong::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
free memory for tables used in pair computations
------------------------------------------------------------------------- */
void PairCoulLong::free_tables()
{
memory->destroy(rtable);
memory->destroy(drtable);
memory->destroy(ftable);
memory->destroy(dftable);
memory->destroy(ctable);
memory->destroy(dctable);
memory->destroy(etable);
memory->destroy(detable);
memory->destroy(vtable);
memory->destroy(dvtable);
memory->destroy(ptable);
memory->destroy(dptable);
}
/* ---------------------------------------------------------------------- */
double PairCoulLong::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r,grij,expm2,t,erfc,prefactor;
double fraction,table,forcecoul,phicoul;
int itable;
r2inv = 1.0/rsq;
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = atom->q[i]*atom->q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = atom->q[i]*atom->q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
fforce = forcecoul * r2inv;
if (!ncoultablebits || rsq <= tabinnersq)
phicoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
phicoul = atom->q[i]*atom->q[j] * table;
}
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
return phicoul;
}
/* ---------------------------------------------------------------------- */
void *PairCoulLong::extract(char *str, int &dim)
{
if (strcmp(str,"cut_coul") == 0) {
dim = 0;
return (void *) &cut_coul;
}
if (strcmp(str,"scale") == 0) {
dim = 2;
return (void *) scale;
}
return NULL;
}
diff --git a/src/KSPACE/pair_lj_charmm_coul_long.cpp b/src/KSPACE/pair_lj_charmm_coul_long.cpp
index 539cf34f7..1ff61a5ec 100644
--- a/src/KSPACE/pair_lj_charmm_coul_long.cpp
+++ b/src/KSPACE/pair_lj_charmm_coul_long.cpp
@@ -1,1200 +1,1197 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_charmm_coul_long.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{GEOMETRIC,ARITHMETIC,SIXTHPOWER}; // same as in pair.cpp
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulLong::PairLJCharmmCoulLong(LAMMPS *lmp) : Pair(lmp)
{
respa_enable = 1;
ftable = NULL;
implicit = 0;
mix_flag = ARITHMETIC;
}
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulLong::~PairLJCharmmCoulLong()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(eps14);
memory->destroy(sigma14);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(lj14_1);
memory->destroy(lj14_2);
memory->destroy(lj14_3);
memory->destroy(lj14_4);
}
if (ftable) free_tables();
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLong::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
double philj,switch1,switch2;
int *ilist,*jlist,*numneigh,**firstneigh;
double rsq;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_bothsq) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
evdwl *= switch1;
}
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLong::compute_inner()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = listinner->inum;
ilist = listinner->ilist;
numneigh = listinner->numneigh;
firstneigh = listinner->firstneigh;
double cut_out_on = cut_respa[0];
double cut_out_off = cut_respa[1];
double cut_out_diff = cut_out_off - cut_out_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq) {
r2inv = 1.0/rsq;
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul;
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLong::compute_middle()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double philj,switch1,switch2;
double rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = listmiddle->inum;
ilist = listmiddle->ilist;
numneigh = listmiddle->numneigh;
firstneigh = listmiddle->firstneigh;
double cut_in_off = cut_respa[0];
double cut_in_on = cut_respa[1];
double cut_out_on = cut_respa[2];
double cut_out_off = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_out_diff = cut_out_off - cut_out_on;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) {
r2inv = 1.0/rsq;
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul;
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLong::compute_outer(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
double philj,switch1,switch2;
double rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double rsq;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = listouter->inum;
ilist = listouter->ilist;
numneigh = listouter->numneigh;
firstneigh = listouter->firstneigh;
double cut_in_off = cut_respa[2];
double cut_in_on = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cut_bothsq) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2 - 1.0);
if (rsq > cut_in_off_sq) {
if (rsq < cut_in_on_sq) {
rsw = (r - cut_in_off)/cut_in_diff;
forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw);
if (factor_coul < 1.0)
forcecoul -=
(1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw);
} else {
forcecoul += prefactor;
if (factor_coul < 1.0)
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq && rsq > cut_in_off_sq) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
forcelj *= rsw*rsw*(3.0 - 2.0*rsw);
}
} else forcelj = 0.0;
fpair = (forcecoul + forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
ecoul = prefactor*erfc;
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ptable[itable] + fraction*dptable[itable];
prefactor = qtmp*q[j] * table;
ecoul -= (1.0-factor_coul)*prefactor;
}
}
} else ecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
evdwl *= switch1;
}
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (vflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
table = vtable[itable] + fraction*dvtable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ptable[itable] + fraction*dptable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq <= cut_in_off_sq) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
} else if (rsq <= cut_in_on_sq) {
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
}
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(eps14,n+1,n+1,"pair:eps14");
memory->create(sigma14,n+1,n+1,"pair:sigma14");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(lj14_1,n+1,n+1,"pair:lj14_1");
memory->create(lj14_2,n+1,n+1,"pair:lj14_2");
memory->create(lj14_3,n+1,n+1,"pair:lj14_3");
memory->create(lj14_4,n+1,n+1,"pair:lj14_4");
}
/* ----------------------------------------------------------------------
global settings
unlike other pair styles,
there are no individual pair settings that these override
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::settings(int narg, char **arg)
{
- if (narg != 2 && narg != 3) error->all("Illegal pair_style command");
+ if (narg != 2 && narg != 3) error->all(FLERR,"Illegal pair_style command");
cut_lj_inner = force->numeric(arg[0]);
cut_lj = force->numeric(arg[1]);
if (narg == 2) cut_coul = cut_lj;
else cut_coul = force->numeric(arg[2]);
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::coeff(int narg, char **arg)
{
- if (narg != 4 && narg != 6) error->all("Illegal pair_coeff command");
+ if (narg != 4 && narg != 6) error->all(FLERR,"Illegal pair_coeff command");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double eps14_one = epsilon_one;
double sigma14_one = sigma_one;
if (narg == 6) {
eps14_one = force->numeric(arg[4]);
sigma14_one = force->numeric(arg[5]);
}
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
eps14[i][j] = eps14_one;
sigma14[i][j] = sigma14_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/charmm/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/charmm/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
} else irequest = neighbor->request(this);
// require cut_lj_inner < cut_lj
if (cut_lj_inner >= cut_lj)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) *
(cut_ljsq-cut_lj_innersq);
// set & error check interior rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0) {
cut_respa = ((Respa *) update->integrate)->cutoff;
if (MIN(cut_lj,cut_coul) < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
if (cut_lj_inner < cut_respa[1])
- error->all("Pair inner cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair inner cutoff < Respa interior cutoff");
} else cut_respa = NULL;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
regular or rRESPA
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listinner = ptr;
else if (id == 2) listmiddle = ptr;
else if (id == 3) listouter = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJCharmmCoulLong::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
eps14[i][j] = mix_energy(eps14[i][i],eps14[j][j],
sigma14[i][i],sigma14[j][j]);
sigma14[i][j] = mix_distance(sigma14[i][i],sigma14[j][j]);
}
double cut = MAX(cut_lj,cut_coul);
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj14_1[i][j] = 48.0 * eps14[i][j] * pow(sigma14[i][j],12.0);
lj14_2[i][j] = 24.0 * eps14[i][j] * pow(sigma14[i][j],6.0);
lj14_3[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],12.0);
lj14_4[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],6.0);
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
lj14_1[j][i] = lj14_1[i][j];
lj14_2[j][i] = lj14_2[i][j];
lj14_3[j][i] = lj14_3[i][j];
lj14_4[j][i] = lj14_4[i][j];
return cut;
}
/* ----------------------------------------------------------------------
setup force tables used in compute routines
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::init_tables()
{
int masklo,maskhi;
double r,grij,expm2,derfc,rsw;
double qqrd2e = force->qqrd2e;
tabinnersq = tabinner*tabinner;
init_bitmap(tabinner,cut_coul,ncoultablebits,
masklo,maskhi,ncoulmask,ncoulshiftbits);
int ntable = 1;
for (int i = 0; i < ncoultablebits; i++) ntable *= 2;
// linear lookup tables of length N = 2^ncoultablebits
// stored value = value at lower edge of bin
// d values = delta from lower edge to upper edge of bin
if (ftable) free_tables();
memory->create(rtable,ntable,"pair:rtable");
memory->create(ftable,ntable,"pair:ftable");
memory->create(ctable,ntable,"pair:ctable");
memory->create(etable,ntable,"pair:etable");
memory->create(drtable,ntable,"pair:drtable");
memory->create(dftable,ntable,"pair:dftable");
memory->create(dctable,ntable,"pair:dctable");
memory->create(detable,ntable,"pair:detable");
if (cut_respa == NULL) {
vtable = ptable = dvtable = dptable = NULL;
} else {
memory->create(vtable,ntable,"pair:vtable");
memory->create(ptable,ntable,"pair:ptable");
memory->create(dvtable,ntable,"pair:dvtable");
memory->create(dptable,ntable,"pair:dptable");
}
union_int_float_t rsq_lookup;
union_int_float_t minrsq_lookup;
int itablemin;
minrsq_lookup.i = 0 << ncoulshiftbits;
minrsq_lookup.i |= maskhi;
for (int i = 0; i < ntable; i++) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tabinnersq) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= maskhi;
}
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
etable[i] = qqrd2e/r * derfc;
} else {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
ctable[i] = 0.0;
etable[i] = qqrd2e/r * derfc;
ptable[i] = qqrd2e/r;
vtable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
ftable[i] += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
ctable[i] = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
}
}
}
minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f);
}
tabinnersq = minrsq_lookup.f;
int ntablem1 = ntable - 1;
for (int i = 0; i < ntablem1; i++) {
drtable[i] = 1.0/(rtable[i+1] - rtable[i]);
dftable[i] = ftable[i+1] - ftable[i];
dctable[i] = ctable[i+1] - ctable[i];
detable[i] = etable[i+1] - etable[i];
}
if (cut_respa) {
for (int i = 0; i < ntablem1; i++) {
dvtable[i] = vtable[i+1] - vtable[i];
dptable[i] = ptable[i+1] - ptable[i];
}
}
// get the delta values for the last table entries
// tables are connected periodically between 0 and ntablem1
drtable[ntablem1] = 1.0/(rtable[0] - rtable[ntablem1]);
dftable[ntablem1] = ftable[0] - ftable[ntablem1];
dctable[ntablem1] = ctable[0] - ctable[ntablem1];
detable[ntablem1] = etable[0] - etable[ntablem1];
if (cut_respa) {
dvtable[ntablem1] = vtable[0] - vtable[ntablem1];
dptable[ntablem1] = ptable[0] - ptable[ntablem1];
}
// get the correct delta values at itablemax
// smallest r is in bin itablemin
// largest r is in bin itablemax, which is itablemin-1,
// or ntablem1 if itablemin=0
// deltas at itablemax only needed if corresponding rsq < cut*cut
// if so, compute deltas between rsq and cut*cut
double f_tmp,c_tmp,e_tmp,p_tmp,v_tmp;
itablemin = minrsq_lookup.i & ncoulmask;
itablemin >>= ncoulshiftbits;
int itablemax = itablemin - 1;
if (itablemin == 0) itablemax = ntablem1;
rsq_lookup.i = itablemax << ncoulshiftbits;
rsq_lookup.i |= maskhi;
if (rsq_lookup.f < cut_coulsq) {
rsq_lookup.f = cut_coulsq;
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
e_tmp = qqrd2e/r * derfc;
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
c_tmp = 0.0;
e_tmp = qqrd2e/r * derfc;
p_tmp = qqrd2e/r;
v_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
f_tmp += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
c_tmp = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
}
}
}
drtable[itablemax] = 1.0/(rsq_lookup.f - rtable[itablemax]);
dftable[itablemax] = f_tmp - ftable[itablemax];
dctable[itablemax] = c_tmp - ctable[itablemax];
detable[itablemax] = e_tmp - etable[itablemax];
if (cut_respa) {
dvtable[itablemax] = v_tmp - vtable[itablemax];
dptable[itablemax] = p_tmp - ptable[itablemax];
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&eps14[i][j],sizeof(double),1,fp);
fwrite(&sigma14[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&eps14[i][j],sizeof(double),1,fp);
fread(&sigma14[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&eps14[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma14[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_inner,sizeof(double),1,fp);
fwrite(&cut_lj,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_inner,sizeof(double),1,fp);
fread(&cut_lj,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_inner,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
free memory for tables used in pair computations
------------------------------------------------------------------------- */
void PairLJCharmmCoulLong::free_tables()
{
memory->destroy(rtable);
memory->destroy(drtable);
memory->destroy(ftable);
memory->destroy(dftable);
memory->destroy(ctable);
memory->destroy(dctable);
memory->destroy(etable);
memory->destroy(detable);
memory->destroy(vtable);
memory->destroy(dvtable);
memory->destroy(ptable);
memory->destroy(dptable);
}
/* ---------------------------------------------------------------------- */
double PairLJCharmmCoulLong::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,grij,expm2,t,erfc,prefactor;
double switch1,switch2,fraction,table,forcecoul,forcelj,phicoul,philj;
int itable;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = atom->q[i]*atom->q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = atom->q[i]*atom->q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
} else forcelj = 0.0;
fforce = (forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
phicoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
phicoul = atom->q[i]*atom->q[j] * table;
}
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
eng += phicoul;
}
if (rsq < cut_ljsq) {
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
philj *= switch1;
}
eng += factor_lj*philj;
}
return eng;
}
/* ---------------------------------------------------------------------- */
void *PairLJCharmmCoulLong::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"lj14_1") == 0) return (void *) lj14_1;
if (strcmp(str,"lj14_2") == 0) return (void *) lj14_2;
if (strcmp(str,"lj14_3") == 0) return (void *) lj14_3;
if (strcmp(str,"lj14_4") == 0) return (void *) lj14_4;
dim = 0;
if (strcmp(str,"implicit") == 0) return (void *) &implicit;
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul;
return NULL;
}
diff --git a/src/KSPACE/pair_lj_cut_coul_long.cpp b/src/KSPACE/pair_lj_cut_coul_long.cpp
index 7ab653b58..ba9e390ba 100644
--- a/src/KSPACE/pair_lj_cut_coul_long.cpp
+++ b/src/KSPACE/pair_lj_cut_coul_long.cpp
@@ -1,1132 +1,1129 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_cut_coul_long.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJCutCoulLong::PairLJCutCoulLong(LAMMPS *lmp) : Pair(lmp)
{
respa_enable = 1;
ftable = NULL;
}
/* ---------------------------------------------------------------------- */
PairLJCutCoulLong::~PairLJCutCoulLong()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
if (ftable) free_tables();
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLong::compute(int eflag, int vflag)
{
int i,ii,j,jj,inum,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
int *ilist,*jlist,*numneigh,**firstneigh;
double rsq;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLong::compute_inner()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = listinner->inum;
ilist = listinner->ilist;
numneigh = listinner->numneigh;
firstneigh = listinner->firstneigh;
double cut_out_on = cut_respa[0];
double cut_out_off = cut_respa[1];
double cut_out_diff = cut_out_off - cut_out_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq) {
r2inv = 1.0/rsq;
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul;
jtype = type[j];
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLong::compute_middle()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = listmiddle->inum;
ilist = listmiddle->ilist;
numneigh = listmiddle->numneigh;
firstneigh = listmiddle->firstneigh;
double cut_in_off = cut_respa[0];
double cut_in_on = cut_respa[1];
double cut_out_on = cut_respa[2];
double cut_out_off = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_out_diff = cut_out_off - cut_out_on;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) {
r2inv = 1.0/rsq;
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*forcecoul;
jtype = type[j];
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLong::compute_outer(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype,itable;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
double rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double rsq;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = listouter->inum;
ilist = listouter->ilist;
numneigh = listouter->numneigh;
firstneigh = listouter->firstneigh;
double cut_in_off = cut_respa[2];
double cut_in_on = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2 - 1.0);
if (rsq > cut_in_off_sq) {
if (rsq < cut_in_on_sq) {
rsw = (r - cut_in_off)/cut_in_diff;
forcecoul += prefactor*rsw*rsw*(3.0 - 2.0*rsw);
if (factor_coul < 1.0)
forcecoul -= (1.0-factor_coul)*prefactor*rsw*rsw*(3.0 - 2.0*rsw);
} else {
forcecoul += prefactor;
if (factor_coul < 1.0)
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype] && rsq > cut_in_off_sq) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
forcelj *= rsw*rsw*(3.0 - 2.0*rsw);
}
} else forcelj = 0.0;
fpair = (forcecoul + forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
ecoul = prefactor*erfc;
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ptable[itable] + fraction*dptable[itable];
prefactor = qtmp*q[j] * table;
ecoul -= (1.0-factor_coul)*prefactor;
}
}
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (vflag) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
table = vtable[itable] + fraction*dvtable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ptable[itable] + fraction*dptable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq <= cut_in_off_sq) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else if (rsq <= cut_in_on_sq)
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = (forcecoul + factor_lj*forcelj) * r2inv;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJCutCoulLong::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJCutCoulLong::settings(int narg, char **arg)
{
- if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul = cut_lj_global;
else cut_coul = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJCutCoulLong::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_lj_one = cut_lj_global;
if (narg == 5) cut_lj_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_lj[i][j] = cut_lj_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCutCoulLong::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
} else irequest = neighbor->request(this);
cut_coulsq = cut_coul * cut_coul;
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
// insure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
regular or rRESPA
------------------------------------------------------------------------- */
void PairLJCutCoulLong::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listinner = ptr;
else if (id == 2) listmiddle = ptr;
else if (id == 3) listouter = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJCutCoulLong::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]);
}
double cut = MAX(cut_lj[i][j],cut_coul);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut_lj[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
// check interior rRESPA cutoff
if (cut_respa && MIN(cut_lj[i][j],cut_coul) < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig2 = sigma[i][j]*sigma[i][j];
double sig6 = sig2*sig2*sig2;
double rc3 = cut_lj[i][j]*cut_lj[i][j]*cut_lj[i][j];
double rc6 = rc3*rc3;
double rc9 = rc3*rc6;
etail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig6 - 3.0*rc6) / (9.0*rc9);
ptail_ij = 16.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9);
}
return cut;
}
/* ----------------------------------------------------------------------
setup force tables used in compute routines
------------------------------------------------------------------------- */
void PairLJCutCoulLong::init_tables()
{
int masklo,maskhi;
double r,grij,expm2,derfc,rsw;
double qqrd2e = force->qqrd2e;
tabinnersq = tabinner*tabinner;
init_bitmap(tabinner,cut_coul,ncoultablebits,
masklo,maskhi,ncoulmask,ncoulshiftbits);
int ntable = 1;
for (int i = 0; i < ncoultablebits; i++) ntable *= 2;
// linear lookup tables of length N = 2^ncoultablebits
// stored value = value at lower edge of bin
// d values = delta from lower edge to upper edge of bin
if (ftable) free_tables();
memory->create(rtable,ntable,"pair:rtable");
memory->create(ftable,ntable,"pair:ftable");
memory->create(ctable,ntable,"pair:ctable");
memory->create(etable,ntable,"pair:etable");
memory->create(drtable,ntable,"pair:drtable");
memory->create(dftable,ntable,"pair:dftable");
memory->create(dctable,ntable,"pair:dctable");
memory->create(detable,ntable,"pair:detable");
if (cut_respa == NULL) {
vtable = ptable = dvtable = dptable = NULL;
} else {
memory->create(vtable,ntable*sizeof(double),"pair:vtable");
memory->create(ptable,ntable*sizeof(double),"pair:ptable");
memory->create(dvtable,ntable*sizeof(double),"pair:dvtable");
memory->create(dptable,ntable*sizeof(double),"pair:dptable");
}
union_int_float_t rsq_lookup;
union_int_float_t minrsq_lookup;
int itablemin;
minrsq_lookup.i = 0 << ncoulshiftbits;
minrsq_lookup.i |= maskhi;
for (int i = 0; i < ntable; i++) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tabinnersq) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= maskhi;
}
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
etable[i] = qqrd2e/r * derfc;
} else {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
ctable[i] = 0.0;
etable[i] = qqrd2e/r * derfc;
ptable[i] = qqrd2e/r;
vtable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
ftable[i] += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
ctable[i] = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
}
}
}
minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f);
}
tabinnersq = minrsq_lookup.f;
int ntablem1 = ntable - 1;
for (int i = 0; i < ntablem1; i++) {
drtable[i] = 1.0/(rtable[i+1] - rtable[i]);
dftable[i] = ftable[i+1] - ftable[i];
dctable[i] = ctable[i+1] - ctable[i];
detable[i] = etable[i+1] - etable[i];
}
if (cut_respa) {
for (int i = 0; i < ntablem1; i++) {
dvtable[i] = vtable[i+1] - vtable[i];
dptable[i] = ptable[i+1] - ptable[i];
}
}
// get the delta values for the last table entries
// tables are connected periodically between 0 and ntablem1
drtable[ntablem1] = 1.0/(rtable[0] - rtable[ntablem1]);
dftable[ntablem1] = ftable[0] - ftable[ntablem1];
dctable[ntablem1] = ctable[0] - ctable[ntablem1];
detable[ntablem1] = etable[0] - etable[ntablem1];
if (cut_respa) {
dvtable[ntablem1] = vtable[0] - vtable[ntablem1];
dptable[ntablem1] = ptable[0] - ptable[ntablem1];
}
// get the correct delta values at itablemax
// smallest r is in bin itablemin
// largest r is in bin itablemax, which is itablemin-1,
// or ntablem1 if itablemin=0
// deltas at itablemax only needed if corresponding rsq < cut*cut
// if so, compute deltas between rsq and cut*cut
double f_tmp,c_tmp,e_tmp,p_tmp,v_tmp;
itablemin = minrsq_lookup.i & ncoulmask;
itablemin >>= ncoulshiftbits;
int itablemax = itablemin - 1;
if (itablemin == 0) itablemax = ntablem1;
rsq_lookup.i = itablemax << ncoulshiftbits;
rsq_lookup.i |= maskhi;
if (rsq_lookup.f < cut_coulsq) {
rsq_lookup.f = cut_coulsq;
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
e_tmp = qqrd2e/r * derfc;
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
c_tmp = 0.0;
e_tmp = qqrd2e/r * derfc;
p_tmp = qqrd2e/r;
v_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
f_tmp += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
c_tmp = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
}
}
}
drtable[itablemax] = 1.0/(rsq_lookup.f - rtable[itablemax]);
dftable[itablemax] = f_tmp - ftable[itablemax];
dctable[itablemax] = c_tmp - ctable[itablemax];
detable[itablemax] = e_tmp - etable[itablemax];
if (cut_respa) {
dvtable[itablemax] = v_tmp - vtable[itablemax];
dptable[itablemax] = p_tmp - ptable[itablemax];
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCutCoulLong::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCutCoulLong::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCutCoulLong::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCutCoulLong::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
free memory for tables used in pair computations
------------------------------------------------------------------------- */
void PairLJCutCoulLong::free_tables()
{
memory->destroy(rtable);
memory->destroy(drtable);
memory->destroy(ftable);
memory->destroy(dftable);
memory->destroy(ctable);
memory->destroy(dctable);
memory->destroy(etable);
memory->destroy(detable);
memory->destroy(vtable);
memory->destroy(dvtable);
memory->destroy(ptable);
memory->destroy(dptable);
}
/* ---------------------------------------------------------------------- */
double PairLJCutCoulLong::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,grij,expm2,t,erfc,prefactor;
double fraction,table,forcecoul,forcelj,phicoul,philj;
int itable;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = force->qqrd2e * atom->q[i]*atom->q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) forcecoul -= (1.0-factor_coul)*prefactor;
} else {
union_int_float_t rsq_lookup_single;
rsq_lookup_single.f = rsq;
itable = rsq_lookup_single.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup_single.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = atom->q[i]*atom->q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = atom->q[i]*atom->q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fforce = (forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
phicoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
phicoul = atom->q[i]*atom->q[j] * table;
}
if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor;
eng += phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
eng += factor_lj*philj;
}
return eng;
}
/* ---------------------------------------------------------------------- */
void *PairLJCutCoulLong::extract(char *str, int &dim)
{
dim = 0;
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul;
return NULL;
}
diff --git a/src/KSPACE/pair_lj_cut_coul_long_tip4p.cpp b/src/KSPACE/pair_lj_cut_coul_long_tip4p.cpp
index 2df4235f5..bc3cfc98d 100644
--- a/src/KSPACE/pair_lj_cut_coul_long_tip4p.cpp
+++ b/src/KSPACE/pair_lj_cut_coul_long_tip4p.cpp
@@ -1,518 +1,515 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Amalie Frischknecht and Ahmed Ismail (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_cut_coul_long_tip4p.h"
#include "angle.h"
#include "atom.h"
#include "bond.h"
#include "comm.h"
#include "domain.h"
#include "force.h"
#include "kspace.h"
#include "update.h"
#include "respa.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJCutCoulLongTIP4P::PairLJCutCoulLongTIP4P(LAMMPS *lmp) :
PairLJCutCoulLong(lmp)
{
single_enable = 0;
respa_enable = 0;
// TIP4P cannot compute virial as F dot r
// due to find_M() finding bonded H atoms which are not near O atom
no_virial_fdotr_compute = 1;
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLongTIP4P::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype,itable;
int n,vlist[6];
int iH1,iH2,jH1,jH2;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul;
double fraction,table;
double delxOM, delyOM, delzOM;
double r,r2inv,r6inv,forcecoul,forcelj,cforce;
double factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc,ddotf;
double xiM[3],xjM[3],fO[3],fH[3],fd[3],f1[3],v[6],xH1[3],xH2[3];
double *x1,*x2;
int *ilist,*jlist,*numneigh,**firstneigh;
double rsq;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **f = atom->f;
double **x = atom->x;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
if (itype == typeO) {
find_M(i,iH1,iH2,xiM);
x1 = xiM;
} else x1 = x[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
forcelj *= factor_lj * r2inv;
f[i][0] += delx*forcelj;
f[i][1] += dely*forcelj;
f[i][2] += delz*forcelj;
f[j][0] -= delx*forcelj;
f[j][1] -= dely*forcelj;
f[j][2] -= delz*forcelj;
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,forcelj,delx,dely,delz);
}
// adjust rsq and delxyz for off-site O charge(s)
if (itype == typeO || jtype == typeO) {
if (jtype == typeO) {
find_M(j,jH1,jH2,xjM);
x2 = xjM;
} else x2 = x[j];
delx = x1[0] - x2[0];
dely = x1[1] - x2[1];
delz = x1[2] - x2[2];
rsq = delx*delx + dely*dely + delz*delz;
}
// test current rsq against cutoff and compute Coulombic force
if (rsq < cut_coulsq) {
r2inv = 1 / rsq;
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * expm2;
prefactor = qqrd2e * qtmp*q[j]/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) {
forcecoul -= (1.0-factor_coul)*prefactor;
}
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = qtmp*q[j] * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = qtmp*q[j] * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
cforce = forcecoul * r2inv;
// if i,j are not O atoms, force is applied directly
// if i or j are O atoms, force is on fictitious atom & partitioned
// force partitioning due to Feenstra, J Comp Chem, 20, 786 (1999)
// f_f = fictitious force, fO = f_f (1 - 2 alpha), fH = alpha f_f
// preserves total force and torque on water molecule
// virial = sum(r x F) where each water's atoms are near xi and xj
// vlist stores 2,4,6 atoms whose forces contribute to virial
n = 0;
if (itype != typeO) {
f[i][0] += delx * cforce;
f[i][1] += dely * cforce;
f[i][2] += delz * cforce;
if (vflag) {
v[0] = x[i][0] * delx * cforce;
v[1] = x[i][1] * dely * cforce;
v[2] = x[i][2] * delz * cforce;
v[3] = x[i][0] * dely * cforce;
v[4] = x[i][0] * delz * cforce;
v[5] = x[i][1] * delz * cforce;
vlist[n++] = i;
}
} else {
fd[0] = delx*cforce;
fd[1] = dely*cforce;
fd[2] = delz*cforce;
delxOM = x[i][0] - x1[0];
delyOM = x[i][1] - x1[1];
delzOM = x[i][2] - x1[2];
ddotf = (delxOM * fd[0] + delyOM * fd[1] + delzOM * fd[2]) /
(qdist*qdist);
f1[0] = ddotf * delxOM;
f1[1] = ddotf * delyOM;
f1[2] = ddotf * delzOM;
fO[0] = fd[0] - alpha * (fd[0] - f1[0]);
fO[1] = fd[1] - alpha * (fd[1] - f1[1]);
fO[2] = fd[2] - alpha * (fd[2] - f1[2]);
fH[0] = 0.5 * alpha * (fd[0] - f1[0]);
fH[1] = 0.5 * alpha * (fd[1] - f1[1]);
fH[2] = 0.5 * alpha * (fd[2] - f1[2]);
f[i][0] += fO[0];
f[i][1] += fO[1];
f[i][2] += fO[2];
f[iH1][0] += fH[0];
f[iH1][1] += fH[1];
f[iH1][2] += fH[2];
f[iH2][0] += fH[0];
f[iH2][1] += fH[1];
f[iH2][2] += fH[2];
if (vflag) {
domain->closest_image(x[i],x[iH1],xH1);
domain->closest_image(x[i],x[iH2],xH2);
v[0] = x[i][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0];
v[1] = x[i][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1];
v[2] = x[i][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2];
v[3] = x[i][0]*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1];
v[4] = x[i][0]*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2];
v[5] = x[i][1]*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2];
vlist[n++] = i;
vlist[n++] = iH1;
vlist[n++] = iH2;
}
}
if (jtype != typeO) {
f[j][0] -= delx * cforce;
f[j][1] -= dely * cforce;
f[j][2] -= delz * cforce;
if (vflag) {
v[0] -= x[j][0] * delx * cforce;
v[1] -= x[j][1] * dely * cforce;
v[2] -= x[j][2] * delz * cforce;
v[3] -= x[j][0] * dely * cforce;
v[4] -= x[j][0] * delz * cforce;
v[5] -= x[j][1] * delz * cforce;
vlist[n++] = j;
}
} else {
fd[0] = -delx*cforce;
fd[1] = -dely*cforce;
fd[2] = -delz*cforce;
delxOM = x[j][0] - x2[0];
delyOM = x[j][1] - x2[1];
delzOM = x[j][2] - x2[2];
ddotf = (delxOM * fd[0] + delyOM * fd[1] + delzOM * fd[2]) /
(qdist*qdist);
f1[0] = ddotf * delxOM;
f1[1] = ddotf * delyOM;
f1[2] = ddotf * delzOM;
fO[0] = fd[0] - alpha * (fd[0] - f1[0]);
fO[1] = fd[1] - alpha * (fd[1] - f1[1]);
fO[2] = fd[2] - alpha * (fd[2] - f1[2]);
fH[0] = 0.5 * alpha * (fd[0] - f1[0]);
fH[1] = 0.5 * alpha * (fd[1] - f1[1]);
fH[2] = 0.5 * alpha * (fd[2] - f1[2]);
f[j][0] += fO[0];
f[j][1] += fO[1];
f[j][2] += fO[2];
f[jH1][0] += fH[0];
f[jH1][1] += fH[1];
f[jH1][2] += fH[2];
f[jH2][0] += fH[0];
f[jH2][1] += fH[1];
f[jH2][2] += fH[2];
if (vflag) {
domain->closest_image(x[j],x[jH1],xH1);
domain->closest_image(x[j],x[jH2],xH2);
v[0] += x[j][0]*fO[0] + xH1[0]*fH[0] + xH2[0]*fH[0];
v[1] += x[j][1]*fO[1] + xH1[1]*fH[1] + xH2[1]*fH[1];
v[2] += x[j][2]*fO[2] + xH1[2]*fH[2] + xH2[2]*fH[2];
v[3] += x[j][0]*fO[1] + xH1[0]*fH[1] + xH2[0]*fH[1];
v[4] += x[j][0]*fO[2] + xH1[0]*fH[2] + xH2[0]*fH[2];
v[5] += x[j][1]*fO[2] + xH1[1]*fH[2] + xH2[1]*fH[2];
vlist[n++] = j;
vlist[n++] = jH1;
vlist[n++] = jH2;
}
}
if (eflag) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = qtmp*q[j] * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (evflag) ev_tally_list(n,vlist,ecoul,v);
}
}
}
}
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJCutCoulLongTIP4P::settings(int narg, char **arg)
{
- if (narg < 6 || narg > 7) error->all("Illegal pair_style command");
+ if (narg < 6 || narg > 7) error->all(FLERR,"Illegal pair_style command");
typeO = force->inumeric(arg[0]);
typeH = force->inumeric(arg[1]);
typeB = force->inumeric(arg[2]);
typeA = force->inumeric(arg[3]);
qdist = force->numeric(arg[4]);
cut_lj_global = force->numeric(arg[5]);
if (narg == 6) cut_coul = cut_lj_global;
else cut_coul = force->numeric(arg[6]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCutCoulLongTIP4P::init_style()
{
if (atom->tag_enable == 0)
- error->all("Pair style lj/cut/coul/long/tip4p requires atom IDs");
+ error->all(FLERR,"Pair style lj/cut/coul/long/tip4p requires atom IDs");
if (!force->newton_pair)
- error->all("Pair style lj/cut/coul/long/tip4p requires newton pair on");
+ error->all(FLERR,"Pair style lj/cut/coul/long/tip4p requires newton pair on");
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/long/tip4p requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/long/tip4p requires atom attribute q");
if (strcmp(force->kspace_style,"pppm/tip4p") != 0)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
if (force->bond == NULL)
- error->all("Must use a bond style with TIP4P potential");
+ error->all(FLERR,"Must use a bond style with TIP4P potential");
if (force->angle == NULL)
- error->all("Must use an angle style with TIP4P potential");
+ error->all(FLERR,"Must use an angle style with TIP4P potential");
PairLJCutCoulLong::init_style();
// set alpha parameter
double theta = force->angle->equilibrium_angle(typeA);
double blen = force->bond->equilibrium_distance(typeB);
alpha = qdist / (cos(0.5*theta) * blen);
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCutCoulLongTIP4P::write_restart_settings(FILE *fp)
{
fwrite(&typeO,sizeof(int),1,fp);
fwrite(&typeH,sizeof(int),1,fp);
fwrite(&typeB,sizeof(int),1,fp);
fwrite(&typeA,sizeof(int),1,fp);
fwrite(&qdist,sizeof(double),1,fp);
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCutCoulLongTIP4P::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&typeO,sizeof(int),1,fp);
fread(&typeH,sizeof(int),1,fp);
fread(&typeB,sizeof(int),1,fp);
fread(&typeA,sizeof(int),1,fp);
fread(&qdist,sizeof(double),1,fp);
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&typeO,1,MPI_INT,0,world);
MPI_Bcast(&typeH,1,MPI_INT,0,world);
MPI_Bcast(&typeB,1,MPI_INT,0,world);
MPI_Bcast(&typeA,1,MPI_INT,0,world);
MPI_Bcast(&qdist,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
find 2 H atoms bonded to O atom i
compute position xM of fictitious charge site for O atom
also return local indices iH1,iH2 of H atoms
------------------------------------------------------------------------- */
void PairLJCutCoulLongTIP4P::find_M(int i, int &iH1, int &iH2, double *xM)
{
// test that O is correctly bonded to 2 succesive H atoms
iH1 = atom->map(atom->tag[i] + 1);
iH2 = atom->map(atom->tag[i] + 2);
- if (iH1 == -1 || iH2 == -1) error->one("TIP4P hydrogen is missing");
+ if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing");
if (atom->type[iH1] != typeH || atom->type[iH2] != typeH)
- error->one("TIP4P hydrogen has incorrect atom type");
+ error->one(FLERR,"TIP4P hydrogen has incorrect atom type");
double **x = atom->x;
double delx1 = x[iH1][0] - x[i][0];
double dely1 = x[iH1][1] - x[i][1];
double delz1 = x[iH1][2] - x[i][2];
domain->minimum_image(delx1,dely1,delz1);
double delx2 = x[iH2][0] - x[i][0];
double dely2 = x[iH2][1] - x[i][1];
double delz2 = x[iH2][2] - x[i][2];
domain->minimum_image(delx2,dely2,delz2);
xM[0] = x[i][0] + alpha * 0.5 * (delx1 + delx2);
xM[1] = x[i][1] + alpha * 0.5 * (dely1 + dely2);
xM[2] = x[i][2] + alpha * 0.5 * (delz1 + delz2);
}
/* ---------------------------------------------------------------------- */
void *PairLJCutCoulLongTIP4P::extract(char *str, int &dim)
{
dim = 0;
if (strcmp(str,"qdist") == 0) return (void *) &qdist;
if (strcmp(str,"typeO") == 0) return (void *) &typeO;
if (strcmp(str,"typeH") == 0) return (void *) &typeH;
if (strcmp(str,"typeA") == 0) return (void *) &typeA;
if (strcmp(str,"typeB") == 0) return (void *) &typeB;
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul;
return NULL;
}
diff --git a/src/KSPACE/pppm.cpp b/src/KSPACE/pppm.cpp
index 40730df6f..cc92e1719 100644
--- a/src/KSPACE/pppm.cpp
+++ b/src/KSPACE/pppm.cpp
@@ -1,1945 +1,1942 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Roy Pollock (LLNL), Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "pppm.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "domain.h"
#include "fft3d_wrap.h"
#include "remap_wrap.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXORDER 7
#define OFFSET 16384
#define SMALL 0.00001
#define LARGE 10000.0
#define EPS_HOC 1.0e-7
#ifdef FFT_SINGLE
#define ZEROF 0.0f
#define ONEF 1.0f
#else
#define ZEROF 0.0
#define ONEF 1.0
#endif
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PPPM::PPPM(LAMMPS *lmp, int narg, char **arg) : KSpace(lmp, narg, arg)
{
- if (narg < 1) error->all("Illegal kspace_style pppm command");
+ if (narg < 1) error->all(FLERR,"Illegal kspace_style pppm command");
precision = atof(arg[0]);
PI = 4.0*atan(1.0);
nfactors = 3;
factors = new int[nfactors];
factors[0] = 2;
factors[1] = 3;
factors[2] = 5;
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
density_brick = vdx_brick = vdy_brick = vdz_brick = NULL;
density_fft = NULL;
greensfn = NULL;
work1 = work2 = NULL;
vg = NULL;
fkx = fky = fkz = NULL;
buf1 = buf2 = NULL;
gf_b = NULL;
rho1d = rho_coeff = NULL;
fft1 = fft2 = NULL;
remap = NULL;
nmax = 0;
part2grid = NULL;
}
/* ----------------------------------------------------------------------
free all memory
------------------------------------------------------------------------- */
PPPM::~PPPM()
{
delete [] factors;
deallocate();
memory->destroy(part2grid);
}
/* ----------------------------------------------------------------------
called once before run
------------------------------------------------------------------------- */
void PPPM::init()
{
if (me == 0) {
if (screen) fprintf(screen,"PPPM initialization ...\n");
if (logfile) fprintf(logfile,"PPPM initialization ...\n");
}
// error check
if (domain->triclinic)
- error->all("Cannot (yet) use PPPM with triclinic box");
- if (domain->dimension == 2) error->all("Cannot use PPPM with 2d simulation");
+ error->all(FLERR,"Cannot (yet) use PPPM with triclinic box");
+ if (domain->dimension == 2) error->all(FLERR,"Cannot use PPPM with 2d simulation");
- if (!atom->q_flag) error->all("Kspace style requires atom attribute q");
+ if (!atom->q_flag) error->all(FLERR,"Kspace style requires atom attribute q");
if (slabflag == 0 && domain->nonperiodic > 0)
- error->all("Cannot use nonperiodic boundaries with PPPM");
+ error->all(FLERR,"Cannot use nonperiodic boundaries with PPPM");
if (slabflag == 1) {
if (domain->xperiodic != 1 || domain->yperiodic != 1 ||
domain->boundary[2][0] != 1 || domain->boundary[2][1] != 1)
- error->all("Incorrect boundaries with slab PPPM");
+ error->all(FLERR,"Incorrect boundaries with slab PPPM");
}
if (order > MAXORDER) {
char str[128];
sprintf(str,"PPPM order cannot be greater than %d",MAXORDER);
- error->all(str);
+ error->all(FLERR,str);
}
// free all arrays previously allocated
deallocate();
// extract short-range Coulombic cutoff from pair style
qqrd2e = force->qqrd2e;
scale = 1.0;
if (force->pair == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
int itmp;
double *p_cutoff = (double *) force->pair->extract("cut_coul",itmp);
if (p_cutoff == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
cutoff = *p_cutoff;
// if kspace is TIP4P, extract TIP4P params from pair style
// bond/angle are not yet init(), so insure equilibrium request is valid
qdist = 0.0;
if (strcmp(force->kspace_style,"pppm/tip4p") == 0) {
if (force->pair == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
double *p_qdist = (double *) force->pair->extract("qdist",itmp);
int *p_typeO = (int *) force->pair->extract("typeO",itmp);
int *p_typeH = (int *) force->pair->extract("typeH",itmp);
int *p_typeA = (int *) force->pair->extract("typeA",itmp);
int *p_typeB = (int *) force->pair->extract("typeB",itmp);
if (!p_qdist || !p_typeO || !p_typeH || !p_typeA || !p_typeB)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
qdist = *p_qdist;
typeO = *p_typeO;
typeH = *p_typeH;
int typeA = *p_typeA;
int typeB = *p_typeB;
if (force->angle == NULL || force->bond == NULL)
- error->all("Bond and angle potentials must be defined for TIP4P");
+ error->all(FLERR,"Bond and angle potentials must be defined for TIP4P");
if (typeA < 1 || typeA > atom->nangletypes ||
force->angle->setflag[typeA] == 0)
- error->all("Bad TIP4P angle type for PPPM/TIP4P");
+ error->all(FLERR,"Bad TIP4P angle type for PPPM/TIP4P");
if (typeB < 1 || typeB > atom->nbondtypes ||
force->bond->setflag[typeB] == 0)
- error->all("Bad TIP4P bond type for PPPM/TIP4P");
+ error->all(FLERR,"Bad TIP4P bond type for PPPM/TIP4P");
double theta = force->angle->equilibrium_angle(typeA);
double blen = force->bond->equilibrium_distance(typeB);
alpha = qdist / (cos(0.5*theta) * blen);
}
// compute qsum & qsqsum and warn if not charge-neutral
qsum = qsqsum = 0.0;
for (int i = 0; i < atom->nlocal; i++) {
qsum += atom->q[i];
qsqsum += atom->q[i]*atom->q[i];
}
double tmp;
MPI_Allreduce(&qsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
qsum = tmp;
MPI_Allreduce(&qsqsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
qsqsum = tmp;
if (qsqsum == 0.0)
- error->all("Cannot use kspace solver on system with no charge");
+ error->all(FLERR,"Cannot use kspace solver on system with no charge");
if (fabs(qsum) > SMALL && me == 0) {
char str[128];
sprintf(str,"System is not charge neutral, net charge = %g",qsum);
- error->warning(str);
+ error->warning(FLERR,str);
}
// setup FFT grid resolution and g_ewald
// normally one iteration thru while loop is all that is required
// if grid stencil extends beyond neighbor proc, reduce order and try again
int iteration = 0;
while (order > 0) {
if (iteration && me == 0)
- error->warning("Reducing PPPM order b/c stencil extends "
+ error->warning(FLERR,"Reducing PPPM order b/c stencil extends "
"beyond neighbor processor");
iteration++;
set_grid();
if (nx_pppm >= OFFSET || ny_pppm >= OFFSET || nz_pppm >= OFFSET)
- error->all("PPPM grid is too large");
+ error->all(FLERR,"PPPM grid is too large");
// global indices of PPPM grid range from 0 to N-1
// nlo_in,nhi_in = lower/upper limits of the 3d sub-brick of
// global PPPM grid that I own without ghost cells
// for slab PPPM, assign z grid as if it were not extended
nxlo_in = comm->myloc[0]*nx_pppm / comm->procgrid[0];
nxhi_in = (comm->myloc[0]+1)*nx_pppm / comm->procgrid[0] - 1;
nylo_in = comm->myloc[1]*ny_pppm / comm->procgrid[1];
nyhi_in = (comm->myloc[1]+1)*ny_pppm / comm->procgrid[1] - 1;
nzlo_in = comm->myloc[2] *
(static_cast<int> (nz_pppm/slab_volfactor)) / comm->procgrid[2];
nzhi_in = (comm->myloc[2]+1) *
(static_cast<int> (nz_pppm/slab_volfactor)) / comm->procgrid[2] - 1;
// nlower,nupper = stencil size for mapping particles to PPPM grid
nlower = -(order-1)/2;
nupper = order/2;
// shift values for particle <-> grid mapping
// add/subtract OFFSET to avoid int(-0.75) = 0 when want it to be -1
if (order % 2) shift = OFFSET + 0.5;
else shift = OFFSET;
if (order % 2) shiftone = 0.0;
else shiftone = 0.5;
// nlo_out,nhi_out = lower/upper limits of the 3d sub-brick of
// global PPPM grid that my particles can contribute charge to
// effectively nlo_in,nhi_in + ghost cells
// nlo,nhi = global coords of grid pt to "lower left" of smallest/largest
// position a particle in my box can be at
// dist[3] = particle position bound = subbox + skin/2.0 + qdist
// qdist = offset due to TIP4P fictitious charge
// convert to triclinic if necessary
// nlo_out,nhi_out = nlo,nhi + stencil size for particle mapping
// for slab PPPM, assign z grid as if it were not extended
triclinic = domain->triclinic;
double *prd,*sublo,*subhi;
if (triclinic == 0) {
prd = domain->prd;
boxlo = domain->boxlo;
sublo = domain->sublo;
subhi = domain->subhi;
} else {
prd = domain->prd_lamda;
boxlo = domain->boxlo_lamda;
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
double xprd = prd[0];
double yprd = prd[1];
double zprd = prd[2];
double zprd_slab = zprd*slab_volfactor;
double dist[3];
double cuthalf = 0.5*neighbor->skin + qdist;
if (triclinic == 0) dist[0] = dist[1] = dist[2] = cuthalf;
else {
dist[0] = cuthalf/domain->prd[0];
dist[1] = cuthalf/domain->prd[1];
dist[2] = cuthalf/domain->prd[2];
}
int nlo,nhi;
nlo = static_cast<int> ((sublo[0]-dist[0]-boxlo[0]) *
nx_pppm/xprd + shift) - OFFSET;
nhi = static_cast<int> ((subhi[0]+dist[0]-boxlo[0]) *
nx_pppm/xprd + shift) - OFFSET;
nxlo_out = nlo + nlower;
nxhi_out = nhi + nupper;
nlo = static_cast<int> ((sublo[1]-dist[1]-boxlo[1]) *
ny_pppm/yprd + shift) - OFFSET;
nhi = static_cast<int> ((subhi[1]+dist[1]-boxlo[1]) *
ny_pppm/yprd + shift) - OFFSET;
nylo_out = nlo + nlower;
nyhi_out = nhi + nupper;
nlo = static_cast<int> ((sublo[2]-dist[2]-boxlo[2]) *
nz_pppm/zprd_slab + shift) - OFFSET;
nhi = static_cast<int> ((subhi[2]+dist[2]-boxlo[2]) *
nz_pppm/zprd_slab + shift) - OFFSET;
nzlo_out = nlo + nlower;
nzhi_out = nhi + nupper;
// for slab PPPM, change the grid boundary for processors at +z end
// to include the empty volume between periodically repeating slabs
// for slab PPPM, want charge data communicated from -z proc to +z proc,
// but not vice versa, also want field data communicated from +z proc to
// -z proc, but not vice versa
// this is accomplished by nzhi_in = nzhi_out on +z end (no ghost cells)
if (slabflag && ((comm->myloc[2]+1) == (comm->procgrid[2]))) {
nzhi_in = nz_pppm - 1;
nzhi_out = nz_pppm - 1;
}
// nlo_ghost,nhi_ghost = # of planes I will recv from 6 directions
// that overlay domain I own
// proc in that direction tells me via sendrecv()
// if no neighbor proc, value is from self since I have ghosts regardless
int nplanes;
MPI_Status status;
nplanes = nxlo_in - nxlo_out;
if (comm->procneigh[0][0] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[0][0],0,
&nxhi_ghost,1,MPI_INT,comm->procneigh[0][1],0,
world,&status);
else nxhi_ghost = nplanes;
nplanes = nxhi_out - nxhi_in;
if (comm->procneigh[0][1] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[0][1],0,
&nxlo_ghost,1,MPI_INT,comm->procneigh[0][0],
0,world,&status);
else nxlo_ghost = nplanes;
nplanes = nylo_in - nylo_out;
if (comm->procneigh[1][0] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[1][0],0,
&nyhi_ghost,1,MPI_INT,comm->procneigh[1][1],0,
world,&status);
else nyhi_ghost = nplanes;
nplanes = nyhi_out - nyhi_in;
if (comm->procneigh[1][1] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[1][1],0,
&nylo_ghost,1,MPI_INT,comm->procneigh[1][0],0,
world,&status);
else nylo_ghost = nplanes;
nplanes = nzlo_in - nzlo_out;
if (comm->procneigh[2][0] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[2][0],0,
&nzhi_ghost,1,MPI_INT,comm->procneigh[2][1],0,
world,&status);
else nzhi_ghost = nplanes;
nplanes = nzhi_out - nzhi_in;
if (comm->procneigh[2][1] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[2][1],0,
&nzlo_ghost,1,MPI_INT,comm->procneigh[2][0],0,
world,&status);
else nzlo_ghost = nplanes;
// test that ghost overlap is not bigger than my sub-domain
int flag = 0;
if (nxlo_ghost > nxhi_in-nxlo_in+1) flag = 1;
if (nxhi_ghost > nxhi_in-nxlo_in+1) flag = 1;
if (nylo_ghost > nyhi_in-nylo_in+1) flag = 1;
if (nyhi_ghost > nyhi_in-nylo_in+1) flag = 1;
if (nzlo_ghost > nzhi_in-nzlo_in+1) flag = 1;
if (nzhi_ghost > nzhi_in-nzlo_in+1) flag = 1;
int flag_all;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
if (flag_all == 0) break;
order--;
}
- if (order == 0) error->all("PPPM order has been reduced to 0");
+ if (order == 0) error->all(FLERR,"PPPM order has been reduced to 0");
// decomposition of FFT mesh
// global indices range from 0 to N-1
// proc owns entire x-dimension, clump of columns in y,z dimensions
// npey_fft,npez_fft = # of procs in y,z dims
// if nprocs is small enough, proc can own 1 or more entire xy planes,
// else proc owns 2d sub-blocks of yz plane
// me_y,me_z = which proc (0-npe_fft-1) I am in y,z dimensions
// nlo_fft,nhi_fft = lower/upper limit of the section
// of the global FFT mesh that I own
int npey_fft,npez_fft;
if (nz_pppm >= nprocs) {
npey_fft = 1;
npez_fft = nprocs;
} else procs2grid2d(nprocs,ny_pppm,nz_pppm,&npey_fft,&npez_fft);
int me_y = me % npey_fft;
int me_z = me / npey_fft;
nxlo_fft = 0;
nxhi_fft = nx_pppm - 1;
nylo_fft = me_y*ny_pppm/npey_fft;
nyhi_fft = (me_y+1)*ny_pppm/npey_fft - 1;
nzlo_fft = me_z*nz_pppm/npez_fft;
nzhi_fft = (me_z+1)*nz_pppm/npez_fft - 1;
// PPPM grid for this proc, including ghosts
ngrid = (nxhi_out-nxlo_out+1) * (nyhi_out-nylo_out+1) *
(nzhi_out-nzlo_out+1);
// FFT arrays on this proc, without ghosts
// nfft = FFT points in FFT decomposition on this proc
// nfft_brick = FFT points in 3d brick-decomposition on this proc
// nfft_both = greater of 2 values
nfft = (nxhi_fft-nxlo_fft+1) * (nyhi_fft-nylo_fft+1) *
(nzhi_fft-nzlo_fft+1);
int nfft_brick = (nxhi_in-nxlo_in+1) * (nyhi_in-nylo_in+1) *
(nzhi_in-nzlo_in+1);
nfft_both = MAX(nfft,nfft_brick);
// buffer space for use in brick2fft and fillbrick
// idel = max # of ghost planes to send or recv in +/- dir of each dim
// nx,ny,nz = owned planes (including ghosts) in each dim
// nxx,nyy,nzz = max # of grid cells to send in each dim
// nbuf = max in any dim, augment by 3x for components of vd_xyz in fillbrick
int idelx,idely,idelz,nx,ny,nz,nxx,nyy,nzz;
idelx = MAX(nxlo_ghost,nxhi_ghost);
idelx = MAX(idelx,nxhi_out-nxhi_in);
idelx = MAX(idelx,nxlo_in-nxlo_out);
idely = MAX(nylo_ghost,nyhi_ghost);
idely = MAX(idely,nyhi_out-nyhi_in);
idely = MAX(idely,nylo_in-nylo_out);
idelz = MAX(nzlo_ghost,nzhi_ghost);
idelz = MAX(idelz,nzhi_out-nzhi_in);
idelz = MAX(idelz,nzlo_in-nzlo_out);
nx = nxhi_out - nxlo_out + 1;
ny = nyhi_out - nylo_out + 1;
nz = nzhi_out - nzlo_out + 1;
nxx = idelx * ny * nz;
nyy = idely * nx * nz;
nzz = idelz * nx * ny;
nbuf = MAX(nxx,nyy);
nbuf = MAX(nbuf,nzz);
nbuf *= 3;
// print stats
int ngrid_max,nfft_both_max,nbuf_max;
MPI_Allreduce(&ngrid,&ngrid_max,1,MPI_INT,MPI_MAX,world);
MPI_Allreduce(&nfft_both,&nfft_both_max,1,MPI_INT,MPI_MAX,world);
MPI_Allreduce(&nbuf,&nbuf_max,1,MPI_INT,MPI_MAX,world);
if (me == 0) {
if (screen) fprintf(screen," brick FFT buffer size/proc = %d %d %d\n",
ngrid_max,nfft_both_max,nbuf_max);
if (logfile) fprintf(logfile," brick FFT buffer size/proc = %d %d %d\n",
ngrid_max,nfft_both_max,nbuf_max);
}
// allocate K-space dependent memory
allocate();
// pre-compute Green's function denomiator expansion
// pre-compute 1d charge distribution coefficients
compute_gf_denom();
compute_rho_coeff();
}
/* ----------------------------------------------------------------------
adjust PPPM coeffs, called initially and whenever volume has changed
------------------------------------------------------------------------- */
void PPPM::setup()
{
int i,j,k,l,m,n;
double *prd;
// volume-dependent factors
// adjust z dimension for 2d slab PPPM
// z dimension for 3d PPPM is zprd since slab_volfactor = 1.0
if (triclinic == 0) prd = domain->prd;
else prd = domain->prd_lamda;
double xprd = prd[0];
double yprd = prd[1];
double zprd = prd[2];
double zprd_slab = zprd*slab_volfactor;
volume = xprd * yprd * zprd_slab;
delxinv = nx_pppm/xprd;
delyinv = ny_pppm/yprd;
delzinv = nz_pppm/zprd_slab;
delvolinv = delxinv*delyinv*delzinv;
double unitkx = (2.0*PI/xprd);
double unitky = (2.0*PI/yprd);
double unitkz = (2.0*PI/zprd_slab);
// fkx,fky,fkz for my FFT grid pts
double per;
for (i = nxlo_fft; i <= nxhi_fft; i++) {
per = i - nx_pppm*(2*i/nx_pppm);
fkx[i] = unitkx*per;
}
for (i = nylo_fft; i <= nyhi_fft; i++) {
per = i - ny_pppm*(2*i/ny_pppm);
fky[i] = unitky*per;
}
for (i = nzlo_fft; i <= nzhi_fft; i++) {
per = i - nz_pppm*(2*i/nz_pppm);
fkz[i] = unitkz*per;
}
// virial coefficients
double sqk,vterm;
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++) {
for (j = nylo_fft; j <= nyhi_fft; j++) {
for (i = nxlo_fft; i <= nxhi_fft; i++) {
sqk = fkx[i]*fkx[i] + fky[j]*fky[j] + fkz[k]*fkz[k];
if (sqk == 0.0) {
vg[n][0] = 0.0;
vg[n][1] = 0.0;
vg[n][2] = 0.0;
vg[n][3] = 0.0;
vg[n][4] = 0.0;
vg[n][5] = 0.0;
} else {
vterm = -2.0 * (1.0/sqk + 0.25/(g_ewald*g_ewald));
vg[n][0] = 1.0 + vterm*fkx[i]*fkx[i];
vg[n][1] = 1.0 + vterm*fky[j]*fky[j];
vg[n][2] = 1.0 + vterm*fkz[k]*fkz[k];
vg[n][3] = vterm*fkx[i]*fky[j];
vg[n][4] = vterm*fkx[i]*fkz[k];
vg[n][5] = vterm*fky[j]*fkz[k];
}
n++;
}
}
}
// modified (Hockney-Eastwood) Coulomb Green's function
int nx,ny,nz,kper,lper,mper;
double snx,sny,snz,snx2,sny2,snz2;
double argx,argy,argz,wx,wy,wz,sx,sy,sz,qx,qy,qz;
double sum1,dot1,dot2;
double numerator,denominator;
int nbx = static_cast<int> ((g_ewald*xprd/(PI*nx_pppm)) *
pow(-log(EPS_HOC),0.25));
int nby = static_cast<int> ((g_ewald*yprd/(PI*ny_pppm)) *
pow(-log(EPS_HOC),0.25));
int nbz = static_cast<int> ((g_ewald*zprd_slab/(PI*nz_pppm)) *
pow(-log(EPS_HOC),0.25));
double form = 1.0;
n = 0;
for (m = nzlo_fft; m <= nzhi_fft; m++) {
mper = m - nz_pppm*(2*m/nz_pppm);
snz = sin(0.5*unitkz*mper*zprd_slab/nz_pppm);
snz2 = snz*snz;
for (l = nylo_fft; l <= nyhi_fft; l++) {
lper = l - ny_pppm*(2*l/ny_pppm);
sny = sin(0.5*unitky*lper*yprd/ny_pppm);
sny2 = sny*sny;
for (k = nxlo_fft; k <= nxhi_fft; k++) {
kper = k - nx_pppm*(2*k/nx_pppm);
snx = sin(0.5*unitkx*kper*xprd/nx_pppm);
snx2 = snx*snx;
sqk = pow(unitkx*kper,2.0) + pow(unitky*lper,2.0) +
pow(unitkz*mper,2.0);
if (sqk != 0.0) {
numerator = form*12.5663706/sqk;
denominator = gf_denom(snx2,sny2,snz2);
sum1 = 0.0;
for (nx = -nbx; nx <= nbx; nx++) {
qx = unitkx*(kper+nx_pppm*nx);
sx = exp(-.25*pow(qx/g_ewald,2.0));
wx = 1.0;
argx = 0.5*qx*xprd/nx_pppm;
if (argx != 0.0) wx = pow(sin(argx)/argx,order);
for (ny = -nby; ny <= nby; ny++) {
qy = unitky*(lper+ny_pppm*ny);
sy = exp(-.25*pow(qy/g_ewald,2.0));
wy = 1.0;
argy = 0.5*qy*yprd/ny_pppm;
if (argy != 0.0) wy = pow(sin(argy)/argy,order);
for (nz = -nbz; nz <= nbz; nz++) {
qz = unitkz*(mper+nz_pppm*nz);
sz = exp(-.25*pow(qz/g_ewald,2.0));
wz = 1.0;
argz = 0.5*qz*zprd_slab/nz_pppm;
if (argz != 0.0) wz = pow(sin(argz)/argz,order);
dot1 = unitkx*kper*qx + unitky*lper*qy + unitkz*mper*qz;
dot2 = qx*qx+qy*qy+qz*qz;
sum1 += (dot1/dot2) * sx*sy*sz * pow(wx*wy*wz,2.0);
}
}
}
greensfn[n++] = numerator*sum1/denominator;
} else greensfn[n++] = 0.0;
}
}
}
}
/* ----------------------------------------------------------------------
compute the PPPM long-range force, energy, virial
------------------------------------------------------------------------- */
void PPPM::compute(int eflag, int vflag)
{
int i;
// convert atoms from box to lamda coords
if (triclinic == 0) boxlo = domain->boxlo;
else {
boxlo = domain->boxlo_lamda;
domain->x2lamda(atom->nlocal);
}
// extend size of per-atom arrays if necessary
if (atom->nlocal > nmax) {
memory->destroy(part2grid);
nmax = atom->nmax;
memory->create(part2grid,nmax,3,"pppm:part2grid");
}
energy = 0.0;
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
// find grid points for all my particles
// map my particle charge onto my local 3d density grid
particle_map();
make_rho();
// all procs communicate density values from their ghost cells
// to fully sum contribution in their 3d bricks
// remap from 3d decomposition to FFT decomposition
brick2fft();
// compute potential gradient on my FFT grid and
// portion of e_long on this proc's FFT grid
// return gradients (electric fields) in 3d brick decomposition
poisson(eflag,vflag);
// all procs communicate E-field values to fill ghost cells
// surrounding their 3d bricks
fillbrick();
// calculate the force on my particles
fieldforce();
// sum energy across procs and add in volume-dependent term
if (eflag) {
double energy_all;
MPI_Allreduce(&energy,&energy_all,1,MPI_DOUBLE,MPI_SUM,world);
energy = energy_all;
energy *= 0.5*volume;
energy -= g_ewald*qsqsum/1.772453851 +
0.5*PI*qsum*qsum / (g_ewald*g_ewald*volume);
energy *= qqrd2e*scale;
}
// sum virial across procs
if (vflag) {
double virial_all[6];
MPI_Allreduce(virial,virial_all,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) virial[i] = 0.5*qqrd2e*scale*volume*virial_all[i];
}
// 2d slab correction
if (slabflag) slabcorr(eflag);
// convert atoms back from lamda to box coords
if (triclinic) domain->lamda2x(atom->nlocal);
}
/* ----------------------------------------------------------------------
allocate memory that depends on # of K-vectors and order
------------------------------------------------------------------------- */
void PPPM::allocate()
{
memory->create3d_offset(density_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:density_brick");
memory->create3d_offset(vdx_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vdx_brick");
memory->create3d_offset(vdy_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vdy_brick");
memory->create3d_offset(vdz_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vdz_brick");
memory->create(density_fft,nfft_both,"pppm:density_fft");
memory->create(greensfn,nfft_both,"pppm:greensfn");
memory->create(work1,2*nfft_both,"pppm:work1");
memory->create(work2,2*nfft_both,"pppm:work2");
memory->create(vg,nfft_both,6,"pppm:vg");
memory->create1d_offset(fkx,nxlo_fft,nxhi_fft,"pppm:fkx");
memory->create1d_offset(fky,nylo_fft,nyhi_fft,"pppm:fky");
memory->create1d_offset(fkz,nzlo_fft,nzhi_fft,"pppm:fkz");
memory->create(buf1,nbuf,"pppm:buf1");
memory->create(buf2,nbuf,"pppm:buf2");
// summation coeffs
memory->create(gf_b,order,"pppm:gf_b");
memory->create2d_offset(rho1d,3,-order/2,order/2,"pppm:rho1d");
memory->create2d_offset(rho_coeff,order,(1-order)/2,order/2,"pppm:rho_coeff");
// create 2 FFTs and a Remap
// 1st FFT keeps data in FFT decompostion
// 2nd FFT returns data in 3d brick decomposition
// remap takes data from 3d brick to FFT decomposition
int tmp;
fft1 = new FFT3d(lmp,world,nx_pppm,ny_pppm,nz_pppm,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
0,0,&tmp);
fft2 = new FFT3d(lmp,world,nx_pppm,ny_pppm,nz_pppm,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in,
0,0,&tmp);
remap = new Remap(lmp,world,
nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
1,0,0,FFT_PRECISION);
}
/* ----------------------------------------------------------------------
deallocate memory that depends on # of K-vectors and order
------------------------------------------------------------------------- */
void PPPM::deallocate()
{
memory->destroy3d_offset(density_brick,nzlo_out,nylo_out,nxlo_out);
memory->destroy3d_offset(vdx_brick,nzlo_out,nylo_out,nxlo_out);
memory->destroy3d_offset(vdy_brick,nzlo_out,nylo_out,nxlo_out);
memory->destroy3d_offset(vdz_brick,nzlo_out,nylo_out,nxlo_out);
memory->destroy(density_fft);
memory->destroy(greensfn);
memory->destroy(work1);
memory->destroy(work2);
memory->destroy(vg);
memory->destroy1d_offset(fkx,nxlo_fft);
memory->destroy1d_offset(fky,nylo_fft);
memory->destroy1d_offset(fkz,nzlo_fft);
memory->destroy(buf1);
memory->destroy(buf2);
memory->destroy(gf_b);
memory->destroy2d_offset(rho1d,-order/2);
memory->destroy2d_offset(rho_coeff,(1-order)/2);
delete fft1;
delete fft2;
delete remap;
}
/* ----------------------------------------------------------------------
set size of FFT grid (nx,ny,nz_pppm) and g_ewald
------------------------------------------------------------------------- */
void PPPM::set_grid()
{
// see JCP 109, pg 7698 for derivation of coefficients
// higher order coefficients may be computed if needed
double **acons;
memory->create(acons,8,7,"pppm:acons");
acons[1][0] = 2.0 / 3.0;
acons[2][0] = 1.0 / 50.0;
acons[2][1] = 5.0 / 294.0;
acons[3][0] = 1.0 / 588.0;
acons[3][1] = 7.0 / 1440.0;
acons[3][2] = 21.0 / 3872.0;
acons[4][0] = 1.0 / 4320.0;
acons[4][1] = 3.0 / 1936.0;
acons[4][2] = 7601.0 / 2271360.0;
acons[4][3] = 143.0 / 28800.0;
acons[5][0] = 1.0 / 23232.0;
acons[5][1] = 7601.0 / 13628160.0;
acons[5][2] = 143.0 / 69120.0;
acons[5][3] = 517231.0 / 106536960.0;
acons[5][4] = 106640677.0 / 11737571328.0;
acons[6][0] = 691.0 / 68140800.0;
acons[6][1] = 13.0 / 57600.0;
acons[6][2] = 47021.0 / 35512320.0;
acons[6][3] = 9694607.0 / 2095994880.0;
acons[6][4] = 733191589.0 / 59609088000.0;
acons[6][5] = 326190917.0 / 11700633600.0;
acons[7][0] = 1.0 / 345600.0;
acons[7][1] = 3617.0 / 35512320.0;
acons[7][2] = 745739.0 / 838397952.0;
acons[7][3] = 56399353.0 / 12773376000.0;
acons[7][4] = 25091609.0 / 1560084480.0;
acons[7][5] = 1755948832039.0 / 36229939200000.0;
acons[7][6] = 4887769399.0 / 37838389248.0;
double q2 = qsqsum / force->dielectric;
bigint natoms = atom->natoms;
// use xprd,yprd,zprd even if triclinic so grid size is the same
// adjust z dimension for 2d slab PPPM
// 3d PPPM just uses zprd since slab_volfactor = 1.0
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double zprd_slab = zprd*slab_volfactor;
// make initial g_ewald estimate
// based on desired error and real space cutoff
// fluid-occupied volume used to estimate real-space error
// zprd used rather than zprd_slab
double h_x,h_y,h_z;
if (!gewaldflag)
g_ewald = sqrt(-log(precision*sqrt(natoms*cutoff*xprd*yprd*zprd) /
(2.0*q2))) / cutoff;
// set optimal nx_pppm,ny_pppm,nz_pppm based on order and precision
// nz_pppm uses extended zprd_slab instead of zprd
// h = 1/g_ewald is upper bound on h such that h*g_ewald <= 1
// reduce it until precision target is met
if (!gridflag) {
double err;
h_x = h_y = h_z = 1/g_ewald;
nx_pppm = static_cast<int> (xprd/h_x + 1);
ny_pppm = static_cast<int> (yprd/h_y + 1);
nz_pppm = static_cast<int> (zprd_slab/h_z + 1);
err = rms(h_x,xprd,natoms,q2,acons);
while (err > precision) {
err = rms(h_x,xprd,natoms,q2,acons);
nx_pppm++;
h_x = xprd/nx_pppm;
}
err = rms(h_y,yprd,natoms,q2,acons);
while (err > precision) {
err = rms(h_y,yprd,natoms,q2,acons);
ny_pppm++;
h_y = yprd/ny_pppm;
}
err = rms(h_z,zprd_slab,natoms,q2,acons);
while (err > precision) {
err = rms(h_z,zprd_slab,natoms,q2,acons);
nz_pppm++;
h_z = zprd_slab/nz_pppm;
}
}
// boost grid size until it is factorable
while (!factorable(nx_pppm)) nx_pppm++;
while (!factorable(ny_pppm)) ny_pppm++;
while (!factorable(nz_pppm)) nz_pppm++;
// adjust g_ewald for new grid size
h_x = xprd/nx_pppm;
h_y = yprd/ny_pppm;
h_z = zprd_slab/nz_pppm;
if (!gewaldflag) {
double gew1,gew2,dgew,f,fmid,hmin,rtb;
int ncount;
gew1 = 0.0;
g_ewald = gew1;
f = diffpr(h_x,h_y,h_z,q2,acons);
hmin = MIN(h_x,MIN(h_y,h_z));
gew2 = 10/hmin;
g_ewald = gew2;
fmid = diffpr(h_x,h_y,h_z,q2,acons);
- if (f*fmid >= 0.0) error->all("Cannot compute PPPM G");
+ if (f*fmid >= 0.0) error->all(FLERR,"Cannot compute PPPM G");
rtb = f < 0.0 ? (dgew=gew2-gew1,gew1) : (dgew=gew1-gew2,gew2);
ncount = 0;
while (fabs(dgew) > SMALL && fmid != 0.0) {
dgew *= 0.5;
g_ewald = rtb + dgew;
fmid = diffpr(h_x,h_y,h_z,q2,acons);
if (fmid <= 0.0) rtb = g_ewald;
ncount++;
- if (ncount > LARGE) error->all("Cannot compute PPPM G");
+ if (ncount > LARGE) error->all(FLERR,"Cannot compute PPPM G");
}
}
// final RMS precision
double lprx = rms(h_x,xprd,natoms,q2,acons);
double lpry = rms(h_y,yprd,natoms,q2,acons);
double lprz = rms(h_z,zprd_slab,natoms,q2,acons);
double lpr = sqrt(lprx*lprx + lpry*lpry + lprz*lprz) / sqrt(3.0);
double spr = 2.0*q2 * exp(-g_ewald*g_ewald*cutoff*cutoff) /
sqrt(natoms*cutoff*xprd*yprd*zprd_slab);
// free local memory
memory->destroy(acons);
// print info
if (me == 0) {
#ifdef FFT_SINGLE
const char fft_prec[] = "single";
#else
const char fft_prec[] = "double";
#endif
if (screen) {
fprintf(screen," G vector = %g\n",g_ewald);
fprintf(screen," grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
fprintf(screen," stencil order = %d\n",order);
fprintf(screen," RMS precision = %g\n",MAX(lpr,spr));
fprintf(screen," using %s precision FFTs\n",fft_prec);
}
if (logfile) {
fprintf(logfile," G vector = %g\n",g_ewald);
fprintf(logfile," grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
fprintf(logfile," stencil order = %d\n",order);
fprintf(logfile," RMS precision = %g\n",MAX(lpr,spr));
fprintf(logfile," using %s precision FFTs\n",fft_prec);
}
}
}
/* ----------------------------------------------------------------------
check if all factors of n are in list of factors
return 1 if yes, 0 if no
------------------------------------------------------------------------- */
int PPPM::factorable(int n)
{
int i;
while (n > 1) {
for (i = 0; i < nfactors; i++) {
if (n % factors[i] == 0) {
n /= factors[i];
break;
}
}
if (i == nfactors) return 0;
}
return 1;
}
/* ----------------------------------------------------------------------
compute RMS precision for a dimension
------------------------------------------------------------------------- */
double PPPM::rms(double h, double prd, bigint natoms,
double q2, double **acons)
{
double sum = 0.0;
for (int m = 0; m < order; m++)
sum += acons[order][m] * pow(h*g_ewald,2.0*m);
double value = q2 * pow(h*g_ewald,order) *
sqrt(g_ewald*prd*sqrt(2.0*PI)*sum/natoms) / (prd*prd);
return value;
}
/* ----------------------------------------------------------------------
compute difference in real-space and kspace RMS precision
------------------------------------------------------------------------- */
double PPPM::diffpr(double h_x, double h_y, double h_z, double q2, double **acons)
{
double lprx,lpry,lprz,kspace_prec,real_prec;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
bigint natoms = atom->natoms;
lprx = rms(h_x,xprd,natoms,q2,acons);
lpry = rms(h_y,yprd,natoms,q2,acons);
lprz = rms(h_z,zprd*slab_volfactor,natoms,q2,acons);
kspace_prec = sqrt(lprx*lprx + lpry*lpry + lprz*lprz) / sqrt(3.0);
real_prec = 2.0*q2 * exp(-g_ewald*g_ewald*cutoff*cutoff) /
sqrt(static_cast<double>(natoms)*cutoff*xprd*yprd*zprd);
double value = kspace_prec - real_prec;
return value;
}
/* ----------------------------------------------------------------------
denominator for Hockney-Eastwood Green's function
of x,y,z = sin(kx*deltax/2), etc
inf n-1
S(n,k) = Sum W(k+pi*j)**2 = Sum b(l)*(z*z)**l
j=-inf l=0
= -(z*z)**n /(2n-1)! * (d/dx)**(2n-1) cot(x) at z = sin(x)
gf_b = denominator expansion coeffs
------------------------------------------------------------------------- */
double PPPM::gf_denom(double x, double y, double z)
{
double sx,sy,sz;
sz = sy = sx = 0.0;
for (int l = order-1; l >= 0; l--) {
sx = gf_b[l] + sx*x;
sy = gf_b[l] + sy*y;
sz = gf_b[l] + sz*z;
}
double s = sx*sy*sz;
return s*s;
}
/* ----------------------------------------------------------------------
pre-compute Green's function denominator expansion coeffs, Gamma(2n)
------------------------------------------------------------------------- */
void PPPM::compute_gf_denom()
{
int k,l,m;
for (l = 1; l < order; l++) gf_b[l] = 0.0;
gf_b[0] = 1.0;
for (m = 1; m < order; m++) {
for (l = m; l > 0; l--)
gf_b[l] = 4.0 * (gf_b[l]*(l-m)*(l-m-0.5)-gf_b[l-1]*(l-m-1)*(l-m-1));
gf_b[0] = 4.0 * (gf_b[0]*(l-m)*(l-m-0.5));
}
int ifact = 1;
for (k = 1; k < 2*order; k++) ifact *= k;
double gaminv = 1.0/ifact;
for (l = 0; l < order; l++) gf_b[l] *= gaminv;
}
/* ----------------------------------------------------------------------
ghost-swap to accumulate full density in brick decomposition
remap density from 3d brick decomposition to FFT decomposition
------------------------------------------------------------------------- */
void PPPM::brick2fft()
{
int i,n,ix,iy,iz;
MPI_Request request;
MPI_Status status;
// pack my ghosts for +x processor
// pass data to self or +x processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxhi_in+1; ix <= nxhi_out; ix++)
buf1[n++] = density_brick[iz][iy][ix];
if (comm->procneigh[0][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxlo_in; ix < nxlo_in+nxlo_ghost; ix++)
density_brick[iz][iy][ix] += buf2[n++];
// pack my ghosts for -x processor
// pass data to self or -x processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxlo_out; ix < nxlo_in; ix++)
buf1[n++] = density_brick[iz][iy][ix];
if (comm->procneigh[0][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxhi_in-nxhi_ghost+1; ix <= nxhi_in; ix++)
density_brick[iz][iy][ix] += buf2[n++];
// pack my ghosts for +y processor
// pass data to self or +y processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in+1; iy <= nyhi_out; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick[iz][iy][ix];
if (comm->procneigh[1][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy < nylo_in+nylo_ghost; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick[iz][iy][ix] += buf2[n++];
// pack my ghosts for -y processor
// pass data to self or -y processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy < nylo_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick[iz][iy][ix];
if (comm->procneigh[1][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in-nyhi_ghost+1; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick[iz][iy][ix] += buf2[n++];
// pack my ghosts for +z processor
// pass data to self or +z processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzhi_in+1; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick[iz][iy][ix];
if (comm->procneigh[2][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_in; iz < nzlo_in+nzlo_ghost; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick[iz][iy][ix] += buf2[n++];
// pack my ghosts for -z processor
// pass data to self or -z processor
// unpack and sum recv data into my real cells
n = 0;
for (iz = nzlo_out; iz < nzlo_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
buf1[n++] = density_brick[iz][iy][ix];
if (comm->procneigh[2][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzhi_in-nzhi_ghost+1; iz <= nzhi_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_brick[iz][iy][ix] += buf2[n++];
// remap from 3d brick decomposition to FFT decomposition
// copy grabs inner portion of density from 3d brick
// remap could be done as pre-stage of FFT,
// but this works optimally on only double values, not complex values
n = 0;
for (iz = nzlo_in; iz <= nzhi_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++)
density_fft[n++] = density_brick[iz][iy][ix];
remap->perform(density_fft,density_fft,work1);
}
/* ----------------------------------------------------------------------
ghost-swap to fill ghost cells of my brick with field values
------------------------------------------------------------------------- */
void PPPM::fillbrick()
{
int i,n,ix,iy,iz;
MPI_Request request;
MPI_Status status;
// pack my real cells for +z processor
// pass data to self or +z processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzhi_in-nzhi_ghost+1; iz <= nzhi_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
buf1[n++] = vdx_brick[iz][iy][ix];
buf1[n++] = vdy_brick[iz][iy][ix];
buf1[n++] = vdz_brick[iz][iy][ix];
}
if (comm->procneigh[2][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz < nzlo_in; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
vdx_brick[iz][iy][ix] = buf2[n++];
vdy_brick[iz][iy][ix] = buf2[n++];
vdz_brick[iz][iy][ix] = buf2[n++];
}
// pack my real cells for -z processor
// pass data to self or -z processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_in; iz < nzlo_in+nzlo_ghost; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
buf1[n++] = vdx_brick[iz][iy][ix];
buf1[n++] = vdy_brick[iz][iy][ix];
buf1[n++] = vdz_brick[iz][iy][ix];
}
if (comm->procneigh[2][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[2][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[2][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzhi_in+1; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
vdx_brick[iz][iy][ix] = buf2[n++];
vdy_brick[iz][iy][ix] = buf2[n++];
vdz_brick[iz][iy][ix] = buf2[n++];
}
// pack my real cells for +y processor
// pass data to self or +y processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in-nyhi_ghost+1; iy <= nyhi_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
buf1[n++] = vdx_brick[iz][iy][ix];
buf1[n++] = vdy_brick[iz][iy][ix];
buf1[n++] = vdz_brick[iz][iy][ix];
}
if (comm->procneigh[1][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy < nylo_in; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
vdx_brick[iz][iy][ix] = buf2[n++];
vdy_brick[iz][iy][ix] = buf2[n++];
vdz_brick[iz][iy][ix] = buf2[n++];
}
// pack my real cells for -y processor
// pass data to self or -y processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_in; iy < nylo_in+nylo_ghost; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
buf1[n++] = vdx_brick[iz][iy][ix];
buf1[n++] = vdy_brick[iz][iy][ix];
buf1[n++] = vdz_brick[iz][iy][ix];
}
if (comm->procneigh[1][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[1][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[1][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nyhi_in+1; iy <= nyhi_out; iy++)
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
vdx_brick[iz][iy][ix] = buf2[n++];
vdy_brick[iz][iy][ix] = buf2[n++];
vdz_brick[iz][iy][ix] = buf2[n++];
}
// pack my real cells for +x processor
// pass data to self or +x processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxhi_in-nxhi_ghost+1; ix <= nxhi_in; ix++) {
buf1[n++] = vdx_brick[iz][iy][ix];
buf1[n++] = vdy_brick[iz][iy][ix];
buf1[n++] = vdz_brick[iz][iy][ix];
}
if (comm->procneigh[0][1] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxlo_out; ix < nxlo_in; ix++) {
vdx_brick[iz][iy][ix] = buf2[n++];
vdy_brick[iz][iy][ix] = buf2[n++];
vdz_brick[iz][iy][ix] = buf2[n++];
}
// pack my real cells for -x processor
// pass data to self or -x processor
// unpack and sum recv data into my ghost cells
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxlo_in; ix < nxlo_in+nxlo_ghost; ix++) {
buf1[n++] = vdx_brick[iz][iy][ix];
buf1[n++] = vdy_brick[iz][iy][ix];
buf1[n++] = vdz_brick[iz][iy][ix];
}
if (comm->procneigh[0][0] == me)
for (i = 0; i < n; i++) buf2[i] = buf1[i];
else {
MPI_Irecv(buf2,nbuf,MPI_FFT_SCALAR,comm->procneigh[0][1],0,world,&request);
MPI_Send(buf1,n,MPI_FFT_SCALAR,comm->procneigh[0][0],0,world);
MPI_Wait(&request,&status);
}
n = 0;
for (iz = nzlo_out; iz <= nzhi_out; iz++)
for (iy = nylo_out; iy <= nyhi_out; iy++)
for (ix = nxhi_in+1; ix <= nxhi_out; ix++) {
vdx_brick[iz][iy][ix] = buf2[n++];
vdy_brick[iz][iy][ix] = buf2[n++];
vdz_brick[iz][iy][ix] = buf2[n++];
}
}
/* ----------------------------------------------------------------------
find center grid pt for each of my particles
check that full stencil for the particle will fit in my 3d brick
store central grid pt indices in part2grid array
------------------------------------------------------------------------- */
void PPPM::particle_map()
{
int nx,ny,nz;
double **x = atom->x;
int nlocal = atom->nlocal;
int flag = 0;
for (int i = 0; i < nlocal; i++) {
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// current particle coord can be outside global and local box
// add/subtract OFFSET to avoid int(-0.75) = 0 when want it to be -1
nx = static_cast<int> ((x[i][0]-boxlo[0])*delxinv+shift) - OFFSET;
ny = static_cast<int> ((x[i][1]-boxlo[1])*delyinv+shift) - OFFSET;
nz = static_cast<int> ((x[i][2]-boxlo[2])*delzinv+shift) - OFFSET;
part2grid[i][0] = nx;
part2grid[i][1] = ny;
part2grid[i][2] = nz;
// check that entire stencil around nx,ny,nz will fit in my 3d brick
if (nx+nlower < nxlo_out || nx+nupper > nxhi_out ||
ny+nlower < nylo_out || ny+nupper > nyhi_out ||
nz+nlower < nzlo_out || nz+nupper > nzhi_out) flag = 1;
}
- if (flag) error->one("Out of range atoms - cannot compute PPPM");
+ if (flag) error->one(FLERR,"Out of range atoms - cannot compute PPPM");
}
/* ----------------------------------------------------------------------
create discretized "density" on section of global grid due to my particles
density(x,y,z) = charge "density" at grid points of my 3d brick
(nxlo:nxhi,nylo:nyhi,nzlo:nzhi) is extent of my brick (including ghosts)
in global grid
------------------------------------------------------------------------- */
void PPPM::make_rho()
{
int i,l,m,n,nx,ny,nz,mx,my,mz;
FFT_SCALAR dx,dy,dz,x0,y0,z0;
// clear 3d density array
FFT_SCALAR *vec = &density_brick[nzlo_out][nylo_out][nxlo_out];
for (i = 0; i < ngrid; i++) vec[i] = ZEROF;
// loop over my charges, add their contribution to nearby grid points
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// (dx,dy,dz) = distance to "lower left" grid pt
// (mx,my,mz) = global coords of moving stencil pt
double *q = atom->q;
double **x = atom->x;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
nx = part2grid[i][0];
ny = part2grid[i][1];
nz = part2grid[i][2];
dx = nx+shiftone - (x[i][0]-boxlo[0])*delxinv;
dy = ny+shiftone - (x[i][1]-boxlo[1])*delyinv;
dz = nz+shiftone - (x[i][2]-boxlo[2])*delzinv;
compute_rho1d(dx,dy,dz);
z0 = delvolinv * q[i];
for (n = nlower; n <= nupper; n++) {
mz = n+nz;
y0 = z0*rho1d[2][n];
for (m = nlower; m <= nupper; m++) {
my = m+ny;
x0 = y0*rho1d[1][m];
for (l = nlower; l <= nupper; l++) {
mx = l+nx;
density_brick[mz][my][mx] += x0*rho1d[0][l];
}
}
}
}
}
/* ----------------------------------------------------------------------
FFT-based Poisson solver
------------------------------------------------------------------------- */
void PPPM::poisson(int eflag, int vflag)
{
int i,j,k,n;
double eng;
// transform charge density (r -> k)
n = 0;
for (i = 0; i < nfft; i++) {
work1[n++] = density_fft[i];
work1[n++] = ZEROF;
}
fft1->compute(work1,work1,1);
// if requested, compute energy and virial contribution
double scaleinv = 1.0/(nx_pppm*ny_pppm*nz_pppm);
double s2 = scaleinv*scaleinv;
if (eflag || vflag) {
if (vflag) {
n = 0;
for (i = 0; i < nfft; i++) {
eng = s2 * greensfn[i] * (work1[n]*work1[n] + work1[n+1]*work1[n+1]);
for (j = 0; j < 6; j++) virial[j] += eng*vg[i][j];
energy += eng;
n += 2;
}
} else {
n = 0;
for (i = 0; i < nfft; i++) {
energy +=
s2 * greensfn[i] * (work1[n]*work1[n] + work1[n+1]*work1[n+1]);
n += 2;
}
}
}
// scale by 1/total-grid-pts to get rho(k)
// multiply by Green's function to get V(k)
n = 0;
for (i = 0; i < nfft; i++) {
work1[n++] *= scaleinv * greensfn[i];
work1[n++] *= scaleinv * greensfn[i];
}
// compute gradients of V(r) in each of 3 dims by transformimg -ik*V(k)
// FFT leaves data in 3d brick decomposition
// copy it into inner portion of vdx,vdy,vdz arrays
// x direction gradient
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++)
for (j = nylo_fft; j <= nyhi_fft; j++)
for (i = nxlo_fft; i <= nxhi_fft; i++) {
work2[n] = fkx[i]*work1[n+1];
work2[n+1] = -fkx[i]*work1[n];
n += 2;
}
fft2->compute(work2,work2,-1);
n = 0;
for (k = nzlo_in; k <= nzhi_in; k++)
for (j = nylo_in; j <= nyhi_in; j++)
for (i = nxlo_in; i <= nxhi_in; i++) {
vdx_brick[k][j][i] = work2[n];
n += 2;
}
// y direction gradient
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++)
for (j = nylo_fft; j <= nyhi_fft; j++)
for (i = nxlo_fft; i <= nxhi_fft; i++) {
work2[n] = fky[j]*work1[n+1];
work2[n+1] = -fky[j]*work1[n];
n += 2;
}
fft2->compute(work2,work2,-1);
n = 0;
for (k = nzlo_in; k <= nzhi_in; k++)
for (j = nylo_in; j <= nyhi_in; j++)
for (i = nxlo_in; i <= nxhi_in; i++) {
vdy_brick[k][j][i] = work2[n];
n += 2;
}
// z direction gradient
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++)
for (j = nylo_fft; j <= nyhi_fft; j++)
for (i = nxlo_fft; i <= nxhi_fft; i++) {
work2[n] = fkz[k]*work1[n+1];
work2[n+1] = -fkz[k]*work1[n];
n += 2;
}
fft2->compute(work2,work2,-1);
n = 0;
for (k = nzlo_in; k <= nzhi_in; k++)
for (j = nylo_in; j <= nyhi_in; j++)
for (i = nxlo_in; i <= nxhi_in; i++) {
vdz_brick[k][j][i] = work2[n];
n += 2;
}
}
/* ----------------------------------------------------------------------
interpolate from grid to get electric field & force on my particles
------------------------------------------------------------------------- */
void PPPM::fieldforce()
{
int i,l,m,n,nx,ny,nz,mx,my,mz;
FFT_SCALAR dx,dy,dz,x0,y0,z0;
FFT_SCALAR ekx,eky,ekz;
// loop over my charges, interpolate electric field from nearby grid points
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// (dx,dy,dz) = distance to "lower left" grid pt
// (mx,my,mz) = global coords of moving stencil pt
// ek = 3 components of E-field on particle
double *q = atom->q;
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
nx = part2grid[i][0];
ny = part2grid[i][1];
nz = part2grid[i][2];
dx = nx+shiftone - (x[i][0]-boxlo[0])*delxinv;
dy = ny+shiftone - (x[i][1]-boxlo[1])*delyinv;
dz = nz+shiftone - (x[i][2]-boxlo[2])*delzinv;
compute_rho1d(dx,dy,dz);
ekx = eky = ekz = ZEROF;
for (n = nlower; n <= nupper; n++) {
mz = n+nz;
z0 = rho1d[2][n];
for (m = nlower; m <= nupper; m++) {
my = m+ny;
y0 = z0*rho1d[1][m];
for (l = nlower; l <= nupper; l++) {
mx = l+nx;
x0 = y0*rho1d[0][l];
ekx -= x0*vdx_brick[mz][my][mx];
eky -= x0*vdy_brick[mz][my][mx];
ekz -= x0*vdz_brick[mz][my][mx];
}
}
}
// convert E-field to force
const double qfactor = qqrd2e*scale*q[i];
f[i][0] += qfactor*ekx;
f[i][1] += qfactor*eky;
f[i][2] += qfactor*ekz;
}
}
/* ----------------------------------------------------------------------
map nprocs to NX by NY grid as PX by PY procs - return optimal px,py
------------------------------------------------------------------------- */
void PPPM::procs2grid2d(int nprocs, int nx, int ny, int *px, int *py)
{
// loop thru all possible factorizations of nprocs
// surf = surface area of largest proc sub-domain
// innermost if test minimizes surface area and surface/volume ratio
int bestsurf = 2 * (nx + ny);
int bestboxx = 0;
int bestboxy = 0;
int boxx,boxy,surf,ipx,ipy;
ipx = 1;
while (ipx <= nprocs) {
if (nprocs % ipx == 0) {
ipy = nprocs/ipx;
boxx = nx/ipx;
if (nx % ipx) boxx++;
boxy = ny/ipy;
if (ny % ipy) boxy++;
surf = boxx + boxy;
if (surf < bestsurf ||
(surf == bestsurf && boxx*boxy > bestboxx*bestboxy)) {
bestsurf = surf;
bestboxx = boxx;
bestboxy = boxy;
*px = ipx;
*py = ipy;
}
}
ipx++;
}
}
/* ----------------------------------------------------------------------
charge assignment into rho1d
dx,dy,dz = distance of particle from "lower left" grid point
------------------------------------------------------------------------- */
void PPPM::compute_rho1d(const FFT_SCALAR &dx, const FFT_SCALAR &dy,
const FFT_SCALAR &dz)
{
int k,l;
for (k = (1-order)/2; k <= order/2; k++) {
rho1d[0][k] = ZEROF;
rho1d[1][k] = ZEROF;
rho1d[2][k] = ZEROF;
for (l = order-1; l >= 0; l--) {
rho1d[0][k] = rho_coeff[l][k] + rho1d[0][k]*dx;
rho1d[1][k] = rho_coeff[l][k] + rho1d[1][k]*dy;
rho1d[2][k] = rho_coeff[l][k] + rho1d[2][k]*dz;
}
}
}
/* ----------------------------------------------------------------------
generate coeffients for the weight function of order n
(n-1)
Wn(x) = Sum wn(k,x) , Sum is over every other integer
k=-(n-1)
For k=-(n-1),-(n-1)+2, ....., (n-1)-2,n-1
k is odd integers if n is even and even integers if n is odd
---
| n-1
| Sum a(l,j)*(x-k/2)**l if abs(x-k/2) < 1/2
wn(k,x) = < l=0
|
| 0 otherwise
---
a coeffients are packed into the array rho_coeff to eliminate zeros
rho_coeff(l,((k+mod(n+1,2))/2) = a(l,k)
------------------------------------------------------------------------- */
void PPPM::compute_rho_coeff()
{
int j,k,l,m;
FFT_SCALAR s;
FFT_SCALAR **a;
memory->create2d_offset(a,order,-order,order,"pppm:a");
for (k = -order; k <= order; k++)
for (l = 0; l < order; l++)
a[l][k] = 0.0;
a[0][0] = 1.0;
for (j = 1; j < order; j++) {
for (k = -j; k <= j; k += 2) {
s = 0.0;
for (l = 0; l < j; l++) {
a[l+1][k] = (a[l][k+1]-a[l][k-1]) / (l+1);
#ifdef FFT_SINGLE
s += powf(0.5,(float) l+1) *
(a[l][k-1] + powf(-1.0,(float) l) * a[l][k+1]) / (l+1);
#else
s += pow(0.5,(double) l+1) *
(a[l][k-1] + pow(-1.0,(double) l) * a[l][k+1]) / (l+1);
#endif
}
a[0][k] = s;
}
}
m = (1-order)/2;
for (k = -(order-1); k < order; k += 2) {
for (l = 0; l < order; l++)
rho_coeff[l][m] = a[l][k];
m++;
}
memory->destroy2d_offset(a,-order);
}
/* ----------------------------------------------------------------------
Slab-geometry correction term to dampen inter-slab interactions between
periodically repeating slabs. Yields good approximation to 2D Ewald if
adequate empty space is left between repeating slabs (J. Chem. Phys.
111, 3155). Slabs defined here to be parallel to the xy plane.
------------------------------------------------------------------------- */
void PPPM::slabcorr(int eflag)
{
// compute local contribution to global dipole moment
double *q = atom->q;
double **x = atom->x;
int nlocal = atom->nlocal;
double dipole = 0.0;
for (int i = 0; i < nlocal; i++) dipole += q[i]*x[i][2];
// sum local contributions to get global dipole moment
double dipole_all;
MPI_Allreduce(&dipole,&dipole_all,1,MPI_DOUBLE,MPI_SUM,world);
// compute corrections
double e_slabcorr = 2.0*PI*dipole_all*dipole_all/volume;
if (eflag) energy += qqrd2e*scale * e_slabcorr;
// add on force corrections
double ffact = -4.0*PI*dipole_all/volume;
double **f = atom->f;
for (int i = 0; i < nlocal; i++) f[i][2] += qqrd2e*scale * q[i]*ffact;
}
/* ----------------------------------------------------------------------
perform and time the 4 FFTs required for N timesteps
------------------------------------------------------------------------- */
void PPPM::timing(int n, double &time3d, double &time1d)
{
double time1,time2;
for (int i = 0; i < 2*nfft_both; i++) work1[i] = ZEROF;
MPI_Barrier(world);
time1 = MPI_Wtime();
for (int i = 0; i < n; i++) {
fft1->compute(work1,work1,1);
fft2->compute(work1,work1,-1);
fft2->compute(work1,work1,-1);
fft2->compute(work1,work1,-1);
}
MPI_Barrier(world);
time2 = MPI_Wtime();
time3d = time2 - time1;
MPI_Barrier(world);
time1 = MPI_Wtime();
for (int i = 0; i < n; i++) {
fft1->timing1d(work1,nfft_both,1);
fft2->timing1d(work1,nfft_both,-1);
fft2->timing1d(work1,nfft_both,-1);
fft2->timing1d(work1,nfft_both,-1);
}
MPI_Barrier(world);
time2 = MPI_Wtime();
time1d = time2 - time1;
}
/* ----------------------------------------------------------------------
memory usage of local arrays
------------------------------------------------------------------------- */
double PPPM::memory_usage()
{
double bytes = nmax*3 * sizeof(double);
int nbrick = (nxhi_out-nxlo_out+1) * (nyhi_out-nylo_out+1) *
(nzhi_out-nzlo_out+1);
bytes += 4 * nbrick * sizeof(FFT_SCALAR);
bytes += 6 * nfft_both * sizeof(double);
bytes += nfft_both * sizeof(double);
bytes += nfft_both*5 * sizeof(FFT_SCALAR);
bytes += 2 * nbuf * sizeof(FFT_SCALAR);
return bytes;
}
diff --git a/src/KSPACE/pppm_cg.cpp b/src/KSPACE/pppm_cg.cpp
index 74b29e465..12860f7ae 100644
--- a/src/KSPACE/pppm_cg.cpp
+++ b/src/KSPACE/pppm_cg.cpp
@@ -1,399 +1,399 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Axel Kohlmeyer (Temple U)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "atom.h"
#include "domain.h"
#include "error.h"
#include "memory.h"
#include "pppm_cg.h"
using namespace LAMMPS_NS;
#define OFFSET 16384
#define SMALLQ 0.00001
#if defined(FFT_SINGLE)
#define ZEROF 0.0f
#else
#define ZEROF 0.0
#endif
/* ---------------------------------------------------------------------- */
PPPMCG::PPPMCG(LAMMPS *lmp, int narg, char **arg) : PPPM(lmp, narg, arg)
{
- if ((narg < 1) || (narg > 2)) error->all("Illegal kspace_style pppm/cg command");
+ if ((narg < 1) || (narg > 2)) error->all(FLERR,"Illegal kspace_style pppm/cg command");
if (narg == 2)
smallq = atof(arg[1]);
else
smallq = SMALLQ;
num_charged = -1;
is_charged = NULL;
}
/* ----------------------------------------------------------------------
free all memory
------------------------------------------------------------------------- */
PPPMCG::~PPPMCG()
{
memory->destroy(is_charged);
}
/* ----------------------------------------------------------------------
compute the PPPM long-range force, energy, virial
------------------------------------------------------------------------- */
void PPPMCG::compute(int eflag, int vflag)
{
int i;
// convert atoms from box to lamda coords
if (triclinic == 0) boxlo = domain->boxlo;
else {
boxlo = domain->boxlo_lamda;
domain->x2lamda(atom->nlocal);
}
// extend size of per-atom arrays if necessary
if (atom->nlocal > nmax) {
memory->destroy(part2grid);
memory->destroy(is_charged);
nmax = atom->nmax;
memory->create(part2grid,nmax,3,"pppm:part2grid");
memory->create(is_charged,nmax,"pppm/cg:is_charged");
}
// one time setup message.
if (num_charged < 0) {
bigint charged_all, charged_num;
double charged_frac, charged_fmax, charged_fmin;
num_charged=0;
for (i=0; i < atom->nlocal; ++i)
if (fabs(atom->q[i]) > smallq)
++num_charged;
// get fraction of charged particles per domain
if (atom->nlocal > 0)
charged_frac = static_cast<double>(num_charged) * 100.0
/ static_cast<double>(atom->nlocal);
else
charged_frac = 0.0;
MPI_Reduce(&charged_frac,&charged_fmax,1,MPI_DOUBLE,MPI_MAX,0,world);
MPI_Reduce(&charged_frac,&charged_fmin,1,MPI_DOUBLE,MPI_MIN,0,world);
// get fraction of charged particles overall
charged_num = num_charged;
MPI_Reduce(&charged_num,&charged_all,1,MPI_LMP_BIGINT,MPI_SUM,0,world);
charged_frac = static_cast<double>(charged_all) * 100.0
/ static_cast<double>(atom->natoms);
if (me == 0) {
if (screen)
fprintf(screen,
" PPPM/cg optimization cutoff: %g\n"
" Total charged atoms: %.1f%%\n"
" Min/max charged atoms/proc: %.1f%% %.1f%%\n",
smallq,charged_frac,charged_fmin,charged_fmax);
if (logfile)
fprintf(logfile,
" PPPM/cg optimization cutoff: %g\n"
" Total charged atoms: %.1f%%\n"
" Min/max charged atoms/proc: %.1f%% %.1f%%\n",
smallq,charged_frac,charged_fmin,charged_fmax);
}
}
num_charged=0;
for (i=0; i < atom->nlocal; ++i)
if (fabs(atom->q[i]) > smallq) {
is_charged[num_charged] = i;
++num_charged;
}
energy = 0.0;
if (vflag) for (i = 0; i < 6; i++) virial[i] = 0.0;
// find grid points for all my particles
// map my particle charge onto my local 3d density grid
particle_map();
make_rho();
// all procs communicate density values from their ghost cells
// to fully sum contribution in their 3d bricks
// remap from 3d decomposition to FFT decomposition
brick2fft();
// compute potential gradient on my FFT grid and
// portion of e_long on this proc's FFT grid
// return gradients (electric fields) in 3d brick decomposition
poisson(eflag,vflag);
// all procs communicate E-field values to fill ghost cells
// surrounding their 3d bricks
fillbrick();
// calculate the force on my particles
fieldforce();
// sum energy across procs and add in volume-dependent term
if (eflag) {
double energy_all;
MPI_Allreduce(&energy,&energy_all,1,MPI_DOUBLE,MPI_SUM,world);
energy = energy_all;
energy *= 0.5*volume;
energy -= g_ewald*qsqsum/1.772453851 +
0.5*PI*qsum*qsum / (g_ewald*g_ewald*volume);
energy *= qqrd2e*scale;
}
// sum virial across procs
if (vflag) {
double virial_all[6];
MPI_Allreduce(virial,virial_all,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) virial[i] = 0.5*qqrd2e*scale*volume*virial_all[i];
}
// 2d slab correction
if (slabflag) slabcorr(eflag);
// convert atoms back from lamda to box coords
if (triclinic) domain->lamda2x(atom->nlocal);
}
/* ----------------------------------------------------------------------
find center grid pt for each of my particles
check that full stencil for the particle will fit in my 3d brick
store central grid pt indices in part2grid array
------------------------------------------------------------------------- */
void PPPMCG::particle_map()
{
int nx,ny,nz;
double **x = atom->x;
int flag = 0;
for (int j = 0; j < num_charged; j++) {
int i = is_charged[j];
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// current particle coord can be outside global and local box
// add/subtract OFFSET to avoid int(-0.75) = 0 when want it to be -1
nx = static_cast<int> ((x[i][0]-boxlo[0])*delxinv+shift) - OFFSET;
ny = static_cast<int> ((x[i][1]-boxlo[1])*delyinv+shift) - OFFSET;
nz = static_cast<int> ((x[i][2]-boxlo[2])*delzinv+shift) - OFFSET;
part2grid[i][0] = nx;
part2grid[i][1] = ny;
part2grid[i][2] = nz;
// check that entire stencil around nx,ny,nz will fit in my 3d brick
if (nx+nlower < nxlo_out || nx+nupper > nxhi_out ||
ny+nlower < nylo_out || ny+nupper > nyhi_out ||
nz+nlower < nzlo_out || nz+nupper > nzhi_out) flag = 1;
}
- if (flag) error->one("Out of range atoms - cannot compute PPPM");
+ if (flag) error->one(FLERR,"Out of range atoms - cannot compute PPPM");
}
/* ----------------------------------------------------------------------
create discretized "density" on section of global grid due to my particles
density(x,y,z) = charge "density" at grid points of my 3d brick
(nxlo:nxhi,nylo:nyhi,nzlo:nzhi) is extent of my brick (including ghosts)
in global grid
------------------------------------------------------------------------- */
void PPPMCG::make_rho()
{
int i,l,m,n,nx,ny,nz,mx,my,mz;
FFT_SCALAR dx,dy,dz,x0,y0,z0;
// clear 3d density array
FFT_SCALAR *vec = &density_brick[nzlo_out][nylo_out][nxlo_out];
for (i = 0; i < ngrid; i++) vec[i] = ZEROF;
// loop over my charges, add their contribution to nearby grid points
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// (dx,dy,dz) = distance to "lower left" grid pt
// (mx,my,mz) = global coords of moving stencil pt
double *q = atom->q;
double **x = atom->x;
for (int j = 0; j < num_charged; j++) {
int i = is_charged[j];
nx = part2grid[i][0];
ny = part2grid[i][1];
nz = part2grid[i][2];
dx = nx+shiftone - (x[i][0]-boxlo[0])*delxinv;
dy = ny+shiftone - (x[i][1]-boxlo[1])*delyinv;
dz = nz+shiftone - (x[i][2]-boxlo[2])*delzinv;
compute_rho1d(dx,dy,dz);
z0 = delvolinv * q[i];
for (n = nlower; n <= nupper; n++) {
mz = n+nz;
y0 = z0*rho1d[2][n];
for (m = nlower; m <= nupper; m++) {
my = m+ny;
x0 = y0*rho1d[1][m];
for (l = nlower; l <= nupper; l++) {
mx = l+nx;
density_brick[mz][my][mx] += x0*rho1d[0][l];
}
}
}
}
}
/* ----------------------------------------------------------------------
interpolate from grid to get electric field & force on my particles
------------------------------------------------------------------------- */
void PPPMCG::fieldforce()
{
int i,l,m,n,nx,ny,nz,mx,my,mz;
FFT_SCALAR dx,dy,dz,x0,y0,z0;
FFT_SCALAR ekx,eky,ekz;
// loop over my charges, interpolate electric field from nearby grid points
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// (dx,dy,dz) = distance to "lower left" grid pt
// (mx,my,mz) = global coords of moving stencil pt
// ek = 3 components of E-field on particle
double *q = atom->q;
double **x = atom->x;
double **f = atom->f;
for (int j = 0; j < num_charged; j++) {
i = is_charged[j];
nx = part2grid[i][0];
ny = part2grid[i][1];
nz = part2grid[i][2];
dx = nx+shiftone - (x[i][0]-boxlo[0])*delxinv;
dy = ny+shiftone - (x[i][1]-boxlo[1])*delyinv;
dz = nz+shiftone - (x[i][2]-boxlo[2])*delzinv;
compute_rho1d(dx,dy,dz);
ekx = eky = ekz = ZEROF;
for (n = nlower; n <= nupper; n++) {
mz = n+nz;
z0 = rho1d[2][n];
for (m = nlower; m <= nupper; m++) {
my = m+ny;
y0 = z0*rho1d[1][m];
for (l = nlower; l <= nupper; l++) {
mx = l+nx;
x0 = y0*rho1d[0][l];
ekx -= x0*vdx_brick[mz][my][mx];
eky -= x0*vdy_brick[mz][my][mx];
ekz -= x0*vdz_brick[mz][my][mx];
}
}
}
// convert E-field to force
const double qfactor = qqrd2e*scale*q[i];
f[i][0] += qfactor*ekx;
f[i][1] += qfactor*eky;
f[i][2] += qfactor*ekz;
}
}
/* ----------------------------------------------------------------------
Slab-geometry correction term to dampen inter-slab interactions between
periodically repeating slabs. Yields good approximation to 2D Ewald if
adequate empty space is left between repeating slabs (J. Chem. Phys.
111, 3155). Slabs defined here to be parallel to the xy plane.
------------------------------------------------------------------------- */
void PPPMCG::slabcorr(int eflag)
{
// compute local contribution to global dipole moment
double *q = atom->q;
double **x = atom->x;
double dipole = 0.0;
for (int j = 0; j < num_charged; j++) {
int i = is_charged[j];
dipole += q[i]*x[i][2];
}
// sum local contributions to get global dipole moment
double dipole_all;
MPI_Allreduce(&dipole,&dipole_all,1,MPI_DOUBLE,MPI_SUM,world);
// compute corrections
double e_slabcorr = 2.0*PI*dipole_all*dipole_all/volume;
if (eflag) energy += qqrd2e*scale * e_slabcorr;
// add on force corrections
double ffact = -4.0*PI*dipole_all/volume * qqrd2e * scale;
double **f = atom->f;
for (int j = 0; j < num_charged; j++) {
int i = is_charged[j];
f[i][2] += q[i]*ffact;
}
}
/* ----------------------------------------------------------------------
memory usage of local arrays
------------------------------------------------------------------------- */
double PPPMCG::memory_usage()
{
double bytes = PPPM::memory_usage();
bytes += nmax * sizeof(int);
return bytes;
}
diff --git a/src/KSPACE/pppm_tip4p.cpp b/src/KSPACE/pppm_tip4p.cpp
index af0af92fa..a191fa742 100644
--- a/src/KSPACE/pppm_tip4p.cpp
+++ b/src/KSPACE/pppm_tip4p.cpp
@@ -1,275 +1,275 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Amalie Frischknecht and Ahmed Ismail (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "pppm_tip4p.h"
#include "atom.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define OFFSET 16384
#ifdef FFT_SINGLE
#define ZEROF 0.0f
#define ONEF 1.0f
#else
#define ZEROF 0.0
#define ONEF 1.0
#endif
/* ---------------------------------------------------------------------- */
PPPMTIP4P::PPPMTIP4P(LAMMPS *lmp, int narg, char **arg) :
PPPM(lmp, narg, arg) {}
/* ----------------------------------------------------------------------
find center grid pt for each of my particles
check that full stencil for the particle will fit in my 3d brick
store central grid pt indices in part2grid array
------------------------------------------------------------------------- */
void PPPMTIP4P::particle_map()
{
int nx,ny,nz,iH1,iH2;
double *xi,xM[3];
int *type = atom->type;
double **x = atom->x;
int nlocal = atom->nlocal;
int flag = 0;
for (int i = 0; i < nlocal; i++) {
if (type[i] == typeO) {
find_M(i,iH1,iH2,xM);
xi = xM;
} else xi = x[i];
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// current particle coord can be outside global and local box
// add/subtract OFFSET to avoid int(-0.75) = 0 when want it to be -1
nx = static_cast<int> ((xi[0]-boxlo[0])*delxinv+shift) - OFFSET;
ny = static_cast<int> ((xi[1]-boxlo[1])*delyinv+shift) - OFFSET;
nz = static_cast<int> ((xi[2]-boxlo[2])*delzinv+shift) - OFFSET;
part2grid[i][0] = nx;
part2grid[i][1] = ny;
part2grid[i][2] = nz;
// check that entire stencil around nx,ny,nz will fit in my 3d brick
if (nx+nlower < nxlo_out || nx+nupper > nxhi_out ||
ny+nlower < nylo_out || ny+nupper > nyhi_out ||
nz+nlower < nzlo_out || nz+nupper > nzhi_out) flag++;
}
int flag_all;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Out of range atoms - cannot compute PPPM");
+ if (flag_all) error->all(FLERR,"Out of range atoms - cannot compute PPPM");
}
/* ----------------------------------------------------------------------
create discretized "density" on section of global grid due to my particles
density(x,y,z) = charge "density" at grid points of my 3d brick
(nxlo:nxhi,nylo:nyhi,nzlo:nzhi) is extent of my brick (including ghosts)
in global grid
------------------------------------------------------------------------- */
void PPPMTIP4P::make_rho()
{
int i,l,m,n,nx,ny,nz,mx,my,mz,iH1,iH2;
FFT_SCALAR dx,dy,dz,x0,y0,z0;
double *xi,xM[3];
// clear 3d density array
FFT_SCALAR *vec = &density_brick[nzlo_out][nylo_out][nxlo_out];
for (i = 0; i < ngrid; i++) vec[i] = ZEROF;
// loop over my charges, add their contribution to nearby grid points
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// (dx,dy,dz) = distance to "lower left" grid pt
// (mx,my,mz) = global coords of moving stencil pt
int *type = atom->type;
double *q = atom->q;
double **x = atom->x;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (type[i] == typeO) {
find_M(i,iH1,iH2,xM);
xi = xM;
} else xi = x[i];
nx = part2grid[i][0];
ny = part2grid[i][1];
nz = part2grid[i][2];
dx = nx+shiftone - (xi[0]-boxlo[0])*delxinv;
dy = ny+shiftone - (xi[1]-boxlo[1])*delyinv;
dz = nz+shiftone - (xi[2]-boxlo[2])*delzinv;
compute_rho1d(dx,dy,dz);
z0 = delvolinv * q[i];
for (n = nlower; n <= nupper; n++) {
mz = n+nz;
y0 = z0*rho1d[2][n];
for (m = nlower; m <= nupper; m++) {
my = m+ny;
x0 = y0*rho1d[1][m];
for (l = nlower; l <= nupper; l++) {
mx = l+nx;
density_brick[mz][my][mx] += x0*rho1d[0][l];
}
}
}
}
}
/* ----------------------------------------------------------------------
interpolate from grid to get electric field & force on my particles
------------------------------------------------------------------------- */
void PPPMTIP4P::fieldforce()
{
int i,l,m,n,nx,ny,nz,mx,my,mz;
FFT_SCALAR dx,dy,dz,x0,y0,z0;
FFT_SCALAR ekx,eky,ekz;
double *xi;
int iH1,iH2;
double xM[3];
double fx,fy,fz;
double ddotf, rOMx, rOMy, rOMz, f1x, f1y, f1z;
// loop over my charges, interpolate electric field from nearby grid points
// (nx,ny,nz) = global coords of grid pt to "lower left" of charge
// (dx,dy,dz) = distance to "lower left" grid pt
// (mx,my,mz) = global coords of moving stencil pt
// ek = 3 components of E-field on particle
double *q = atom->q;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (type[i] == typeO) {
find_M(i,iH1,iH2,xM);
xi = xM;
} else xi = x[i];
nx = part2grid[i][0];
ny = part2grid[i][1];
nz = part2grid[i][2];
dx = nx+shiftone - (xi[0]-boxlo[0])*delxinv;
dy = ny+shiftone - (xi[1]-boxlo[1])*delyinv;
dz = nz+shiftone - (xi[2]-boxlo[2])*delzinv;
compute_rho1d(dx,dy,dz);
ekx = eky = ekz = ZEROF;
for (n = nlower; n <= nupper; n++) {
mz = n+nz;
z0 = rho1d[2][n];
for (m = nlower; m <= nupper; m++) {
my = m+ny;
y0 = z0*rho1d[1][m];
for (l = nlower; l <= nupper; l++) {
mx = l+nx;
x0 = y0*rho1d[0][l];
ekx -= x0*vdx_brick[mz][my][mx];
eky -= x0*vdy_brick[mz][my][mx];
ekz -= x0*vdz_brick[mz][my][mx];
}
}
}
// convert E-field to force
const double qfactor = qqrd2e*scale*q[i];
if (type[i] != typeO) {
f[i][0] += qfactor*ekx;
f[i][1] += qfactor*eky;
f[i][2] += qfactor*ekz;
} else {
fx = qfactor * ekx;
fy = qfactor * eky;
fz = qfactor * ekz;
find_M(i,iH1,iH2,xM);
rOMx = xM[0] - x[i][0];
rOMy = xM[1] - x[i][1];
rOMz = xM[2] - x[i][2];
ddotf = (rOMx * fx + rOMy * fy + rOMz * fz) / (qdist * qdist);
f1x = ddotf * rOMx;
f1y = ddotf * rOMy;
f1z = ddotf * rOMz;
f[i][0] += fx - alpha * (fx - f1x);
f[i][1] += fy - alpha * (fy - f1y);
f[i][2] += fz - alpha * (fz - f1z);
f[iH1][0] += 0.5*alpha*(fx - f1x);
f[iH1][1] += 0.5*alpha*(fy - f1y);
f[iH1][2] += 0.5*alpha*(fz - f1z);
f[iH2][0] += 0.5*alpha*(fx - f1x);
f[iH2][1] += 0.5*alpha*(fy - f1y);
f[iH2][2] += 0.5*alpha*(fz - f1z);
}
}
}
/* ----------------------------------------------------------------------
find 2 H atoms bonded to O atom i
compute position xM of fictitious charge site for O atom
also return local indices iH1,iH2 of H atoms
------------------------------------------------------------------------- */
void PPPMTIP4P::find_M(int i, int &iH1, int &iH2, double *xM)
{
iH1 = atom->map(atom->tag[i] + 1);
iH2 = atom->map(atom->tag[i] + 2);
- if (iH1 == -1 || iH2 == -1) error->one("TIP4P hydrogen is missing");
+ if (iH1 == -1 || iH2 == -1) error->one(FLERR,"TIP4P hydrogen is missing");
if (atom->type[iH1] != typeH || atom->type[iH2] != typeH)
- error->one("TIP4P hydrogen has incorrect atom type");
+ error->one(FLERR,"TIP4P hydrogen has incorrect atom type");
double **x = atom->x;
double delx1 = x[iH1][0] - x[i][0];
double dely1 = x[iH1][1] - x[i][1];
double delz1 = x[iH1][2] - x[i][2];
domain->minimum_image(delx1,dely1,delz1);
double delx2 = x[iH2][0] - x[i][0];
double dely2 = x[iH2][1] - x[i][1];
double delz2 = x[iH2][2] - x[i][2];
domain->minimum_image(delx2,dely2,delz2);
xM[0] = x[i][0] + alpha * 0.5 * (delx1 + delx2);
xM[1] = x[i][1] + alpha * 0.5 * (dely1 + dely2);
xM[2] = x[i][2] + alpha * 0.5 * (delz1 + delz2);
}
diff --git a/src/KSPACE/remap_wrap.cpp b/src/KSPACE/remap_wrap.cpp
index 83631defe..679c2a836 100644
--- a/src/KSPACE/remap_wrap.cpp
+++ b/src/KSPACE/remap_wrap.cpp
@@ -1,48 +1,48 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "remap_wrap.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Remap::Remap(LAMMPS *lmp, MPI_Comm comm,
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
int in_klo, int in_khi,
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
int out_klo, int out_khi,
int nqty, int permute, int memory, int precision) : Pointers(lmp)
{
plan = remap_3d_create_plan(comm,
in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
out_ilo,out_ihi,out_jlo,out_jhi,out_klo,out_khi,
nqty,permute,memory,precision);
- if (plan == NULL) error->one("Could not create 3d remap plan");
+ if (plan == NULL) error->one(FLERR,"Could not create 3d remap plan");
}
/* ---------------------------------------------------------------------- */
Remap::~Remap()
{
remap_3d_destroy_plan(plan);
}
/* ---------------------------------------------------------------------- */
void Remap::perform(FFT_SCALAR *in, FFT_SCALAR *out, FFT_SCALAR *buf)
{
remap_3d(in,out,buf,plan);
}
diff --git a/src/MANYBODY/fix_qeq_comb.cpp b/src/MANYBODY/fix_qeq_comb.cpp
index d1537f78b..7d36ee157 100644
--- a/src/MANYBODY/fix_qeq_comb.cpp
+++ b/src/MANYBODY/fix_qeq_comb.cpp
@@ -1,255 +1,252 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Tzu-Ray Shan (U Florida, rayshan@ufl.edu)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_qeq_comb.h"
#include "atom.h"
#include "force.h"
#include "group.h"
#include "respa.h"
#include "pair_comb.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixQEQComb::FixQEQComb(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix qeq/comb command");
+ if (narg < 5) error->all(FLERR,"Illegal fix qeq/comb command");
peratom_flag = 1;
size_peratom_cols = 0;
peratom_freq = 1;
nevery = force->inumeric(arg[3]);
precision = force->numeric(arg[4]);
if (nevery <= 0 || precision <= 0.0)
- error->all("Illegal fix qeq/comb command");
+ error->all(FLERR,"Illegal fix qeq/comb command");
MPI_Comm_rank(world,&me);
// optional args
fp = NULL;
int iarg = 5;
while (iarg < narg) {
if (strcmp(arg[iarg],"file") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix qeq/comb command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix qeq/comb command");
if (me == 0) {
fp = fopen(arg[iarg+1],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix qeq/comb file %s",arg[iarg+1]);
- error->one(str);
+ error->one(FLERR,str);
}
}
iarg += 2;
- } else error->all("Illegal fix qeq/comb command");
+ } else error->all(FLERR,"Illegal fix qeq/comb command");
}
nmax = atom->nmax;
memory->create(qf,nmax,"qeq:qf");
memory->create(q1,nmax,"qeq:q1");
memory->create(q2,nmax,"qeq:q2");
vector_atom = qf;
// zero the vector since dump may access it on timestep 0
// zero the vector since a variable may access it before first run
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) qf[i] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixQEQComb::~FixQEQComb()
{
if (me == 0 && fp) fclose(fp);
memory->destroy(qf);
memory->destroy(q1);
memory->destroy(q2);
}
/* ---------------------------------------------------------------------- */
int FixQEQComb::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixQEQComb::init()
{
if (!atom->q_flag)
- error->all("Fix qeq/comb requires atom attribute q");
+ error->all(FLERR,"Fix qeq/comb requires atom attribute q");
comb = (PairComb *) force->pair_match("comb",1);
- if (comb == NULL) error->all("Must use pair_style comb with fix qeq/comb");
+ if (comb == NULL) error->all(FLERR,"Must use pair_style comb with fix qeq/comb");
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
ngroup = group->count(igroup);
- if (ngroup == 0) error->all("Fix qeq/comb group has no atoms");
+ if (ngroup == 0) error->all(FLERR,"Fix qeq/comb group has no atoms");
}
/* ---------------------------------------------------------------------- */
void FixQEQComb::setup(int vflag)
{
firstflag = 1;
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
firstflag = 0;
}
/* ---------------------------------------------------------------------- */
void FixQEQComb::post_force(int vflag)
{
int i,iloop,loopmax;
double heatpq,qmass,dtq,dtq2;
double enegchkall,enegmaxall;
if (update->ntimestep % nevery) return;
// reallocate work arrays if necessary
// qf = charge force
// q1 = charge displacement
// q2 = tmp storage of charge force for next iteration
if (atom->nmax > nmax) {
memory->destroy(qf);
memory->destroy(q1);
memory->destroy(q2);
nmax = atom->nmax;
memory->create(qf,nmax,"qeq:qf");
memory->create(q1,nmax,"qeq:q1");
memory->create(q2,nmax,"qeq:q2");
vector_atom = qf;
}
// more loops for first-time charge equilibrium
iloop = 0;
if (firstflag) loopmax = 5000;
else loopmax = 2000;
// charge-equilibration loop
if (me == 0 && fp)
fprintf(fp,"Charge equilibration on step " BIGINT_FORMAT "\n",
update->ntimestep);
heatpq = 0.05;
qmass = 0.000548580;
dtq = 0.0006;
dtq2 = 0.5*dtq*dtq/qmass;
double enegchk = 0.0;
double enegtot = 0.0;
double enegmax = 0.0;
double *q = atom->q;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
q1[i] = q2[i] = qf[i] = 0.0;
for (iloop = 0; iloop < loopmax; iloop ++ ) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
q1[i] += qf[i]*dtq2 - heatpq*q1[i];
q[i] += q1[i];
}
enegtot = comb->yasu_char(qf,igroup);
enegtot /= ngroup;
enegchk = enegmax = 0.0;
for (i = 0; i < nlocal ; i++)
if (mask[i] & groupbit) {
q2[i] = enegtot-qf[i];
enegmax = MAX(enegmax,fabs(q2[i]));
enegchk += fabs(q2[i]);
qf[i] = q2[i];
}
MPI_Allreduce(&enegchk,&enegchkall,1,MPI_DOUBLE,MPI_SUM,world);
enegchk = enegchkall/ngroup;
MPI_Allreduce(&enegmax,&enegmaxall,1,MPI_DOUBLE,MPI_MAX,world);
enegmax = enegmaxall;
if (enegchk <= precision && enegmax <= 100.0*precision) break;
if (me == 0 && fp)
fprintf(fp," iteration: %d, enegtot %.6g, "
"enegmax %.6g, fq deviation: %.6g\n",
iloop,enegtot,enegmax,enegchk);
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
q1[i] += qf[i]*dtq2 - heatpq*q1[i];
}
if (me == 0 && fp) {
if (iloop == loopmax)
fprintf(fp,"Charges did not converge in %d iterations\n",iloop);
else
fprintf(fp,"Charges converged in %d iterations to %.10f tolerance\n",
iloop,enegchk);
}
}
/* ---------------------------------------------------------------------- */
void FixQEQComb::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixQEQComb::memory_usage()
{
double bytes = atom->nmax*3 * sizeof(double);
return bytes;
}
diff --git a/src/MANYBODY/pair_adp.cpp b/src/MANYBODY/pair_adp.cpp
index c2823c73e..0f6b0a6a9 100644
--- a/src/MANYBODY/pair_adp.cpp
+++ b/src/MANYBODY/pair_adp.cpp
@@ -1,1032 +1,1029 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Christopher Weinberger (SNL), Stephen Foiles (SNL),
Chandra Veer Singh (Cornell)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_adp.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairADP::PairADP(LAMMPS *lmp) : Pair(lmp)
{
nmax = 0;
rho = NULL;
fp = NULL;
mu = NULL;
lambda = NULL;
setfl = NULL;
frho = NULL;
rhor = NULL;
z2r = NULL;
u2r = NULL;
w2r = NULL;
frho_spline = NULL;
rhor_spline = NULL;
z2r_spline = NULL;
u2r_spline = NULL;
w2r_spline = NULL;
// set comm size needed by this Pair
comm_forward = 10;
comm_reverse = 10;
single_enable = 0;
one_coeff = 1;
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairADP::~PairADP()
{
memory->destroy(rho);
memory->destroy(fp);
memory->destroy(mu);
memory->destroy(lambda);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
delete [] type2frho;
memory->destroy(type2rhor);
memory->destroy(type2z2r);
memory->destroy(type2u2r);
memory->destroy(type2w2r);
}
if (setfl) {
for (int i = 0; i < setfl->nelements; i++) delete [] setfl->elements[i];
delete [] setfl->elements;
delete [] setfl->mass;
memory->destroy(setfl->frho);
memory->destroy(setfl->rhor);
memory->destroy(setfl->z2r);
memory->destroy(setfl->u2r);
memory->destroy(setfl->w2r);
delete setfl;
}
memory->destroy(frho);
memory->destroy(rhor);
memory->destroy(z2r);
memory->destroy(u2r);
memory->destroy(w2r);
memory->destroy(frho_spline);
memory->destroy(rhor_spline);
memory->destroy(z2r_spline);
memory->destroy(u2r_spline);
memory->destroy(w2r_spline);
}
/* ---------------------------------------------------------------------- */
void PairADP::compute(int eflag, int vflag)
{
int i,j,ii,jj,m,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,p,rhoip,rhojp,z2,z2p,recip,phip,psip,phi;
double u2,u2p,w2,w2p,nu;
double *coeff;
int *ilist,*jlist,*numneigh,**firstneigh;
double delmux,delmuy,delmuz,trdelmu,tradellam;
double adpx,adpy,adpz,fx,fy,fz;
double sumlamxx,sumlamyy,sumlamzz,sumlamyz,sumlamxz,sumlamxy;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
// grow local arrays if necessary
// need to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(rho);
memory->destroy(fp);
memory->destroy(mu);
memory->destroy(lambda);
nmax = atom->nmax;
memory->create(rho,nmax,"pair:rho");
memory->create(fp,nmax,"pair:fp");
memory->create(mu,nmax,3,"pair:mu");
memory->create(lambda,nmax,6,"pair:lambda");
}
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// zero out density
if (newton_pair) {
m = nlocal + atom->nghost;
for (i = 0; i < m; i++) {
rho[i] = 0.0;
mu[i][0] = 0.0; mu[i][1] = 0.0; mu[i][2] = 0.0;
lambda[i][0] = 0.0; lambda[i][1] = 0.0; lambda[i][2] = 0.0;
lambda[i][3] = 0.0; lambda[i][4] = 0.0; lambda[i][5] = 0.0;
}
} else {
for (i = 0; i < nlocal; i++) {
rho[i] = 0.0;
mu[i][0] = 0.0; mu[i][1] = 0.0; mu[i][2] = 0.0;
lambda[i][0] = 0.0; lambda[i][1] = 0.0; lambda[i][2] = 0.0;
lambda[i][3] = 0.0; lambda[i][4] = 0.0; lambda[i][5] = 0.0;
}
}
// rho = density at each atom
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutforcesq) {
jtype = type[j];
p = sqrt(rsq)*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
coeff = rhor_spline[type2rhor[jtype][itype]][m];
rho[i] += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
coeff = u2r_spline[type2u2r[jtype][itype]][m];
u2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
mu[i][0] += u2*delx;
mu[i][1] += u2*dely;
mu[i][2] += u2*delz;
coeff = w2r_spline[type2w2r[jtype][itype]][m];
w2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
lambda[i][0] += w2*delx*delx;
lambda[i][1] += w2*dely*dely;
lambda[i][2] += w2*delz*delz;
lambda[i][3] += w2*dely*delz;
lambda[i][4] += w2*delx*delz;
lambda[i][5] += w2*delx*dely;
if (newton_pair || j < nlocal) {
// verify sign difference for mu and lambda
coeff = rhor_spline[type2rhor[itype][jtype]][m];
rho[j] += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
coeff = u2r_spline[type2u2r[itype][jtype]][m];
u2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
mu[j][0] -= u2*delx;
mu[j][1] -= u2*dely;
mu[j][2] -= u2*delz;
coeff = w2r_spline[type2w2r[itype][jtype]][m];
w2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
lambda[j][0] += w2*delx*delx;
lambda[j][1] += w2*dely*dely;
lambda[j][2] += w2*delz*delz;
lambda[j][3] += w2*dely*delz;
lambda[j][4] += w2*delx*delz;
lambda[j][5] += w2*delx*dely;
}
}
}
}
// communicate and sum densities
if (newton_pair) comm->reverse_comm_pair(this);
// fp = derivative of embedding energy at each atom
// phi = embedding energy at each atom
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
p = rho[i]*rdrho + 1.0;
m = static_cast<int> (p);
m = MAX(1,MIN(m,nrho-1));
p -= m;
p = MIN(p,1.0);
coeff = frho_spline[type2frho[type[i]]][m];
fp[i] = (coeff[0]*p + coeff[1])*p + coeff[2];
if (eflag) {
phi = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
phi += 0.5*(mu[i][0]*mu[i][0]+mu[i][1]*mu[i][1]+mu[i][2]*mu[i][2]);
phi += 0.5*(lambda[i][0]*lambda[i][0]+lambda[i][1]*
lambda[i][1]+lambda[i][2]*lambda[i][2]);
phi += 1.0*(lambda[i][3]*lambda[i][3]+lambda[i][4]*
lambda[i][4]+lambda[i][5]*lambda[i][5]);
phi -= 1.0/6.0*(lambda[i][0]+lambda[i][1]+lambda[i][2])*
(lambda[i][0]+lambda[i][1]+lambda[i][2]);
if (eflag_global) eng_vdwl += phi;
if (eflag_atom) eatom[i] += phi;
}
}
// communicate derivative of embedding function
comm->forward_comm_pair(this);
// compute forces on each atom
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutforcesq) {
jtype = type[j];
r = sqrt(rsq);
p = r*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
// rhoip = derivative of (density at atom j due to atom i)
// rhojp = derivative of (density at atom i due to atom j)
// phi = pair potential energy
// phip = phi'
// z2 = phi * r
// z2p = (phi * r)' = (phi' r) + phi
// u2 = u
// u2p = u'
// w2 = w
// w2p = w'
// psip needs both fp[i] and fp[j] terms since r_ij appears in two
// terms of embed eng: Fi(sum rho_ij) and Fj(sum rho_ji)
// hence embed' = Fi(sum rho_ij) rhojp + Fj(sum rho_ji) rhoip
coeff = rhor_spline[type2rhor[itype][jtype]][m];
rhoip = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = rhor_spline[type2rhor[jtype][itype]][m];
rhojp = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = z2r_spline[type2z2r[itype][jtype]][m];
z2p = (coeff[0]*p + coeff[1])*p + coeff[2];
z2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
coeff = u2r_spline[type2u2r[itype][jtype]][m];
u2p = (coeff[0]*p + coeff[1])*p + coeff[2];
u2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
coeff = w2r_spline[type2w2r[itype][jtype]][m];
w2p = (coeff[0]*p + coeff[1])*p + coeff[2];
w2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
recip = 1.0/r;
phi = z2*recip;
phip = z2p*recip - phi*recip;
psip = fp[i]*rhojp + fp[j]*rhoip + phip;
fpair = -psip*recip;
delmux = mu[i][0]-mu[j][0];
delmuy = mu[i][1]-mu[j][1];
delmuz = mu[i][2]-mu[j][2];
trdelmu = delmux*delx+delmuy*dely+delmuz*delz;
sumlamxx = lambda[i][0]+lambda[j][0];
sumlamyy = lambda[i][1]+lambda[j][1];
sumlamzz = lambda[i][2]+lambda[j][2];
sumlamyz = lambda[i][3]+lambda[j][3];
sumlamxz = lambda[i][4]+lambda[j][4];
sumlamxy = lambda[i][5]+lambda[j][5];
tradellam = sumlamxx*delx*delx+sumlamyy*dely*dely+
sumlamzz*delz*delz+2.0*sumlamxy*delx*dely+
2.0*sumlamxz*delx*delz+2.0*sumlamyz*dely*delz;
nu = sumlamxx+sumlamyy+sumlamzz;
adpx = delmux*u2 + trdelmu*u2p*delx*recip +
2.0*w2*(sumlamxx*delx+sumlamxy*dely+sumlamxz*delz) +
w2p*delx*recip*tradellam - 1.0/3.0*nu*(w2p*r+2.0*w2)*delx;
adpy = delmuy*u2 + trdelmu*u2p*dely*recip +
2.0*w2*(sumlamxy*delx+sumlamyy*dely+sumlamyz*delz) +
w2p*dely*recip*tradellam - 1.0/3.0*nu*(w2p*r+2.0*w2)*dely;
adpz = delmuz*u2 + trdelmu*u2p*delz*recip +
2.0*w2*(sumlamxz*delx+sumlamyz*dely+sumlamzz*delz) +
w2p*delz*recip*tradellam - 1.0/3.0*nu*(w2p*r+2.0*w2)*delz;
adpx*=-1.0; adpy*=-1.0; adpz*=-1.0;
fx = delx*fpair+adpx;
fy = dely*fpair+adpy;
fz = delz*fpair+adpz;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
if (newton_pair || j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
}
if (eflag) evdwl = phi;
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,evdwl,0.0,
fx,fy,fz,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairADP::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
for (int i = 1; i <= n; i++) map[i] = -1;
type2frho = new int[n+1];
memory->create(type2rhor,n+1,n+1,"pair:type2rhor");
memory->create(type2z2r,n+1,n+1,"pair:type2z2r");
memory->create(type2u2r,n+1,n+1,"pair:type2u2r");
memory->create(type2w2r,n+1,n+1,"pair:type2w2r");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairADP::settings(int narg, char **arg)
{
- if (narg > 0) error->all("Illegal pair_style command");
+ if (narg > 0) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
read concatenated *.plt file
------------------------------------------------------------------------- */
void PairADP::coeff(int narg, char **arg)
{
int i,j;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read ADP parameter file
if (setfl) {
for (i = 0; i < setfl->nelements; i++) delete [] setfl->elements[i];
delete [] setfl->elements;
delete [] setfl->mass;
memory->destroy(setfl->frho);
memory->destroy(setfl->rhor);
memory->destroy(setfl->z2r);
memory->destroy(setfl->u2r);
memory->destroy(setfl->w2r);
delete setfl;
}
setfl = new Setfl();
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
for (i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
continue;
}
for (j = 0; j < setfl->nelements; j++)
if (strcmp(arg[i],setfl->elements[j]) == 0) break;
if (j < setfl->nelements) map[i-2] = j;
- else error->all("No matching element in ADP potential file");
+ else error->all(FLERR,"No matching element in ADP potential file");
}
// clear setflag since coeff() called once with I,J = * *
int n = atom->ntypes;
for (i = 1; i <= n; i++)
for (j = i; j <= n; j++)
setflag[i][j] = 0;
// set setflag i,j for type pairs where both are mapped to elements
// set mass of atom type if i = j
int count = 0;
for (i = 1; i <= n; i++) {
for (j = i; j <= n; j++) {
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
if (i == j) atom->set_mass(i,setfl->mass[map[i]]);
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairADP::init_style()
{
// convert read-in file(s) to arrays and spline them
file2array();
array2spline();
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairADP::init_one(int i, int j)
{
// single global cutoff = max of cut from all files read in
// for funcfl could be multiple files
// for setfl or fs, just one file
if (setfl) cutmax = setfl->cut;
cutforcesq = cutmax*cutmax;
return cutmax;
}
/* ----------------------------------------------------------------------
read potential values from a DYNAMO single element funcfl file
------------------------------------------------------------------------- */
void PairADP::read_file(char *filename)
{
Setfl *file = setfl;
// open potential file
int me = comm->me;
FILE *fp;
char line[MAXLINE];
if (me == 0) {
fp = fopen(filename,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open ADP potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read and broadcast header
// extract element names from nelements line
int n;
if (me == 0) {
fgets(line,MAXLINE,fp);
fgets(line,MAXLINE,fp);
fgets(line,MAXLINE,fp);
fgets(line,MAXLINE,fp);
n = strlen(line) + 1;
}
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
sscanf(line,"%d",&file->nelements);
int nwords = atom->count_words(line);
if (nwords != file->nelements + 1)
- error->all("Incorrect element names in ADP potential file");
+ error->all(FLERR,"Incorrect element names in ADP potential file");
char **words = new char*[file->nelements+1];
nwords = 0;
strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
file->elements = new char*[file->nelements];
for (int i = 0; i < file->nelements; i++) {
n = strlen(words[i]) + 1;
file->elements[i] = new char[n];
strcpy(file->elements[i],words[i]);
}
delete [] words;
if (me == 0) {
fgets(line,MAXLINE,fp);
sscanf(line,"%d %lg %d %lg %lg",
&file->nrho,&file->drho,&file->nr,&file->dr,&file->cut);
}
MPI_Bcast(&file->nrho,1,MPI_INT,0,world);
MPI_Bcast(&file->drho,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->nr,1,MPI_INT,0,world);
MPI_Bcast(&file->dr,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->cut,1,MPI_DOUBLE,0,world);
file->mass = new double[file->nelements];
memory->create(file->frho,file->nelements,file->nrho+1,"pair:frho");
memory->create(file->rhor,file->nelements,file->nr+1,"pair:rhor");
memory->create(file->z2r,file->nelements,file->nelements,file->nr+1,
"pair:z2r");
memory->create(file->u2r,file->nelements,file->nelements,file->nr+1,
"pair:u2r");
memory->create(file->w2r,file->nelements,file->nelements,file->nr+1,
"pair:w2r");
int i,j,tmp;
for (i = 0; i < file->nelements; i++) {
if (me == 0) {
fgets(line,MAXLINE,fp);
sscanf(line,"%d %lg",&tmp,&file->mass[i]);
}
MPI_Bcast(&file->mass[i],1,MPI_DOUBLE,0,world);
if (me == 0) grab(fp,file->nrho,&file->frho[i][1]);
MPI_Bcast(&file->frho[i][1],file->nrho,MPI_DOUBLE,0,world);
if (me == 0) grab(fp,file->nr,&file->rhor[i][1]);
MPI_Bcast(&file->rhor[i][1],file->nr,MPI_DOUBLE,0,world);
}
for (i = 0; i < file->nelements; i++)
for (j = 0; j <= i; j++) {
if (me == 0) grab(fp,file->nr,&file->z2r[i][j][1]);
MPI_Bcast(&file->z2r[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
for (i = 0; i < file->nelements; i++)
for (j = 0; j <= i; j++) {
if (me == 0) grab(fp,file->nr,&file->u2r[i][j][1]);
MPI_Bcast(&file->u2r[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
for (i = 0; i < file->nelements; i++)
for (j = 0; j <= i; j++) {
if (me == 0) grab(fp,file->nr,&file->w2r[i][j][1]);
MPI_Bcast(&file->w2r[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
// close the potential file
if (me == 0) fclose(fp);
}
/* ----------------------------------------------------------------------
convert read-in funcfl potential(s) to standard array format
interpolate all file values to a single grid and cutoff
------------------------------------------------------------------------- */
void PairADP::file2array()
{
int i,j,m,n;
int ntypes = atom->ntypes;
// set function params directly from setfl file
nrho = setfl->nrho;
nr = setfl->nr;
drho = setfl->drho;
dr = setfl->dr;
// ------------------------------------------------------------------
// setup frho arrays
// ------------------------------------------------------------------
// allocate frho arrays
// nfrho = # of setfl elements + 1 for zero array
nfrho = setfl->nelements + 1;
memory->destroy(frho);
memory->create(frho,nfrho,nrho+1,"pair:frho");
// copy each element's frho to global frho
for (i = 0; i < setfl->nelements; i++)
for (m = 1; m <= nrho; m++) frho[i][m] = setfl->frho[i][m];
// add extra frho of zeroes for non-ADP types to point to (pair hybrid)
// this is necessary b/c fp is still computed for non-ADP atoms
for (m = 1; m <= nrho; m++) frho[nfrho-1][m] = 0.0;
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
// if atom type doesn't point to element (non-ADP atom in pair hybrid)
// then map it to last frho array of zeroes
for (i = 1; i <= ntypes; i++)
if (map[i] >= 0) type2frho[i] = map[i];
else type2frho[i] = nfrho-1;
// ------------------------------------------------------------------
// setup rhor arrays
// ------------------------------------------------------------------
// allocate rhor arrays
// nrhor = # of setfl elements
nrhor = setfl->nelements;
memory->destroy(rhor);
memory->create(rhor,nrhor,nr+1,"pair:rhor");
// copy each element's rhor to global rhor
for (i = 0; i < setfl->nelements; i++)
for (m = 1; m <= nr; m++) rhor[i][m] = setfl->rhor[i][m];
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
// for setfl files, I,J mapping only depends on I
// OK if map = -1 (non-APD atom in pair hybrid) b/c type2rhor not used
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++)
type2rhor[i][j] = map[i];
// ------------------------------------------------------------------
// setup z2r arrays
// ------------------------------------------------------------------
// allocate z2r arrays
// nz2r = N*(N+1)/2 where N = # of setfl elements
nz2r = setfl->nelements * (setfl->nelements+1) / 2;
memory->destroy(z2r);
memory->create(z2r,nz2r,nr+1,"pair:z2r");
// copy each element pair z2r to global z2r, only for I >= J
n = 0;
for (i = 0; i < setfl->nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) z2r[n][m] = setfl->z2r[i][j][m];
n++;
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// OK if map = -1 (non-ADP atom in pair hybrid) b/c type2z2r not used
int irow,icol;
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) continue;
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2z2r[i][j] = n;
}
}
// ------------------------------------------------------------------
// setup u2r arrays
// ------------------------------------------------------------------
// allocate u2r arrays
// nu2r = N*(N+1)/2 where N = # of setfl elements
nu2r = setfl->nelements * (setfl->nelements+1) / 2;
memory->destroy(u2r);
memory->create(u2r,nu2r,nr+1,"pair:u2r");
// copy each element pair z2r to global z2r, only for I >= J
n = 0;
for (i = 0; i < setfl->nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) u2r[n][m] = setfl->u2r[i][j][m];
n++;
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// OK if map = -1 (non-ADP atom in pair hybrid) b/c type2z2r not used
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) continue;
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2u2r[i][j] = n;
}
}
// ------------------------------------------------------------------
// setup w2r arrays
// ------------------------------------------------------------------
// allocate w2r arrays
// nw2r = N*(N+1)/2 where N = # of setfl elements
nw2r = setfl->nelements * (setfl->nelements+1) / 2;
memory->destroy(w2r);
memory->create(w2r,nw2r,nr+1,"pair:w2r");
// copy each element pair z2r to global z2r, only for I >= J
n = 0;
for (i = 0; i < setfl->nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) w2r[n][m] = setfl->w2r[i][j][m];
n++;
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// OK if map = -1 (non-ADP atom in pair hybrid) b/c type2z2r not used
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) continue;
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2w2r[i][j] = n;
}
}
}
/* ---------------------------------------------------------------------- */
void PairADP::array2spline()
{
rdr = 1.0/dr;
rdrho = 1.0/drho;
memory->destroy(frho_spline);
memory->destroy(rhor_spline);
memory->destroy(z2r_spline);
memory->destroy(u2r_spline);
memory->destroy(w2r_spline);
memory->create(frho_spline,nfrho,nrho+1,7,"pair:frho");
memory->create(rhor_spline,nrhor,nr+1,7,"pair:rhor");
memory->create(z2r_spline,nz2r,nr+1,7,"pair:z2r");
memory->create(u2r_spline,nz2r,nr+1,7,"pair:u2r");
memory->create(w2r_spline,nz2r,nr+1,7,"pair:w2r");
for (int i = 0; i < nfrho; i++)
interpolate(nrho,drho,frho[i],frho_spline[i]);
for (int i = 0; i < nrhor; i++)
interpolate(nr,dr,rhor[i],rhor_spline[i]);
for (int i = 0; i < nz2r; i++)
interpolate(nr,dr,z2r[i],z2r_spline[i]);
for (int i = 0; i < nu2r; i++)
interpolate(nr,dr,u2r[i],u2r_spline[i]);
for (int i = 0; i < nw2r; i++)
interpolate(nr,dr,w2r[i],w2r_spline[i]);
}
/* ---------------------------------------------------------------------- */
void PairADP::interpolate(int n, double delta, double *f, double **spline)
{
for (int m = 1; m <= n; m++) spline[m][6] = f[m];
spline[1][5] = spline[2][6] - spline[1][6];
spline[2][5] = 0.5 * (spline[3][6]-spline[1][6]);
spline[n-1][5] = 0.5 * (spline[n][6]-spline[n-2][6]);
spline[n][5] = spline[n][6] - spline[n-1][6];
for (int m = 3; m <= n-2; m++)
spline[m][5] = ((spline[m-2][6]-spline[m+2][6]) +
8.0*(spline[m+1][6]-spline[m-1][6])) / 12.0;
for (int m = 1; m <= n-1; m++) {
spline[m][4] = 3.0*(spline[m+1][6]-spline[m][6]) -
2.0*spline[m][5] - spline[m+1][5];
spline[m][3] = spline[m][5] + spline[m+1][5] -
2.0*(spline[m+1][6]-spline[m][6]);
}
spline[n][4] = 0.0;
spline[n][3] = 0.0;
for (int m = 1; m <= n; m++) {
spline[m][2] = spline[m][5]/delta;
spline[m][1] = 2.0*spline[m][4]/delta;
spline[m][0] = 3.0*spline[m][3]/delta;
}
}
/* ----------------------------------------------------------------------
grab n values from file fp and put them in list
values can be several to a line
only called by proc 0
------------------------------------------------------------------------- */
void PairADP::grab(FILE *fp, int n, double *list)
{
char *ptr;
char line[MAXLINE];
int i = 0;
while (i < n) {
fgets(line,MAXLINE,fp);
ptr = strtok(line," \t\n\r\f");
list[i++] = atof(ptr);
while (ptr = strtok(NULL," \t\n\r\f")) list[i++] = atof(ptr);
}
}
/* ---------------------------------------------------------------------- */
int PairADP::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = fp[j];
buf[m++] = mu[j][0];
buf[m++] = mu[j][1];
buf[m++] = mu[j][2];
buf[m++] = lambda[j][0];
buf[m++] = lambda[j][1];
buf[m++] = lambda[j][2];
buf[m++] = lambda[j][3];
buf[m++] = lambda[j][4];
buf[m++] = lambda[j][5];
}
return 10;
}
/* ---------------------------------------------------------------------- */
void PairADP::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
fp[i] = buf[m++];
mu[i][0] = buf[m++];
mu[i][1] = buf[m++];
mu[i][2] = buf[m++];
lambda[i][0] = buf[m++];
lambda[i][1] = buf[m++];
lambda[i][2] = buf[m++];
lambda[i][3] = buf[m++];
lambda[i][4] = buf[m++];
lambda[i][5] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int PairADP::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = rho[i];
buf[m++] = mu[i][0];
buf[m++] = mu[i][1];
buf[m++] = mu[i][2];
buf[m++] = lambda[i][0];
buf[m++] = lambda[i][1];
buf[m++] = lambda[i][2];
buf[m++] = lambda[i][3];
buf[m++] = lambda[i][4];
buf[m++] = lambda[i][5];
}
return 10;
}
/* ---------------------------------------------------------------------- */
void PairADP::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
rho[j] += buf[m++];
mu[j][0] += buf[m++];
mu[j][1] += buf[m++];
mu[j][2] += buf[m++];
lambda[j][0] += buf[m++];
lambda[j][1] += buf[m++];
lambda[j][2] += buf[m++];
lambda[j][3] += buf[m++];
lambda[j][4] += buf[m++];
lambda[j][5] += buf[m++];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairADP::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
bytes += 21 * nmax * sizeof(double);
return bytes;
}
diff --git a/src/MANYBODY/pair_airebo.cpp b/src/MANYBODY/pair_airebo.cpp
index 427495433..e8c623b47 100644
--- a/src/MANYBODY/pair_airebo.cpp
+++ b/src/MANYBODY/pair_airebo.cpp
@@ -1,4255 +1,4252 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Ase Henry (MIT)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "mpi.h"
#include "pair_airebo.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define MAXLINE 1024
#define TOL 1.0e-9
#define PGDELTA 1
/* ---------------------------------------------------------------------- */
PairAIREBO::PairAIREBO(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
ghostneigh = 1;
maxlocal = 0;
REBO_numneigh = NULL;
REBO_firstneigh = NULL;
maxpage = 0;
pages = NULL;
nC = nH = NULL;
PI = 4.0*atan(1.0);
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairAIREBO::~PairAIREBO()
{
memory->destroy(REBO_numneigh);
memory->sfree(REBO_firstneigh);
for (int i = 0; i < maxpage; i++) memory->destroy(pages[i]);
memory->sfree(pages);
memory->destroy(nC);
memory->destroy(nH);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cutghost);
memory->destroy(cutljsq);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
delete [] map;
}
}
/* ---------------------------------------------------------------------- */
void PairAIREBO::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = vflag_atom = 0;
REBO_neigh();
FREBO(eflag,vflag);
if (ljflag) FLJ(eflag,vflag);
if (torflag) TORSION(eflag,vflag);
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairAIREBO::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cutghost,n+1,n+1,"pair:cutghost");
// only sized by C,H = 2 types
memory->create(cutljsq,2,2,"pair:cutljsq");
memory->create(lj1,2,2,"pair:lj1");
memory->create(lj2,2,2,"pair:lj2");
memory->create(lj3,2,2,"pair:lj3");
memory->create(lj4,2,2,"pair:lj4");
map = new int[n+1];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairAIREBO::settings(int narg, char **arg)
{
- if (narg != 1 && narg != 3) error->all("Illegal pair_style command");
+ if (narg != 1 && narg != 3) error->all(FLERR,"Illegal pair_style command");
cutlj = force->numeric(arg[0]);
ljflag = torflag = 1;
if (narg == 3) {
ljflag = force->inumeric(arg[1]);
torflag = force->inumeric(arg[2]);
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairAIREBO::coeff(int narg, char **arg)
{
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read args that map atom types to C and H
// map[i] = which element (0,1) the Ith atom type is, -1 if NULL
for (int i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
continue;
} else if (strcmp(arg[i],"C") == 0) {
map[i-2] = 0;
} else if (strcmp(arg[i],"H") == 0) {
map[i-2] = 1;
- } else error->all("Incorrect args for pair coefficients");
+ } else error->all(FLERR,"Incorrect args for pair coefficients");
}
// read potential file and initialize fitting splines
read_file(arg[2]);
spline_init();
// clear setflag since coeff() called once with I,J = * *
int 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;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairAIREBO::init_style()
{
if (atom->tag_enable == 0)
- error->all("Pair style AIREBO requires atom IDs");
+ error->all(FLERR,"Pair style AIREBO requires atom IDs");
if (force->newton_pair == 0)
- error->all("Pair style AIREBO requires newton pair on");
+ error->all(FLERR,"Pair style AIREBO requires newton pair on");
// need a full neighbor list, including neighbors of ghosts
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->ghost = 1;
// local REBO neighbor list memory
pgsize = neighbor->pgsize;
oneatom = neighbor->oneatom;
if (maxpage == 0) add_pages(0);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairAIREBO::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
// convert to C,H types
int ii = map[i];
int jj = map[j];
// use C-C values for these cutoffs since C atoms are biggest
// cut3rebo = 3 REBO distances
cut3rebo = 3.0 * rcmax[0][0];
// cutljrebosq = furthest distance from an owned atom a ghost atom can be
// to need its REBO neighs computed
// interaction = M-K-I-J-L-N with I = owned and J = ghost
// this insures N is in the REBO neigh list of L
// since I-J < rcLJmax and J-L < rmax
double cutljrebo = rcLJmax[0][0] + rcmax[0][0];
cutljrebosq = cutljrebo * cutljrebo;
// cutmax = furthest distance from an owned atom
// at which another atom will feel force, i.e. the ghost cutoff
// for REBO term in potential:
// interaction = M-K-I-J-L-N with I = owned and J = ghost
// I to N is max distance = 3 REBO distances
// for LJ term in potential:
// short interaction = M-K-I-J-L-N with I = owned, J = ghost, I-J < rcLJmax
// rcLJmax + 2*rcmax, since I-J < rcLJmax and J-L,L-N = REBO distances
// long interaction = I-J with I = owned and J = ghost
// cutlj*sigma, since I-J < LJ cutoff
// cutghost = REBO cutoff used in REBO_neigh() for neighbors of ghosts
double cutmax = cut3rebo;
if (ljflag) {
cutmax = MAX(cutmax,rcLJmax[0][0] + 2.0*rcmax[0][0]);
cutmax = MAX(cutmax,cutlj*sigma[0][0]);
}
cutghost[i][j] = rcmax[ii][jj];
cutljsq[ii][jj] = cutlj*sigma[ii][jj] * cutlj*sigma[ii][jj];
lj1[ii][jj] = 48.0 * epsilon[ii][jj] * pow(sigma[ii][jj],12.0);
lj2[ii][jj] = 24.0 * epsilon[ii][jj] * pow(sigma[ii][jj],6.0);
lj3[ii][jj] = 4.0 * epsilon[ii][jj] * pow(sigma[ii][jj],12.0);
lj4[ii][jj] = 4.0 * epsilon[ii][jj] * pow(sigma[ii][jj],6.0);
cutghost[j][i] = cutghost[i][j];
cutljsq[jj][ii] = cutljsq[ii][jj];
lj1[jj][ii] = lj1[ii][jj];
lj2[jj][ii] = lj2[ii][jj];
lj3[jj][ii] = lj3[ii][jj];
lj4[jj][ii] = lj4[ii][jj];
return cutmax;
}
/* ----------------------------------------------------------------------
create REBO neighbor list from main neighbor list
REBO neighbor list stores neighbors of ghost atoms
------------------------------------------------------------------------- */
void PairAIREBO::REBO_neigh()
{
int i,j,ii,jj,n,allnum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq,dS;
int *ilist,*jlist,*numneigh,**firstneigh;
int *neighptr;
double **x = atom->x;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (nall > maxlocal) {
maxlocal = atom->nmax;
memory->destroy(REBO_numneigh);
memory->sfree(REBO_firstneigh);
memory->destroy(nC);
memory->destroy(nH);
memory->create(REBO_numneigh,maxlocal,"AIREBO:numneigh");
REBO_firstneigh = (int **) memory->smalloc(maxlocal*sizeof(int *),
"AIREBO:firstneigh");
memory->create(nC,maxlocal,"AIREBO:nC");
memory->create(nH,maxlocal,"AIREBO:nH");
}
allnum = list->inum + list->gnum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// store all REBO neighs of owned and ghost atoms
// scan full neighbor list of I
npage = 0;
int npnt = 0;
for (ii = 0; ii < allnum; ii++) {
i = ilist[ii];
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == maxpage) add_pages(npage);
}
neighptr = &pages[npage][npnt];
n = 0;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = map[type[i]];
nC[i] = nH[i] = 0.0;
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = map[type[j]];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < rcmaxsq[itype][jtype]) {
neighptr[n++] = j;
if (jtype == 0)
nC[i] += Sp(sqrt(rsq),rcmin[itype][jtype],rcmax[itype][jtype],dS);
else
nH[i] += Sp(sqrt(rsq),rcmin[itype][jtype],rcmax[itype][jtype],dS);
}
}
REBO_firstneigh[i] = neighptr;
REBO_numneigh[i] = n;
npnt += n;
if (npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
}
/* ----------------------------------------------------------------------
REBO forces and energy
------------------------------------------------------------------------- */
void PairAIREBO::FREBO(int eflag, int vflag)
{
int i,j,k,m,ii,inum,itype,jtype,itag,jtag;
double delx,dely,delz,evdwl,fpair,xtmp,ytmp,ztmp;
double rsq,rij,wij;
double Qij,Aij,alphaij,VR,pre,dVRdi,VA,term,bij,dVAdi,dVA;
double dwij,del[3];
int *ilist,*REBO_neighs;
evdwl = 0.0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int *tag = atom->tag;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
// two-body interactions from REBO neighbor list, skip half of them
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
itype = map[type[i]];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
REBO_neighs = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
j = REBO_neighs[k];
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
jtype = map[type[j]];
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
rij = sqrt(rsq);
wij = Sp(rij,rcmin[itype][jtype],rcmax[itype][jtype],dwij);
if (wij <= TOL) continue;
Qij = Q[itype][jtype];
Aij = A[itype][jtype];
alphaij = alpha[itype][jtype];
VR = wij*(1.0+(Qij/rij)) * Aij*exp(-alphaij*rij);
pre = wij*Aij * exp(-alphaij*rij);
dVRdi = pre * ((-alphaij)-(Qij/rsq)-(Qij*alphaij/rij));
dVRdi += VR/wij * dwij;
VA = dVA = 0.0;
for (m = 0; m < 3; m++) {
term = -wij * BIJc[itype][jtype][m] * exp(-Beta[itype][jtype][m]*rij);
VA += term;
dVA += -Beta[itype][jtype][m] * term;
}
dVA += VA/wij * dwij;
del[0] = delx;
del[1] = dely;
del[2] = delz;
bij = bondorder(i,j,del,rij,VA,f,vflag_atom);
dVAdi = bij*dVA;
fpair = -(dVRdi+dVAdi) / rij;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
if (eflag) evdwl = VR + bij*VA;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
/* ----------------------------------------------------------------------
compute LJ forces and energy
find 3- and 4-step paths between atoms I,J via REBO neighbor lists
------------------------------------------------------------------------- */
void PairAIREBO::FLJ(int eflag, int vflag)
{
int i,j,k,m,ii,jj,kk,mm,inum,jnum,itype,jtype,ktype,mtype,itag,jtag;
int atomi,atomj,atomk,atomm;
int testpath,npath,done;
double evdwl,fpair,xtmp,ytmp,ztmp;
double rsq,best,wik,wkm,cij,rij,dwij,dwik,dwkj,dwkm,dwmj;
double delij[3],rijsq,delik[3],rik,deljk[3];
double rkj,wkj,dC,VLJ,dVLJ,VA,Str,dStr,Stb;
double vdw,slw,dvdw,dslw,drij,swidth,tee,tee2;
double rljmin,rljmax,sigcut,sigmin,sigwid;
double delkm[3],rkm,deljm[3],rmj,wmj,r2inv,r6inv,scale,delscale[3];
int *ilist,*jlist,*numneigh,**firstneigh;
int *REBO_neighs_i,*REBO_neighs_k;
double delikS[3],deljkS[3],delkmS[3],deljmS[3],delimS[3];
double rikS,rkjS,rkmS,rmjS,wikS,dwikS;
double wkjS,dwkjS,wkmS,dwkmS,wmjS,dwmjS;
double fpair1,fpair2,fpair3;
double fi[3],fj[3],fk[3],fm[3];
// I-J interaction from full neighbor list
// skip 1/2 of interactions since only consider each pair once
evdwl = 0.0;
rljmin = 0.0;
rljmax = 0.0;
sigcut = 0.0;
sigmin = 0.0;
sigwid = 0.0;
double **x = atom->x;
double **f = atom->f;
int *tag = atom->tag;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
itype = map[type[i]];
atomi = i;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
jtype = map[type[j]];
atomj = j;
delij[0] = xtmp - x[j][0];
delij[1] = ytmp - x[j][1];
delij[2] = ztmp - x[j][2];
rijsq = delij[0]*delij[0] + delij[1]*delij[1] + delij[2]*delij[2];
// if outside of LJ cutoff, skip
// if outside of 4-path cutoff, best = 0.0, no need to test paths
// if outside of 2-path cutoff but inside 4-path cutoff,
// best = 0.0, test 3-,4-paths
// if inside 2-path cutoff, best = wij, only test 3-,4-paths if best < 1
if (rijsq >= cutljsq[itype][jtype]) continue;
rij = sqrt(rijsq);
if (rij >= cut3rebo) {
best = 0.0;
testpath = 0;
} else if (rij >= rcmax[itype][jtype]) {
best = 0.0;
testpath = 1;
} else {
best = Sp(rij,rcmin[itype][jtype],rcmax[itype][jtype],dwij);
npath = 2;
if (best < 1.0) testpath = 1;
else testpath = 0;
}
done = 0;
if (testpath) {
// test all 3-body paths = I-K-J
// I-K interactions come from atom I's REBO neighbors
// if wik > current best, compute wkj
// if best = 1.0, done
REBO_neighs_i = REBO_firstneigh[i];
for (kk = 0; kk < REBO_numneigh[i] && done==0; kk++) {
k = REBO_neighs_i[kk];
if (k == j) continue;
ktype = map[type[k]];
delik[0] = x[i][0] - x[k][0];
delik[1] = x[i][1] - x[k][1];
delik[2] = x[i][2] - x[k][2];
rsq = delik[0]*delik[0] + delik[1]*delik[1] + delik[2]*delik[2];
if (rsq < rcmaxsq[itype][ktype]) {
rik = sqrt(rsq);
wik = Sp(rik,rcmin[itype][ktype],rcmax[itype][ktype],dwik);
} else wik = 0.0;
if (wik > best) {
deljk[0] = x[j][0] - x[k][0];
deljk[1] = x[j][1] - x[k][1];
deljk[2] = x[j][2] - x[k][2];
rsq = deljk[0]*deljk[0] + deljk[1]*deljk[1] + deljk[2]*deljk[2];
if (rsq < rcmaxsq[ktype][jtype]) {
rkj = sqrt(rsq);
wkj = Sp(rkj,rcmin[ktype][jtype],rcmax[ktype][jtype],dwkj);
if (wik*wkj > best) {
best = wik*wkj;
npath = 3;
atomk = k;
delikS[0] = delik[0];
delikS[1] = delik[1];
delikS[2] = delik[2];
rikS = rik;
wikS = wik;
dwikS = dwik;
deljkS[0] = deljk[0];
deljkS[1] = deljk[1];
deljkS[2] = deljk[2];
rkjS = rkj;
wkjS = wkj;
dwkjS = dwkj;
if (best == 1.0) {
done = 1;
break;
}
}
}
// test all 4-body paths = I-K-M-J
// K-M interactions come from atom K's REBO neighbors
// if wik*wkm > current best, compute wmj
// if best = 1.0, done
REBO_neighs_k = REBO_firstneigh[k];
for (mm = 0; mm < REBO_numneigh[k] && done==0; mm++) {
m = REBO_neighs_k[mm];
if (m == i || m == j) continue;
mtype = map[type[m]];
delkm[0] = x[k][0] - x[m][0];
delkm[1] = x[k][1] - x[m][1];
delkm[2] = x[k][2] - x[m][2];
rsq = delkm[0]*delkm[0] + delkm[1]*delkm[1] + delkm[2]*delkm[2];
if (rsq < rcmaxsq[ktype][mtype]) {
rkm = sqrt(rsq);
wkm = Sp(rkm,rcmin[ktype][mtype],rcmax[ktype][mtype],dwkm);
} else wkm = 0.0;
if (wik*wkm > best) {
deljm[0] = x[j][0] - x[m][0];
deljm[1] = x[j][1] - x[m][1];
deljm[2] = x[j][2] - x[m][2];
rsq = deljm[0]*deljm[0] + deljm[1]*deljm[1] +
deljm[2]*deljm[2];
if (rsq < rcmaxsq[mtype][jtype]) {
rmj = sqrt(rsq);
wmj = Sp(rmj,rcmin[mtype][jtype],rcmax[mtype][jtype],dwmj);
if (wik*wkm*wmj > best) {
best = wik*wkm*wmj;
npath = 4;
atomk = k;
delikS[0] = delik[0];
delikS[1] = delik[1];
delikS[2] = delik[2];
rikS = rik;
wikS = wik;
dwikS = dwik;
atomm = m;
delkmS[0] = delkm[0];
delkmS[1] = delkm[1];
delkmS[2] = delkm[2];
rkmS = rkm;
wkmS = wkm;
dwkmS = dwkm;
deljmS[0] = deljm[0];
deljmS[1] = deljm[1];
deljmS[2] = deljm[2];
rmjS = rmj;
wmjS = wmj;
dwmjS = dwmj;
if (best == 1.0) {
done = 1;
break;
}
}
}
}
}
}
}
}
cij = 1.0 - best;
if (cij == 0.0) continue;
// compute LJ forces and energy
sigwid = 0.84;
sigcut = 3.0;
sigmin = sigcut - sigwid;
rljmin = sigma[itype][jtype];
rljmax = sigcut * rljmin;
rljmin = sigmin * rljmin;
if (rij > rljmax){
slw = 0.0;
dslw = 0.0;}
else if (rij > rljmin){
drij = rij - rljmin;
swidth = rljmax - rljmin;
tee = drij / swidth;
tee2 = pow (tee,2);
slw = 1.0 - tee2 * (3.0 - 2.0 * tee);
dslw = 6.0 * tee * (1.0 - tee) / rij / swidth;
}
else
slw = 1.0;
dslw = 0.0;
r2inv = 1.0/rijsq;
r6inv = r2inv*r2inv*r2inv;
vdw = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
dvdw = -r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]) / rij;
// VLJ now becomes vdw * slw, derivaties, etc.
VLJ = vdw * slw;
dVLJ = dvdw * slw + vdw * dslw;
Str = Sp2(rij,rcLJmin[itype][jtype],rcLJmax[itype][jtype],dStr);
VA = Str*cij*VLJ;
if (Str > 0.0) {
scale = rcmin[itype][jtype] / rij;
delscale[0] = scale * delij[0];
delscale[1] = scale * delij[1];
delscale[2] = scale * delij[2];
Stb = bondorderLJ(i,j,delscale,rcmin[itype][jtype],VA,
delij,rij,f,vflag_atom);
} else Stb = 0.0;
fpair = -(dStr * (Stb*cij*VLJ - cij*VLJ) +
dVLJ * (Str*Stb*cij + cij - Str*cij)) / rij;
f[i][0] += delij[0]*fpair;
f[i][1] += delij[1]*fpair;
f[i][2] += delij[2]*fpair;
f[j][0] -= delij[0]*fpair;
f[j][1] -= delij[1]*fpair;
f[j][2] -= delij[2]*fpair;
if (eflag) evdwl = VA*Stb + (1.0-Str)*cij*VLJ;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delij[0],delij[1],delij[2]);
if (cij < 1.0) {
dC = Str*Stb*VLJ + (1.0-Str)*VLJ;
if (npath == 2) {
fpair = dC*dwij / rij;
f[atomi][0] += delij[0]*fpair;
f[atomi][1] += delij[1]*fpair;
f[atomi][2] += delij[2]*fpair;
f[atomj][0] -= delij[0]*fpair;
f[atomj][1] -= delij[1]*fpair;
f[atomj][2] -= delij[2]*fpair;
if (vflag_atom) v_tally2(atomi,atomj,fpair,delij);
} else if (npath == 3) {
fpair1 = dC*dwikS*wkjS / rikS;
fi[0] = delikS[0]*fpair1;
fi[1] = delikS[1]*fpair1;
fi[2] = delikS[2]*fpair1;
fpair2 = dC*wikS*dwkjS / rkjS;
fj[0] = deljkS[0]*fpair2;
fj[1] = deljkS[1]*fpair2;
fj[2] = deljkS[2]*fpair2;
f[atomi][0] += fi[0];
f[atomi][1] += fi[1];
f[atomi][2] += fi[2];
f[atomj][0] += fj[0];
f[atomj][1] += fj[1];
f[atomj][2] += fj[2];
f[atomk][0] -= fi[0] + fj[0];
f[atomk][1] -= fi[1] + fj[1];
f[atomk][2] -= fi[2] + fj[2];
if (vflag_atom)
v_tally3(atomi,atomj,atomk,fi,fj,delikS,deljkS);
} else {
fpair1 = dC*dwikS*wkmS*wmjS / rikS;
fi[0] = delikS[0]*fpair1;
fi[1] = delikS[1]*fpair1;
fi[2] = delikS[2]*fpair1;
fpair2 = dC*wikS*dwkmS*wmjS / rkmS;
fk[0] = delkmS[0]*fpair2 - fi[0];
fk[1] = delkmS[1]*fpair2 - fi[1];
fk[2] = delkmS[2]*fpair2 - fi[2];
fpair3 = dC*wikS*wkmS*dwmjS / rmjS;
fj[0] = deljmS[0]*fpair3;
fj[1] = deljmS[1]*fpair3;
fj[2] = deljmS[2]*fpair3;
fm[0] = -delkmS[0]*fpair2 - fj[0];
fm[1] = -delkmS[1]*fpair2 - fj[1];
fm[2] = -delkmS[2]*fpair2 - fj[2];
f[atomi][0] += fi[0];
f[atomi][1] += fi[1];
f[atomi][2] += fi[2];
f[atomj][0] += fj[0];
f[atomj][1] += fj[1];
f[atomj][2] += fj[2];
f[atomk][0] += fk[0];
f[atomk][1] += fk[1];
f[atomk][2] += fk[2];
f[atomm][0] += fm[0];
f[atomm][1] += fm[1];
f[atomm][2] += fm[2];
if (vflag_atom) {
delimS[0] = delikS[0] + delkmS[0];
delimS[1] = delikS[1] + delkmS[1];
delimS[2] = delikS[2] + delkmS[2];
v_tally4(atomi,atomj,atomk,atomm,fi,fj,fk,delimS,deljmS,delkmS);
}
}
}
}
}
}
/* ----------------------------------------------------------------------
torsional forces and energy
------------------------------------------------------------------------- */
void PairAIREBO::TORSION(int eflag, int vflag)
{
int i,j,k,l,ii,inum,itag,jtag;
double evdwl,fpair,xtmp,ytmp,ztmp;
double cos321;
double w21,dw21,cos234,w34,dw34;
double cross321[3],cross321mag,cross234[3],cross234mag;
double w23,dw23,cw2,ekijl,Ec;
double cw,cwnum,cwnom;
double rij,rij2,rik,rjl,tspjik,dtsjik,tspijl,dtsijl,costmp,fcpc;
double sin321,sin234,rjk2,rik2,ril2,rjl2;
double rjk,ril;
double Vtors;
double dndij[3],tmpvec[3],dndik[3],dndjl[3];
double dcidij,dcidik,dcidjk,dcjdji,dcjdjl,dcjdil;
double dsidij,dsidik,dsidjk,dsjdji,dsjdjl,dsjdil;
double dxidij,dxidik,dxidjk,dxjdji,dxjdjl,dxjdil;
double ddndij,ddndik,ddndjk,ddndjl,ddndil,dcwddn,dcwdn,dvpdcw,Ftmp[3];
double del32[3],rsq,r32,del23[3],del21[3],r21;
double deljk[3],del34[3],delil[3],delkl[3],r23,r34;
double fi[3],fj[3],fk[3],fl[3];
int itype,jtype,ktype,ltype,kk,ll,jj;
int *ilist,*REBO_neighs_i,*REBO_neighs_j;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int *tag = atom->tag;
inum = list->inum;
ilist = list->ilist;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
itype = map[type[i]];
if (itype != 0) continue;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
REBO_neighs_i = REBO_firstneigh[i];
for (jj = 0; jj < REBO_numneigh[i]; jj++) {
j = REBO_neighs_i[jj];
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
jtype = map[type[j]];
if (jtype != 0) continue;
del32[0] = x[j][0]-x[i][0];
del32[1] = x[j][1]-x[i][1];
del32[2] = x[j][2]-x[i][2];
rsq = del32[0]*del32[0] + del32[1]*del32[1] + del32[2]*del32[2];
r32 = sqrt(rsq);
del23[0] = -del32[0];
del23[1] = -del32[1];
del23[2] = -del32[2];
r23 = r32;
w23 = Sp(r23,rcmin[itype][jtype],rcmax[itype][jtype],dw23);
for (kk = 0; kk < REBO_numneigh[i]; kk++) {
k = REBO_neighs_i[kk];
ktype = map[type[k]];
if (k == j) continue;
del21[0] = x[i][0]-x[k][0];
del21[1] = x[i][1]-x[k][1];
del21[2] = x[i][2]-x[k][2];
rsq = del21[0]*del21[0] + del21[1]*del21[1] + del21[2]*del21[2];
r21 = sqrt(rsq);
cos321 = - ((del21[0]*del32[0]) + (del21[1]*del32[1]) +
(del21[2]*del32[2])) / (r21*r32);
cos321 = MIN(cos321,1.0);
cos321 = MAX(cos321,-1.0);
sin321 = sqrt(1.0 - cos321*cos321);
if (sin321 < TOL) continue;
deljk[0] = del21[0]-del23[0];
deljk[1] = del21[1]-del23[1];
deljk[2] = del21[2]-del23[2];
rjk2 = deljk[0]*deljk[0] + deljk[1]*deljk[1] + deljk[2]*deljk[2];
rjk=sqrt(rjk2);
rik2 = r21*r21;
w21 = Sp(r21,rcmin[itype][ktype],rcmax[itype][ktype],dw21);
rij = r32;
rik = r21;
rij2 = r32*r32;
rik2 = r21*r21;
costmp = 0.5*(rij2+rik2-rjk2)/rij/rik;
tspjik = Sp2(costmp,thmin,thmax,dtsjik);
dtsjik = -dtsjik;
REBO_neighs_j = REBO_firstneigh[j];
for (ll = 0; ll < REBO_numneigh[j]; ll++) {
l = REBO_neighs_j[ll];
ltype = map[type[l]];
if (l == i || l == k) continue;
del34[0] = x[j][0]-x[l][0];
del34[1] = x[j][1]-x[l][1];
del34[2] = x[j][2]-x[l][2];
rsq = del34[0]*del34[0] + del34[1]*del34[1] + del34[2]*del34[2];
r34 = sqrt(rsq);
cos234 = (del32[0]*del34[0] + del32[1]*del34[1] +
del32[2]*del34[2]) / (r32*r34);
cos234 = MIN(cos234,1.0);
cos234 = MAX(cos234,-1.0);
sin234 = sqrt(1.0 - cos234*cos234);
if (sin234 < TOL) continue;
w34 = Sp(r34,rcmin[jtype][ltype],rcmax[jtype][ltype],dw34);
delil[0] = del23[0] + del34[0];
delil[1] = del23[1] + del34[1];
delil[2] = del23[2] + del34[2];
ril2 = delil[0]*delil[0] + delil[1]*delil[1] + delil[2]*delil[2];
ril=sqrt(ril2);
rjl2 = r34*r34;
rjl = r34;
rjl2 = r34*r34;
costmp = 0.5*(rij2+rjl2-ril2)/rij/rjl;
tspijl = Sp2(costmp,thmin,thmax,dtsijl);
dtsijl = -dtsijl; //need minus sign
cross321[0] = (del32[1]*del21[2])-(del32[2]*del21[1]);
cross321[1] = (del32[2]*del21[0])-(del32[0]*del21[2]);
cross321[2] = (del32[0]*del21[1])-(del32[1]*del21[0]);
cross321mag = sqrt(cross321[0]*cross321[0]+
cross321[1]*cross321[1]+
cross321[2]*cross321[2]);
cross234[0] = (del23[1]*del34[2])-(del23[2]*del34[1]);
cross234[1] = (del23[2]*del34[0])-(del23[0]*del34[2]);
cross234[2] = (del23[0]*del34[1])-(del23[1]*del34[0]);
cross234mag = sqrt(cross234[0]*cross234[0]+
cross234[1]*cross234[1]+
cross234[2]*cross234[2]);
cwnum = (cross321[0]*cross234[0]) +
(cross321[1]*cross234[1])+(cross321[2]*cross234[2]);
cwnom = r21*r34*r32*r32*sin321*sin234;
cw = cwnum/cwnom;
cw2 = (.5*(1.0-cw));
ekijl = epsilonT[ktype][ltype];
Ec = 256.0*ekijl/405.0;
Vtors = (Ec*(pow(cw2,5.0)))-(ekijl/10.0);
if (eflag) evdwl = Vtors*w21*w23*w34*(1.0-tspjik)*(1.0-tspijl);
dndij[0] = (cross234[1]*del21[2])-(cross234[2]*del21[1]);
dndij[1] = (cross234[2]*del21[0])-(cross234[0]*del21[2]);
dndij[2] = (cross234[0]*del21[1])-(cross234[1]*del21[0]);
tmpvec[0] = (del34[1]*cross321[2])-(del34[2]*cross321[1]);
tmpvec[1] = (del34[2]*cross321[0])-(del34[0]*cross321[2]);
tmpvec[2] = (del34[0]*cross321[1])-(del34[1]*cross321[0]);
dndij[0] = dndij[0]+tmpvec[0];
dndij[1] = dndij[1]+tmpvec[1];
dndij[2] = dndij[2]+tmpvec[2];
dndik[0] = (del23[1]*cross234[2])-(del23[2]*cross234[1]);
dndik[1] = (del23[2]*cross234[0])-(del23[0]*cross234[2]);
dndik[2] = (del23[0]*cross234[1])-(del23[1]*cross234[0]);
dndjl[0] = (cross321[1]*del23[2])-(cross321[2]*del23[1]);
dndjl[1] = (cross321[2]*del23[0])-(cross321[0]*del23[2]);
dndjl[2] = (cross321[0]*del23[1])-(cross321[1]*del23[0]);
dcidij = ((r23*r23)-(r21*r21)+(rjk*rjk))/(2.0*r23*r23*r21);
dcidik = ((r21*r21)-(r23*r23)+(rjk*rjk))/(2.0*r23*r21*r21);
dcidjk = (-rjk)/(r23*r21);
dcjdji = ((r23*r23)-(r34*r34)+(ril*ril))/(2.0*r23*r23*r34);
dcjdjl = ((r34*r34)-(r23*r23)+(ril*ril))/(2.0*r23*r34*r34);
dcjdil = (-ril)/(r23*r34);
dsidij = (-cos321/sin321)*dcidij;
dsidik = (-cos321/sin321)*dcidik;
dsidjk = (-cos321/sin321)*dcidjk;
dsjdji = (-cos234/sin234)*dcjdji;
dsjdjl = (-cos234/sin234)*dcjdjl;
dsjdil = (-cos234/sin234)*dcjdil;
dxidij = (r21*sin321)+(r23*r21*dsidij);
dxidik = (r23*sin321)+(r23*r21*dsidik);
dxidjk = (r23*r21*dsidjk);
dxjdji = (r34*sin234)+(r23*r34*dsjdji);
dxjdjl = (r23*sin234)+(r23*r34*dsjdjl);
dxjdil = (r23*r34*dsjdil);
ddndij = (dxidij*cross234mag)+(cross321mag*dxjdji);
ddndik = dxidik*cross234mag;
ddndjk = dxidjk*cross234mag;
ddndjl = cross321mag*dxjdjl;
ddndil = cross321mag*dxjdil;
dcwddn = -cwnum/(cwnom*cwnom);
dcwdn = 1.0/cwnom;
dvpdcw = (-1.0)*Ec*(-.5)*5.0*pow(cw2,4.0) *
w23*w21*w34*(1.0-tspjik)*(1.0-tspijl);
Ftmp[0] = dvpdcw*((dcwdn*dndij[0])+(dcwddn*ddndij*del23[0]/r23));
Ftmp[1] = dvpdcw*((dcwdn*dndij[1])+(dcwddn*ddndij*del23[1]/r23));
Ftmp[2] = dvpdcw*((dcwdn*dndij[2])+(dcwddn*ddndij*del23[2]/r23));
fi[0] = Ftmp[0];
fi[1] = Ftmp[1];
fi[2] = Ftmp[2];
fj[0] = -Ftmp[0];
fj[1] = -Ftmp[1];
fj[2] = -Ftmp[2];
Ftmp[0] = dvpdcw*((dcwdn*dndik[0])+(dcwddn*ddndik*del21[0]/r21));
Ftmp[1] = dvpdcw*((dcwdn*dndik[1])+(dcwddn*ddndik*del21[1]/r21));
Ftmp[2] = dvpdcw*((dcwdn*dndik[2])+(dcwddn*ddndik*del21[2]/r21));
fi[0] += Ftmp[0];
fi[1] += Ftmp[1];
fi[2] += Ftmp[2];
fk[0] = -Ftmp[0];
fk[1] = -Ftmp[1];
fk[2] = -Ftmp[2];
Ftmp[0] = (dvpdcw*dcwddn*ddndjk*deljk[0])/rjk;
Ftmp[1] = (dvpdcw*dcwddn*ddndjk*deljk[1])/rjk;
Ftmp[2] = (dvpdcw*dcwddn*ddndjk*deljk[2])/rjk;
fj[0] += Ftmp[0];
fj[1] += Ftmp[1];
fj[2] += Ftmp[2];
fk[0] -= Ftmp[0];
fk[1] -= Ftmp[1];
fk[2] -= Ftmp[2];
Ftmp[0] = dvpdcw*((dcwdn*dndjl[0])+(dcwddn*ddndjl*del34[0]/r34));
Ftmp[1] = dvpdcw*((dcwdn*dndjl[1])+(dcwddn*ddndjl*del34[1]/r34));
Ftmp[2] = dvpdcw*((dcwdn*dndjl[2])+(dcwddn*ddndjl*del34[2]/r34));
fj[0] += Ftmp[0];
fj[1] += Ftmp[1];
fj[2] += Ftmp[2];
fl[0] = -Ftmp[0];
fl[1] = -Ftmp[1];
fl[2] = -Ftmp[2];
Ftmp[0] = (dvpdcw*dcwddn*ddndil*delil[0])/ril;
Ftmp[1] = (dvpdcw*dcwddn*ddndil*delil[1])/ril;
Ftmp[2] = (dvpdcw*dcwddn*ddndil*delil[2])/ril;
fi[0] += Ftmp[0];
fi[1] += Ftmp[1];
fi[2] += Ftmp[2];
fl[0] -= Ftmp[0];
fl[1] -= Ftmp[1];
fl[2] -= Ftmp[2];
// coordination forces
fpair = Vtors*dw21*w23*w34*(1.0-tspjik)*(1.0-tspijl) / r21;
fi[0] -= del21[0]*fpair;
fi[1] -= del21[1]*fpair;
fi[2] -= del21[2]*fpair;
fk[0] += del21[0]*fpair;
fk[1] += del21[1]*fpair;
fk[2] += del21[2]*fpair;
fpair = Vtors*w21*dw23*w34*(1.0-tspjik)*(1.0-tspijl) / r23;
fi[0] -= del23[0]*fpair;
fi[1] -= del23[1]*fpair;
fi[2] -= del23[2]*fpair;
fj[0] += del23[0]*fpair;
fj[1] += del23[1]*fpair;
fj[2] += del23[2]*fpair;
fpair = Vtors*w21*w23*dw34*(1.0-tspjik)*(1.0-tspijl) / r34;
fj[0] -= del34[0]*fpair;
fj[1] -= del34[1]*fpair;
fj[2] -= del34[2]*fpair;
fl[0] += del34[0]*fpair;
fl[1] += del34[1]*fpair;
fl[2] += del34[2]*fpair;
// additional cut off function forces
fcpc = -Vtors*w21*w23*w34*dtsjik*(1.0-tspijl);
fpair = fcpc*dcidij/rij;
fi[0] += fpair*del23[0];
fi[1] += fpair*del23[1];
fi[2] += fpair*del23[2];
fj[0] -= fpair*del23[0];
fj[1] -= fpair*del23[1];
fj[2] -= fpair*del23[2];
fpair = fcpc*dcidik/rik;
fi[0] += fpair*del21[0];
fi[1] += fpair*del21[1];
fi[2] += fpair*del21[2];
fk[0] -= fpair*del21[0];
fk[1] -= fpair*del21[1];
fk[2] -= fpair*del21[2];
fpair = fcpc*dcidjk/rjk;
fj[0] += fpair*deljk[0];
fj[1] += fpair*deljk[1];
fj[2] += fpair*deljk[2];
fk[0] -= fpair*deljk[0];
fk[1] -= fpair*deljk[1];
fk[2] -= fpair*deljk[2];
fcpc = -Vtors*w21*w23*w34*(1.0-tspjik)*dtsijl;
fpair = fcpc*dcjdji/rij;
fi[0] += fpair*del23[0];
fi[1] += fpair*del23[1];
fi[2] += fpair*del23[2];
fj[0] -= fpair*del23[0];
fj[1] -= fpair*del23[1];
fj[2] -= fpair*del23[2];
fpair = fcpc*dcjdjl/rjl;
fj[0] += fpair*del34[0];
fj[1] += fpair*del34[1];
fj[2] += fpair*del34[2];
fl[0] -= fpair*del34[0];
fl[1] -= fpair*del34[1];
fl[2] -= fpair*del34[2];
fpair = fcpc*dcjdil/ril;
fi[0] += fpair*delil[0];
fi[1] += fpair*delil[1];
fi[2] += fpair*delil[2];
fl[0] -= fpair*delil[0];
fl[1] -= fpair*delil[1];
fl[2] -= fpair*delil[2];
// sum per-atom forces into atom force array
f[i][0] += fi[0]; f[i][1] += fi[1]; f[i][2] += fi[2];
f[j][0] += fj[0]; f[j][1] += fj[1]; f[j][2] += fj[2];
f[k][0] += fk[0]; f[k][1] += fk[1]; f[k][2] += fk[2];
f[l][0] += fl[0]; f[l][1] += fl[1]; f[l][2] += fl[2];
if (evflag) {
delkl[0] = delil[0] - del21[0];
delkl[1] = delil[1] - del21[1];
delkl[2] = delil[2] - del21[2];
ev_tally4(i,j,k,l,evdwl,fi,fj,fk,delil,del34,delkl);
}
}
}
}
}
}
// ----------------------------------------------------------------------
// S'(t) and S(t) cutoff functions
// ----------------------------------------------------------------------
/* ----------------------------------------------------------------------
cutoff function Sprime
return cutoff and dX = derivative
------------------------------------------------------------------------- */
double PairAIREBO::Sp(double Xij, double Xmin, double Xmax, double &dX)
{
double cutoff;
double t = (Xij-Xmin) / (Xmax-Xmin);
if (t <= 0.0) {
cutoff = 1.0;
dX = 0.0;
}
else if (t >= 1.0) {
cutoff = 0.0;
dX = 0.0;
}
else {
cutoff = 0.5 * (1.0+cos(PI*t));
dX = (-0.5*PI*sin(PI*t)) / (Xmax-Xmin);
}
return cutoff;
}
/* ----------------------------------------------------------------------
LJ cutoff function Sp2
return cutoff and dX = derivative
------------------------------------------------------------------------- */
double PairAIREBO::Sp2(double Xij, double Xmin, double Xmax, double &dX)
{
double cutoff;
double t = (Xij-Xmin) / (Xmax-Xmin);
if (t <= 0.0) {
cutoff = 1.0;
dX = 0.0;
}
if (t >= 1.0) {
cutoff = 0.0;
dX = 0.0;
}
if (t>0.0 && t<1.0) {
cutoff = (1.0-(t*t*(3.0-2.0*t)));
dX = 6.0*(t*t-t) / (Xmax-Xmin);
}
return cutoff;
}
/* ----------------------------------------------------------------------
Bij function
------------------------------------------------------------------------- */
double PairAIREBO::bondorder(int i, int j, double rij[3],
double rijmag, double VA,
double **f, int vflag_atom)
{
int atomi,atomj,k,n,l,atomk,atoml,atomn,atom1,atom2,atom3,atom4;
int itype,jtype,ktype,ltype,ntype;
double rik[3],rjl[3],rkn[3],rji[3],rki[3],rlj[3],rknmag,dNki,dwjl,bij;
double NijC,NijH,NjiC,NjiH,wik,dwik,dwkn,wjl;
double rikmag,rjlmag,cosjik,cosijl,g,tmp2,tmp3;
double Etmp,pij,tmp,wij,dwij,NconjtmpI,NconjtmpJ,Nki,Nlj,dS;
double lamdajik,lamdaijl,dgdc,dgdN,pji,Nijconj,piRC;
double dcosjikdri[3],dcosijldri[3],dcosjikdrk[3];
double dN2[2],dN3[3];
double dcosjikdrj[3],dcosijldrj[3],dcosijldrl[3];
double Tij;
double r32[3],r32mag,cos321,r43[3],r13[3];
double dNlj;
double om1234,rln[3];
double rlnmag,dwln,r23[3],r23mag,r21[3],r21mag;
double w21,dw21,r34[3],r34mag,cos234,w34,dw34;
double cross321[3],cross234[3],prefactor,SpN;
double fcijpc,fcikpc,fcjlpc,fcjkpc,fcilpc;
double dt2dik[3],dt2djl[3],dt2dij[3],aa,aaa1,aaa2,at2,cw,cwnum,cwnom;
double sin321,sin234,rr,rijrik,rijrjl,rjk2,rik2,ril2,rjl2;
double dctik,dctjk,dctjl,dctij,dctji,dctil,rik2i,rjl2i,sink2i,sinl2i;
double rjk[3],ril[3],dt1dik,dt1djk,dt1djl,dt1dil,dt1dij;
double F23[3],F12[3],F34[3],F31[3],F24[3],fi[3],fj[3],fk[3],fl[3];
double f1[3],f2[3],f3[3],f4[4];
double dcut321,PijS,PjiS;
double rij2,tspjik,dtsjik,tspijl,dtsijl,costmp;
int *REBO_neighs,*REBO_neighs_i,*REBO_neighs_j,*REBO_neighs_k,*REBO_neighs_l;
double **x = atom->x;
int *type = atom->type;
atomi = i;
atomj = j;
itype = map[type[i]];
jtype = map[type[j]];
wij = Sp(rijmag,rcmin[itype][jtype],rcmax[itype][jtype],dwij);
NijC = nC[i]-(wij*kronecker(jtype,0));
NijH = nH[i]-(wij*kronecker(jtype,1));
NjiC = nC[j]-(wij*kronecker(itype,0));
NjiH = nH[j]-(wij*kronecker(itype,1));
bij = 0.0;
tmp = 0.0;
tmp2 = 0.0;
tmp3 = 0.0;
dgdc = 0.0;
dgdN = 0.0;
NconjtmpI = 0.0;
NconjtmpJ = 0.0;
Etmp = 0.0;
REBO_neighs = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs[k];
if (atomk != atomj) {
ktype = map[type[atomk]];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
lamdajik = 4.0*kronecker(itype,1) *
((rho[ktype][1]-rikmag)-(rho[jtype][1]-rijmag));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dS);
Nki = nC[atomk]-(wik*kronecker(itype,0))+nH[atomk] -
(wik*kronecker(itype,1));
cosjik = ((rij[0]*rik[0])+(rij[1]*rik[1])+(rij[2]*rik[2])) /
(rijmag*rikmag);
cosjik = MIN(cosjik,1.0);
cosjik = MAX(cosjik,-1.0);
// evaluate splines g and derivatives dg
g = gSpline(cosjik,(NijC+NijH),itype,&dgdc,&dgdN);
Etmp = Etmp+(wik*g*exp(lamdajik));
tmp3 = tmp3+(wik*dgdN*exp(lamdajik));
NconjtmpI = NconjtmpI+(kronecker(ktype,0)*wik*Sp(Nki,Nmin,Nmax,dS));
}
}
PijS = 0.0;
dN2[0] = 0.0;
dN2[1] = 0.0;
PijS = PijSpline(NijC,NijH,itype,jtype,dN2);
pij = pow(1.0+Etmp+PijS,-0.5);
tmp = -0.5*pow(pij,3.0);
// pij forces
REBO_neighs = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs[k];
if (atomk != atomj) {
ktype = map[type[atomk]];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
lamdajik = 4.0*kronecker(itype,1) *
((rho[ktype][1]-rikmag)-(rho[jtype][1]-rijmag));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dwik);
cosjik = (rij[0]*rik[0] + rij[1]*rik[1] + rij[2]*rik[2]) /
(rijmag*rikmag);
cosjik = MIN(cosjik,1.0);
cosjik = MAX(cosjik,-1.0);
dcosjikdri[0] = ((rij[0]+rik[0])/(rijmag*rikmag)) -
(cosjik*((rij[0]/(rijmag*rijmag))+(rik[0]/(rikmag*rikmag))));
dcosjikdri[1] = ((rij[1]+rik[1])/(rijmag*rikmag)) -
(cosjik*((rij[1]/(rijmag*rijmag))+(rik[1]/(rikmag*rikmag))));
dcosjikdri[2] = ((rij[2]+rik[2])/(rijmag*rikmag)) -
(cosjik*((rij[2]/(rijmag*rijmag))+(rik[2]/(rikmag*rikmag))));
dcosjikdrk[0] = (-rij[0]/(rijmag*rikmag)) +
(cosjik*(rik[0]/(rikmag*rikmag)));
dcosjikdrk[1] = (-rij[1]/(rijmag*rikmag)) +
(cosjik*(rik[1]/(rikmag*rikmag)));
dcosjikdrk[2] = (-rij[2]/(rijmag*rikmag)) +
(cosjik*(rik[2]/(rikmag*rikmag)));
dcosjikdrj[0] = (-rik[0]/(rijmag*rikmag)) +
(cosjik*(rij[0]/(rijmag*rijmag)));
dcosjikdrj[1] = (-rik[1]/(rijmag*rikmag)) +
(cosjik*(rij[1]/(rijmag*rijmag)));
dcosjikdrj[2] = (-rik[2]/(rijmag*rikmag)) +
(cosjik*(rij[2]/(rijmag*rijmag)));
g = gSpline(cosjik,(NijC+NijH),itype,&dgdc,&dgdN);
tmp2 = VA*.5*(tmp*wik*dgdc*exp(lamdajik));
fj[0] = -tmp2*dcosjikdrj[0];
fj[1] = -tmp2*dcosjikdrj[1];
fj[2] = -tmp2*dcosjikdrj[2];
fi[0] = -tmp2*dcosjikdri[0];
fi[1] = -tmp2*dcosjikdri[1];
fi[2] = -tmp2*dcosjikdri[2];
fk[0] = -tmp2*dcosjikdrk[0];
fk[1] = -tmp2*dcosjikdrk[1];
fk[2] = -tmp2*dcosjikdrk[2];
tmp2 = VA*.5*(tmp*wik*g*exp(lamdajik)*4.0*kronecker(itype,1));
fj[0] -= tmp2*(-rij[0]/rijmag);
fj[1] -= tmp2*(-rij[1]/rijmag);
fj[2] -= tmp2*(-rij[2]/rijmag);
fi[0] -= tmp2*((-rik[0]/rikmag)+(rij[0]/rijmag));
fi[1] -= tmp2*((-rik[1]/rikmag)+(rij[1]/rijmag));
fi[2] -= tmp2*((-rik[2]/rikmag)+(rij[2]/rijmag));
fk[0] -= tmp2*(rik[0]/rikmag);
fk[1] -= tmp2*(rik[1]/rikmag);
fk[2] -= tmp2*(rik[2]/rikmag);
// coordination forces
// dwik forces
tmp2 = VA*.5*(tmp*dwik*g*exp(lamdajik))/rikmag;
fi[0] -= tmp2*rik[0];
fi[1] -= tmp2*rik[1];
fi[2] -= tmp2*rik[2];
fk[0] += tmp2*rik[0];
fk[1] += tmp2*rik[1];
fk[2] += tmp2*rik[2];
// PIJ forces
tmp2 = VA*.5*(tmp*dN2[ktype]*dwik)/rikmag;
fi[0] -= tmp2*rik[0];
fi[1] -= tmp2*rik[1];
fi[2] -= tmp2*rik[2];
fk[0] += tmp2*rik[0];
fk[1] += tmp2*rik[1];
fk[2] += tmp2*rik[2];
// dgdN forces
tmp2 = VA*.5*(tmp*tmp3*dwik)/rikmag;
fi[0] -= tmp2*rik[0];
fi[1] -= tmp2*rik[1];
fi[2] -= tmp2*rik[2];
fk[0] += tmp2*rik[0];
fk[1] += tmp2*rik[1];
fk[2] += tmp2*rik[2];
f[atomi][0] += fi[0]; f[atomi][1] += fi[1]; f[atomi][2] += fi[2];
f[atomj][0] += fj[0]; f[atomj][1] += fj[1]; f[atomj][2] += fj[2];
f[atomk][0] += fk[0]; f[atomk][1] += fk[1]; f[atomk][2] += fk[2];
if (vflag_atom) {
rji[0] = -rij[0]; rji[1] = -rij[1]; rji[2] = -rij[2];
rki[0] = -rik[0]; rki[1] = -rik[1]; rki[2] = -rik[2];
v_tally3(atomi,atomj,atomk,fj,fk,rji,rki);
}
}
}
tmp = 0.0;
tmp2 = 0.0;
tmp3 = 0.0;
Etmp = 0.0;
REBO_neighs = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs[l];
if (atoml != atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
lamdaijl = 4.0*kronecker(jtype,1) *
((rho[ltype][1]-rjlmag)-(rho[itype][1]-rijmag));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dS);
Nlj = nC[atoml]-(wjl*kronecker(jtype,0)) +
nH[atoml]-(wjl*kronecker(jtype,1));
cosijl = -1.0*((rij[0]*rjl[0])+(rij[1]*rjl[1])+(rij[2]*rjl[2])) /
(rijmag*rjlmag);
cosijl = MIN(cosijl,1.0);
cosijl = MAX(cosijl,-1.0);
// evaluate splines g and derivatives dg
g = gSpline(cosijl,NjiC+NjiH,jtype,&dgdc,&dgdN);
Etmp = Etmp+(wjl*g*exp(lamdaijl));
tmp3 = tmp3+(wjl*dgdN*exp(lamdaijl));
NconjtmpJ = NconjtmpJ+(kronecker(ltype,0)*wjl*Sp(Nlj,Nmin,Nmax,dS));
}
}
PjiS = 0.0;
dN2[0] = 0.0;
dN2[1] = 0.0;
PjiS = PijSpline(NjiC,NjiH,jtype,itype,dN2);
pji = pow(1.0+Etmp+PjiS,-0.5);
tmp = -0.5*pow(pji,3.0);
REBO_neighs = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs[l];
if (atoml != atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
lamdaijl = 4.0*kronecker(jtype,1) *
((rho[ltype][1]-rjlmag)-(rho[itype][1]-rijmag));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dwjl);
cosijl = (-1.0*((rij[0]*rjl[0])+(rij[1]*rjl[1])+(rij[2]*rjl[2]))) /
(rijmag*rjlmag);
cosijl = MIN(cosijl,1.0);
cosijl = MAX(cosijl,-1.0);
dcosijldri[0] = (-rjl[0]/(rijmag*rjlmag)) -
(cosijl*rij[0]/(rijmag*rijmag));
dcosijldri[1] = (-rjl[1]/(rijmag*rjlmag)) -
(cosijl*rij[1]/(rijmag*rijmag));
dcosijldri[2] = (-rjl[2]/(rijmag*rjlmag)) -
(cosijl*rij[2]/(rijmag*rijmag));
dcosijldrj[0] = ((-rij[0]+rjl[0])/(rijmag*rjlmag)) +
(cosijl*((rij[0]/pow(rijmag,2.0))-(rjl[0]/(rjlmag*rjlmag))));
dcosijldrj[1] = ((-rij[1]+rjl[1])/(rijmag*rjlmag)) +
(cosijl*((rij[1]/pow(rijmag,2.0))-(rjl[1]/(rjlmag*rjlmag))));
dcosijldrj[2] = ((-rij[2]+rjl[2])/(rijmag*rjlmag)) +
(cosijl*((rij[2]/pow(rijmag,2.0))-(rjl[2]/(rjlmag*rjlmag))));
dcosijldrl[0] = (rij[0]/(rijmag*rjlmag))+(cosijl*rjl[0]/(rjlmag*rjlmag));
dcosijldrl[1] = (rij[1]/(rijmag*rjlmag))+(cosijl*rjl[1]/(rjlmag*rjlmag));
dcosijldrl[2] = (rij[2]/(rijmag*rjlmag))+(cosijl*rjl[2]/(rjlmag*rjlmag));
// evaluate splines g and derivatives dg
g = gSpline(cosijl,NjiC+NjiH,jtype,&dgdc,&dgdN);
tmp2 = VA*.5*(tmp*wjl*dgdc*exp(lamdaijl));
fi[0] = -tmp2*dcosijldri[0];
fi[1] = -tmp2*dcosijldri[1];
fi[2] = -tmp2*dcosijldri[2];
fj[0] = -tmp2*dcosijldrj[0];
fj[1] = -tmp2*dcosijldrj[1];
fj[2] = -tmp2*dcosijldrj[2];
fl[0] = -tmp2*dcosijldrl[0];
fl[1] = -tmp2*dcosijldrl[1];
fl[2] = -tmp2*dcosijldrl[2];
tmp2 = VA*.5*(tmp*wjl*g*exp(lamdaijl)*4.0*kronecker(jtype,1));
fi[0] -= tmp2*(rij[0]/rijmag);
fi[1] -= tmp2*(rij[1]/rijmag);
fi[2] -= tmp2*(rij[2]/rijmag);
fj[0] -= tmp2*((-rjl[0]/rjlmag)-(rij[0]/rijmag));
fj[1] -= tmp2*((-rjl[1]/rjlmag)-(rij[1]/rijmag));
fj[2] -= tmp2*((-rjl[2]/rjlmag)-(rij[2]/rijmag));
fl[0] -= tmp2*(rjl[0]/rjlmag);
fl[1] -= tmp2*(rjl[1]/rjlmag);
fl[2] -= tmp2*(rjl[2]/rjlmag);
// coordination forces
// dwik forces
tmp2 = VA*.5*(tmp*dwjl*g*exp(lamdaijl))/rjlmag;
fj[0] -= tmp2*rjl[0];
fj[1] -= tmp2*rjl[1];
fj[2] -= tmp2*rjl[2];
fl[0] += tmp2*rjl[0];
fl[1] += tmp2*rjl[1];
fl[2] += tmp2*rjl[2];
// PIJ forces
tmp2 = VA*.5*(tmp*dN2[ltype]*dwjl)/rjlmag;
fj[0] -= tmp2*rjl[0];
fj[1] -= tmp2*rjl[1];
fj[2] -= tmp2*rjl[2];
fl[0] += tmp2*rjl[0];
fl[1] += tmp2*rjl[1];
fl[2] += tmp2*rjl[2];
// dgdN forces
tmp2 = VA*.5*(tmp*tmp3*dwjl)/rjlmag;
fj[0] -= tmp2*rjl[0];
fj[1] -= tmp2*rjl[1];
fj[2] -= tmp2*rjl[2];
fl[0] += tmp2*rjl[0];
fl[1] += tmp2*rjl[1];
fl[2] += tmp2*rjl[2];
f[atomi][0] += fi[0]; f[atomi][1] += fi[1]; f[atomi][2] += fi[2];
f[atomj][0] += fj[0]; f[atomj][1] += fj[1]; f[atomj][2] += fj[2];
f[atoml][0] += fl[0]; f[atoml][1] += fl[1]; f[atoml][2] += fl[2];
if (vflag_atom) {
rlj[0] = -rjl[0]; rlj[1] = -rjl[1]; rlj[2] = -rjl[2];
v_tally3(atomi,atomj,atoml,fi,fl,rij,rlj);
}
}
}
// evaluate Nij conj
Nijconj = 1.0+(NconjtmpI*NconjtmpI)+(NconjtmpJ*NconjtmpJ);
piRC = piRCSpline(NijC+NijH,NjiC+NjiH,Nijconj,itype,jtype,dN3);
// piRC forces
REBO_neighs_i = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs_i[k];
if (atomk !=atomj) {
ktype = map[type[atomk]];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dwik);
Nki = nC[atomk]-(wik*kronecker(itype,0))+nH[atomk] -
(wik*kronecker(itype,1));
SpN = Sp(Nki,Nmin,Nmax,dNki);
tmp2 = VA*dN3[0]*dwik/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*dwik*SpN)/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
if (fabs(dNki) > TOL) {
REBO_neighs_k = REBO_firstneigh[atomk];
for (n = 0; n < REBO_numneigh[atomk]; n++) {
atomn = REBO_neighs_k[n];
if (atomn != atomi) {
ntype = map[type[atomn]];
rkn[0] = x[atomk][0]-x[atomn][0];
rkn[1] = x[atomk][1]-x[atomn][1];
rkn[2] = x[atomk][2]-x[atomn][2];
rknmag = sqrt((rkn[0]*rkn[0])+(rkn[1]*rkn[1])+(rkn[2]*rkn[2]));
Sp(rknmag,rcmin[ktype][ntype],rcmax[ktype][ntype],dwkn);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*wik*dNki*dwkn)/rknmag;
f[atomk][0] -= tmp2*rkn[0];
f[atomk][1] -= tmp2*rkn[1];
f[atomk][2] -= tmp2*rkn[2];
f[atomn][0] += tmp2*rkn[0];
f[atomn][1] += tmp2*rkn[1];
f[atomn][2] += tmp2*rkn[2];
if (vflag_atom) v_tally2(atomk,atomn,-tmp2,rkn);
}
}
}
}
}
// piRC forces
REBO_neighs = REBO_firstneigh[atomj];
for (l = 0; l < REBO_numneigh[atomj]; l++) {
atoml = REBO_neighs[l];
if (atoml !=atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dwjl);
Nlj = nC[atoml]-(wjl*kronecker(jtype,0))+nH[atoml] -
(wjl*kronecker(jtype,1));
SpN = Sp(Nlj,Nmin,Nmax,dNlj);
tmp2 = VA*dN3[1]*dwjl/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*dwjl*SpN)/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
if (fabs(dNlj) > TOL) {
REBO_neighs_l = REBO_firstneigh[atoml];
for (n = 0; n < REBO_numneigh[atoml]; n++) {
atomn = REBO_neighs_l[n];
if (atomn != atomj) {
ntype = map[type[atomn]];
rln[0] = x[atoml][0]-x[atomn][0];
rln[1] = x[atoml][1]-x[atomn][1];
rln[2] = x[atoml][2]-x[atomn][2];
rlnmag = sqrt((rln[0]*rln[0])+(rln[1]*rln[1])+(rln[2]*rln[2]));
Sp(rlnmag,rcmin[ltype][ntype],rcmax[ltype][ntype],dwln);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*wjl*dNlj*dwln)/rlnmag;
f[atoml][0] -= tmp2*rln[0];
f[atoml][1] -= tmp2*rln[1];
f[atoml][2] -= tmp2*rln[2];
f[atomn][0] += tmp2*rln[0];
f[atomn][1] += tmp2*rln[1];
f[atomn][2] += tmp2*rln[2];
if (vflag_atom) v_tally2(atoml,atomn,-tmp2,rln);
}
}
}
}
}
Tij = 0.0;
dN3[0] = 0.0;
dN3[1] = 0.0;
dN3[2] = 0.0;
if (itype == 0 && jtype == 0)
Tij=TijSpline((NijC+NijH),(NjiC+NjiH),Nijconj,dN3);
Etmp = 0.0;
if (fabs(Tij) > TOL) {
atom2 = atomi;
atom3 = atomj;
r32[0] = x[atom3][0]-x[atom2][0];
r32[1] = x[atom3][1]-x[atom2][1];
r32[2] = x[atom3][2]-x[atom2][2];
r32mag = sqrt((r32[0]*r32[0])+(r32[1]*r32[1])+(r32[2]*r32[2]));
r23[0] = -r32[0];
r23[1] = -r32[1];
r23[2] = -r32[2];
r23mag = r32mag;
REBO_neighs_i = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs_i[k];
atom1 = atomk;
ktype = map[type[atomk]];
if (atomk != atomj) {
r21[0] = x[atom2][0]-x[atom1][0];
r21[1] = x[atom2][1]-x[atom1][1];
r21[2] = x[atom2][2]-x[atom1][2];
r21mag = sqrt(r21[0]*r21[0] + r21[1]*r21[1] + r21[2]*r21[2]);
cos321 = -1.0*((r21[0]*r32[0])+(r21[1]*r32[1])+(r21[2]*r32[2])) /
(r21mag*r32mag);
cos321 = MIN(cos321,1.0);
cos321 = MAX(cos321,-1.0);
Sp2(cos321,thmin,thmax,dcut321);
sin321 = sqrt(1.0 - cos321*cos321);
sink2i = 1.0/(sin321*sin321);
rik2i = 1.0/(r21mag*r21mag);
if (sin321 != 0.0) {
rr = (r23mag*r23mag)-(r21mag*r21mag);
rjk[0] = r21[0]-r23[0];
rjk[1] = r21[1]-r23[1];
rjk[2] = r21[2]-r23[2];
rjk2 = (rjk[0]*rjk[0])+(rjk[1]*rjk[1])+(rjk[2]*rjk[2]);
rijrik = 2.0*r23mag*r21mag;
rik2 = r21mag*r21mag;
dctik = (-rr+rjk2)/(rijrik*rik2);
dctij = (rr+rjk2)/(rijrik*r23mag*r23mag);
dctjk = -2.0/rijrik;
w21 = Sp(r21mag,rcmin[itype][ktype],rcmaxp[itype][ktype],dw21);
rijmag = r32mag;
rikmag = r21mag;
rij2 = r32mag*r32mag;
rik2 = r21mag*r21mag;
costmp = 0.5*(rij2+rik2-rjk2)/rijmag/rikmag;
tspjik = Sp2(costmp,thmin,thmax,dtsjik);
dtsjik = -dtsjik;
REBO_neighs_j = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs_j[l];
atom4 = atoml;
ltype = map[type[atoml]];
if (!(atoml == atomi || atoml == atomk)) {
r34[0] = x[atom3][0]-x[atom4][0];
r34[1] = x[atom3][1]-x[atom4][1];
r34[2] = x[atom3][2]-x[atom4][2];
r34mag = sqrt((r34[0]*r34[0])+(r34[1]*r34[1])+(r34[2]*r34[2]));
cos234 = (r32[0]*r34[0] + r32[1]*r34[1] + r32[2]*r34[2]) /
(r32mag*r34mag);
cos234 = MIN(cos234,1.0);
cos234 = MAX(cos234,-1.0);
sin234 = sqrt(1.0 - cos234*cos234);
sinl2i = 1.0/(sin234*sin234);
rjl2i = 1.0/(r34mag*r34mag);
if (sin234 != 0.0) {
w34 = Sp(r34mag,rcmin[jtype][ltype],rcmaxp[jtype][ltype],dw34);
rr = (r23mag*r23mag)-(r34mag*r34mag);
ril[0] = r23[0]+r34[0];
ril[1] = r23[1]+r34[1];
ril[2] = r23[2]+r34[2];
ril2 = (ril[0]*ril[0])+(ril[1]*ril[1])+(ril[2]*ril[2]);
rijrjl = 2.0*r23mag*r34mag;
rjl2 = r34mag*r34mag;
dctjl = (-rr+ril2)/(rijrjl*rjl2);
dctji = (rr+ril2)/(rijrjl*r23mag*r23mag);
dctil = -2.0/rijrjl;
rjlmag = r34mag;
rjl2 = r34mag*r34mag;
costmp = 0.5*(rij2+rjl2-ril2)/rijmag/rjlmag;
tspijl = Sp2(costmp,thmin,thmax,dtsijl);
dtsijl = -dtsijl;
prefactor = VA*Tij;
cross321[0] = (r32[1]*r21[2])-(r32[2]*r21[1]);
cross321[1] = (r32[2]*r21[0])-(r32[0]*r21[2]);
cross321[2] = (r32[0]*r21[1])-(r32[1]*r21[0]);
cross234[0] = (r23[1]*r34[2])-(r23[2]*r34[1]);
cross234[1] = (r23[2]*r34[0])-(r23[0]*r34[2]);
cross234[2] = (r23[0]*r34[1])-(r23[1]*r34[0]);
cwnum = (cross321[0]*cross234[0]) +
(cross321[1]*cross234[1]) + (cross321[2]*cross234[2]);
cwnom = r21mag*r34mag*r23mag*r23mag*sin321*sin234;
om1234 = cwnum/cwnom;
cw = om1234;
Etmp += ((1.0-pow(om1234,2.0))*w21*w34) *
(1.0-tspjik)*(1.0-tspijl);
dt1dik = (rik2i)-(dctik*sink2i*cos321);
dt1djk = (-dctjk*sink2i*cos321);
dt1djl = (rjl2i)-(dctjl*sinl2i*cos234);
dt1dil = (-dctil*sinl2i*cos234);
dt1dij = (2.0/(r23mag*r23mag))-(dctij*sink2i*cos321) -
(dctji*sinl2i*cos234);
dt2dik[0] = (-r23[2]*cross234[1])+(r23[1]*cross234[2]);
dt2dik[1] = (-r23[0]*cross234[2])+(r23[2]*cross234[0]);
dt2dik[2] = (-r23[1]*cross234[0])+(r23[0]*cross234[1]);
dt2djl[0] = (-r23[1]*cross321[2])+(r23[2]*cross321[1]);
dt2djl[1] = (-r23[2]*cross321[0])+(r23[0]*cross321[2]);
dt2djl[2] = (-r23[0]*cross321[1])+(r23[1]*cross321[0]);
dt2dij[0] = (r21[2]*cross234[1])-(r34[2]*cross321[1]) -
(r21[1]*cross234[2])+(r34[1]*cross321[2]);
dt2dij[1] = (r21[0]*cross234[2])-(r34[0]*cross321[2]) -
(r21[2]*cross234[0])+(r34[2]*cross321[0]);
dt2dij[2] = (r21[1]*cross234[0])-(r34[1]*cross321[0]) -
(r21[0]*cross234[1])+(r34[0]*cross321[1]);
aa = (prefactor*2.0*cw/cwnom)*w21*w34 *
(1.0-tspjik)*(1.0-tspijl);
aaa1 = -prefactor*(1.0-pow(om1234,2.0)) *
(1.0-tspjik)*(1.0-tspijl);
aaa2 = aaa1*w21*w34;
at2 = aa*cwnum;
fcijpc = (-dt1dij*at2)+(aaa2*dtsjik*dctij*(1.0-tspijl)) +
(aaa2*dtsijl*dctji*(1.0-tspjik));
fcikpc = (-dt1dik*at2)+(aaa2*dtsjik*dctik*(1.0-tspijl));
fcjlpc = (-dt1djl*at2)+(aaa2*dtsijl*dctjl*(1.0-tspjik));
fcjkpc = (-dt1djk*at2)+(aaa2*dtsjik*dctjk*(1.0-tspijl));
fcilpc = (-dt1dil*at2)+(aaa2*dtsijl*dctil*(1.0-tspjik));
F23[0] = (fcijpc*r23[0])+(aa*dt2dij[0]);
F23[1] = (fcijpc*r23[1])+(aa*dt2dij[1]);
F23[2] = (fcijpc*r23[2])+(aa*dt2dij[2]);
F12[0] = (fcikpc*r21[0])+(aa*dt2dik[0]);
F12[1] = (fcikpc*r21[1])+(aa*dt2dik[1]);
F12[2] = (fcikpc*r21[2])+(aa*dt2dik[2]);
F34[0] = (fcjlpc*r34[0])+(aa*dt2djl[0]);
F34[1] = (fcjlpc*r34[1])+(aa*dt2djl[1]);
F34[2] = (fcjlpc*r34[2])+(aa*dt2djl[2]);
F31[0] = (fcjkpc*rjk[0]);
F31[1] = (fcjkpc*rjk[1]);
F31[2] = (fcjkpc*rjk[2]);
F24[0] = (fcilpc*ril[0]);
F24[1] = (fcilpc*ril[1]);
F24[2] = (fcilpc*ril[2]);
f1[0] = -F12[0]-F31[0];
f1[1] = -F12[1]-F31[1];
f1[2] = -F12[2]-F31[2];
f2[0] = F23[0]+F12[0]+F24[0];
f2[1] = F23[1]+F12[1]+F24[1];
f2[2] = F23[2]+F12[2]+F24[2];
f3[0] = -F23[0]+F34[0]+F31[0];
f3[1] = -F23[1]+F34[1]+F31[1];
f3[2] = -F23[2]+F34[2]+F31[2];
f4[0] = -F34[0]-F24[0];
f4[1] = -F34[1]-F24[1];
f4[2] = -F34[2]-F24[2];
// coordination forces
tmp2 = VA*Tij*((1.0-(om1234*om1234))) *
(1.0-tspjik)*(1.0-tspijl)*dw21*w34/r21mag;
f2[0] -= tmp2*r21[0];
f2[1] -= tmp2*r21[1];
f2[2] -= tmp2*r21[2];
f1[0] += tmp2*r21[0];
f1[1] += tmp2*r21[1];
f1[2] += tmp2*r21[2];
tmp2 = VA*Tij*((1.0-(om1234*om1234))) *
(1.0-tspjik)*(1.0-tspijl)*w21*dw34/r34mag;
f3[0] -= tmp2*r34[0];
f3[1] -= tmp2*r34[1];
f3[2] -= tmp2*r34[2];
f4[0] += tmp2*r34[0];
f4[1] += tmp2*r34[1];
f4[2] += tmp2*r34[2];
f[atom1][0] += f1[0]; f[atom1][1] += f1[1];
f[atom1][2] += f1[2];
f[atom2][0] += f2[0]; f[atom2][1] += f2[1];
f[atom2][2] += f2[2];
f[atom3][0] += f3[0]; f[atom3][1] += f3[1];
f[atom3][2] += f3[2];
f[atom4][0] += f4[0]; f[atom4][1] += f4[1];
f[atom4][2] += f4[2];
if (vflag_atom) {
r13[0] = -rjk[0]; r13[1] = -rjk[1]; r13[2] = -rjk[2];
r43[0] = -r34[0]; r43[1] = -r34[1]; r43[2] = -r34[2];
v_tally4(atom1,atom2,atom3,atom4,f1,f2,f4,r13,r23,r43);
}
}
}
}
}
}
}
// Tij forces now that we have Etmp
REBO_neighs = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs[k];
if (atomk != atomj) {
ktype = map[type[atomk]];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dwik);
Nki = nC[atomk]-(wik*kronecker(itype,0))+nH[atomk] -
(wik*kronecker(itype,1));
SpN = Sp(Nki,Nmin,Nmax,dNki);
tmp2 = VA*dN3[0]*dwik*Etmp/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*dwik*SpN)*Etmp/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
if (fabs(dNki) > TOL) {
REBO_neighs_k = REBO_firstneigh[atomk];
for (n = 0; n < REBO_numneigh[atomk]; n++) {
atomn = REBO_neighs_k[n];
ntype = map[type[atomn]];
if (atomn != atomi) {
rkn[0] = x[atomk][0]-x[atomn][0];
rkn[1] = x[atomk][1]-x[atomn][1];
rkn[2] = x[atomk][2]-x[atomn][2];
rknmag = sqrt((rkn[0]*rkn[0])+(rkn[1]*rkn[1])+(rkn[2]*rkn[2]));
Sp(rknmag,rcmin[ktype][ntype],rcmax[ktype][ntype],dwkn);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*wik*dNki*dwkn)*Etmp/rknmag;
f[atomk][0] -= tmp2*rkn[0];
f[atomk][1] -= tmp2*rkn[1];
f[atomk][2] -= tmp2*rkn[2];
f[atomn][0] += tmp2*rkn[0];
f[atomn][1] += tmp2*rkn[1];
f[atomn][2] += tmp2*rkn[2];
if (vflag_atom) v_tally2(atomk,atomn,-tmp2,rkn);
}
}
}
}
}
// Tij forces
REBO_neighs = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs[l];
if (atoml != atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dwjl);
Nlj = nC[atoml]-(wjl*kronecker(jtype,0))+nH[atoml] -
(wjl*kronecker(jtype,1));
SpN = Sp(Nlj,Nmin,Nmax,dNlj);
tmp2 = VA*dN3[1]*dwjl*Etmp/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*dwjl*SpN)*Etmp/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
if (fabs(dNlj) > TOL) {
REBO_neighs_l = REBO_firstneigh[atoml];
for (n = 0; n < REBO_numneigh[atoml]; n++) {
atomn = REBO_neighs_l[n];
ntype = map[type[atomn]];
if (atomn !=atomj) {
rln[0] = x[atoml][0]-x[atomn][0];
rln[1] = x[atoml][1]-x[atomn][1];
rln[2] = x[atoml][2]-x[atomn][2];
rlnmag = sqrt((rln[0]*rln[0])+(rln[1]*rln[1])+(rln[2]*rln[2]));
Sp(rlnmag,rcmin[ltype][ntype],rcmax[ltype][ntype],dwln);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*wjl*dNlj*dwln)*Etmp/rlnmag;
f[atoml][0] -= tmp2*rln[0];
f[atoml][1] -= tmp2*rln[1];
f[atoml][2] -= tmp2*rln[2];
f[atomn][0] += tmp2*rln[0];
f[atomn][1] += tmp2*rln[1];
f[atomn][2] += tmp2*rln[2];
if (vflag_atom) v_tally2(atoml,atomn,-tmp2,rln);
}
}
}
}
}
}
bij = (0.5*(pij+pji))+piRC+(Tij*Etmp);
return bij;
}
/* ----------------------------------------------------------------------
Bij* function
------------------------------------------------------------------------- */
double PairAIREBO::bondorderLJ(int i, int j, double rij[3], double rijmag,
double VA, double rij0[3], double rij0mag,
double **f, int vflag_atom)
{
int k,n,l,atomk,atoml,atomn,atom1,atom2,atom3,atom4;
int atomi,atomj,itype,jtype,ktype,ltype,ntype;
double rik[3], rjl[3], rkn[3],rknmag,dNki;
double NijC,NijH,NjiC,NjiH,wik,dwik,dwkn,wjl;
double rikmag,rjlmag,cosjik,cosijl,g,tmp2,tmp3;
double Etmp,pij,tmp,wij,dwij,NconjtmpI,NconjtmpJ;
double Nki,Nlj,dS,lamdajik,lamdaijl,dgdc,dgdN,pji,Nijconj,piRC;
double dcosjikdri[3],dcosijldri[3],dcosjikdrk[3];
double dN2[2],dN3[3];
double dcosijldrj[3],dcosijldrl[3],dcosjikdrj[3],dwjl;
double Tij,crosskij[3],crosskijmag;
double crossijl[3],crossijlmag,omkijl;
double tmppij,tmppji,dN2PIJ[2],dN2PJI[2],dN3piRC[3],dN3Tij[3];
double bij,tmp3pij,tmp3pji,Stb,dStb;
double r32[3],r32mag,cos321;
double om1234,rln[3];
double rlnmag,dwln,r23[3],r23mag,r21[3],r21mag;
double w21,dw21,r34[3],r34mag,cos234,w34,dw34;
double cross321[3],cross234[3],prefactor,SpN;
double fcijpc,fcikpc,fcjlpc,fcjkpc,fcilpc;
double dt2dik[3],dt2djl[3],dt2dij[3],aa,aaa1,aaa2,at2,cw,cwnum,cwnom;
double sin321,sin234,rr,rijrik,rijrjl,rjk2,rik2,ril2,rjl2;
double dctik,dctjk,dctjl,dctij,dctji,dctil,rik2i,rjl2i,sink2i,sinl2i;
double rjk[3],ril[3],dt1dik,dt1djk,dt1djl,dt1dil,dt1dij;
double dNlj;
double PijS,PjiS;
double rij2,tspjik,dtsjik,tspijl,dtsijl,costmp;
int *REBO_neighs,*REBO_neighs_i,*REBO_neighs_j,*REBO_neighs_k,*REBO_neighs_l;
double F12[3],F23[3],F34[3],F31[3],F24[3];
double fi[3],fj[3],fk[3],fl[3],f1[3],f2[3],f3[3],f4[4];
double rji[3],rki[3],rlj[3],r13[3],r43[3];
double **x = atom->x;
int *type = atom->type;
atomi = i;
atomj = j;
itype = map[type[atomi]];
jtype = map[type[atomj]];
wij = Sp(rij0mag,rcmin[itype][jtype],rcmax[itype][jtype],dwij);
NijC = nC[atomi]-(wij*kronecker(jtype,0));
NijH = nH[atomi]-(wij*kronecker(jtype,1));
NjiC = nC[atomj]-(wij*kronecker(itype,0));
NjiH = nH[atomj]-(wij*kronecker(itype,1));
rij[0] = rij0[0];
rij[1] = rij0[1];
rij[2] = rij0[2];
rijmag = rij0mag;
bij = 0.0;
tmp = 0.0;
tmp2 = 0.0;
tmp3 = 0.0;
dgdc = 0.0;
dgdN = 0.0;
NconjtmpI = 0.0;
NconjtmpJ = 0.0;
Etmp = 0.0;
REBO_neighs = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs[k];
if (atomk != atomj) {
ktype = map[type[atomk]];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
lamdajik = 4.0*kronecker(itype,1) *
((rho[ktype][1]-rikmag)-(rho[jtype][1]-rijmag));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dS);
Nki = nC[atomk]-(wik*kronecker(itype,0)) +
nH[atomk]-(wik*kronecker(itype,1));
cosjik = ((rij[0]*rik[0])+(rij[1]*rik[1])+(rij[2]*rik[2])) /
(rijmag*rikmag);
cosjik = MIN(cosjik,1.0);
cosjik = MAX(cosjik,-1.0);
// evaluate splines g and derivatives dg
g = gSpline(cosjik,(NijC+NijH),itype,&dgdc,&dgdN);
Etmp = Etmp+(wik*g*exp(lamdajik));
tmp3 = tmp3+(wik*dgdN*exp(lamdajik));
NconjtmpI = NconjtmpI+(kronecker(ktype,0)*wik*Sp(Nki,Nmin,Nmax,dS));
}
}
PijS = 0.0;
dN2PIJ[0] = 0.0;
dN2PIJ[1] = 0.0;
PijS = PijSpline(NijC,NijH,itype,jtype,dN2PIJ);
pij = pow(1.0+Etmp+PijS,-0.5);
tmppij = -.5*pow(pij,3.0);
tmp3pij = tmp3;
tmp = 0.0;
tmp2 = 0.0;
tmp3 = 0.0;
Etmp = 0.0;
REBO_neighs = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs[l];
if (atoml != atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
lamdaijl = 4.0*kronecker(jtype,1) *
((rho[ltype][1]-rjlmag)-(rho[itype][1]-rijmag));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dS);
Nlj = nC[atoml]-(wjl*kronecker(jtype,0))+nH[atoml] -
(wjl*kronecker(jtype,1));
cosijl = -1.0*((rij[0]*rjl[0])+(rij[1]*rjl[1])+(rij[2]*rjl[2])) /
(rijmag*rjlmag);
cosijl = MIN(cosijl,1.0);
cosijl = MAX(cosijl,-1.0);
// evaluate splines g and derivatives dg
g = gSpline(cosijl,NjiC+NjiH,jtype,&dgdc,&dgdN);
Etmp = Etmp+(wjl*g*exp(lamdaijl));
tmp3 = tmp3+(wjl*dgdN*exp(lamdaijl));
NconjtmpJ = NconjtmpJ+(kronecker(ltype,0)*wjl*Sp(Nlj,Nmin,Nmax,dS));
}
}
PjiS = 0.0;
dN2PJI[0] = 0.0;
dN2PJI[1] = 0.0;
PjiS = PijSpline(NjiC,NjiH,jtype,itype,dN2PJI);
pji = pow(1.0+Etmp+PjiS,-0.5);
tmppji = -.5*pow(pji,3.0);
tmp3pji = tmp3;
// evaluate Nij conj
Nijconj = 1.0+(NconjtmpI*NconjtmpI)+(NconjtmpJ*NconjtmpJ);
piRC = piRCSpline(NijC+NijH,NjiC+NjiH,Nijconj,itype,jtype,dN3piRC);
Tij = 0.0;
dN3Tij[0] = 0.0;
dN3Tij[1] = 0.0;
dN3Tij[2] = 0.0;
if (itype == 0 && jtype == 0)
Tij=TijSpline((NijC+NijH),(NjiC+NjiH),Nijconj,dN3Tij);
Etmp = 0.0;
if (fabs(Tij) > TOL) {
REBO_neighs_i = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs_i[k];
ktype = map[type[atomk]];
if (atomk != atomj) {
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
cos321 = ((rij[0]*rik[0])+(rij[1]*rik[1])+(rij[2]*rik[2])) /
(rijmag*rikmag);
cos321 = MIN(cos321,1.0);
cos321 = MAX(cos321,-1.0);
rjk[0] = rik[0]-rij[0];
rjk[1] = rik[1]-rij[1];
rjk[2] = rik[2]-rij[2];
rjk2 = (rjk[0]*rjk[0])+(rjk[1]*rjk[1])+(rjk[2]*rjk[2]);
rij2 = rijmag*rijmag;
rik2 = rikmag*rikmag;
costmp = 0.5*(rij2+rik2-rjk2)/rijmag/rikmag;
tspjik = Sp2(costmp,thmin,thmax,dtsjik);
if (sqrt(1.0 - cos321*cos321) != 0.0) {
wik = Sp(rikmag,rcmin[itype][ktype],rcmaxp[itype][ktype],dwik);
REBO_neighs_j = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs_j[l];
ltype = map[type[atoml]];
if (!(atoml == atomi || atoml == atomk)) {
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt(rjl[0]*rjl[0] + rjl[1]*rjl[1] + rjl[2]*rjl[2]);
cos234 = -((rij[0]*rjl[0])+(rij[1]*rjl[1])+(rij[2]*rjl[2])) /
(rijmag*rjlmag);
cos234 = MIN(cos234,1.0);
cos234 = MAX(cos234,-1.0);
ril[0] = rij[0]+rjl[0];
ril[1] = rij[1]+rjl[1];
ril[2] = rij[2]+rjl[2];
ril2 = (ril[0]*ril[0])+(ril[1]*ril[1])+(ril[2]*ril[2]);
rijrjl = 2.0*rijmag*rjlmag;
rjl2 = rjlmag*rjlmag;
costmp = 0.5*(rij2+rjl2-ril2)/rijmag/rjlmag;
tspijl = Sp2(costmp,thmin,thmax,dtsijl);
if (sqrt(1.0 - cos234*cos234) != 0.0) {
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmaxp[jtype][ltype],dS);
crosskij[0] = (rij[1]*rik[2]-rij[2]*rik[1]);
crosskij[1] = (rij[2]*rik[0]-rij[0]*rik[2]);
crosskij[2] = (rij[0]*rik[1]-rij[1]*rik[0]);
crosskijmag = sqrt(crosskij[0]*crosskij[0] +
crosskij[1]*crosskij[1] +
crosskij[2]*crosskij[2]);
crossijl[0] = (rij[1]*rjl[2]-rij[2]*rjl[1]);
crossijl[1] = (rij[2]*rjl[0]-rij[0]*rjl[2]);
crossijl[2] = (rij[0]*rjl[1]-rij[1]*rjl[0]);
crossijlmag = sqrt(crossijl[0]*crossijl[0] +
crossijl[1]*crossijl[1] +
crossijl[2]*crossijl[2]);
omkijl = -1.0*(((crosskij[0]*crossijl[0]) +
(crosskij[1]*crossijl[1]) +
(crosskij[2]*crossijl[2])) /
(crosskijmag*crossijlmag));
Etmp += ((1.0-pow(omkijl,2.0))*wik*wjl) *
(1.0-tspjik)*(1.0-tspijl);
}
}
}
}
}
}
}
bij = (.5*(pij+pji))+piRC+(Tij*Etmp);
Stb = Sp2(bij,bLJmin[itype][jtype],bLJmax[itype][jtype],dStb);
VA = VA*dStb;
if (dStb != 0.0) {
tmp = tmppij;
dN2[0] = dN2PIJ[0];
dN2[1] = dN2PIJ[1];
tmp3 = tmp3pij;
// pij forces
REBO_neighs_i = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs_i[k];
if (atomk != atomj) {
lamdajik = 0.0;
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt(rik[0]*rik[0] + rik[1]*rik[1] + rik[2]*rik[2]);
lamdajik = 4.0*kronecker(itype,1) *
((rho[ktype][1]-rikmag)-(rho[jtype][1]-rijmag));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dwik);
cosjik = ((rij[0]*rik[0])+(rij[1]*rik[1])+(rij[2]*rik[2])) /
(rijmag*rikmag);
cosjik = MIN(cosjik,1.0);
cosjik = MAX(cosjik,-1.0);
dcosjikdri[0] = ((rij[0]+rik[0])/(rijmag*rikmag)) -
(cosjik*((rij[0]/(rijmag*rijmag))+(rik[0]/(rikmag*rikmag))));
dcosjikdri[1] = ((rij[1]+rik[1])/(rijmag*rikmag)) -
(cosjik*((rij[1]/(rijmag*rijmag))+(rik[1]/(rikmag*rikmag))));
dcosjikdri[2] = ((rij[2]+rik[2])/(rijmag*rikmag)) -
(cosjik*((rij[2]/(rijmag*rijmag))+(rik[2]/(rikmag*rikmag))));
dcosjikdrk[0] = (-rij[0]/(rijmag*rikmag)) +
(cosjik*(rik[0]/(rikmag*rikmag)));
dcosjikdrk[1] = (-rij[1]/(rijmag*rikmag)) +
(cosjik*(rik[1]/(rikmag*rikmag)));
dcosjikdrk[2] = (-rij[2]/(rijmag*rikmag)) +
(cosjik*(rik[2]/(rikmag*rikmag)));
dcosjikdrj[0] = (-rik[0]/(rijmag*rikmag)) +
(cosjik*(rij[0]/(rijmag*rijmag)));
dcosjikdrj[1] = (-rik[1]/(rijmag*rikmag)) +
(cosjik*(rij[1]/(rijmag*rijmag)));
dcosjikdrj[2] = (-rik[2]/(rijmag*rikmag)) +
(cosjik*(rij[2]/(rijmag*rijmag)));
g = gSpline(cosjik,(NijC+NijH),itype,&dgdc,&dgdN);
tmp2 = VA*.5*(tmp*wik*dgdc*exp(lamdajik));
fj[0] = -tmp2*dcosjikdrj[0];
fj[1] = -tmp2*dcosjikdrj[1];
fj[2] = -tmp2*dcosjikdrj[2];
fi[0] = -tmp2*dcosjikdri[0];
fi[1] = -tmp2*dcosjikdri[1];
fi[2] = -tmp2*dcosjikdri[2];
fk[0] = -tmp2*dcosjikdrk[0];
fk[1] = -tmp2*dcosjikdrk[1];
fk[2] = -tmp2*dcosjikdrk[2];
tmp2 = VA*.5*(tmp*wik*g*exp(lamdajik)*4.0*kronecker(itype,1));
fj[0] -= tmp2*(-rij[0]/rijmag);
fj[1] -= tmp2*(-rij[1]/rijmag);
fj[2] -= tmp2*(-rij[2]/rijmag);
fi[0] -= tmp2*((-rik[0]/rikmag)+(rij[0]/rijmag));
fi[1] -= tmp2*((-rik[1]/rikmag)+(rij[1]/rijmag));
fi[2] -= tmp2*((-rik[2]/rikmag)+(rij[2]/rijmag));
fk[0] -= tmp2*(rik[0]/rikmag);
fk[1] -= tmp2*(rik[1]/rikmag);
fk[2] -= tmp2*(rik[2]/rikmag);
// coordination forces
// dwik forces
tmp2 = VA*.5*(tmp*dwik*g*exp(lamdajik))/rikmag;
fi[0] -= tmp2*rik[0];
fi[1] -= tmp2*rik[1];
fi[2] -= tmp2*rik[2];
fk[0] += tmp2*rik[0];
fk[1] += tmp2*rik[1];
fk[2] += tmp2*rik[2];
// PIJ forces
tmp2 = VA*.5*(tmp*dN2[ktype]*dwik)/rikmag;
fi[0] -= tmp2*rik[0];
fi[1] -= tmp2*rik[1];
fi[2] -= tmp2*rik[2];
fk[0] += tmp2*rik[0];
fk[1] += tmp2*rik[1];
fk[2] += tmp2*rik[2];
// dgdN forces
tmp2 = VA*.5*(tmp*tmp3*dwik)/rikmag;
fi[0] -= tmp2*rik[0];
fi[1] -= tmp2*rik[1];
fi[2] -= tmp2*rik[2];
fk[0] += tmp2*rik[0];
fk[1] += tmp2*rik[1];
fk[2] += tmp2*rik[2];
f[atomi][0] += fi[0]; f[atomi][1] += fi[1]; f[atomi][2] += fi[2];
f[atomj][0] += fj[0]; f[atomj][1] += fj[1]; f[atomj][2] += fj[2];
f[atomk][0] += fk[0]; f[atomk][1] += fk[1]; f[atomk][2] += fk[2];
if (vflag_atom) {
rji[0] = -rij[0]; rji[1] = -rij[1]; rji[2] = -rij[2];
rki[0] = -rik[0]; rki[1] = -rik[1]; rki[2] = -rik[2];
v_tally3(atomi,atomj,atomk,fj,fk,rji,rki);
}
}
}
tmp = tmppji;
tmp3 = tmp3pji;
dN2[0] = dN2PJI[0];
dN2[1] = dN2PJI[1];
REBO_neighs = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs[l];
if (atoml !=atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
lamdaijl = 4.0*kronecker(jtype,1) *
((rho[ltype][1]-rjlmag)-(rho[itype][1]-rijmag));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dwjl);
cosijl = (-1.0*((rij[0]*rjl[0])+(rij[1]*rjl[1])+(rij[2]*rjl[2]))) /
(rijmag*rjlmag);
cosijl = MIN(cosijl,1.0);
cosijl = MAX(cosijl,-1.0);
dcosijldri[0] = (-rjl[0]/(rijmag*rjlmag)) -
(cosijl*rij[0]/(rijmag*rijmag));
dcosijldri[1] = (-rjl[1]/(rijmag*rjlmag)) -
(cosijl*rij[1]/(rijmag*rijmag));
dcosijldri[2] = (-rjl[2]/(rijmag*rjlmag)) -
(cosijl*rij[2]/(rijmag*rijmag));
dcosijldrj[0] = ((-rij[0]+rjl[0])/(rijmag*rjlmag)) +
(cosijl*((rij[0]/pow(rijmag,2.0))-(rjl[0]/(rjlmag*rjlmag))));
dcosijldrj[1] = ((-rij[1]+rjl[1])/(rijmag*rjlmag)) +
(cosijl*((rij[1]/pow(rijmag,2.0))-(rjl[1]/(rjlmag*rjlmag))));
dcosijldrj[2] = ((-rij[2]+rjl[2])/(rijmag*rjlmag)) +
(cosijl*((rij[2]/pow(rijmag,2.0))-(rjl[2]/(rjlmag*rjlmag))));
dcosijldrl[0] = (rij[0]/(rijmag*rjlmag)) +
(cosijl*rjl[0]/(rjlmag*rjlmag));
dcosijldrl[1] = (rij[1]/(rijmag*rjlmag)) +
(cosijl*rjl[1]/(rjlmag*rjlmag));
dcosijldrl[2] = (rij[2]/(rijmag*rjlmag)) +
(cosijl*rjl[2]/(rjlmag*rjlmag));
// evaluate splines g and derivatives dg
g = gSpline(cosijl,NjiC+NjiH,jtype,&dgdc,&dgdN);
tmp2 = VA*.5*(tmp*wjl*dgdc*exp(lamdaijl));
fi[0] = -tmp2*dcosijldri[0];
fi[1] = -tmp2*dcosijldri[1];
fi[2] = -tmp2*dcosijldri[2];
fj[0] = -tmp2*dcosijldrj[0];
fj[1] = -tmp2*dcosijldrj[1];
fj[2] = -tmp2*dcosijldrj[2];
fl[0] = -tmp2*dcosijldrl[0];
fl[1] = -tmp2*dcosijldrl[1];
fl[2] = -tmp2*dcosijldrl[2];
tmp2 = VA*.5*(tmp*wjl*g*exp(lamdaijl)*4.0*kronecker(jtype,1));
fi[0] -= tmp2*(rij[0]/rijmag);
fi[1] -= tmp2*(rij[1]/rijmag);
fi[2] -= tmp2*(rij[2]/rijmag);
fj[0] -= tmp2*((-rjl[0]/rjlmag)-(rij[0]/rijmag));
fj[1] -= tmp2*((-rjl[1]/rjlmag)-(rij[1]/rijmag));
fj[2] -= tmp2*((-rjl[2]/rjlmag)-(rij[2]/rijmag));
fl[0] -= tmp2*(rjl[0]/rjlmag);
fl[1] -= tmp2*(rjl[1]/rjlmag);
fl[2] -= tmp2*(rjl[2]/rjlmag);
// coordination forces
// dwik forces
tmp2 = VA*.5*(tmp*dwjl*g*exp(lamdaijl))/rjlmag;
fj[0] -= tmp2*rjl[0];
fj[1] -= tmp2*rjl[1];
fj[2] -= tmp2*rjl[2];
fl[0] += tmp2*rjl[0];
fl[1] += tmp2*rjl[1];
fl[2] += tmp2*rjl[2];
// PIJ forces
tmp2 = VA*.5*(tmp*dN2[ltype]*dwjl)/rjlmag;
fj[0] -= tmp2*rjl[0];
fj[1] -= tmp2*rjl[1];
fj[2] -= tmp2*rjl[2];
fl[0] += tmp2*rjl[0];
fl[1] += tmp2*rjl[1];
fl[2] += tmp2*rjl[2];
// dgdN forces
tmp2=VA*.5*(tmp*tmp3*dwjl)/rjlmag;
fj[0] -= tmp2*rjl[0];
fj[1] -= tmp2*rjl[1];
fj[2] -= tmp2*rjl[2];
fl[0] += tmp2*rjl[0];
fl[1] += tmp2*rjl[1];
fl[2] += tmp2*rjl[2];
f[atomi][0] += fi[0]; f[atomi][1] += fi[1]; f[atomi][2] += fi[2];
f[atomj][0] += fj[0]; f[atomj][1] += fj[1]; f[atomj][2] += fj[2];
f[atoml][0] += fl[0]; f[atoml][1] += fl[1]; f[atoml][2] += fl[2];
if (vflag_atom) {
rlj[0] = -rjl[0]; rlj[1] = -rjl[1]; rlj[2] = -rjl[2];
v_tally3(atomi,atomj,atoml,fi,fl,rij,rlj);
}
}
}
// piRC forces
dN3[0] = dN3piRC[0];
dN3[1] = dN3piRC[1];
dN3[2] = dN3piRC[2];
REBO_neighs_i = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs_i[k];
if (atomk != atomj) {
ktype = map[type[atomk]];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dwik);
Nki = nC[atomk]-(wik*kronecker(itype,0))+nH[atomk] -
(wik*kronecker(itype,1));
SpN = Sp(Nki,Nmin,Nmax,dNki);
tmp2 = VA*dN3[0]*dwik/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*dwik*SpN)/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
if (fabs(dNki) > TOL) {
REBO_neighs_k = REBO_firstneigh[atomk];
for (n = 0; n < REBO_numneigh[atomk]; n++) {
atomn = REBO_neighs_k[n];
if (atomn != atomi) {
ntype = map[type[atomn]];
rkn[0] = x[atomk][0]-x[atomn][0];
rkn[1] = x[atomk][1]-x[atomn][1];
rkn[2] = x[atomk][2]-x[atomn][2];
rknmag = sqrt((rkn[0]*rkn[0])+(rkn[1]*rkn[1])+(rkn[2]*rkn[2]));
Sp(rknmag,rcmin[ktype][ntype],rcmax[ktype][ntype],dwkn);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*wik*dNki*dwkn)/rknmag;
f[atomk][0] -= tmp2*rkn[0];
f[atomk][1] -= tmp2*rkn[1];
f[atomk][2] -= tmp2*rkn[2];
f[atomn][0] += tmp2*rkn[0];
f[atomn][1] += tmp2*rkn[1];
f[atomn][2] += tmp2*rkn[2];
if (vflag_atom) v_tally2(atomk,atomn,-tmp2,rkn);
}
}
}
}
}
// piRC forces to J side
REBO_neighs = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs[l];
if (atoml != atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dwjl);
Nlj = nC[atoml]-(wjl*kronecker(jtype,0))+nH[atoml] -
(wjl*kronecker(jtype,1));
SpN = Sp(Nlj,Nmin,Nmax,dNlj);
tmp2 = VA*dN3[1]*dwjl/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*dwjl*SpN)/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
if (fabs(dNlj) > TOL) {
REBO_neighs_l = REBO_firstneigh[atoml];
for (n = 0; n < REBO_numneigh[atoml]; n++) {
atomn = REBO_neighs_l[n];
if (atomn != atomj) {
ntype = map[type[atomn]];
rln[0] = x[atoml][0]-x[atomn][0];
rln[1] = x[atoml][1]-x[atomn][1];
rln[2] = x[atoml][2]-x[atomn][2];
rlnmag = sqrt((rln[0]*rln[0])+(rln[1]*rln[1])+(rln[2]*rln[2]));
Sp(rlnmag,rcmin[ltype][ntype],rcmax[ltype][ntype],dwln);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*wjl*dNlj*dwln)/rlnmag;
f[atoml][0] -= tmp2*rln[0];
f[atoml][1] -= tmp2*rln[1];
f[atoml][2] -= tmp2*rln[2];
f[atomn][0] += tmp2*rln[0];
f[atomn][1] += tmp2*rln[1];
f[atomn][2] += tmp2*rln[2];
if (vflag_atom) v_tally2(atoml,atomn,-tmp2,rln);
}
}
}
}
}
if (fabs(Tij) > TOL) {
dN3[0] = dN3Tij[0];
dN3[1] = dN3Tij[1];
dN3[2] = dN3Tij[2];
atom2 = atomi;
atom3 = atomj;
r32[0] = x[atom3][0]-x[atom2][0];
r32[1] = x[atom3][1]-x[atom2][1];
r32[2] = x[atom3][2]-x[atom2][2];
r32mag = sqrt((r32[0]*r32[0])+(r32[1]*r32[1])+(r32[2]*r32[2]));
r23[0] = -r32[0];
r23[1] = -r32[1];
r23[2] = -r32[2];
r23mag = r32mag;
REBO_neighs_i = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs_i[k];
atom1 = atomk;
ktype = map[type[atomk]];
if (atomk != atomj) {
r21[0] = x[atom2][0]-x[atom1][0];
r21[1] = x[atom2][1]-x[atom1][1];
r21[2] = x[atom2][2]-x[atom1][2];
r21mag = sqrt(r21[0]*r21[0] + r21[1]*r21[1] + r21[2]*r21[2]);
cos321 = ((r21[0]*rij[0])+(r21[1]*rij[1])+(r21[2]*rij[2])) /
(r21mag*rijmag);
cos321 = MIN(cos321,1.0);
cos321 = MAX(cos321,-1.0);
sin321 = sqrt(1.0 - cos321*cos321);
sink2i = 1.0/(sin321*sin321);
rik2i = 1.0/(r21mag*r21mag);
if (sin321 != 0.0) {
rr = (rijmag*rijmag)-(r21mag*r21mag);
rjk[0] = r21[0]-rij[0];
rjk[1] = r21[1]-rij[1];
rjk[2] = r21[2]-rij[2];
rjk2 = (rjk[0]*rjk[0])+(rjk[1]*rjk[1])+(rjk[2]*rjk[2]);
rijrik = 2.0*rijmag*r21mag;
rik2 = r21mag*r21mag;
dctik = (-rr+rjk2)/(rijrik*rik2);
dctij = (rr+rjk2)/(rijrik*rijmag*rijmag);
dctjk = -2.0/rijrik;
w21 = Sp(r21mag,rcmin[itype][ktype],rcmaxp[itype][ktype],dw21);
rikmag = r21mag;
rij2 = r32mag*r32mag;
rik2 = r21mag*r21mag;
costmp = 0.5*(rij2+rik2-rjk2)/rijmag/rikmag;
tspjik = Sp2(costmp,thmin,thmax,dtsjik);
dtsjik = -dtsjik;
REBO_neighs_j = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs_j[l];
atom4 = atoml;
ltype = map[type[atoml]];
if (!(atoml == atomi || atoml == atomk)) {
r34[0] = x[atom3][0]-x[atom4][0];
r34[1] = x[atom3][1]-x[atom4][1];
r34[2] = x[atom3][2]-x[atom4][2];
r34mag = sqrt(r34[0]*r34[0] + r34[1]*r34[1] + r34[2]*r34[2]);
cos234 = -1.0*((rij[0]*r34[0])+(rij[1]*r34[1]) +
(rij[2]*r34[2]))/(rijmag*r34mag);
cos234 = MIN(cos234,1.0);
cos234 = MAX(cos234,-1.0);
sin234 = sqrt(1.0 - cos234*cos234);
sinl2i = 1.0/(sin234*sin234);
rjl2i = 1.0/(r34mag*r34mag);
if (sin234 != 0.0) {
w34 = Sp(r34mag,rcmin[jtype][ltype],
rcmaxp[jtype][ltype],dw34);
rr = (r23mag*r23mag)-(r34mag*r34mag);
ril[0] = r23[0]+r34[0];
ril[1] = r23[1]+r34[1];
ril[2] = r23[2]+r34[2];
ril2 = (ril[0]*ril[0])+(ril[1]*ril[1])+(ril[2]*ril[2]);
rijrjl = 2.0*r23mag*r34mag;
rjl2 = r34mag*r34mag;
dctjl = (-rr+ril2)/(rijrjl*rjl2);
dctji = (rr+ril2)/(rijrjl*r23mag*r23mag);
dctil = -2.0/rijrjl;
rjlmag = r34mag;
rjl2 = r34mag*r34mag;
costmp = 0.5*(rij2+rjl2-ril2)/rijmag/rjlmag;
tspijl = Sp2(costmp,thmin,thmax,dtsijl);
dtsijl = -dtsijl; //need minus sign
prefactor = VA*Tij;
cross321[0] = (r32[1]*r21[2])-(r32[2]*r21[1]);
cross321[1] = (r32[2]*r21[0])-(r32[0]*r21[2]);
cross321[2] = (r32[0]*r21[1])-(r32[1]*r21[0]);
cross234[0] = (r23[1]*r34[2])-(r23[2]*r34[1]);
cross234[1] = (r23[2]*r34[0])-(r23[0]*r34[2]);
cross234[2] = (r23[0]*r34[1])-(r23[1]*r34[0]);
cwnum = (cross321[0]*cross234[0]) +
(cross321[1]*cross234[1])+(cross321[2]*cross234[2]);
cwnom = r21mag*r34mag*r23mag*r23mag*sin321*sin234;
om1234 = cwnum/cwnom;
cw = om1234;
Etmp += ((1.0-pow(om1234,2.0))*w21*w34) *
(1.0-tspjik)*(1.0-tspijl);
dt1dik = (rik2i)-(dctik*sink2i*cos321);
dt1djk = (-dctjk*sink2i*cos321);
dt1djl = (rjl2i)-(dctjl*sinl2i*cos234);
dt1dil = (-dctil*sinl2i*cos234);
dt1dij = (2.0/(r23mag*r23mag)) -
(dctij*sink2i*cos321)-(dctji*sinl2i*cos234);
dt2dik[0] = (-r23[2]*cross234[1])+(r23[1]*cross234[2]);
dt2dik[1] = (-r23[0]*cross234[2])+(r23[2]*cross234[0]);
dt2dik[2] = (-r23[1]*cross234[0])+(r23[0]*cross234[1]);
dt2djl[0] = (-r23[1]*cross321[2])+(r23[2]*cross321[1]);
dt2djl[1] = (-r23[2]*cross321[0])+(r23[0]*cross321[2]);
dt2djl[2] = (-r23[0]*cross321[1])+(r23[1]*cross321[0]);
dt2dij[0] = (r21[2]*cross234[1]) -
(r34[2]*cross321[1])-(r21[1]*cross234[2]) +
(r34[1]*cross321[2]);
dt2dij[1] = (r21[0]*cross234[2]) -
(r34[0]*cross321[2])-(r21[2]*cross234[0]) +
(r34[2]*cross321[0]);
dt2dij[2] = (r21[1]*cross234[0]) -
(r34[1]*cross321[0])-(r21[0]*cross234[1]) +
(r34[0]*cross321[1]);
aa = (prefactor*2.0*cw/cwnom)*w21*w34 *
(1.0-tspjik)*(1.0-tspijl);
aaa1 = -prefactor*(1.0-pow(om1234,2.0)) *
(1.0-tspjik)*(1.0-tspijl);
aaa2 = aaa1*w21*w34;
at2 = aa*cwnum;
fcijpc = (-dt1dij*at2)+(aaa2*dtsjik*dctij*(1.0-tspijl)) +
(aaa2*dtsijl*dctji*(1.0-tspjik));
fcikpc = (-dt1dik*at2)+(aaa2*dtsjik*dctik*(1.0-tspijl));
fcjlpc = (-dt1djl*at2)+(aaa2*dtsijl*dctjl*(1.0-tspjik));
fcjkpc = (-dt1djk*at2)+(aaa2*dtsjik*dctjk*(1.0-tspijl));
fcilpc = (-dt1dil*at2)+(aaa2*dtsijl*dctil*(1.0-tspjik));
F23[0] = (fcijpc*r23[0])+(aa*dt2dij[0]);
F23[1] = (fcijpc*r23[1])+(aa*dt2dij[1]);
F23[2] = (fcijpc*r23[2])+(aa*dt2dij[2]);
F12[0] = (fcikpc*r21[0])+(aa*dt2dik[0]);
F12[1] = (fcikpc*r21[1])+(aa*dt2dik[1]);
F12[2] = (fcikpc*r21[2])+(aa*dt2dik[2]);
F34[0] = (fcjlpc*r34[0])+(aa*dt2djl[0]);
F34[1] = (fcjlpc*r34[1])+(aa*dt2djl[1]);
F34[2] = (fcjlpc*r34[2])+(aa*dt2djl[2]);
F31[0] = (fcjkpc*rjk[0]);
F31[1] = (fcjkpc*rjk[1]);
F31[2] = (fcjkpc*rjk[2]);
F24[0] = (fcilpc*ril[0]);
F24[1] = (fcilpc*ril[1]);
F24[2] = (fcilpc*ril[2]);
f1[0] = -F12[0]-F31[0];
f1[1] = -F12[1]-F31[1];
f1[2] = -F12[2]-F31[2];
f2[0] = F23[0]+F12[0]+F24[0];
f2[1] = F23[1]+F12[1]+F24[1];
f2[2] = F23[2]+F12[2]+F24[2];
f3[0] = -F23[0]+F34[0]+F31[0];
f3[1] = -F23[1]+F34[1]+F31[1];
f3[2] = -F23[2]+F34[2]+F31[2];
f4[0] = -F34[0]-F24[0];
f4[1] = -F34[1]-F24[1];
f4[2] = -F34[2]-F24[2];
// coordination forces
tmp2 = VA*Tij*((1.0-(om1234*om1234))) *
(1.0-tspjik)*(1.0-tspijl)*dw21*w34/r21mag;
f2[0] -= tmp2*r21[0];
f2[1] -= tmp2*r21[1];
f2[2] -= tmp2*r21[2];
f1[0] += tmp2*r21[0];
f1[1] += tmp2*r21[1];
f1[2] += tmp2*r21[2];
tmp2 = VA*Tij*((1.0-(om1234*om1234))) *
(1.0-tspjik)*(1.0-tspijl)*w21*dw34/r34mag;
f3[0] -= tmp2*r34[0];
f3[1] -= tmp2*r34[1];
f3[2] -= tmp2*r34[2];
f4[0] += tmp2*r34[0];
f4[1] += tmp2*r34[1];
f4[2] += tmp2*r34[2];
f[atom1][0] += f1[0]; f[atom1][1] += f1[1];
f[atom1][2] += f1[2];
f[atom2][0] += f2[0]; f[atom2][1] += f2[1];
f[atom2][2] += f2[2];
f[atom3][0] += f3[0]; f[atom3][1] += f3[1];
f[atom3][2] += f3[2];
f[atom4][0] += f4[0]; f[atom4][1] += f4[1];
f[atom4][2] += f4[2];
if (vflag_atom) {
r13[0] = -rjk[0]; r13[1] = -rjk[1]; r13[2] = -rjk[2];
r43[0] = -r34[0]; r43[1] = -r34[1]; r43[2] = -r34[2];
v_tally4(atom1,atom2,atom3,atom4,f1,f2,f4,r13,r23,r43);
}
}
}
}
}
}
}
REBO_neighs = REBO_firstneigh[i];
for (k = 0; k < REBO_numneigh[i]; k++) {
atomk = REBO_neighs[k];
if (atomk != atomj) {
ktype = map[type[atomk]];
rik[0] = x[atomi][0]-x[atomk][0];
rik[1] = x[atomi][1]-x[atomk][1];
rik[2] = x[atomi][2]-x[atomk][2];
rikmag = sqrt((rik[0]*rik[0])+(rik[1]*rik[1])+(rik[2]*rik[2]));
wik = Sp(rikmag,rcmin[itype][ktype],rcmax[itype][ktype],dwik);
Nki = nC[atomk]-(wik*kronecker(itype,0))+nH[atomk] -
(wik*kronecker(itype,1));
SpN = Sp(Nki,Nmin,Nmax,dNki);
tmp2 = VA*dN3[0]*dwik*Etmp/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*dwik*SpN)*Etmp/rikmag;
f[atomi][0] -= tmp2*rik[0];
f[atomi][1] -= tmp2*rik[1];
f[atomi][2] -= tmp2*rik[2];
f[atomk][0] += tmp2*rik[0];
f[atomk][1] += tmp2*rik[1];
f[atomk][2] += tmp2*rik[2];
if (vflag_atom) v_tally2(atomi,atomk,-tmp2,rik);
if (fabs(dNki) >TOL) {
REBO_neighs_k = REBO_firstneigh[atomk];
for (n = 0; n < REBO_numneigh[atomk]; n++) {
atomn = REBO_neighs_k[n];
ntype = map[type[atomn]];
if (atomn !=atomi) {
rkn[0] = x[atomk][0]-x[atomn][0];
rkn[1] = x[atomk][1]-x[atomn][1];
rkn[2] = x[atomk][2]-x[atomn][2];
rknmag = sqrt((rkn[0]*rkn[0])+(rkn[1]*rkn[1])+(rkn[2]*rkn[2]));
Sp(rknmag,rcmin[ktype][ntype],rcmax[ktype][ntype],dwkn);
tmp2 = VA*dN3[2]*(2.0*NconjtmpI*wik*dNki*dwkn)*Etmp/rknmag;
f[atomk][0] -= tmp2*rkn[0];
f[atomk][1] -= tmp2*rkn[1];
f[atomk][2] -= tmp2*rkn[2];
f[atomn][0] += tmp2*rkn[0];
f[atomn][1] += tmp2*rkn[1];
f[atomn][2] += tmp2*rkn[2];
if (vflag_atom) v_tally2(atomk,atomn,-tmp2,rkn);
}
}
}
}
}
// Tij forces
REBO_neighs = REBO_firstneigh[j];
for (l = 0; l < REBO_numneigh[j]; l++) {
atoml = REBO_neighs[l];
if (atoml != atomi) {
ltype = map[type[atoml]];
rjl[0] = x[atomj][0]-x[atoml][0];
rjl[1] = x[atomj][1]-x[atoml][1];
rjl[2] = x[atomj][2]-x[atoml][2];
rjlmag = sqrt((rjl[0]*rjl[0])+(rjl[1]*rjl[1])+(rjl[2]*rjl[2]));
wjl = Sp(rjlmag,rcmin[jtype][ltype],rcmax[jtype][ltype],dwjl);
Nlj = nC[atoml]-(wjl*kronecker(jtype,0))+nH[atoml] -
(wjl*kronecker(jtype,1));
SpN = Sp(Nlj,Nmin,Nmax,dNlj);
tmp2 = VA*dN3[1]*dwjl*Etmp/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*dwjl*SpN)*Etmp/rjlmag;
f[atomj][0] -= tmp2*rjl[0];
f[atomj][1] -= tmp2*rjl[1];
f[atomj][2] -= tmp2*rjl[2];
f[atoml][0] += tmp2*rjl[0];
f[atoml][1] += tmp2*rjl[1];
f[atoml][2] += tmp2*rjl[2];
if (vflag_atom) v_tally2(atomj,atoml,-tmp2,rjl);
if (fabs(dNlj) > TOL) {
REBO_neighs_l = REBO_firstneigh[atoml];
for (n = 0; n < REBO_numneigh[atoml]; n++) {
atomn = REBO_neighs_l[n];
ntype = map[type[atomn]];
if (atomn != atomj) {
rln[0] = x[atoml][0]-x[atomn][0];
rln[1] = x[atoml][1]-x[atomn][1];
rln[2] = x[atoml][2]-x[atomn][2];
rlnmag = sqrt((rln[0]*rln[0])+(rln[1]*rln[1])+(rln[2]*rln[2]));
Sp(rlnmag,rcmin[ltype][ntype],rcmax[ltype][ntype],dwln);
tmp2 = VA*dN3[2]*(2.0*NconjtmpJ*wjl*dNlj*dwln)*Etmp/rlnmag;
f[atoml][0] -= tmp2*rln[0];
f[atoml][1] -= tmp2*rln[1];
f[atoml][2] -= tmp2*rln[2];
f[atomn][0] += tmp2*rln[0];
f[atomn][1] += tmp2*rln[1];
f[atomn][2] += tmp2*rln[2];
if (vflag_atom) v_tally2(atoml,atomn,-tmp2,rln);
}
}
}
}
}
}
}
return Stb;
}
/* ----------------------------------------------------------------------
G spline
------------------------------------------------------------------------- */
double PairAIREBO::gSpline(double costh, double Nij, int typei,
double *dgdc, double *dgdN)
{
double coeffs[6],dS,g1,g2,dg1,dg2,cut,g;
int i,j;
i = 0;
j = 0;
g = 0.0;
cut = 0.0;
dS = 0.0;
dg1 = 0.0;
dg2 = 0.0;
*dgdc = 0.0;
*dgdN = 0.0;
// central atom is Carbon
if (typei == 0) {
if (costh < gCdom[0]) costh = gCdom[0];
if (costh > gCdom[4]) costh = gCdom[4];
if (Nij >= NCmax) {
for (i = 0; i < 4; i++) {
if (costh >= gCdom[i] && costh <= gCdom[i+1]) {
for (j = 0; j < 6; j++) coeffs[j] = gC2[i][j];
}
}
g2 = Sp5th(costh,coeffs,&dg2);
g = g2;
*dgdc = dg2;
*dgdN = 0.0;
}
if (Nij <= NCmin) {
for (i = 0; i < 4; i++) {
if (costh >= gCdom[i] && costh <= gCdom[i+1]) {
for (j = 0; j < 6; j++) coeffs[j] = gC1[i][j];
}
}
g1 = Sp5th(costh,coeffs,&dg1);
g = g1;
*dgdc = dg1;
*dgdN = 0.0;
}
if (Nij > NCmin && Nij < NCmax) {
for (i = 0; i < 4; i++) {
if (costh >= gCdom[i] && costh <= gCdom[i+1]) {
for (j = 0; j < 6; j++) coeffs[j] = gC1[i][j];
}
}
g1 = Sp5th(costh,coeffs,&dg1);
for (i = 0; i < 4; i++) {
if (costh >= gCdom[i] && costh <= gCdom[i+1]) {
for (j = 0; j < 6; j++) coeffs[j] = gC2[i][j];
}
}
g2 = Sp5th(costh,coeffs,&dg2);
cut = Sp(Nij,NCmin,NCmax,dS);
g = g2+cut*(g1-g2);
*dgdc = dg2+(cut*(dg1-dg2));
*dgdN = dS*(g1-g2);
}
}
// central atom is Hydrogen
if (typei == 1) {
if (costh < gHdom[0]) costh = gHdom[0];
if (costh > gHdom[3]) costh = gHdom[3];
for (i = 0; i < 3; i++) {
if (costh >= gHdom[i] && costh <= gHdom[i+1]) {
for (j = 0; j < 6; j++) coeffs[j] = gH[i][j];
}
}
g = Sp5th(costh,coeffs,&dg1);
*dgdN = 0.0;
*dgdc = dg1;
}
return g;
}
/* ----------------------------------------------------------------------
Pij spline
------------------------------------------------------------------------- */
double PairAIREBO::PijSpline(double NijC, double NijH, int typei, int typej,
double dN2[2])
{
int x,y,i,done;
double Pij,coeffs[16];
for (i = 0; i < 16; i++) coeffs[i]=0.0;
x = 0;
y = 0;
dN2[0] = 0.0;
dN2[1] = 0.0;
done = 0;
// if inputs are out of bounds set them back to a point in bounds
if (typei == 0 && typej == 0) {
if (NijC < pCCdom[0][0]) NijC=pCCdom[0][0];
if (NijC > pCCdom[0][1]) NijC=pCCdom[0][1];
if (NijH < pCCdom[1][0]) NijH=pCCdom[1][0];
if (NijH > pCCdom[1][1]) NijH=pCCdom[1][1];
if (fabs(NijC-floor(NijC)) < TOL && fabs(NijH-floor(NijH)) < TOL) {
Pij = PCCf[(int) NijC][(int) NijH];
dN2[0] = PCCdfdx[(int) NijC][(int) NijH];
dN2[1] = PCCdfdy[(int) NijC][(int) NijH];
done = 1;
}
if (done == 0) {
x = (int) (floor(NijC));
y = (int) (floor(NijH));
for (i = 0; i<16; i++) coeffs[i] = pCC[x][y][i];
Pij = Spbicubic(NijC,NijH,coeffs,dN2);
}
}
// if inputs are out of bounds set them back to a point in bounds
if (typei == 0 && typej == 1){
if (NijC < pCHdom[0][0]) NijC=pCHdom[0][0];
if (NijC > pCHdom[0][1]) NijC=pCHdom[0][1];
if (NijH < pCHdom[0][0]) NijH=pCHdom[1][0];
if (NijH > pCHdom[1][1]) NijH=pCHdom[1][1];
if (fabs(NijC-floor(NijC)) < TOL && fabs(NijH-floor(NijH)) < TOL) {
Pij = PCHf[(int) NijC][(int) NijH];
dN2[0] = PCHdfdx[(int) NijC][(int) NijH];
dN2[1] = PCHdfdy[(int) NijC][(int) NijH];
done = 1;
}
if (done == 0) {
x = (int) (floor(NijC));
y = (int) (floor(NijH));
for (i = 0; i<16; i++) coeffs[i] = pCH[x][y][i];
Pij = Spbicubic(NijC,NijH,coeffs,dN2);
}
}
if (typei == 1 && typej == 0) {
Pij = 0.0;
dN2[0] = 0.0;
dN2[1] = 0.0;
}
if (typei == 1 && typej == 1) {
Pij = 0.0;
dN2[0] = 0.0;
dN2[1] = 0.0;
}
return Pij;
}
/* ----------------------------------------------------------------------
PiRC spline
------------------------------------------------------------------------- */
double PairAIREBO::piRCSpline(double Nij, double Nji, double Nijconj,
int typei, int typej, double dN3[3])
{
int x,y,z,i,done;
double piRC,coeffs[64];
x=0;
y=0;
z=0;
i=0;
done=0;
for (i=0; i<64; i++) coeffs[i]=0.0;
if (typei==0 && typej==0) {
//if the inputs are out of bounds set them back to a point in bounds
if (Nij<piCCdom[0][0]) Nij=piCCdom[0][0];
if (Nij>piCCdom[0][1]) Nij=piCCdom[0][1];
if (Nji<piCCdom[1][0]) Nji=piCCdom[1][0];
if (Nji>piCCdom[1][1]) Nji=piCCdom[1][1];
if (Nijconj<piCCdom[2][0]) Nijconj=piCCdom[2][0];
if (Nijconj>piCCdom[2][1]) Nijconj=piCCdom[2][1];
if (fabs(Nij-floor(Nij))<TOL && fabs(Nji-floor(Nji))<TOL &&
fabs(Nijconj-floor(Nijconj))<TOL) {
piRC=piCCf[(int) Nij][(int) Nji][(int) Nijconj];
dN3[0]=piCCdfdx[(int) Nij][(int) Nji][(int) Nijconj];
dN3[1]=piCCdfdy[(int) Nij][(int) Nji][(int) Nijconj];
dN3[2]=piCCdfdz[(int) Nij][(int) Nji][(int) Nijconj];
done=1;
}
if (done==0) {
for (i=0; i<piCCdom[0][1]; i++)
if (Nij>=(double) i && Nij<=(double) i+1 || Nij==(double) i) x=i;
for (i=0; i<piCCdom[1][1]; i++)
if (Nji>=(double) i && Nji<=(double) i+1 || Nji==(double) i) y=i;
for (i=0; i<piCCdom[2][1]; i++)
if (Nijconj>=(double) i && Nijconj<=(double) i+1 ||
Nijconj==(double) i) z=i;
for (i=0; i<64; i++) coeffs[i]=piCC[x][y][z][i];
piRC=Sptricubic(Nij,Nji,Nijconj,coeffs,dN3);
}
}
// CH interaction
if (typei==0 && typej==1 || typei==1 && typej==0) {
// if the inputs are out of bounds set them back to a point in bounds
if (Nij<piCHdom[0][0] || Nij>piCHdom[0][1] ||
Nji<piCHdom[1][0] || Nji>piCHdom[1][1] ||
Nijconj<piCHdom[2][0] || Nijconj>piCHdom[2][1]) {
if (Nij<piCHdom[0][0]) Nij=piCHdom[0][0];
if (Nij>piCHdom[0][1]) Nij=piCHdom[0][1];
if (Nji<piCHdom[1][0]) Nji=piCHdom[1][0];
if (Nji>piCHdom[1][1]) Nji=piCHdom[1][1];
if (Nijconj<piCHdom[2][0]) Nijconj=piCHdom[2][0];
if (Nijconj>piCHdom[2][1]) Nijconj=piCHdom[2][1];
}
if (fabs(Nij-floor(Nij))<TOL && fabs(Nji-floor(Nji))<TOL &&
fabs(Nijconj-floor(Nijconj))<TOL) {
piRC=piCHf[(int) Nij][(int) Nji][(int) Nijconj];
dN3[0]=piCHdfdx[(int) Nij][(int) Nji][(int) Nijconj];
dN3[1]=piCHdfdy[(int) Nij][(int) Nji][(int) Nijconj];
dN3[2]=piCHdfdz[(int) Nij][(int) Nji][(int) Nijconj];
done=1;
}
if (done==0) {
for (i=0; i<piCHdom[0][1]; i++)
if (Nij>=i && Nij<=i+1) x=i;
for (i=0; i<piCHdom[1][1]; i++)
if (Nji>=i && Nji<=i+1) y=i;
for (i=0; i<piCHdom[2][1]; i++)
if (Nijconj>=i && Nijconj<=i+1) z=i;
for (i=0; i<64; i++) coeffs[i]=piCH[x][y][z][i];
piRC=Sptricubic(Nij,Nji,Nijconj,coeffs,dN3);
}
}
if (typei==1 && typej==1) {
if (Nij<piHHdom[0][0] || Nij>piHHdom[0][1] ||
Nji<piHHdom[1][0] || Nji>piHHdom[1][1] ||
Nijconj<piHHdom[2][0] || Nijconj>piHHdom[2][1]) {
Nij=0.0;
Nji=0.0;
Nijconj=0.0;
}
if (fabs(Nij-floor(Nij))<TOL && fabs(Nji-floor(Nji))<TOL &&
fabs(Nijconj-floor(Nijconj))<TOL) {
piRC=piHHf[(int) Nij][(int) Nji][(int) Nijconj];
dN3[0]=piHHdfdx[(int) Nij][(int) Nji][(int) Nijconj];
dN3[1]=piHHdfdy[(int) Nij][(int) Nji][(int) Nijconj];
dN3[2]=piHHdfdz[(int) Nij][(int) Nji][(int) Nijconj];
done=1;
}
if (done==0) {
for (i=0; i<piHHdom[0][1]; i++)
if (Nij>=i && Nij<=i+1) x=i;
for (i=0; i<piHHdom[1][1]; i++)
if (Nji>=i && Nji<=i+1) y=i;
for (i=0; i<piHHdom[2][1]; i++)
if (Nijconj>=i && Nijconj<=i+1) z=i;
for (i=0; i<64; i++) coeffs[i]=piHH[x][y][z][i];
piRC=Sptricubic(Nij,Nji,Nijconj,coeffs,dN3);
}
}
return piRC;
}
/* ----------------------------------------------------------------------
Tij spline
------------------------------------------------------------------------- */
double PairAIREBO::TijSpline(double Nij, double Nji,
double Nijconj, double dN3[3])
{
int x,y,z,i,done;
double Tijf,coeffs[64];
x=0;
y=0;
z=0;
i=0;
Tijf=0.0;
done=0;
for (i=0; i<64; i++) coeffs[i]=0.0;
//if the inputs are out of bounds set them back to a point in bounds
if (Nij<Tijdom[0][0]) Nij=Tijdom[0][0];
if (Nij>Tijdom[0][1]) Nij=Tijdom[0][1];
if (Nji<Tijdom[1][0]) Nji=Tijdom[1][0];
if (Nji>Tijdom[1][1]) Nji=Tijdom[1][1];
if (Nijconj<Tijdom[2][0]) Nijconj=Tijdom[2][0];
if (Nijconj>Tijdom[2][1]) Nijconj=Tijdom[2][1];
if (fabs(Nij-floor(Nij))<TOL && fabs(Nji-floor(Nji))<TOL &&
fabs(Nijconj-floor(Nijconj))<TOL) {
Tijf=Tf[(int) Nij][(int) Nji][(int) Nijconj];
dN3[0]=Tdfdx[(int) Nij][(int) Nji][(int) Nijconj];
dN3[1]=Tdfdy[(int) Nij][(int) Nji][(int) Nijconj];
dN3[2]=Tdfdz[(int) Nij][(int) Nji][(int) Nijconj];
done=1;
}
if (done==0) {
for (i=0; i<Tijdom[0][1]; i++)
if (Nij>=i && Nij<=i+1) x=i;
for (i=0; i<Tijdom[1][1]; i++)
if (Nji>=i && Nji<=i+1) y=i;
for (i=0; i<Tijdom[2][1]; i++)
if (Nijconj>=i && Nijconj<=i+1) z=i;
for (i=0; i<64; i++) coeffs[i]=Tijc[x][y][z][i];
Tijf=Sptricubic(Nij,Nji,Nijconj,coeffs,dN3);
}
return Tijf;
}
/* ----------------------------------------------------------------------
Kronecker delta function
------------------------------------------------------------------------- */
double PairAIREBO::kronecker(int a, int b)
{
double kd;
if (a == b) kd = 1.0;
else kd = 0.0;
return kd;
}
/* ----------------------------------------------------------------------
add pages to REBO neighbor list, starting at npage
------------------------------------------------------------------------- */
void PairAIREBO::add_pages(int npage)
{
maxpage += PGDELTA;
pages = (int **)
memory->srealloc(pages,maxpage*sizeof(int *),"AIREBO:pages");
for (int i = npage; i < maxpage; i++)
memory->create(pages[i],pgsize,"AIREBO:pages[i]");
}
/* ----------------------------------------------------------------------
read AIREBO potential file
------------------------------------------------------------------------- */
void PairAIREBO::read_file(char *filename)
{
int i,j,k,l,limit;
char s[MAXLINE];
// REBO Parameters (AIREBO)
double rcmin_CC,rcmin_CH,rcmin_HH,rcmax_CC,rcmax_CH,
rcmax_HH,rcmaxp_CC,rcmaxp_CH,rcmaxp_HH;
double Q_CC,Q_CH,Q_HH,alpha_CC,alpha_CH,alpha_HH,A_CC,A_CH,A_HH;
double BIJc_CC1,BIJc_CC2,BIJc_CC3,BIJc_CH1,BIJc_CH2,BIJc_CH3,
BIJc_HH1,BIJc_HH2,BIJc_HH3;
double Beta_CC1,Beta_CC2,Beta_CC3,Beta_CH1,Beta_CH2,Beta_CH3,
Beta_HH1,Beta_HH2,Beta_HH3;
double rho_CC,rho_CH,rho_HH;
// LJ Parameters (AIREBO)
double rcLJmin_CC,rcLJmin_CH,rcLJmin_HH,rcLJmax_CC,rcLJmax_CH,
rcLJmax_HH,bLJmin_CC;
double bLJmin_CH,bLJmin_HH,bLJmax_CC,bLJmax_CH,bLJmax_HH,
epsilon_CC,epsilon_CH,epsilon_HH;
double sigma_CC,sigma_CH,sigma_HH,epsilonT_CCCC,epsilonT_CCCH,epsilonT_HCCH;
MPI_Comm_rank(world,&me);
// read file on proc 0
if (me == 0) {
FILE *fp = fopen(filename,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open AIREBO potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
// skip initial comment lines
while (1) {
fgets(s,MAXLINE,fp);
if (s[0] != '#') break;
}
// read parameters
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmin_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmin_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmin_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmax_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmax_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmax_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmaxp_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmaxp_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcmaxp_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&smin);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Nmin);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Nmax);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&NCmin);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&NCmax);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Q_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Q_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Q_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&alpha_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&alpha_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&alpha_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&A_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&A_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&A_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_CC1);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_CC2);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_CC3);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_CH1);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_CH2);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_CH3);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_HH1);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_HH2);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&BIJc_HH3);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_CC1);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_CC2);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_CC3);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_CH1);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_CH2);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_CH3);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_HH1);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_HH2);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Beta_HH3);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rho_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rho_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rho_HH);
// LJ parameters
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcLJmin_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcLJmin_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcLJmin_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcLJmax_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcLJmax_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&rcLJmax_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&bLJmin_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&bLJmin_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&bLJmin_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&bLJmax_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&bLJmax_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&bLJmax_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&epsilon_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&epsilon_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&epsilon_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&sigma_CC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&sigma_CH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&sigma_HH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&epsilonT_CCCC);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&epsilonT_CCCH);
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&epsilonT_HCCH);
// gC spline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
// number-1 = # of domains for the spline
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit; i++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&gCdom[i]);
}
fgets(s,MAXLINE,fp);
for (i = 0; i < limit-1; i++) {
for (j = 0; j < 6; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&gC1[i][j]);
}
}
fgets(s,MAXLINE,fp);
for (i = 0; i < limit-1; i++) {
for (j = 0; j < 6; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&gC2[i][j]);
}
}
// gH spline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit; i++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&gHdom[i]);
}
fgets(s,MAXLINE,fp);
for (i = 0; i < limit-1; i++) {
for (j = 0; j < 6; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&gH[i][j]);
}
}
// pCC spline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit/2; i++) {
for (j = 0; j < limit/2; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&pCCdom[i][j]);
}
}
fgets(s,MAXLINE,fp);
for (i = 0; i < (int) pCCdom[0][1]; i++) {
for (j = 0; j < (int) pCCdom[1][1]; j++) {
for (k = 0; k < 16; k++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&pCC[i][j][k]);
}
}
}
// pCH spline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit/2; i++) {
for (j = 0; j < limit/2; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&pCHdom[i][j]);
}
}
fgets(s,MAXLINE,fp);
for (i = 0; i < (int) pCHdom[0][1]; i++) {
for (j = 0; j < (int) pCHdom[1][1]; j++) {
for (k = 0; k < 16; k++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&pCH[i][j][k]);
}
}
}
// piCC cpline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit/2; i++) {
for (j = 0; j < limit/3; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&piCCdom[i][j]);
}
}
fgets(s,MAXLINE,fp);
for (i = 0; i < (int) piCCdom[0][1]; i++) {
for (j = 0; j < (int) piCCdom[1][1]; j++) {
for (k = 0; k < (int) piCCdom[2][1]; k++) {
for (l = 0; l < 64; l = l+1) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&piCC[i][j][k][l]);
}
}
}
}
// piCH spline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit/2; i++) {
for (j = 0; j < limit/3; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&piCHdom[i][j]);
}
}
fgets(s,MAXLINE,fp);
for (i = 0; i < (int) piCHdom[0][1]; i++) {
for (j = 0; j < (int) piCHdom[1][1]; j++) {
for (k = 0; k < (int) piCHdom[2][1]; k++) {
for (l = 0; l < 64; l = l+1) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&piCH[i][j][k][l]);
}
}
}
}
// piHH spline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit/2; i++) {
for (j = 0; j < limit/3; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&piHHdom[i][j]);
}
}
fgets(s,MAXLINE,fp);
for (i = 0; i < (int) piHHdom[0][1]; i++) {
for (j = 0; j < (int) piHHdom[1][1]; j++) {
for (k = 0; k < (int) piHHdom[2][1]; k++) {
for (l = 0; l < 64; l = l+1) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&piHH[i][j][k][l]);
}
}
}
}
// Tij spline
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
fgets(s,MAXLINE,fp);
sscanf(s,"%d",&limit);
for (i = 0; i < limit/2; i++) {
for (j = 0; j < limit/3; j++) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Tijdom[i][j]);
}
}
fgets(s,MAXLINE,fp);
for (i = 0; i < (int) Tijdom[0][1]; i++) {
for (j = 0; j < (int) Tijdom[1][1]; j++) {
for (k = 0; k < (int) Tijdom[2][1]; k++) {
for (l = 0; l < 64; l = l+1) {
fgets(s,MAXLINE,fp);
sscanf(s,"%lg",&Tijc[i][j][k][l]);
}
}
}
}
fclose(fp);
}
// store read-in values in arrays
if (me == 0) {
// REBO
rcmin[0][0] = rcmin_CC;
rcmin[0][1] = rcmin_CH;
rcmin[1][0] = rcmin[0][1];
rcmin[1][1] = rcmin_HH;
rcmax[0][0] = rcmax_CC;
rcmax[0][1] = rcmax_CH;
rcmax[1][0] = rcmax[0][1];
rcmax[1][1] = rcmax_HH;
rcmaxsq[0][0] = rcmax[0][0]*rcmax[0][0];
rcmaxsq[1][0] = rcmax[1][0]*rcmax[1][0];
rcmaxsq[0][1] = rcmax[0][1]*rcmax[0][1];
rcmaxsq[1][1] = rcmax[1][1]*rcmax[1][1];
rcmaxp[0][0] = rcmaxp_CC;
rcmaxp[0][1] = rcmaxp_CH;
rcmaxp[1][0] = rcmaxp[0][1];
rcmaxp[1][1] = rcmaxp_HH;
Q[0][0] = Q_CC;
Q[0][1] = Q_CH;
Q[1][0] = Q[0][1];
Q[1][1] = Q_HH;
alpha[0][0] = alpha_CC;
alpha[0][1] = alpha_CH;
alpha[1][0] = alpha[0][1];
alpha[1][1] = alpha_HH;
A[0][0] = A_CC;
A[0][1] = A_CH;
A[1][0] = A[0][1];
A[1][1] = A_HH;
rho[0][0] = rho_CC;
rho[0][1] = rho_CH;
rho[1][0] = rho[0][1];
rho[1][1] = rho_HH;
BIJc[0][0][0] = BIJc_CC1;
BIJc[0][0][1] = BIJc_CC2;
BIJc[0][0][2] = BIJc_CC3;
BIJc[0][1][0] = BIJc_CH1;
BIJc[0][1][1] = BIJc_CH2;
BIJc[0][1][2] = BIJc_CH3;
BIJc[1][0][0] = BIJc_CH1;
BIJc[1][0][1] = BIJc_CH2;
BIJc[1][0][2] = BIJc_CH3;
BIJc[1][1][0] = BIJc_HH1;
BIJc[1][1][1] = BIJc_HH2;
BIJc[1][1][2] = BIJc_HH3;
Beta[0][0][0] = Beta_CC1;
Beta[0][0][1] = Beta_CC2;
Beta[0][0][2] = Beta_CC3;
Beta[0][1][0] = Beta_CH1;
Beta[0][1][1] = Beta_CH2;
Beta[0][1][2] = Beta_CH3;
Beta[1][0][0] = Beta_CH1;
Beta[1][0][1] = Beta_CH2;
Beta[1][0][2] = Beta_CH3;
Beta[1][1][0] = Beta_HH1;
Beta[1][1][1] = Beta_HH2;
Beta[1][1][2] = Beta_HH3;
// LJ
rcLJmin[0][0] = rcLJmin_CC;
rcLJmin[0][1] = rcLJmin_CH;
rcLJmin[1][0] = rcLJmin[0][1];
rcLJmin[1][1] = rcLJmin_HH;
rcLJmax[0][0] = rcLJmax_CC;
rcLJmax[0][1] = rcLJmax_CH;
rcLJmax[1][0] = rcLJmax[0][1];
rcLJmax[1][1] = rcLJmax_HH;
rcLJmaxsq[0][0] = rcLJmax[0][0]*rcLJmax[0][0];
rcLJmaxsq[1][0] = rcLJmax[1][0]*rcLJmax[1][0];
rcLJmaxsq[0][1] = rcLJmax[0][1]*rcLJmax[0][1];
rcLJmaxsq[1][1] = rcLJmax[1][1]*rcLJmax[1][1];
bLJmin[0][0] = bLJmin_CC;
bLJmin[0][1] = bLJmin_CH;
bLJmin[1][0] = bLJmin[0][1];
bLJmin[1][1] = bLJmin_HH;
bLJmax[0][0] = bLJmax_CC;
bLJmax[0][1] = bLJmax_CH;
bLJmax[1][0] = bLJmax[0][1];
bLJmax[1][1] = bLJmax_HH;
epsilon[0][0] = epsilon_CC;
epsilon[0][1] = epsilon_CH;
epsilon[1][0] = epsilon[0][1];
epsilon[1][1] = epsilon_HH;
sigma[0][0] = sigma_CC;
sigma[0][1] = sigma_CH;
sigma[1][0] = sigma[0][1];
sigma[1][1] = sigma_HH;
// torsional
thmin = -1.0;
thmax = -0.995;
epsilonT[0][0] = epsilonT_CCCC;
epsilonT[0][1] = epsilonT_CCCH;
epsilonT[1][0] = epsilonT[0][1];
epsilonT[1][1] = epsilonT_HCCH;
}
// broadcast read-in and setup values
MPI_Bcast(&thmin,1,MPI_DOUBLE,0,world);
MPI_Bcast(&thmax,1,MPI_DOUBLE,0,world);
MPI_Bcast(&smin,1,MPI_DOUBLE,0,world);
MPI_Bcast(&Nmin,1,MPI_DOUBLE,0,world);
MPI_Bcast(&Nmax,1,MPI_DOUBLE,0,world);
MPI_Bcast(&NCmin,1,MPI_DOUBLE,0,world);
MPI_Bcast(&NCmax,1,MPI_DOUBLE,0,world);
MPI_Bcast(&rcmin[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcmax[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcmaxsq[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcmaxp[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&Q[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&alpha[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&A[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rho[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&BIJc[0][0][0],12,MPI_DOUBLE,0,world);
MPI_Bcast(&Beta[0][0][0],12,MPI_DOUBLE,0,world);
MPI_Bcast(&rcLJmin[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcLJmax[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcLJmaxsq[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcLJmin[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcLJmin[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcLJmin[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&rcLJmax[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&bLJmin[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&bLJmax[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&epsilon[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&epsilonT[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&gCdom[0],5,MPI_DOUBLE,0,world);
MPI_Bcast(&gC1[0][0],24,MPI_DOUBLE,0,world);
MPI_Bcast(&gC2[0][0],24,MPI_DOUBLE,0,world);
MPI_Bcast(&gHdom[0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&gH[0][0],18,MPI_DOUBLE,0,world);
MPI_Bcast(&pCCdom[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&pCHdom[0][0],4,MPI_DOUBLE,0,world);
MPI_Bcast(&pCC[0][0][0],256,MPI_DOUBLE,0,world);
MPI_Bcast(&pCH[0][0][0],256,MPI_DOUBLE,0,world);
MPI_Bcast(&piCCdom[0][0],6,MPI_DOUBLE,0,world);
MPI_Bcast(&piCHdom[0][0],6,MPI_DOUBLE,0,world);
MPI_Bcast(&piHHdom[0][0],6,MPI_DOUBLE,0,world);
MPI_Bcast(&piCC[0][0][0][0],9216,MPI_DOUBLE,0,world);
MPI_Bcast(&piCH[0][0][0][0],9216,MPI_DOUBLE,0,world);
MPI_Bcast(&piHH[0][0][0][0],9216,MPI_DOUBLE,0,world);
MPI_Bcast(&Tijdom[0][0],6,MPI_DOUBLE,0,world);
MPI_Bcast(&Tijc[0][0][0][0],9216,MPI_DOUBLE,0,world);
}
// ----------------------------------------------------------------------
// generic Spline functions
// ----------------------------------------------------------------------
/* ----------------------------------------------------------------------
fifth order spline evaluation
------------------------------------------------------------------------- */
double PairAIREBO::Sp5th(double x, double coeffs[6], double *df)
{
double f;
int i;
i = 0;
f = 0.0;
*df = 0.0;
for (i = 0; i<6; i++) {
f += coeffs[i]*pow(x,((double) i));
if (i > 0) *df += coeffs[i]*((double) i)*pow(x,((double) i-1.0));
}
return f;
}
/* ----------------------------------------------------------------------
bicubic spline evaluation
------------------------------------------------------------------------- */
double PairAIREBO::Spbicubic(double x, double y,
double coeffs[16], double df[2])
{
double f;
int i,j,cn;
f = 0.0;
df[0] = 0.0;
df[1] = 0.0;
cn = 0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
f += coeffs[cn]*pow(x,((double) i))*pow(y,((double) j));
if (i > 0) df[0] +=
(coeffs[cn]*((double) i)*pow(x,((double) i-1.0)) *
pow(y,((double) j)));
if (j > 0) df[1] +=
(coeffs[cn]*((double) j)*pow(x,((double) i)) *
pow(y,((double) j-1.0)));
cn++;
}
}
return f;
}
/* ----------------------------------------------------------------------
tricubic spline evaluation
------------------------------------------------------------------------- */
double PairAIREBO::Sptricubic(double x, double y, double z,
double coeffs[64], double df[3])
{
double f,ir,jr,kr;
int i,j,k,cn;
f = 0.0;
df[0] = 0.0;
df[1] = 0.0;
df[2] = 0.0;
cn = 0;
for (i = 0; i < 4; i++) {
ir = (double) i;
for (j = 0; j < 4; j++) {
jr = (double) j;
for (k = 0; k < 4; k++) {
kr = (double) k;
f += (coeffs[cn]*pow(x,ir)*pow(y,jr)*pow(z,kr));
if (i > 0) df[0] +=
(coeffs[cn]*ir*pow(x,ir-1.0)*pow(y,jr)*pow(z,kr));
if (j > 0) df[1] +=
(coeffs[cn]*jr*pow(x,ir)*pow(y,jr-1.0)*pow(z,kr));
if (k > 0) df[2] +=
(coeffs[cn]*kr*pow(x,ir)*pow(y,jr)*pow(z,kr-1.0));
cn++;
}
}
}
return f;
}
/* ----------------------------------------------------------------------
initialize spline knot values
------------------------------------------------------------------------- */
void PairAIREBO::spline_init()
{
int i,j,k;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
PCCf[i][j] = 0.0;
PCCdfdx[i][j] = 0.0;
PCCdfdy[i][j] = 0.0;
PCHf[i][j] = 0.0;
PCHdfdx[i][j] = 0.0;
PCHdfdy[i][j] = 0.0;
}
}
PCCf[0][2] = -0.00050;
PCCf[0][3] = 0.0161253646;
PCCf[1][1] = -0.010960;
PCCf[1][2] = 0.00632624824;
PCCf[2][0] = -0.0276030;
PCCf[2][1] = 0.00317953083;
PCHf[0][1] = 0.209336733;
PCHf[0][2] = -0.0644496154;
PCHf[0][3] = -0.303927546;
PCHf[1][0] = 0.010;
PCHf[1][1] = -0.125123401;
PCHf[1][2] = -0.298905246;
PCHf[2][0] = -0.122042146;
PCHf[2][1] = -0.300529172;
PCHf[3][0] = -0.307584705;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
for (k = 0; k < 10; k++) {
piCCf[i][j][k] = 0.0;
piCCdfdx[i][j][k] = 0.0;
piCCdfdy[i][j][k] = 0.0;
piCCdfdz[i][j][k] = 0.0;
piCHf[i][j][k] = 0.0;
piCHdfdx[i][j][k] = 0.0;
piCHdfdy[i][j][k] = 0.0;
piCHdfdz[i][j][k] = 0.0;
piHHf[i][j][k] = 0.0;
piHHdfdx[i][j][k] = 0.0;
piHHdfdy[i][j][k] = 0.0;
piHHdfdz[i][j][k] = 0.0;
Tf[i][j][k] = 0.0;
Tdfdx[i][j][k] = 0.0;
Tdfdy[i][j][k] = 0.0;
Tdfdz[i][j][k] = 0.0;
}
}
}
for (i = 3; i < 10; i++) piCCf[0][0][i] = 0.0049586079;
piCCf[1][0][1] = 0.021693495;
piCCf[0][1][1] = 0.021693495;
for (i = 2; i < 10; i++) piCCf[1][0][i] = 0.0049586079;
for (i = 2; i < 10; i++) piCCf[0][1][i] = 0.0049586079;
piCCf[1][1][1] = 0.05250;
piCCf[1][1][2] = -0.002088750;
for (i = 3; i < 10; i++) piCCf[1][1][i] = -0.00804280;
piCCf[2][0][1] = 0.024698831850;
piCCf[0][2][1] = 0.024698831850;
piCCf[2][0][2] = -0.00597133450;
piCCf[0][2][2] = -0.00597133450;
for (i = 3; i < 10; i++) piCCf[2][0][i] = 0.0049586079;
for (i = 3; i < 10; i++) piCCf[0][2][i] = 0.0049586079;
piCCf[2][1][1] = 0.00482478490;
piCCf[1][2][1] = 0.00482478490;
piCCf[2][1][2] = 0.0150;
piCCf[1][2][2] = 0.0150;
piCCf[2][1][3] = -0.010;
piCCf[1][2][3] = -0.010;
piCCf[2][1][4] = -0.01168893870;
piCCf[1][2][4] = -0.01168893870;
piCCf[2][1][5] = -0.013377877400;
piCCf[1][2][5] = -0.013377877400;
piCCf[2][1][6] = -0.015066816000;
piCCf[1][2][6] = -0.015066816000;
for (i = 7; i < 10; i++) piCCf[2][1][i] = -0.015066816000;
for (i = 7; i < 10; i++) piCCf[1][2][i] = -0.015066816000;
piCCf[2][2][1] = 0.0472247850;
piCCf[2][2][2] = 0.0110;
piCCf[2][2][3] = 0.0198529350;
piCCf[2][2][4] = 0.01654411250;
piCCf[2][2][5] = 0.013235290;
piCCf[2][2][6] = 0.00992646749999 ;
piCCf[2][2][7] = 0.006617644999;
piCCf[2][2][8] = 0.00330882250;
piCCf[3][0][1] = -0.05989946750;
piCCf[0][3][1] = -0.05989946750;
piCCf[3][0][2] = -0.05989946750;
piCCf[0][3][2] = -0.05989946750;
for (i = 3; i < 10; i++) piCCf[3][0][i] = 0.0049586079;
for (i = 3; i < 10; i++) piCCf[0][3][i] = 0.0049586079;
piCCf[3][1][2] = -0.0624183760;
piCCf[1][3][2] = -0.0624183760;
for (i = 3; i < 10; i++) piCCf[3][1][i] = -0.0624183760;
for (i = 3; i < 10; i++) piCCf[1][3][i] = -0.0624183760;
piCCf[3][2][1] = -0.02235469150;
piCCf[2][3][1] = -0.02235469150;
for (i = 2; i < 10; i++) piCCf[3][2][i] = -0.02235469150;
for (i = 2; i < 10; i++) piCCf[2][3][i] = -0.02235469150;
piCCdfdx[2][1][1] = -0.026250;
piCCdfdx[2][1][5] = -0.0271880;
piCCdfdx[2][1][6] = -0.0271880;
for (i = 7; i < 10; i++) piCCdfdx[2][1][i] = -0.0271880;
piCCdfdx[1][3][2] = 0.0187723882;
for (i = 2; i < 10; i++) piCCdfdx[2][3][i] = 0.031209;
piCCdfdy[1][2][1] = -0.026250;
piCCdfdy[1][2][5] = -0.0271880;
piCCdfdy[1][2][6] = -0.0271880;
for (i = 7; i < 10; i++) piCCdfdy[1][2][i] = -0.0271880;
piCCdfdy[3][1][2] = 0.0187723882;
for (i = 2; i < 10; i++) piCCdfdy[3][2][i] = 0.031209;
piCCdfdz[1][1][2] = -0.0302715;
piCCdfdz[2][1][4] = -0.0100220;
piCCdfdz[1][2][4] = -0.0100220;
piCCdfdz[2][1][5] = -0.0100220;
piCCdfdz[1][2][5] = -0.0100220;
for (i = 4; i < 9; i++) piCCdfdz[2][2][i] = -0.0033090;
// make top end of piCC flat instead of zero
i = 4;
for (j = 0; j < 4; j++){
for (k = 1; k < 11; k++){
piCCf[i][j][k] = piCCf[i-1][j][k];
}
}
for (i = 0; i < 4; i++){ // also enforces some symmetry
for (j = i+1; j < 5; j++){
for (k = 1; k < 11; k++){
piCCf[i][j][k] = piCCf[j][i][k];
}
}
}
for (k = 1; k < 11; k++) piCCf[4][4][k] = piCCf[3][4][k];
k = 10;
for (i = 0; i < 5; i++){
for (j = 0; j < 5; j++){
piCCf[i][j][k] = piCCf[i][j][k-1];
}
}
piCHf[1][1][1] = -0.050;
piCHf[1][1][2] = -0.050;
piCHf[1][1][3] = -0.30;
for (i = 4; i < 10; i++) piCHf[1][1][i] = -0.050;
for (i = 5; i < 10; i++) piCHf[2][0][i] = -0.004523893758064;
for (i = 5; i < 10; i++) piCHf[0][2][i] = -0.004523893758064;
piCHf[2][1][2] = -0.250;
piCHf[1][2][2] = -0.250;
piCHf[2][1][3] = -0.250;
piCHf[1][2][3] = -0.250;
piCHf[3][1][1] = -0.10;
piCHf[1][3][1] = -0.10;
piCHf[3][1][2] = -0.125;
piCHf[1][3][2] = -0.125;
piCHf[3][1][3] = -0.125;
piCHf[1][3][3] = -0.125;
for (i = 4; i < 10; i++) piCHf[3][1][i] = -0.10;
for (i = 4; i < 10; i++) piCHf[1][3][i] = -0.10;
// make top end of piCH flat instead of zero
// also enforces some symmetry
i = 4;
for (j = 0; j < 4; j++){
for (k = 1; k < 11; k++){
piCHf[i][j][k] = piCHf[i-1][j][k];
}
}
for (i = 0; i < 4; i++){
for (j = i+1; j < 5; j++){
for (k = 1; k < 11; k++){
piCHf[i][j][k] = piCHf[j][i][k];
}
}
}
for (k = 1; k < 11; k++) piCHf[4][4][k] = piCHf[3][4][k];
k = 10;
for (i = 0; i < 5; i++){
for (j = 0; j < 5; j++){
piCHf[i][j][k] = piCHf[i][j][k-1];
}
}
piHHf[1][1][1] = 0.124915958;
Tf[2][2][1] = -0.035140;
for (i = 2; i < 10; i++) Tf[2][2][i] = -0.0040480;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairAIREBO::memory_usage()
{
double bytes = 0.0;
bytes += maxlocal * sizeof(int);
bytes += maxlocal * sizeof(int *);
bytes += maxpage * neighbor->pgsize * sizeof(int);
bytes += 3 * maxlocal * sizeof(double);
return bytes;
}
diff --git a/src/MANYBODY/pair_comb.cpp b/src/MANYBODY/pair_comb.cpp
index 4b203731f..5d0db9499 100644
--- a/src/MANYBODY/pair_comb.cpp
+++ b/src/MANYBODY/pair_comb.cpp
@@ -1,2029 +1,2029 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Tzu-Ray Shan (U Florida, rayshan@ufl.edu)
LAMMPS implementation of the Charge-optimized many-body (COMB) potential
based on the HELL MD program (Prof Simon Phillpot, UF, sphil@mse.ufl.edu)
and Aidan Thompson's Tersoff code in LAMMPS
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_comb.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
#include "group.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
#define DELTA 4
/* ---------------------------------------------------------------------- */
PairComb::PairComb(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
PI = 4.0*atan(1.0);
PI2 = 2.0*atan(1.0);
PI4 = atan(1.0);
PIsq = sqrt(PI);
nmax = 0;
NCo = NULL;
nelements = 0;
elements = NULL;
nparams = 0;
maxparam = 0;
params = NULL;
elem2param = NULL;
intype = NULL;
fafb = NULL;
dfafb = NULL;
ddfafb = NULL;
phin = NULL;
dphin = NULL;
erpaw = NULL;
// set comm size needed by this Pair
comm_forward = 1;
comm_reverse = 1;
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairComb::~PairComb()
{
memory->destroy(NCo);
if (elements)
for (int i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
memory->sfree(params);
memory->destroy(elem2param);
memory->destroy(intype);
memory->destroy(fafb);
memory->destroy(dfafb);
memory->destroy(ddfafb);
memory->destroy(phin);
memory->destroy(dphin);
memory->destroy(erpaw);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
delete [] esm;
}
}
/* ---------------------------------------------------------------------- */
void PairComb::compute(int eflag, int vflag)
{
int i,j,k,ii,jj,kk,inum,jnum,iparam_i;
int itag,jtag,itype,jtype,ktype,iparam_ij,iparam_ijk;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,rsq1,rsq2;
double delr1[3],delr2[3],fi[3],fj[3],fk[3];
double zeta_ij,prefactor;
int *ilist,*jlist,*numneigh,**firstneigh;
int mr1,mr2,mr3;
int rsc,inty;
double elp_ij,filp[3],fjlp[3],fklp[3];
double iq,jq;
double yaself;
double potal,fac11,fac11e;
double vionij,fvionij,sr1,sr2,sr3,Eov,Fov;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = vflag_atom = 0;
// grow coordination array if necessary
if (atom->nmax > nmax) {
memory->destroy(NCo);
nmax = atom->nmax;
memory->create(NCo,nmax,"pair:NCo");
}
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *tag = atom->tag;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
yaself = vionij = fvionij = Eov = Fov = 0.0;
// self energy correction term: potal
potal_calc(potal,fac11,fac11e);
// loop over full neighbor list of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
itype = map[type[i]];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
iq = q[i];
NCo[i] = 0;
iparam_i = elem2param[itype][itype][itype];
// self energy, only on i atom
yaself = self(&params[iparam_i],iq,potal);
if (evflag) ev_tally(i,i,nlocal,0,yaself,0.0,0.0,0.0,0.0,0.0);
// two-body interactions (long and short repulsive)
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < x[i][2]) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
// Qj calculates 2-body Coulombic
jtype = map[type[j]];
jq = q[j];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
iparam_ij = elem2param[itype][jtype][jtype];
// long range q-dependent
if (rsq > params[iparam_ij].lcutsq) continue;
inty = intype[itype][jtype];
// polynomial three-point interpolation
tri_point(rsq, mr1, mr2, mr3, sr1, sr2, sr3, itype);
// 1/r energy and forces
direct(inty,mr1,mr2,mr3,rsq,sr1,sr2,sr3,iq,jq,
potal,fac11,fac11e,vionij,fvionij);
// field correction to self energy
field(&params[iparam_ij],rsq,iq,jq,vionij,fvionij);
// polarization field
// sums up long range forces
f[i][0] += delx*fvionij;
f[i][1] += dely*fvionij;
f[i][2] += delz*fvionij;
f[j][0] -= delx*fvionij;
f[j][1] -= dely*fvionij;
f[j][2] -= delz*fvionij;
if (evflag)
ev_tally(i,j,nlocal,newton_pair,0.0,vionij,fvionij,delx,dely,delz);
// short range q-independent
if (rsq > params[iparam_ij].cutsq) continue;
repulsive(&params[iparam_ij],rsq,fpair,eflag,evdwl,iq,jq);
// repulsion is pure two-body, sums up pair repulsive forces
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
if (evflag)
ev_tally(i,j,nlocal,newton_pair,evdwl,0.0,fpair,delx,dely,delz);
}
// accumulate coordination number information
if (cor_flag) {
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = map[type[j]];
iparam_ij = elem2param[itype][jtype][jtype];
if(params[iparam_ij].hfocor > 0.0 ) {
delr1[0] = x[j][0] - xtmp;
delr1[1] = x[j][1] - ytmp;
delr1[2] = x[j][2] - ztmp;
rsq1 = vec3_dot(delr1,delr1);
if (rsq1 > params[iparam_ij].cutsq) continue;
NCo[i] += 1;
}
}
}
// three-body interactions
// skip immediately if I-J is not within cutoff
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = map[type[j]];
iparam_ij = elem2param[itype][jtype][jtype];
// this Qj for q-dependent BSi
jq = q[j];
delr1[0] = x[j][0] - xtmp;
delr1[1] = x[j][1] - ytmp;
delr1[2] = x[j][2] - ztmp;
rsq1 = vec3_dot(delr1,delr1);
if (rsq1 > params[iparam_ij].cutsq) continue;
// accumulate bondorder zeta for each i-j interaction via loop over k
zeta_ij = 0.0;
cuo_flag1 = 0; cuo_flag2 = 0;
for (kk = 0; kk < jnum; kk++) {
if (jj == kk) continue;
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
iparam_ijk = elem2param[itype][jtype][ktype];
delr2[0] = x[k][0] - xtmp;
delr2[1] = x[k][1] - ytmp;
delr2[2] = x[k][2] - ztmp;
rsq2 = vec3_dot(delr2,delr2);
if (rsq2 > params[iparam_ijk].cutsq) continue;
zeta_ij += zeta(&params[iparam_ijk],rsq1,rsq2,delr1,delr2);
if (params[iparam_ijk].hfocor == -2.0) cuo_flag1 = 1;
if (params[iparam_ijk].hfocor == -1.0) cuo_flag2 = 1;
}
if (cuo_flag1 && cuo_flag2) cuo_flag = 1;
else cuo_flag = 0;
force_zeta(&params[iparam_ij],rsq1,zeta_ij,fpair,
prefactor,eflag,evdwl,iq,jq);
// over-coordination correction for HfO2
if (cor_flag && NCo[i] != 0)
Over_cor(&params[iparam_ij],rsq1,NCo[i],Eov, Fov);
evdwl += Eov;
fpair += Fov;
f[i][0] += delr1[0]*fpair;
f[i][1] += delr1[1]*fpair;
f[i][2] += delr1[2]*fpair;
f[j][0] -= delr1[0]*fpair;
f[j][1] -= delr1[1]*fpair;
f[j][2] -= delr1[2]*fpair;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,-fpair,-delr1[0],-delr1[1],-delr1[2]);
// attractive term via loop over k (3-body forces)
for (kk = 0; kk < jnum; kk++) {
if (jj == kk) continue;
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
iparam_ijk = elem2param[itype][jtype][ktype];
delr2[0] = x[k][0] - xtmp;
delr2[1] = x[k][1] - ytmp;
delr2[2] = x[k][2] - ztmp;
rsq2 = vec3_dot(delr2,delr2);
if (rsq2 > params[iparam_ijk].cutsq) continue;
for (rsc = 0; rsc < 3; rsc++)
fi[rsc] = fj[rsc] = fk[rsc] = 0.0;
attractive(&params[iparam_ijk],prefactor,
rsq1,rsq2,delr1,delr2,fi,fj,fk);
// 3-body LP and BB correction and forces
elp_ij = elp(&params[iparam_ijk],rsq1,rsq2,delr1,delr2);
flp(&params[iparam_ijk],rsq1,rsq2,delr1,delr2,filp,fjlp,fklp);
for (rsc = 0; rsc < 3; rsc++) {
fi[rsc] += filp[rsc];
fj[rsc] += fjlp[rsc];
fk[rsc] += fklp[rsc];
}
for (rsc = 0; rsc < 3; rsc++) {
f[i][rsc] += fi[rsc];
f[j][rsc] += fj[rsc];
f[k][rsc] += fk[rsc];
}
if (evflag)
ev_tally(i,j,nlocal,newton_pair,elp_ij,0.0,0.0,0.0,0.0,0.0);
if (vflag_atom) v_tally3(i,j,k,fj,fk,delr1,delr2);
}
}
if (cuo_flag) params[iparam_i].cutsq *= 0.65;
}
cuo_flag = 0;
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairComb::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
esm = new double[n];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairComb::settings(int narg, char **arg)
{
- if (narg > 0) error->all("Illegal pair_style command");
+ if (narg > 0) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairComb::coeff(int narg, char **arg)
{
int i,j,n;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// 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;
}
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++;
}
}
// read potential file and initialize potential parameters
read_file(arg[2]);
setup();
n = atom->ntypes;
// generate streitz-mintmire direct 1/r energy look-up table
if (comm->me == 0 && screen) fprintf(screen,"Pair COMB:\n");
if (comm->me == 0 && screen)
fprintf(screen," generating Coulomb integral lookup table ...\n");
sm_table();
if (cor_flag && comm->me == 0 && screen)
fprintf(screen," will apply over-coordination correction ...\n");
if (!cor_flag&& comm->me == 0 && screen)
fprintf(screen," will not apply over-coordination correction ...\n");
// clear setflag since coeff() called once with I,J = * *
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
// set setflag i,j for type pairs where both are mapped to elements
int count = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairComb::init_style()
{
if (atom->tag_enable == 0)
- error->all("Pair style COMB requires atom IDs");
+ error->all(FLERR,"Pair style COMB requires atom IDs");
if (force->newton_pair == 0)
- error->all("Pair style COMB requires newton pair on");
+ error->all(FLERR,"Pair style COMB requires newton pair on");
if (!atom->q_flag)
- error->all("Pair style COMB requires atom attribute q");
+ error->all(FLERR,"Pair style COMB requires atom attribute q");
// ptr to QEQ fix
//for (i = 0; i < modify->nfix; i++)
// if (strcmp(modify->fix[i]->style,"qeq") == 0) break;
//if (i < modify->nfix) fixqeq = (FixQEQ *) modify->fix[i];
//else fixqeq = NULL;
// need a full neighbor list
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairComb::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
return cutmax;
}
/* ---------------------------------------------------------------------- */
void PairComb::read_file(char *file)
{
int params_per_line = 49;
char **words = new char*[params_per_line+1];
if (params) delete [] params;
params = NULL;
nparams = 0;
// open file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open COMB potential file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read each line out of file, skipping blank lines or leading '#'
// store line of params if all 3 element tags are in element list
int n,nwords,ielement,jelement,kelement;
char line[MAXLINE],*ptr;
int eof = 0;
while (1) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
if (nwords == 0) continue;
// concatenate additional lines until have params_per_line words
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n],MAXLINE-n,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
}
if (nwords != params_per_line)
- error->all("Incorrect format in COMB potential file");
+ error->all(FLERR,"Incorrect format in COMB potential file");
// words = ptrs to all words in line
nwords = 0;
words[nwords++] = strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next line
for (ielement = 0; ielement < nelements; ielement++)
if (strcmp(words[0],elements[ielement]) == 0) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (strcmp(words[1],elements[jelement]) == 0) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (strcmp(words[2],elements[kelement]) == 0) break;
if (kelement == nelements) continue;
// load up parameter settings and error check their values
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].powerm = atof(words[3]);
params[nparams].c = atof(words[4]);
params[nparams].d = atof(words[5]);
params[nparams].h = atof(words[6]);
params[nparams].powern = atof(words[7]);
params[nparams].beta = atof(words[8]);
params[nparams].lam21 = atof(words[9]);
params[nparams].lam22 = atof(words[10]);
params[nparams].bigb1 = atof(words[11]);
params[nparams].bigb2 = atof(words[12]);
params[nparams].bigr = atof(words[13]);
params[nparams].bigd = atof(words[14]);
params[nparams].lam11 = atof(words[15]);
params[nparams].lam12 = atof(words[16]);
params[nparams].biga1 = atof(words[17]);
params[nparams].biga2 = atof(words[18]);
params[nparams].plp1 = atof(words[19]);
params[nparams].plp3 = atof(words[20]);
params[nparams].plp6 = atof(words[21]);
params[nparams].a123 = atof(words[22]);
params[nparams].aconf= atof(words[23]);
params[nparams].addrep = atof(words[24]);
params[nparams].romigb = atof(words[25]);
params[nparams].romigc = atof(words[26]);
params[nparams].romigd = atof(words[27]);
params[nparams].romiga = atof(words[28]);
params[nparams].QL1 = atof(words[29]);
params[nparams].QU1 = atof(words[30]);
params[nparams].DL1 = atof(words[31]);
params[nparams].DU1 = atof(words[32]);
params[nparams].QL2 = atof(words[33]);
params[nparams].QU2 = atof(words[34]);
params[nparams].DL2 = atof(words[35]);
params[nparams].DU2 = atof(words[36]);
params[nparams].chi = atof(words[37]);
params[nparams].dj = atof(words[38]);
params[nparams].dk = atof(words[39]);
params[nparams].dl = atof(words[40]);
params[nparams].dm = atof(words[41]);
params[nparams].esm1 = atof(words[42]);
params[nparams].cmn1 = atof(words[43]);
params[nparams].cml1 = atof(words[44]);
params[nparams].cmn2 = atof(words[45]);
params[nparams].cml2 = atof(words[46]);
params[nparams].coulcut = atof(words[47]);
params[nparams].hfocor = atof(words[48]);
params[nparams].powermint = int(params[nparams].powerm);
// parameter sanity checks
if (params[nparams].lam11 < 0.0 || params[nparams].lam12 < 0.0 ||
params[nparams].c < 0.0 || params[nparams].d < 0.0 ||
params[nparams].powern < 0.0 || params[nparams].beta < 0.0 ||
params[nparams].lam21 < 0.0 || params[nparams].lam22 < 0.0 ||
params[nparams].bigb1< 0.0 || params[nparams].bigb2< 0.0 ||
params[nparams].biga1< 0.0 || params[nparams].biga2< 0.0 ||
params[nparams].bigr < 0.0 || params[nparams].bigd < 0.0 ||
params[nparams].bigd > params[nparams].bigr ||
params[nparams].powerm - params[nparams].powermint != 0.0 ||
(params[nparams].powermint != 3 && params[nparams].powermint != 1) ||
params[nparams].plp1 < 0.0 || params[nparams].plp3 < 0.0 ||
params[nparams].plp6 < 0.0 ||
params[nparams].a123 > 360.0 || params[nparams].aconf < 0.0 ||
params[nparams].addrep < 0.0 || params[nparams].romigb < 0.0 ||
params[nparams].romigc < 0.0 || params[nparams].romigd < 0.0 ||
params[nparams].romiga < 0.0 ||
params[nparams].QL1 > 0.0 || params[nparams].QU1 < 0.0 ||
params[nparams].DL1 < 0.0 || params[nparams].DU1 > 0.0 ||
params[nparams].QL2 > 0.0 || params[nparams].QU2 < 0.0 ||
params[nparams].DL2 < 0.0 || params[nparams].DU2 > 0.0 ||
params[nparams].chi < 0.0 ||
// params[nparams].dj < 0.0 || params[nparams].dk < 0.0 ||
// params[nparams].dl < 0.0 || params[nparams].dm < 0.0 ||
params[nparams].esm1 < 0.0)
- error->all("Illegal COMB parameter");
+ error->all(FLERR,"Illegal COMB parameter");
if (params[nparams].lam11 < params[nparams].lam21 ||
params[nparams].lam12 < params[nparams].lam22 ||
params[nparams].biga1< params[nparams].bigb1 ||
params[nparams].biga2< params[nparams].bigb2)
- error->all("Illegal COMB parameter");
+ error->all(FLERR,"Illegal COMB parameter");
nparams++;
}
delete [] words;
}
/* ---------------------------------------------------------------------- */
void PairComb::setup()
{
int i,j,k,m,n;
// set elem2param for all element triplet combinations
// must be a single exact match to lines read from file
// do not allow for ACB in place of ABC
memory->destroy(elem2param);
memory->create(elem2param,nelements,nelements,nelements,"pair:elem2param");
for (i = 0; i < nelements; i++)
for (j = 0; j < nelements; j++)
for (k = 0; k < nelements; k++) {
n = -1;
for (m = 0; m < nparams; m++) {
if (i == params[m].ielement && j == params[m].jelement &&
k == params[m].kelement) {
- if (n >= 0) error->all("Potential file has duplicate entry");
+ if (n >= 0) error->all(FLERR,"Potential file has duplicate entry");
n = m;
}
}
- if (n < 0) error->all("Potential file is missing an entry");
+ if (n < 0) error->all(FLERR,"Potential file is missing an entry");
elem2param[i][j][k] = n;
}
// compute parameter values derived from inputs
for (m = 0; m < nparams; m++) {
params[m].cut = params[m].bigr + params[m].bigd;
params[m].cutsq = params[m].cut*params[m].cut;
params[m].c1 = pow(2.0*params[m].powern*1.0e-16,-1.0/params[m].powern);
params[m].c2 = pow(2.0*params[m].powern*1.0e-8,-1.0/params[m].powern);
params[m].c3 = 1.0/params[m].c2;
params[m].c4 = 1.0/params[m].c1;
params[m].rlm1 = 0.5*(params[m].lam11+params[m].lam12)*params[m].romigc;
params[m].rlm2 = 0.5*(params[m].lam21+params[m].lam22)*params[m].romigd;
params[m].Qo1 = (params[m].QU1+params[m].QL1)/2.0; // (A22)
params[m].dQ1 = (params[m].QU1-params[m].QL1)/2.0; // (A21)
params[m].aB1 = 1.0 /
(1.0-pow(fabs(params[m].Qo1/params[m].dQ1),10)); // (A20)
params[m].bB1 = pow(fabs(params[m].aB1),0.1)/params[m].dQ1; // (A19)
params[m].nD1 = log(params[m].DU1/(params[m].DU1-params[m].DL1))/
log(params[m].QU1/(params[m].QU1-params[m].QL1));
params[m].bD1 = (pow((params[m].DL1-params[m].DU1),(1.0/params[m].nD1)))/
(params[m].QU1-params[m].QL1);
params[m].Qo2 = (params[m].QU2+params[m].QL2)/2.0; // (A22)
params[m].dQ2 = (params[m].QU2-params[m].QL2)/2.0; // (A21)
params[m].aB2 = 1.0 /
(1.0-pow(fabs(params[m].Qo2/params[m].dQ2),10)); // (A20)
params[m].bB2 = pow(fabs(params[m].aB2),0.1)/params[m].dQ2; // (A19)
params[m].nD2 = log(params[m].DU2/(params[m].DU2-params[m].DL2))/
log(params[m].QU2/(params[m].QU2-params[m].QL2));
params[m].bD2 = (pow((params[m].DL2-params[m].DU2),(1.0/params[m].nD2)))/
(params[m].QU2-params[m].QL2);
params[m].lcut = params[m].coulcut;
params[m].lcutsq = params[m].lcut*params[m].lcut;
}
// set cutmax to max of all params
cutmax = 0.0;
cor_flag = 0;
for (m = 0; m < nparams; m++) {
if (params[m].cut > cutmax) cutmax = params[m].cut;
if (params[m].lcut > cutmax) cutmax = params[m].lcut;
if (params[m].hfocor > 0.0001) cor_flag = 1;
}
}
/* ---------------------------------------------------------------------- */
void PairComb::repulsive(Param *param, double rsq, double &fforce,
int eflag, double &eng, double iq, double jq)
{
double r,tmp_fc,tmp_fc_d,tmp_exp,Di,Dj;
double bigA,Asi,Asj,vrcs,fvrcs,fforce_tmp;
double rslp,rslp2,rslp4,arr1,arr2,fc2j,fc3j,fcp2j,fcp3j;
double romi = param->addrep;
double rrcs = param->bigr + param->bigd;
r = sqrt(rsq);
if (r > rrcs) return ;
tmp_fc = comb_fc(r,param);
tmp_fc_d = comb_fc_d(r,param);
tmp_exp = exp(-param->rlm1 * r);
arr1 = 2.22850; arr2 = 1.89350;
fc2j = comb_fc2(r);
fc3j = comb_fc3(r);
fcp2j = comb_fc2_d(r);
fcp3j = comb_fc3_d(r);
Di = param->DU1 + pow(fabs(param->bD1*(param->QU1-iq)),param->nD1);
Dj = param->DU2 + pow(fabs(param->bD2*(param->QU2-jq)),param->nD2);
Asi = param->biga1 * exp(param->lam11*Di);
Asj = param->biga2 * exp(param->lam12*Dj);
if ( Asi > 0.0 && Asj > 0.0 )
bigA = sqrt(Asi*Asj)*param->romiga;
else
bigA = 0.0;
fforce = -bigA * tmp_exp * (tmp_fc_d - tmp_fc*param->rlm1) / r;
// additional repulsion for TiO2 and HfO2 (switch by cor_flag)
vrcs = 0.0; fvrcs = 0.0;
if (romi > 0.0) {
if (!cor_flag) {
vrcs = romi * pow((1.0-r/rrcs),2.0);
fvrcs= romi * 2.0 * (r/rrcs-1.0)/rrcs; }
else if (cor_flag) {
rslp = ((arr1-r)/(arr1-arr2));
rslp2 = rslp * rslp; rslp4 = rslp2 * rslp2;
vrcs = fc2j * fc3j * romi * ((50.0*rslp4-30.0*rslp2+4.50))/8.0;
fvrcs = fcp2j*fcp3j*romi*rslp*(-25.0*rslp2+7.50)/(arr1-arr2);
}
fforce_tmp = fforce*vrcs - (tmp_fc * bigA * tmp_exp * fvrcs);
fforce += fforce_tmp;
}
// eng = repulsive energy
if (eflag) eng = (tmp_fc * bigA * tmp_exp)*(1.0+vrcs);
}
/* ---------------------------------------------------------------------- */
double PairComb::zeta(Param *param, double rsqij, double rsqik,
double *delrij, double *delrik)
{
double rij,rik,costheta,arg,ex_delr;
rij = sqrt(rsqij);
if (rij > param->bigr+param->bigd) return 0.0;
rik = sqrt(rsqik);
costheta = vec3_dot(delrij,delrik) / (rij*rik);
if (param->powermint == 3) arg = pow(param->rlm2 * (rij-rik),3.0);
else arg = param->rlm2 * (rij-rik);
if (arg > 69.0776) ex_delr = 1.e30;
else if (arg < -69.0776) ex_delr = 0.0;
else ex_delr = exp(arg);
return comb_fc(rik,param) * comb_gijk(costheta,param) * ex_delr;
}
/* ----------------------------------------------------------------------
Legendre polynomial bond angle correction to energy
------------------------------------------------------------------------- */
double PairComb::elp(Param *param, double rsqij, double rsqik,
double *delrij, double *delrik)
{
if (param->aconf > 1.0e-6 || param->plp1 > 1.0e-6 ||
param->plp3 > 1.0e-6 || param->plp6 > 1.0e-6) {
double rij,rik,costheta,lp1,lp3,lp6;
double rmu,rmu2,comtt,fck;
double pplp1 = param->plp1, pplp3 = param->plp3, pplp6 = param->plp6;
double c123 = cos(param->a123*PI/180.0);
// cos(theta) of the i-j-k
// cutoff function of rik
rij = sqrt(rsqij);
rik = sqrt(rsqik);
costheta = vec3_dot(delrij,delrik) / (rij*rik);
fck = comb_fc(rik,param);
rmu = costheta;
// Legendre Polynomial functions
if (param->plp1 > 1.0e-6 || param->plp3 > 1.0e-6 || param->plp6 > 1.0e-6) {
rmu2 = rmu*rmu;
lp1 = rmu; lp3 = 0.5*(5.0*rmu2*rmu-3.0*rmu);
lp6 = (231.0*rmu2*rmu2*rmu2-315.0*rmu2*rmu2+105.0*rmu2-5.0)/16.0;
comtt = pplp1*lp1 + pplp3*lp3 + pplp6*lp6;
} else comtt = 0.0;
// bond-bending terms
if (param->aconf>1e-4) {
if (param->hfocor >= 0.0)
comtt += param->aconf *(rmu-c123)*(rmu-c123);
else if (param->hfocor < 0.0)
comtt += param->aconf *(4.0-(rmu-c123)*(rmu-c123));
}
return 0.5 * fck * comtt;
}
return 0.0;
}
/* ----------------------------------------------------------------------
Legendre polynomial bond angle correction to forces
------------------------------------------------------------------------- */
void PairComb::flp(Param *param, double rsqij, double rsqik,
double *delrij, double *delrik, double *drilp,
double *drjlp, double *drklp)
{
double ffj1,ffj2,ffk1,ffk2;
ffj1 = 0.0; ffj2 = 0.0; ffk1 = 0.0; ffk2 = 0.0;
if (param->aconf > 1.0e-4 || param->plp1 > 1.0e-6 ||
param->plp3 > 1.0e-6 || param->plp6 > 1.0e-6) {
double rij,rik,costheta,lp1,lp1_d,lp3,lp3_d,lp6,lp6_d;
double rmu,rmu2,comtt,comtt_d,com4k,com5,fcj,fck,fck_d;
double pplp1 = param->plp1;
double pplp3 = param->plp3;
double pplp6 = param->plp6;
double c123 = cos(param->a123*PI/180.0);
// fck_d = derivative of cutoff function
rij = sqrt(rsqij); rik = sqrt(rsqik);
costheta = vec3_dot(delrij,delrik) / (rij*rik);
fcj = comb_fc(rij,param);
fck = comb_fc(rik,param);
fck_d = comb_fc_d(rik,param);
rmu = costheta;
// Legendre Polynomial functions and derivatives
if (param->plp1 > 1.0e-6 || param->plp3 > 1.0e-6 || param->plp6 > 1.0e-6) {
rmu2 = rmu*rmu;
lp1 = rmu; lp3 = (2.5*rmu2*rmu-1.5*rmu);
lp6 = (231.0*rmu2*rmu2*rmu2-315.0*rmu2*rmu2+105.0*rmu2-5.0)/16.0;
lp1_d = 1.0;lp3_d = (7.5*rmu2-1.5);
lp6_d = (1386.0*rmu2*rmu2*rmu-1260.0*rmu2*rmu+210.0)/16.0;
comtt = pplp1*lp1 + pplp3*lp3 + pplp6*lp6;
comtt_d = pplp1*lp1_d + pplp3*lp3_d + pplp6*lp6_d;
} else {
comtt = 0.0;
comtt_d = 0.0;
}
// bond-bending terms derivatives
if (param->aconf > 1.0e-4) {
if (param->hfocor >= 0.0) {
comtt += param->aconf *(rmu-c123)*(rmu-c123);
comtt_d += 2.0*param->aconf*(rmu-c123);
} else if (param->hfocor < 0.0) {
comtt += param->aconf *(4.0-(rmu-c123)*(rmu-c123));
comtt_d += -2.0*param->aconf*(rmu-c123);
}
}
com4k = fcj * fck_d * comtt;
com5 = fcj * fck * comtt_d;
ffj1 =-0.5*(com5/(rij*rik));
ffj2 = 0.5*(com5*rmu/rsqij);
ffk1 = ffj1;
ffk2 = 0.5*(-com4k/rik+com5*rmu/rsqik);
} else {
ffj1 = 0.0; ffj2 = 0.0;
ffk1 = 0.0; ffk2 = 0.0;
}
// j-atom
vec3_scale(ffj1,delrik,drjlp); // (k,x[],y[]), y[]=k*x[]
vec3_scaleadd(ffj2,delrij,drjlp,drjlp); // (k,x[],y[],z[]), z[]=k*x[]+y[]
// k-atom
vec3_scale(ffk1,delrij,drklp);
vec3_scaleadd(ffk2,delrik,drklp,drklp);
// i-atom
vec3_add(drjlp,drklp,drilp); // (x[],y[],z[]), z[]=x[]+y[]
vec3_scale(-1.0,drilp,drilp);
}
/* ---------------------------------------------------------------------- */
void PairComb::force_zeta(Param *param, double rsq, double zeta_ij,
double &fforce, double &prefactor,
int eflag, double &eng, double iq, double jq)
{
double r,fa,fa_d,bij;
r = sqrt(rsq);
if (r > param->bigr+param->bigd) return;
fa = comb_fa(r,param,iq,jq);
fa_d = comb_fa_d(r,param,iq,jq);
bij = comb_bij(zeta_ij,param);
fforce = 0.5*bij*fa_d / r;
prefactor = -0.5*fa * comb_bij_d(zeta_ij,param);
// eng = attractive energy
if (eflag) eng = 0.5*bij*fa;
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fc(double r, Param *param)
{
double comb_R = param->bigr;
double comb_D = param->bigd;
if (r < comb_R-comb_D) return 1.0;
if (r > comb_R+comb_D) return 0.0;
return 0.5*(1.0 + cos(PI*(r - comb_R)/comb_D));
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fc_d(double r, Param *param)
{
double comb_R = param->bigr;
double comb_D = param->bigd;
if (r < comb_R-comb_D) return 0.0;
if (r > comb_R+comb_D) return 0.0;
return -(PI2/comb_D) * sin(PI*(r - comb_R)/comb_D);
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fc2(double r)
{
double comb_R = 1.89350;
double comb_D = comb_R + 0.050;
if (r < comb_R) return 0.0;
if (r > comb_D) return 1.0;
return 0.5*(1.0 + cos(PI*(r - comb_R)/(comb_D-comb_R)));
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fc2_d(double r)
{
double comb_R = 1.89350;
double comb_D = comb_R + 0.050;
if (r < comb_R) return 0.0;
if (r > comb_D) return 0.0;
return -(PI2/(comb_D-comb_R)) * sin(PI*(r - comb_R)/(comb_D-comb_R));
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fc3(double r)
{
double comb_R = 2.51350;
double comb_D = comb_R + 0.050;
if (r < comb_R) return 1.0;
if (r > comb_D) return 0.0;
return 0.5*(1.0 + cos(PI*(r - comb_R)/(comb_D-comb_R)));
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fc3_d(double r)
{
double comb_R = 2.51350;
double comb_D = comb_R + 0.050;
if (r < comb_R) return 0.0;
if (r > comb_D) return 0.0;
return -(PI2/(comb_D-comb_R)) * sin(PI*(r - comb_R)/(comb_D-comb_R));
}
/* ---------------------------------------------------------------------- */
double PairComb::self(Param *param, double qi, double selfpot)
{
double self_tmp, cmin, cmax, qmin, qmax;
double s1=param->chi, s2=param->dj, s3=param->dk, s4=param->dl, s5=param->dm;
self_tmp = 0.0;
qmin = param->QL1*0.90;
qmax = param->QU1*0.90;
cmin = cmax = 1000.0;
self_tmp = qi*(s1+qi*(s2+selfpot+qi*(s3+qi*(s4+qi*qi*s5))));
if (qi < qmin) self_tmp += cmin * pow((qi-qmin),4);
if (qi > qmax) self_tmp += cmax * pow((qi-qmax),4);
return self_tmp;
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fa(double r, Param *param, double iq, double jq)
{
double bigB,Bsi,Bsj;
double qi,qj,Di,Dj;
if (r > param->bigr + param->bigd) return 0.0;
qi = iq; qj = jq;
Di = Dj = Bsi = Bsj = bigB = 0.0;
Di = param->DU1 + pow(fabs(param->bD1*(param->QU1-qi)),param->nD1);
Dj = param->DU2 + pow(fabs(param->bD2*(param->QU2-qj)),param->nD2);
Bsi = param->bigb1 * exp(param->lam21*Di)*
(param->aB1-fabs(pow(param->bB1*(qi-param->Qo1),10)));
Bsj = param->bigb2 * exp(param->lam22*Dj)*
(param->aB2-fabs(pow(param->bB2*(qj-param->Qo2),10)));
if (Bsi > 0.0 && Bsj > 0.0) bigB = sqrt(Bsi*Bsj)*param->romigb;
else bigB = 0.0;
return -bigB * exp(-param->rlm2 * r) * comb_fc(r,param);
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_fa_d(double r, Param *param, double iq, double jq)
{
double bigB,Bsi,Bsj;
double qi,qj,Di,Dj;
if (r > param->bigr + param->bigd) return 0.0;
qi = iq; qj = jq;
Di = Dj = Bsi = Bsj = bigB = 0.0;
Di = param->DU1 + pow(fabs(param->bD1*(param->QU1-qi)),param->nD1);
Dj = param->DU2 + pow(fabs(param->bD2*(param->QU2-qj)),param->nD2);
Bsi = param->bigb1 * exp(param->lam21*Di)*
(param->aB1-fabs(pow(param->bB1*(qi-param->Qo1),10)));
Bsj = param->bigb2 * exp(param->lam22*Dj)*
(param->aB2-fabs(pow(param->bB2*(qj-param->Qo2),10)));
if (Bsi > 0.0 && Bsj > 0.0) bigB = sqrt(Bsi*Bsj)*param->romigb;
else bigB = 0.0;
return bigB * exp(-param->rlm2 * r) *
(param->rlm2 * comb_fc(r,param) - comb_fc_d(r,param));
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_bij(double zeta, Param *param)
{
double tmp = param->beta * zeta;
if (tmp > param->c1) return 1.0/sqrt(tmp);
if (tmp > param->c2)
return (1.0 - pow(tmp,-param->powern) / (2.0*param->powern))/sqrt(tmp);
if (tmp < param->c4) return 1.0;
if (tmp < param->c3)
return 1.0 - pow(tmp,param->powern)/(2.0*param->powern);
return pow(1.0 + pow(tmp,param->powern), -1.0/(2.0*param->powern));
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_bij_d(double zeta, Param *param)
{
double tmp = param->beta * zeta;
if (tmp > param->c1) return param->beta * -0.5*pow(tmp,-1.5);
if (tmp > param->c2)
return param->beta * (-0.5*pow(tmp,-1.5) *
(1.0 - 0.5*(1.0 + 1.0/(2.0*param->powern)) *
pow(tmp,-param->powern)));
if (tmp < param->c4) return 0.0;
if (tmp < param->c3)
return -0.5*param->beta * pow(tmp,param->powern-1.0);
double tmp_n = pow(tmp,param->powern);
return -0.5 * pow(1.0+tmp_n, -1.0-(1.0/(2.0*param->powern)))*tmp_n / zeta;
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_gijk(double costheta, Param *param)
{
double comb_c = param->c;
double comb_d = param->d;
return (1.0 + pow(comb_c/comb_d,2.0) -
pow(comb_c,2.0) / (pow(comb_d,2.0) + pow(param->h - costheta,2.0)));
}
/* ---------------------------------------------------------------------- */
double PairComb::comb_gijk_d(double costheta, Param *param)
{
double numerator = -2.0 * pow(param->c,2) * (param->h - costheta);
double denominator = pow(pow(param->d,2.0) +
pow(param->h - costheta,2.0),2.0);
return numerator/denominator;
}
/*------------------------------------------------------------------------- */
void PairComb::attractive(Param *param, double prefactor,
double rsqij, double rsqik,
double *delrij, double *delrik,
double *fi, double *fj, double *fk)
{
double rij_hat[3],rik_hat[3];
double rij,rijinv,rik,rikinv;
rij = sqrt(rsqij);
rijinv = 1.0/rij;
vec3_scale(rijinv,delrij,rij_hat);
rik = sqrt(rsqik);
rikinv = 1.0/rik;
vec3_scale(rikinv,delrik,rik_hat);
comb_zetaterm_d(prefactor,rij_hat,rij,rik_hat,rik,fi,fj,fk,param);
}
/* ---------------------------------------------------------------------- */
void PairComb::comb_zetaterm_d(double prefactor, double *rij_hat, double rij,
double *rik_hat, double rik, double *dri,
double *drj, double *drk, Param *param)
{
double gijk,gijk_d,ex_delr,ex_delr_d,fc,dfc,cos_theta,tmp;
double dcosdri[3],dcosdrj[3],dcosdrk[3];
fc = comb_fc(rik,param);
dfc = comb_fc_d(rik,param);
if (param->powermint == 3) tmp = pow(param->rlm2 * (rij-rik),3.0);
else tmp = param->rlm2 * (rij-rik);
if (tmp > 69.0776) ex_delr = 1.e30;
else if (tmp < -69.0776) ex_delr = 0.0;
else ex_delr = exp(tmp); // ex_delr is Ygexp
if (param->powermint == 3)
ex_delr_d = 3.0*pow(param->rlm2,3.0) * pow(rij-rik,2.0)*ex_delr; // com3
else ex_delr_d = param->rlm2 * ex_delr; // com3
cos_theta = vec3_dot(rij_hat,rik_hat);
gijk = comb_gijk(cos_theta,param);
gijk_d = comb_gijk_d(cos_theta,param);
costheta_d(rij_hat,rij,rik_hat,rik,dcosdri,dcosdrj,dcosdrk);
// compute the derivative wrt Ri
// dri = -dfc*gijk*ex_delr*rik_hat;
// dri += fc*gijk_d*ex_delr*dcosdri;
// dri += fc*gijk*ex_delr_d*(rik_hat - rij_hat);
// (k,x[],y[]), y[]=k*x[]
// (k,x[],y[],z[]), z[]=k*x[]+y[]
vec3_scale(-dfc*gijk*ex_delr,rik_hat,dri);
vec3_scaleadd(fc*gijk_d*ex_delr,dcosdri,dri,dri);
vec3_scaleadd(fc*gijk*ex_delr_d,rik_hat,dri,dri);
vec3_scaleadd(-fc*gijk*ex_delr_d,rij_hat,dri,dri);
vec3_scale(prefactor,dri,dri);
// compute the derivative wrt Rj
// drj = fc*gijk_d*ex_delr*dcosdrj;
// drj += fc*gijk*ex_delr_d*rij_hat;
vec3_scale(fc*gijk_d*ex_delr,dcosdrj,drj);
vec3_scaleadd(fc*gijk*ex_delr_d,rij_hat,drj,drj);
vec3_scale(prefactor,drj,drj);
// compute the derivative wrt Rk
// drk = dfc*gijk*ex_delr*rik_hat;
// drk += fc*gijk_d*ex_delr*dcosdrk;
// drk += -fc*gijk*ex_delr_d*rik_hat;
vec3_scale(dfc*gijk*ex_delr,rik_hat,drk);
vec3_scaleadd(fc*gijk_d*ex_delr,dcosdrk,drk,drk);
vec3_scaleadd(-fc*gijk*ex_delr_d,rik_hat,drk,drk);
vec3_scale(prefactor,drk,drk);
}
/* ---------------------------------------------------------------------- */
void PairComb::costheta_d(double *rij_hat, double rij,
double *rik_hat, double rik,
double *dri, double *drj, double *drk)
{
// first element is devative wrt Ri, second wrt Rj, third wrt Rk
double cos_theta = vec3_dot(rij_hat,rik_hat);
vec3_scaleadd(-cos_theta,rij_hat,rik_hat,drj);
vec3_scale(1.0/rij,drj,drj);
vec3_scaleadd(-cos_theta,rik_hat,rij_hat,drk);
vec3_scale(1.0/rik,drk,drk);
vec3_add(drj,drk,dri);
vec3_scale(-1.0,dri,dri);
}
/* ---------------------------------------------------------------------- */
void PairComb::sm_table()
{
int i,j,k,m,nntypes,ncoul;
int inty, itype, jtype;
int iparam_i, iparam_ij, iparam_ji;
double r,dra,drin,rc,z,zr,zrc,ea,eb,ea3,eb3,alf;
double exp2er,exp2ersh,fafash,dfafash,F1,dF1,ddF1,E1,E2,E3,E4;
double exp2ear,exp2ebr,exp2earsh,exp2ebrsh,fafbsh,dfafbsh;
int n = atom->ntypes;
dra = 0.001; // lookup table step size
drin = 0.1; // starting distance of 1/r
rc = cutmax;
alf = 0.20;
nntypes = int((n+1)*n/2); // interaction types
ncoul = int((rc-drin)/dra)+1;
memory->destroy(intype);
memory->destroy(fafb);
memory->destroy(dfafb);
memory->destroy(ddfafb);
memory->destroy(phin);
memory->destroy(dphin);
memory->destroy(erpaw);
// allocate arrays
memory->create(intype,n,n,"pair:intype");
memory->create(fafb,ncoul,nntypes,"pair:fafb");
memory->create(dfafb,ncoul,nntypes,"pair:dfafb");
memory->create(ddfafb,ncoul,nntypes,"pair:ddfafb");
memory->create(phin,ncoul,nntypes,"pair:phin");
memory->create(dphin,ncoul,nntypes,"pair:dphin");
memory->create(erpaw,25000,2,"pair:erpaw");
// set interaction number: 0-0=0, 1-1=1, 0-1=1-0=2
m = 0; k = n;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (j == i) {
intype[i][j] = m;
m += 1;
} else if (j != i && j > i) {
intype[i][j] = k;
k += 1;
} else if (j != i && j < i) {
intype[i][j] = intype[j][i];
}
}
}
// default arrays to zero
for (i = 0; i < ncoul; i ++) {
for (j = 0; j < nntypes; j ++) {
fafb[i][j] = 0.0;
dfafb[i][j] = 0.0;
ddfafb[i][j] = 0.0;
phin[i][j] = 0.0;
dphin[i][j] = 0.0;
}
}
// direct 1/r energy with Slater 1S orbital overlap
for (i = 0; i < n; i++) {
r = drin;
itype = params[i].ielement;
iparam_i = elem2param[itype][itype][itype];
z = params[iparam_i].esm1;
for (j = 0; j < ncoul; j++) {
exp2er = exp(-2.0 * z * r);
phin[j][i] = 1.0 - exp2er * (1.0 + 2.0 * z * r * (1.0 + z * r));
dphin[j][i] = (4.0 * exp2er * z * z * z * r * r);
r += dra;
}
}
for (i = 0; i < n; i ++) {
for (j = 0; j < n; j ++) {
r = drin;
if (j == i) {
itype = params[i].ielement;
inty = intype[itype][itype];
iparam_i = elem2param[itype][itype][itype];
z = params[iparam_i].esm1;
zrc = z * rc;
exp2ersh = exp(-2.0 * zrc);
fafash = -exp2ersh * (1.0 / rc +
z * (11.0/8.0 + 3.0/4.0*zrc + zrc*zrc/6.0));
dfafash = exp2ersh * (1.0/(rc*rc) + 2.0*z/rc +
z*z*(2.0 + 7.0/6.0*zrc + zrc*zrc/3.0));
for (k = 0; k < ncoul; k ++) {
zr = z * r;
exp2er = exp(-2.0*zr);
F1 = -exp2er * (1.0 / r +
z * (11.0/8.0 + 3.0/4.0*zr + zr*zr/6.0));
dF1 = exp2er * (1.0/(r*r) + 2.0*z/r +
z*z*(2.0 + 7.0/6.0*zr + zr*zr/3.0));
ddF1 = -exp2er * (2.0/(r*r*r) + 4.0*z/(r*r) -
z*z*z/3.0*(17.0/2.0 + 5.0*zr + 2.0*zr*zr));
fafb[k][inty] = F1-fafash-(r-rc)*dfafash;
dfafb[k][inty] = (dF1 - dfafash);
ddfafb[k][inty] = ddF1;
r += dra;
}
} else if (j != i) {
itype = params[i].ielement;
jtype = params[j].ielement;
inty = intype[itype][jtype];
iparam_ij = elem2param[itype][jtype][jtype];
ea = params[iparam_ij].esm1;
ea3 = ea*ea*ea;
iparam_ji = elem2param[jtype][itype][itype];
eb = params[iparam_ji].esm1;
eb3 = eb*eb*eb;
E1 = ea*eb3*eb/((ea+eb)*(ea+eb)*(ea-eb)*(ea-eb));
E2 = eb*ea3*ea/((ea+eb)*(ea+eb)*(eb-ea)*(eb-ea));
E3 = (3.0*ea*ea*eb3*eb-eb3*eb3) /
((ea+eb)*(ea+eb)*(ea+eb)*(ea-eb)*(ea-eb)*(ea-eb));
E4 = (3.0*eb*eb*ea3*ea-ea3*ea3) /
((ea+eb)*(ea+eb)*(ea+eb)*(eb-ea)*(eb-ea)*(eb-ea));
exp2earsh = exp(-2.0*ea*rc);
exp2ebrsh = exp(-2.0*eb*rc);
fafbsh = -exp2earsh*(E1 + E3/rc)-exp2ebrsh*(E2 + E4/rc);
dfafbsh =
exp2earsh*(2.0*ea*(E1+E3/rc)+E3/(rc*rc)) +
exp2ebrsh*(2.0*eb*(E2+E4/rc)+E4/(rc*rc));
for (k = 0; k < ncoul; k ++) {
exp2ear = exp(-2.0*ea*r);
exp2ebr = exp(-2.0*eb*r);
fafb[k][inty] =
- exp2ear*(E1+E3/r) - exp2ebr*(E2+E4/r)
- fafbsh - (r-rc) * dfafbsh;
dfafb[k][inty] = (exp2ear*(2.0*ea*(E1+E3/r) + E3/(r*r))
+ exp2ebr*(2.0*eb*(E2+E4/r) + E4/(r*r))- dfafbsh);
ddfafb[k][inty] = (- exp2ear*(E3/(r*r)*(1.0/r+2.0*ea/r+2.0/(r*r))
+ 2.0*ea*(E1+E3/r))-
exp2ebr*(E4/(r*r)
*(1.0/r+2.0*eb/r+2.0/(r*r)) +
2.0*eb*(E2+E4/r)));
r += dra;
}
}
}
}
for (i = 0; i < 25000; i ++) {
r = dra * i + drin;
erpaw[i][0] = erfc(r*alf);
erpaw[i][1] = exp(-r*r*alf*alf);
}
}
/* ---------------------------------------------------------------------- */
void PairComb::potal_calc(double &calc1, double &calc2, double &calc3)
{
double alf,rcoul,esucon;
int m;
rcoul = 0.0;
for (m = 0; m < nparams; m++)
if (params[m].lcut > rcoul) rcoul = params[m].lcut;
alf = 0.20;
esucon = force->qqr2e;
calc2 = (erfc(rcoul*alf)/rcoul/rcoul+2.0*alf/PIsq*
exp(-alf*alf*rcoul*rcoul)/rcoul)*esucon/rcoul;
calc3 = (erfc(rcoul*alf)/rcoul)*esucon;
calc1 = -(alf/PIsq*esucon+calc3*0.5);
}
/* ---------------------------------------------------------------------- */
void PairComb::tri_point(double rsq, int &mr1, int &mr2,
int &mr3, double &sr1, double &sr2,
double &sr3, int &itype)
{
double r, rin, dr, dd, rr1, rridr, rridr2;
rin = 0.10; dr = 0.0010;
r = sqrt(rsq);
if (r < rin + 2.0*dr) r = rin + 2.0*dr;
if (r > cutmax - 2.0*dr) r = cutmax - 2.0*dr;
rridr = (r-rin)/dr;
mr1 = int(rridr)-1;
dd = rridr - float(mr1);
if (dd > 0.5) mr1 += 1;
mr2 = mr1 + 1;
mr3 = mr2 + 1;
rr1 = float(mr1)*dr;
rridr = (r - rin - rr1)/dr;
rridr2 = rridr * rridr;
sr1 = (rridr2 - rridr) * 0.50;
sr2 = 1.0 - rridr2;
sr3 = (rridr2 + rridr) * 0.50;
}
/* ---------------------------------------------------------------------- */
void PairComb::direct(int inty, int mr1, int mr2, int mr3, double rsq,
double sr1, double sr2, double sr3,
double iq, double jq,
double potal, double fac11, double fac11e,
double &pot_tmp, double &pot_d)
{
double r,erfcc,fafbn1,potij,sme2,esucon;
double r3,erfcd,dfafbn1,smf2,dvdrr,alf,alfdpi;
r = sqrt(rsq);
r3 = r * rsq;
alf = 0.20;
alfdpi = 2.0*alf/PIsq;
esucon = force->qqr2e;
pot_tmp = 0.0;
pot_d = 0.0;
// 1/r energy
erfcc = sr1*erpaw[mr1][0] + sr2*erpaw[mr2][0] + sr3*erpaw[mr3][0];
fafbn1= sr1*fafb[mr1][inty] + sr2*fafb[mr2][inty] + sr3*fafb[mr3][inty];
potij = (erfcc/r * esucon - fac11e);
sme2 = potij + fafbn1 * esucon;
pot_tmp = 1.0 * iq * jq *sme2;
// 1/r force (wrt r)
erfcd = sr1*erpaw[mr1][1] + sr2*erpaw[mr2][1] + sr3*erpaw[mr3][1];
dfafbn1= sr1*dfafb[mr1][inty] + sr2*dfafb[mr2][inty] + sr3*dfafb[mr3][inty];
dvdrr = (erfcc/r3+alfdpi*erfcd/rsq)*esucon-fac11;
smf2 = dvdrr - dfafbn1 * esucon/r;
pot_d = 1.0 * iq * jq * smf2;
}
/* ---------------------------------------------------------------------- */
void PairComb::field(Param *param, double rsq, double iq,double jq,
double &vionij,double &fvionij)
{
double r,r5,r6,rc,rc5,rc6,rf5,drf6,smpn,smpl,rfx1,rfx2;
double cmi1,cmi2,cmj1,cmj2;
r = sqrt(rsq);
r5 = r*r*r*r*r;
r6 = r5 * r;
rc = param->lcut;
rc5 = rc*rc*rc*rc*rc;
rc6 = rc5 * rc;
cmi1 = param->cmn1;
cmi2 = param->cmn2;
cmj1 = param->cml1;
cmj2 = param->cml2;
rf5 = 1.0/r5 - 1.0/rc5 + 5.0*(r-rc)/rc6;
drf6 = 5.0/rc6 - 5.0/r6;
// field correction energy
smpn = rf5*jq*(cmi1+jq*cmi2);
smpl = rf5*iq*(cmj1+iq*cmj2);
vionij += 1.0 * (smpn + smpl);
// field correction force
rfx1 = jq*drf6*(cmi1+jq*cmi2)/r;
rfx2 = iq*drf6*(cmj1+iq*cmj2)/r;
fvionij -= 1.0 * (rfx1 + rfx2);
}
/* ---------------------------------------------------------------------- */
double PairComb::yasu_char(double *qf_fix, int &igroup)
{
int i,j,k,ii,jj,kk,jnum;
int itype,jtype,ktype,iparam_i,iparam_ij,iparam_ijk;
double xtmp,ytmp,ztmp;
double rsq1,rsq2,delr1[3],delr2[3],zeta_ij;
int *ilist,*jlist,*numneigh,**firstneigh;
double iq,jq,fqi,fqj,fqij,fqjj;
double potal,fac11,fac11e,sr1,sr2,sr3;
int mr1,mr2,mr3,inty;
double **x = atom->x;
double *q = atom->q;
int *type = atom->type;
int inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
int *mask = atom->mask;
int groupbit = group->bitmask[igroup];
qf = qf_fix;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit)
qf[i] = 0.0;
}
// communicating charge force to all nodes, first forward then reverse
comm->forward_comm_pair(this);
// self energy correction term: potal
potal_calc(potal,fac11,fac11e);
// loop over full neighbor list of my atoms
fqi = fqj = fqij = fqjj = 0.0;
for (ii = 0; ii < inum; ii ++) {
i = ilist[ii];
if (mask[i] & groupbit) {
itype = map[type[i]];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
iq = q[i];
iparam_i = elem2param[itype][itype][itype];
// charge force from self energy
fqi = qfo_self(&params[iparam_i],iq,potal);
// two-body interactions
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = map[type[j]];
jq = q[j];
delr1[0] = x[j][0] - xtmp;
delr1[1] = x[j][1] - ytmp;
delr1[2] = x[j][2] - ztmp;
rsq1 = vec3_dot(delr1,delr1);
iparam_ij = elem2param[itype][jtype][jtype];
// long range q-dependent
if (rsq1 > params[iparam_ij].lcutsq) continue;
inty = intype[itype][jtype];
// polynomial three-point interpolation
tri_point(rsq1,mr1,mr2,mr3,sr1,sr2,sr3,itype);
// 1/r charge forces
qfo_direct(inty,mr1,mr2,mr3,rsq1,sr1,sr2,sr3,fac11e,fqij);
fqi += jq * fqij; qf[j] += iq * fqij;
// field correction to self energy and charge force
qfo_field(&params[iparam_ij],rsq1,iq,jq,fqij,fqjj);
fqi += fqij;
qf[j] += fqjj;
// polarization field charge force
// three-body interactions
if (rsq1 > params[iparam_ij].cutsq) continue;
zeta_ij = 0.0;
for (kk = 0; kk < jnum; kk++) {
if (jj == kk) continue;
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
iparam_ijk = elem2param[itype][jtype][ktype];
delr2[0] = x[k][0] - xtmp;
delr2[1] = x[k][1] - ytmp;
delr2[2] = x[k][2] - ztmp;
rsq2 = vec3_dot(delr2,delr2);
if (rsq2 > params[iparam_ijk].cutsq) continue;
zeta_ij += zeta(&params[iparam_ijk],rsq1,rsq2,delr1,delr2);
}
// charge force in Aij and Bij
qfo_short(&params[iparam_ij],rsq1,zeta_ij,iq,jq,fqij,fqjj);
fqi += fqij; qf[j] += fqjj;
}
qf[i] += fqi;
}
}
comm->reverse_comm_pair(this);
// sum charge force on each node and return it
double eneg = 0.0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit)
eneg += qf[i];
}
double enegtot;
MPI_Allreduce(&eneg,&enegtot,1,MPI_DOUBLE,MPI_SUM,world);
return enegtot;
}
/* ---------------------------------------------------------------------- */
double PairComb::qfo_self(Param *param, double qi, double selfpot)
{
double self_d,cmin,cmax,qmin,qmax;
double s1 = param->chi;
double s2 = param->dj;
double s3 = param->dk;
double s4 = param->dl;
double s5 = param->dm;
self_d = 0.0;
qmin = param->QL1*0.90;
qmax = param->QU1*0.90;
if (qmax > 4.50 ) qmax = -0.70;
cmin = cmax = 1000.0;
self_d = s1+qi*(2.0*(s2+selfpot)+qi*(3.0*s3+qi*(4.0*s4+qi*qi*6.0*s5)));
if (qi < qmin) {
// char str[128];
// sprintf(str,"Pair COMB charge %.10f with force %.10f hit min barrier",
// qi,self_d);
- // error->warning(str,0);
+ // error->warning(FLERR,str,0);
self_d += 4.0 * cmin * pow((qi-qmin),3);
}
if (qi > qmax) {
// char str[128];
// sprintf(str,"Pair COMB charge %.10f with force %.10f hit max barrier",
// qi,self_d);
- // error->warning(str,0);
+ // error->warning(FLERR,str,0);
self_d += 4.0 * cmax * pow((qi-qmax),3);
}
return self_d;
}
/* ---------------------------------------------------------------------- */
void PairComb::qfo_direct(int inty, int mr1, int mr2, int mr3,
double rsq, double sr1, double sr2,
double sr3, double fac11e, double &fqij)
{
double r, erfcc, fafbn1, vm, esucon;
r = sqrt(rsq);
esucon=force->qqr2e;
// 1/r force (wrt q)
erfcc = sr1*erpaw[mr1][0] + sr2*erpaw[mr2][0] + sr3*erpaw[mr3][0];
fafbn1= sr1*fafb[mr1][inty] + sr2*fafb[mr2][inty] + sr3*fafb[mr3][inty];
vm = (erfcc/r * esucon - fac11e);
fqij = 0.5 * (vm+esucon*fafbn1);
}
/* ---------------------------------------------------------------------- */
void PairComb::qfo_field(Param *param, double rsq,double iq,double jq,
double &fqij, double &fqjj)
{
double r,r5,r6,rc,rc5,rc6;
double cmi1,cmi2,cmj1,cmj2,rf5;
fqij = fqjj = 0.0;
r = sqrt(rsq);
r5 = r*r*r*r*r;
r6 = r5 * r;
rc = param->lcut;
rc5 = rc*rc*rc*rc*rc;
rc6 = rc5 * rc;
cmi1 = param->cmn1;
cmi2 = param->cmn2;
cmj1 = param->cml1;
cmj2 = param->cml2;
rf5 = 1.0/r5 - 1.0/rc5 + 5.0*(r-rc)/rc6;
// field correction charge force
fqij = 0.5 * rf5 * (cmj1 + 2.0 * iq * cmj2);
fqjj = 0.5 * rf5 * (cmi1 + 2.0 * jq * cmi2);
}
/* ---------------------------------------------------------------------- */
void PairComb::qfo_short(Param *param, double rsq, double zeta_ij,
double iq, double jq, double &fqij, double &fqjj)
{
double r,tmp_fc,tmp_fc_d,tmp_exp1,tmp_exp2;
double bigA,Asi,Asj,vrcs;
double romi = param->addrep,rrcs = param->bigr + param->bigd;
double qi,qj,Di,Dj,bigB,Bsi,Bsj;
double QUchi,QOchi,QUchj,QOchj,YYDiqp,YYDjqp;
double YYAsiqp,YYAsjqp,YYBsiqp,YYBsjqp;
double caj,cbj,bij,cfqr,cfqs;
double romie = param->romiga;
double romib = param->romigb;
double ca1,ca2,ca3,ca4;
double rslp,rslp2,rslp4,arr1,arr2,fc2j,fc3j,fcp2j,fcp3j;
qi = iq; qj = jq; r = sqrt(rsq);
Di = Dj = Asi = Asj = bigA = Bsi = Bsj = bigB = 0.0;
QUchi = QOchi = QUchj = QOchj = YYDiqp = YYDjqp =0.0;
YYAsiqp = YYAsjqp = YYBsiqp = YYBsjqp = 0.0;
caj = cbj = vrcs = cfqr = cfqs = 0.0;
tmp_fc = comb_fc(r,param);
tmp_fc_d = comb_fc_d(r,param);
tmp_exp1 = exp(-param->rlm1 * r);
tmp_exp2 = exp(-param->rlm2 * r);
bij = comb_bij(zeta_ij,param);
arr1 = 2.22850; arr2 = 1.89350;
fc2j = comb_fc2(r);
fc3j = comb_fc3(r);
fcp2j = comb_fc2_d(r);
fcp3j = comb_fc3_d(r);
vrcs = 0.0;
if (romi > 0.0) {
if (!cor_flag) vrcs = romi * pow((1.0-r/rrcs),2.0);
else if (cor_flag) {
rslp = ((arr1-r)/(arr1-arr2));
rslp2 = rslp * rslp; rslp4 = rslp2 * rslp2;
vrcs = fc2j * fc3j * romi * ((50.0*rslp4-30.0*rslp2+4.50))/8.0;
}
}
Di = param->DU1 + pow(fabs(param->bD1*(param->QU1-qi)),param->nD1);
Dj = param->DU2 + pow(fabs(param->bD2*(param->QU2-qj)),param->nD2);
Asi = param->biga1 * exp(param->lam11*Di);
Asj = param->biga2 * exp(param->lam12*Dj);
Bsi = param->bigb1 * exp(param->lam21*Di)*
(param->aB1-fabs(pow(param->bB1*(qi-param->Qo1),10)));
Bsj = param->bigb2 * exp(param->lam22*Dj)*
(param->aB2-fabs(pow(param->bB2*(qj-param->Qo2),10)));
QUchi = (param->QU1-qi)*param->bD1;
QUchj = (param->QU2-qj)*param->bD2;
QOchi = (qi-param->Qo1)*param->bB1;
QOchj = (qj-param->Qo2)*param->bB2;
if (QUchi == 0.0) YYDiqp = 0.0;
else YYDiqp = -param->nD1 * QUchi * param->bD1 *
pow(fabs(QUchi),(param->nD1-2.0));
if (QUchj == 0.0) YYDjqp = 0.0;
else YYDjqp = -param->nD2 * QUchj * param->bD2 *
pow(fabs(QUchj),(param->nD2-2.0));
YYAsiqp = Asi * param->lam11 * YYDiqp;
YYAsjqp = Asj * param->lam12 * YYDjqp;
if (QOchi == 0.0)
YYBsiqp=Bsi*param->lam21*YYDiqp;
else
YYBsiqp=Bsi*param->lam21*YYDiqp-param->bigb1*exp(param->lam21*Di)*
10.0*QOchi*param->bB1*pow(fabs(QOchi),(10.0-2.0));
if (QOchj == 0.0)
YYBsjqp=Bsj*param->lam22*YYDjqp;
else
YYBsjqp=Bsj*param->lam22*YYDjqp-param->bigb2*exp(param->lam22*Dj)*
10.0*QOchj*param->bB2*pow(fabs(QOchj),(10.0-2.0));
if (Asi > 0.0 && Asj > 0.0) caj = 1.0/(2.0*sqrt(Asi*Asj)) * romie;
else caj = 0.0;
if (Bsi > 0.0 && Bsj > 0.0) cbj = 1.0/(2.0*sqrt(Bsi*Bsj)) * romib ;
else cbj = 0.0;
cfqr = 0.50 * tmp_fc * (1.0 + vrcs); // 0.5 b/c full atom loop
cfqs = -0.50 * tmp_fc * bij;
ca1 = Asj * caj * YYAsiqp;
ca2 = Bsj * cbj * YYBsiqp;
ca3 = Asi * caj * YYAsjqp;
ca4 = Bsi * cbj * YYBsjqp;
fqij = cfqr * tmp_exp1 * ca1;
fqij += cfqs * tmp_exp2 * ca2;
fqjj = cfqr * tmp_exp1 * ca3;
fqjj += cfqs * tmp_exp2 * ca4;
}
/* ---------------------------------------------------------------------- */
void PairComb::Over_cor(Param *param, double rsq1, int NCoi,
double &Eov, double &Fov)
{
double ECo,BCo,tmp_fc,tmp_fc_d;
double r = sqrt(rsq1);
int NCon = NCoi - 7;
tmp_fc = comb_fc(r,param);
tmp_fc_d = comb_fc(r,param);
Eov = 0.0; Fov = 0.0;
ECo = param->hfocor;
BCo = 0.1;
if (NCon >= 0.20) {
Eov = tmp_fc * ECo * NCon/(1.0+exp(BCo*NCon));
Fov = -(tmp_fc_d*Eov + tmp_fc*ECo/(1.0+exp(BCo*NCon)) -
(tmp_fc*ECo*NCon*BCo*exp(BCo*NCon)) /
((1.0+exp(BCo*NCon))*(1.0+exp(BCo*NCon))));
Fov /= r;
}
}
/* ---------------------------------------------------------------------- */
int PairComb::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i ++) {
j = list[i];
buf[m++] = qf[j];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void PairComb::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n ;
for (i = first; i < last; i++) qf[i] = buf[m++];
}
/* ---------------------------------------------------------------------- */
int PairComb::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) buf[m++] = qf[i];
return 1;
}
/* ---------------------------------------------------------------------- */
void PairComb::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
qf[j] += buf[m++];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairComb::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
bytes += nmax * sizeof(int);
return bytes;
}
diff --git a/src/MANYBODY/pair_eam.cpp b/src/MANYBODY/pair_eam.cpp
index bc87ad4b8..39a8292bc 100644
--- a/src/MANYBODY/pair_eam.cpp
+++ b/src/MANYBODY/pair_eam.cpp
@@ -1,875 +1,872 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Stephen Foiles (SNL), Murray Daw (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_eam.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairEAM::PairEAM(LAMMPS *lmp) : Pair(lmp)
{
nmax = 0;
rho = NULL;
fp = NULL;
nfuncfl = 0;
funcfl = NULL;
setfl = NULL;
fs = NULL;
frho = NULL;
rhor = NULL;
z2r = NULL;
frho_spline = NULL;
rhor_spline = NULL;
z2r_spline = NULL;
// set comm size needed by this Pair
comm_forward = 1;
comm_reverse = 1;
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairEAM::~PairEAM()
{
memory->destroy(rho);
memory->destroy(fp);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
delete [] type2frho;
memory->destroy(type2rhor);
memory->destroy(type2z2r);
}
if (funcfl) {
for (int i = 0; i < nfuncfl; i++) {
delete [] funcfl[i].file;
memory->destroy(funcfl[i].frho);
memory->destroy(funcfl[i].rhor);
memory->destroy(funcfl[i].zr);
}
memory->sfree(funcfl);
}
if (setfl) {
for (int i = 0; i < setfl->nelements; i++) delete [] setfl->elements[i];
delete [] setfl->elements;
delete [] setfl->mass;
memory->destroy(setfl->frho);
memory->destroy(setfl->rhor);
memory->destroy(setfl->z2r);
delete setfl;
}
if (fs) {
for (int i = 0; i < fs->nelements; i++) delete [] fs->elements[i];
delete [] fs->elements;
delete [] fs->mass;
memory->destroy(fs->frho);
memory->destroy(fs->rhor);
memory->destroy(fs->z2r);
delete fs;
}
memory->destroy(frho);
memory->destroy(rhor);
memory->destroy(z2r);
memory->destroy(frho_spline);
memory->destroy(rhor_spline);
memory->destroy(z2r_spline);
}
/* ---------------------------------------------------------------------- */
void PairEAM::compute(int eflag, int vflag)
{
int i,j,ii,jj,m,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,p,rhoip,rhojp,z2,z2p,recip,phip,psip,phi;
double *coeff;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = eflag_atom = 0;
// grow energy and fp arrays if necessary
// need to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(rho);
memory->destroy(fp);
nmax = atom->nmax;
memory->create(rho,nmax,"pair:rho");
memory->create(fp,nmax,"pair:fp");
}
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// zero out density
if (newton_pair) {
m = nlocal + atom->nghost;
for (i = 0; i < m; i++) rho[i] = 0.0;
} else for (i = 0; i < nlocal; i++) rho[i] = 0.0;
// rho = density at each atom
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutforcesq) {
jtype = type[j];
p = sqrt(rsq)*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
coeff = rhor_spline[type2rhor[jtype][itype]][m];
rho[i] += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
if (newton_pair || j < nlocal) {
coeff = rhor_spline[type2rhor[itype][jtype]][m];
rho[j] += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
}
}
}
}
// communicate and sum densities
if (newton_pair) comm->reverse_comm_pair(this);
// fp = derivative of embedding energy at each atom
// phi = embedding energy at each atom
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
p = rho[i]*rdrho + 1.0;
m = static_cast<int> (p);
m = MAX(1,MIN(m,nrho-1));
p -= m;
p = MIN(p,1.0);
coeff = frho_spline[type2frho[type[i]]][m];
fp[i] = (coeff[0]*p + coeff[1])*p + coeff[2];
if (eflag) {
phi = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
if (eflag_global) eng_vdwl += phi;
if (eflag_atom) eatom[i] += phi;
}
}
// communicate derivative of embedding function
comm->forward_comm_pair(this);
// compute forces on each atom
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutforcesq) {
jtype = type[j];
r = sqrt(rsq);
p = r*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
// rhoip = derivative of (density at atom j due to atom i)
// rhojp = derivative of (density at atom i due to atom j)
// phi = pair potential energy
// phip = phi'
// z2 = phi * r
// z2p = (phi * r)' = (phi' r) + phi
// psip needs both fp[i] and fp[j] terms since r_ij appears in two
// terms of embed eng: Fi(sum rho_ij) and Fj(sum rho_ji)
// hence embed' = Fi(sum rho_ij) rhojp + Fj(sum rho_ji) rhoip
coeff = rhor_spline[type2rhor[itype][jtype]][m];
rhoip = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = rhor_spline[type2rhor[jtype][itype]][m];
rhojp = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = z2r_spline[type2z2r[itype][jtype]][m];
z2p = (coeff[0]*p + coeff[1])*p + coeff[2];
z2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
recip = 1.0/r;
phi = z2*recip;
phip = z2p*recip - phi*recip;
psip = fp[i]*rhojp + fp[j]*rhoip + phip;
fpair = -psip*recip;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) evdwl = phi;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairEAM::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
for (int i = 1; i <= n; i++) map[i] = -1;
type2frho = new int[n+1];
memory->create(type2rhor,n+1,n+1,"pair:type2rhor");
memory->create(type2z2r,n+1,n+1,"pair:type2z2r");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairEAM::settings(int narg, char **arg)
{
- if (narg > 0) error->all("Illegal pair_style command");
+ if (narg > 0) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
read DYNAMO funcfl file
------------------------------------------------------------------------- */
void PairEAM::coeff(int narg, char **arg)
{
if (!allocated) allocate();
- if (narg != 3) error->all("Incorrect args for pair coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for pair coefficients");
// parse pair of atom types
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
// read funcfl file if hasn't already been read
// store filename in Funcfl data struct
int ifuncfl;
for (ifuncfl = 0; ifuncfl < nfuncfl; ifuncfl++)
if (strcmp(arg[2],funcfl[ifuncfl].file) == 0) break;
if (ifuncfl == nfuncfl) {
nfuncfl++;
funcfl = (Funcfl *)
memory->srealloc(funcfl,nfuncfl*sizeof(Funcfl),"pair:funcfl");
read_file(arg[2]);
int n = strlen(arg[2]) + 1;
funcfl[ifuncfl].file = new char[n];
strcpy(funcfl[ifuncfl].file,arg[2]);
}
// set setflag and map only for i,i type pairs
// set mass of atom type if i = j
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
if (i == j) {
setflag[i][i] = 1;
map[i] = ifuncfl;
atom->set_mass(i,funcfl[ifuncfl].mass);
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairEAM::init_style()
{
// convert read-in file(s) to arrays and spline them
file2array();
array2spline();
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairEAM::init_one(int i, int j)
{
// single global cutoff = max of cut from all files read in
// for funcfl could be multiple files
// for setfl or fs, just one file
if (funcfl) {
cutmax = 0.0;
for (int m = 0; m < nfuncfl; m++)
cutmax = MAX(cutmax,funcfl[m].cut);
} else if (setfl) cutmax = setfl->cut;
else if (fs) cutmax = fs->cut;
cutforcesq = cutmax*cutmax;
return cutmax;
}
/* ----------------------------------------------------------------------
read potential values from a DYNAMO single element funcfl file
------------------------------------------------------------------------- */
void PairEAM::read_file(char *filename)
{
Funcfl *file = &funcfl[nfuncfl-1];
int me = comm->me;
FILE *fptr;
char line[MAXLINE];
if (me == 0) {
fptr = fopen(filename,"r");
if (fptr == NULL) {
char str[128];
sprintf(str,"Cannot open EAM potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
}
int tmp;
if (me == 0) {
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg",&tmp,&file->mass);
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg %d %lg %lg",
&file->nrho,&file->drho,&file->nr,&file->dr,&file->cut);
}
MPI_Bcast(&file->mass,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->nrho,1,MPI_INT,0,world);
MPI_Bcast(&file->drho,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->nr,1,MPI_INT,0,world);
MPI_Bcast(&file->dr,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->cut,1,MPI_DOUBLE,0,world);
memory->create(file->frho,(file->nrho+1),"pair:frho");
memory->create(file->rhor,(file->nr+1),"pair:rhor");
memory->create(file->zr,(file->nr+1),"pair:zr");
if (me == 0) grab(fptr,file->nrho,&file->frho[1]);
MPI_Bcast(&file->frho[1],file->nrho,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nr,&file->zr[1]);
MPI_Bcast(&file->zr[1],file->nr,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nr,&file->rhor[1]);
MPI_Bcast(&file->rhor[1],file->nr,MPI_DOUBLE,0,world);
if (me == 0) fclose(fptr);
}
/* ----------------------------------------------------------------------
convert read-in funcfl potential(s) to standard array format
interpolate all file values to a single grid and cutoff
------------------------------------------------------------------------- */
void PairEAM::file2array()
{
int i,j,k,m,n;
int ntypes = atom->ntypes;
double sixth = 1.0/6.0;
// determine max function params from all active funcfl files
// active means some element is pointing at it via map
int active;
double rmax,rhomax;
dr = drho = rmax = rhomax = 0.0;
for (int i = 0; i < nfuncfl; i++) {
active = 0;
for (j = 1; j <= ntypes; j++)
if (map[j] == i) active = 1;
if (active == 0) continue;
Funcfl *file = &funcfl[i];
dr = MAX(dr,file->dr);
drho = MAX(drho,file->drho);
rmax = MAX(rmax,(file->nr-1) * file->dr);
rhomax = MAX(rhomax,(file->nrho-1) * file->drho);
}
// set nr,nrho from cutoff and spacings
// 0.5 is for round-off in divide
nr = static_cast<int> (rmax/dr + 0.5);
nrho = static_cast<int> (rhomax/drho + 0.5);
// ------------------------------------------------------------------
// setup frho arrays
// ------------------------------------------------------------------
// allocate frho arrays
// nfrho = # of funcfl files + 1 for zero array
nfrho = nfuncfl + 1;
memory->destroy(frho);
memory->create(frho,nfrho,nrho+1,"pair:frho");
// interpolate each file's frho to a single grid and cutoff
double r,p,cof1,cof2,cof3,cof4;
n = 0;
for (i = 0; i < nfuncfl; i++) {
Funcfl *file = &funcfl[i];
for (m = 1; m <= nrho; m++) {
r = (m-1)*drho;
p = r/file->drho + 1.0;
k = static_cast<int> (p);
k = MIN(k,file->nrho-2);
k = MAX(k,2);
p -= k;
p = MIN(p,2.0);
cof1 = -sixth*p*(p-1.0)*(p-2.0);
cof2 = 0.5*(p*p-1.0)*(p-2.0);
cof3 = -0.5*p*(p+1.0)*(p-2.0);
cof4 = sixth*p*(p*p-1.0);
frho[n][m] = cof1*file->frho[k-1] + cof2*file->frho[k] +
cof3*file->frho[k+1] + cof4*file->frho[k+2];
}
n++;
}
// add extra frho of zeroes for non-EAM types to point to (pair hybrid)
// this is necessary b/c fp is still computed for non-EAM atoms
for (m = 1; m <= nrho; m++) frho[nfrho-1][m] = 0.0;
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
// if atom type doesn't point to file (non-EAM atom in pair hybrid)
// then map it to last frho array of zeroes
for (i = 1; i <= ntypes; i++)
if (map[i] >= 0) type2frho[i] = map[i];
else type2frho[i] = nfrho-1;
// ------------------------------------------------------------------
// setup rhor arrays
// ------------------------------------------------------------------
// allocate rhor arrays
// nrhor = # of funcfl files
nrhor = nfuncfl;
memory->destroy(rhor);
memory->create(rhor,nrhor,nr+1,"pair:rhor");
// interpolate each file's rhor to a single grid and cutoff
n = 0;
for (i = 0; i < nfuncfl; i++) {
Funcfl *file = &funcfl[i];
for (m = 1; m <= nr; m++) {
r = (m-1)*dr;
p = r/file->dr + 1.0;
k = static_cast<int> (p);
k = MIN(k,file->nr-2);
k = MAX(k,2);
p -= k;
p = MIN(p,2.0);
cof1 = -sixth*p*(p-1.0)*(p-2.0);
cof2 = 0.5*(p*p-1.0)*(p-2.0);
cof3 = -0.5*p*(p+1.0)*(p-2.0);
cof4 = sixth*p*(p*p-1.0);
rhor[n][m] = cof1*file->rhor[k-1] + cof2*file->rhor[k] +
cof3*file->rhor[k+1] + cof4*file->rhor[k+2];
}
n++;
}
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
// for funcfl files, I,J mapping only depends on I
// OK if map = -1 (non-EAM atom in pair hybrid) b/c type2rhor not used
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++)
type2rhor[i][j] = map[i];
// ------------------------------------------------------------------
// setup z2r arrays
// ------------------------------------------------------------------
// allocate z2r arrays
// nz2r = N*(N+1)/2 where N = # of funcfl files
nz2r = nfuncfl*(nfuncfl+1)/2;
memory->destroy(z2r);
memory->create(z2r,nz2r,nr+1,"pair:z2r");
// create a z2r array for each file against other files, only for I >= J
// interpolate zri and zrj to a single grid and cutoff
double zri,zrj;
n = 0;
for (i = 0; i < nfuncfl; i++) {
Funcfl *ifile = &funcfl[i];
for (j = 0; j <= i; j++) {
Funcfl *jfile = &funcfl[j];
for (m = 1; m <= nr; m++) {
r = (m-1)*dr;
p = r/ifile->dr + 1.0;
k = static_cast<int> (p);
k = MIN(k,ifile->nr-2);
k = MAX(k,2);
p -= k;
p = MIN(p,2.0);
cof1 = -sixth*p*(p-1.0)*(p-2.0);
cof2 = 0.5*(p*p-1.0)*(p-2.0);
cof3 = -0.5*p*(p+1.0)*(p-2.0);
cof4 = sixth*p*(p*p-1.0);
zri = cof1*ifile->zr[k-1] + cof2*ifile->zr[k] +
cof3*ifile->zr[k+1] + cof4*ifile->zr[k+2];
p = r/jfile->dr + 1.0;
k = static_cast<int> (p);
k = MIN(k,jfile->nr-2);
k = MAX(k,2);
p -= k;
p = MIN(p,2.0);
cof1 = -sixth*p*(p-1.0)*(p-2.0);
cof2 = 0.5*(p*p-1.0)*(p-2.0);
cof3 = -0.5*p*(p+1.0)*(p-2.0);
cof4 = sixth*p*(p*p-1.0);
zrj = cof1*jfile->zr[k-1] + cof2*jfile->zr[k] +
cof3*jfile->zr[k+1] + cof4*jfile->zr[k+2];
z2r[n][m] = 27.2*0.529 * zri*zrj;
}
n++;
}
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// if map = -1 (non-EAM atom in pair hybrid):
// type2z2r is not used by non-opt
// but set type2z2r to 0 since accessed by opt
int irow,icol;
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2z2r[i][j] = 0;
continue;
}
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2z2r[i][j] = n;
}
}
}
/* ---------------------------------------------------------------------- */
void PairEAM::array2spline()
{
rdr = 1.0/dr;
rdrho = 1.0/drho;
memory->destroy(frho_spline);
memory->destroy(rhor_spline);
memory->destroy(z2r_spline);
memory->create(frho_spline,nfrho,nrho+1,7,"pair:frho");
memory->create(rhor_spline,nrhor,nr+1,7,"pair:rhor");
memory->create(z2r_spline,nz2r,nr+1,7,"pair:z2r");
for (int i = 0; i < nfrho; i++)
interpolate(nrho,drho,frho[i],frho_spline[i]);
for (int i = 0; i < nrhor; i++)
interpolate(nr,dr,rhor[i],rhor_spline[i]);
for (int i = 0; i < nz2r; i++)
interpolate(nr,dr,z2r[i],z2r_spline[i]);
}
/* ---------------------------------------------------------------------- */
void PairEAM::interpolate(int n, double delta, double *f, double **spline)
{
for (int m = 1; m <= n; m++) spline[m][6] = f[m];
spline[1][5] = spline[2][6] - spline[1][6];
spline[2][5] = 0.5 * (spline[3][6]-spline[1][6]);
spline[n-1][5] = 0.5 * (spline[n][6]-spline[n-2][6]);
spline[n][5] = spline[n][6] - spline[n-1][6];
for (int m = 3; m <= n-2; m++)
spline[m][5] = ((spline[m-2][6]-spline[m+2][6]) +
8.0*(spline[m+1][6]-spline[m-1][6])) / 12.0;
for (int m = 1; m <= n-1; m++) {
spline[m][4] = 3.0*(spline[m+1][6]-spline[m][6]) -
2.0*spline[m][5] - spline[m+1][5];
spline[m][3] = spline[m][5] + spline[m+1][5] -
2.0*(spline[m+1][6]-spline[m][6]);
}
spline[n][4] = 0.0;
spline[n][3] = 0.0;
for (int m = 1; m <= n; m++) {
spline[m][2] = spline[m][5]/delta;
spline[m][1] = 2.0*spline[m][4]/delta;
spline[m][0] = 3.0*spline[m][3]/delta;
}
}
/* ----------------------------------------------------------------------
grab n values from file fp and put them in list
values can be several to a line
only called by proc 0
------------------------------------------------------------------------- */
void PairEAM::grab(FILE *fptr, int n, double *list)
{
char *ptr;
char line[MAXLINE];
int i = 0;
while (i < n) {
fgets(line,MAXLINE,fptr);
ptr = strtok(line," \t\n\r\f");
list[i++] = atof(ptr);
while (ptr = strtok(NULL," \t\n\r\f")) list[i++] = atof(ptr);
}
}
/* ---------------------------------------------------------------------- */
double PairEAM::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
int m;
double r,p,rhoip,rhojp,z2,z2p,recip,phi,phip,psip;
double *coeff;
r = sqrt(rsq);
p = r*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
coeff = rhor_spline[type2rhor[itype][jtype]][m];
rhoip = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = rhor_spline[type2rhor[jtype][itype]][m];
rhojp = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = z2r_spline[type2z2r[itype][jtype]][m];
z2p = (coeff[0]*p + coeff[1])*p + coeff[2];
z2 = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
recip = 1.0/r;
phi = z2*recip;
phip = z2p*recip - phi*recip;
psip = fp[i]*rhojp + fp[j]*rhoip + phip;
fforce = -psip*recip;
return phi;
}
/* ---------------------------------------------------------------------- */
int PairEAM::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = fp[j];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void PairEAM::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) fp[i] = buf[m++];
}
/* ---------------------------------------------------------------------- */
int PairEAM::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) buf[m++] = rho[i];
return 1;
}
/* ---------------------------------------------------------------------- */
void PairEAM::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
rho[j] += buf[m++];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairEAM::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
bytes += 2 * nmax * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
swap fp array with one passed in by caller
------------------------------------------------------------------------- */
void PairEAM::swap_eam(double *fp_caller, double **fp_caller_hold)
{
double *tmp = fp;
fp = fp_caller;
*fp_caller_hold = tmp;
}
diff --git a/src/MANYBODY/pair_eam_alloy.cpp b/src/MANYBODY/pair_eam_alloy.cpp
index 058402258..5b6cd72f5 100644
--- a/src/MANYBODY/pair_eam_alloy.cpp
+++ b/src/MANYBODY/pair_eam_alloy.cpp
@@ -1,323 +1,323 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Stephen Foiles (SNL), Murray Daw (SNL)
------------------------------------------------------------------------- */
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_eam_alloy.h"
#include "atom.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairEAMAlloy::PairEAMAlloy(LAMMPS *lmp) : PairEAM(lmp)
{
one_coeff = 1;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
read DYNAMO setfl file
------------------------------------------------------------------------- */
void PairEAMAlloy::coeff(int narg, char **arg)
{
int i,j;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read EAM setfl file
if (setfl) {
for (i = 0; i < setfl->nelements; i++) delete [] setfl->elements[i];
delete [] setfl->elements;
delete [] setfl->mass;
memory->destroy(setfl->frho);
memory->destroy(setfl->rhor);
memory->destroy(setfl->z2r);
delete setfl;
}
setfl = new Setfl();
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
for (i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
continue;
}
for (j = 0; j < setfl->nelements; j++)
if (strcmp(arg[i],setfl->elements[j]) == 0) break;
if (j < setfl->nelements) map[i-2] = j;
- else error->all("No matching element in EAM potential file");
+ else error->all(FLERR,"No matching element in EAM potential file");
}
// clear setflag since coeff() called once with I,J = * *
int n = atom->ntypes;
for (i = 1; i <= n; i++)
for (j = i; j <= n; j++)
setflag[i][j] = 0;
// set setflag i,j for type pairs where both are mapped to elements
// set mass of atom type if i = j
int count = 0;
for (i = 1; i <= n; i++) {
for (j = i; j <= n; j++) {
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
if (i == j) atom->set_mass(i,setfl->mass[map[i]]);
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
read a multi-element DYNAMO setfl file
------------------------------------------------------------------------- */
void PairEAMAlloy::read_file(char *filename)
{
Setfl *file = setfl;
// open potential file
int me = comm->me;
FILE *fptr;
char line[MAXLINE];
if (me == 0) {
fptr = fopen(filename,"r");
if (fptr == NULL) {
char str[128];
sprintf(str,"Cannot open EAM potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read and broadcast header
// extract element names from nelements line
int n;
if (me == 0) {
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
n = strlen(line) + 1;
}
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
sscanf(line,"%d",&file->nelements);
int nwords = atom->count_words(line);
if (nwords != file->nelements + 1)
- error->all("Incorrect element names in EAM potential file");
+ error->all(FLERR,"Incorrect element names in EAM potential file");
char **words = new char*[file->nelements+1];
nwords = 0;
strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
file->elements = new char*[file->nelements];
for (int i = 0; i < file->nelements; i++) {
n = strlen(words[i]) + 1;
file->elements[i] = new char[n];
strcpy(file->elements[i],words[i]);
}
delete [] words;
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg %d %lg %lg",
&file->nrho,&file->drho,&file->nr,&file->dr,&file->cut);
}
MPI_Bcast(&file->nrho,1,MPI_INT,0,world);
MPI_Bcast(&file->drho,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->nr,1,MPI_INT,0,world);
MPI_Bcast(&file->dr,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->cut,1,MPI_DOUBLE,0,world);
file->mass = new double[file->nelements];
memory->create(file->frho,file->nelements,file->nrho+1,"pair:frho");
memory->create(file->rhor,file->nelements,file->nr+1,"pair:rhor");
memory->create(file->z2r,file->nelements,file->nelements,file->nr+1,
"pair:z2r");
int i,j,tmp;
for (i = 0; i < file->nelements; i++) {
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg",&tmp,&file->mass[i]);
}
MPI_Bcast(&file->mass[i],1,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nrho,&file->frho[i][1]);
MPI_Bcast(&file->frho[i][1],file->nrho,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nr,&file->rhor[i][1]);
MPI_Bcast(&file->rhor[i][1],file->nr,MPI_DOUBLE,0,world);
}
for (i = 0; i < file->nelements; i++)
for (j = 0; j <= i; j++) {
if (me == 0) grab(fptr,file->nr,&file->z2r[i][j][1]);
MPI_Bcast(&file->z2r[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
// close the potential file
if (me == 0) fclose(fptr);
}
/* ----------------------------------------------------------------------
copy read-in setfl potential to standard array format
------------------------------------------------------------------------- */
void PairEAMAlloy::file2array()
{
int i,j,m,n;
int ntypes = atom->ntypes;
// set function params directly from setfl file
nrho = setfl->nrho;
nr = setfl->nr;
drho = setfl->drho;
dr = setfl->dr;
// ------------------------------------------------------------------
// setup frho arrays
// ------------------------------------------------------------------
// allocate frho arrays
// nfrho = # of setfl elements + 1 for zero array
nfrho = setfl->nelements + 1;
memory->destroy(frho);
memory->create(frho,nfrho,nrho+1,"pair:frho");
// copy each element's frho to global frho
for (i = 0; i < setfl->nelements; i++)
for (m = 1; m <= nrho; m++) frho[i][m] = setfl->frho[i][m];
// add extra frho of zeroes for non-EAM types to point to (pair hybrid)
// this is necessary b/c fp is still computed for non-EAM atoms
for (m = 1; m <= nrho; m++) frho[nfrho-1][m] = 0.0;
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
// if atom type doesn't point to element (non-EAM atom in pair hybrid)
// then map it to last frho array of zeroes
for (i = 1; i <= ntypes; i++)
if (map[i] >= 0) type2frho[i] = map[i];
else type2frho[i] = nfrho-1;
// ------------------------------------------------------------------
// setup rhor arrays
// ------------------------------------------------------------------
// allocate rhor arrays
// nrhor = # of setfl elements
nrhor = setfl->nelements;
memory->destroy(rhor);
memory->create(rhor,nrhor,nr+1,"pair:rhor");
// copy each element's rhor to global rhor
for (i = 0; i < setfl->nelements; i++)
for (m = 1; m <= nr; m++) rhor[i][m] = setfl->rhor[i][m];
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
// for setfl files, I,J mapping only depends on I
// OK if map = -1 (non-EAM atom in pair hybrid) b/c type2rhor not used
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++)
type2rhor[i][j] = map[i];
// ------------------------------------------------------------------
// setup z2r arrays
// ------------------------------------------------------------------
// allocate z2r arrays
// nz2r = N*(N+1)/2 where N = # of setfl elements
nz2r = setfl->nelements * (setfl->nelements+1) / 2;
memory->destroy(z2r);
memory->create(z2r,nz2r,nr+1,"pair:z2r");
// copy each element pair z2r to global z2r, only for I >= J
n = 0;
for (i = 0; i < setfl->nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) z2r[n][m] = setfl->z2r[i][j][m];
n++;
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// if map = -1 (non-EAM atom in pair hybrid):
// type2z2r is not used by non-opt
// but set type2z2r to 0 since accessed by opt
int irow,icol;
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2z2r[i][j] = 0;
continue;
}
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2z2r[i][j] = n;
}
}
}
diff --git a/src/MANYBODY/pair_eam_fs.cpp b/src/MANYBODY/pair_eam_fs.cpp
index ccd4d7e30..0ac0768b9 100644
--- a/src/MANYBODY/pair_eam_fs.cpp
+++ b/src/MANYBODY/pair_eam_fs.cpp
@@ -1,332 +1,332 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Tim Lau (MIT)
------------------------------------------------------------------------- */
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_eam_fs.h"
#include "atom.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairEAMFS::PairEAMFS(LAMMPS *lmp) : PairEAM(lmp)
{
one_coeff = 1;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
read EAM Finnis-Sinclair file
------------------------------------------------------------------------- */
void PairEAMFS::coeff(int narg, char **arg)
{
int i,j;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read EAM Finnis-Sinclair file
if (fs) {
for (i = 0; i < fs->nelements; i++) delete [] fs->elements[i];
delete [] fs->elements;
delete [] fs->mass;
memory->destroy(fs->frho);
memory->destroy(fs->rhor);
memory->destroy(fs->z2r);
delete fs;
}
fs = new Fs();
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
for (i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
continue;
}
for (j = 0; j < fs->nelements; j++)
if (strcmp(arg[i],fs->elements[j]) == 0) break;
if (j < fs->nelements) map[i-2] = j;
- else error->all("No matching element in EAM potential file");
+ else error->all(FLERR,"No matching element in EAM potential file");
}
// clear setflag since coeff() called once with I,J = * *
int n = atom->ntypes;
for (i = 1; i <= n; i++)
for (j = i; j <= n; j++)
setflag[i][j] = 0;
// set setflag i,j for type pairs where both are mapped to elements
// set mass of atom type if i = j
int count = 0;
for (i = 1; i <= n; i++) {
for (j = i; j <= n; j++) {
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
if (i == j) atom->set_mass(i,fs->mass[map[i]]);
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
read a multi-element DYNAMO setfl file
------------------------------------------------------------------------- */
void PairEAMFS::read_file(char *filename)
{
Fs *file = fs;
// open potential file
int me = comm->me;
FILE *fptr;
char line[MAXLINE];
if (me == 0) {
fptr = fopen(filename,"r");
if (fptr == NULL) {
char str[128];
sprintf(str,"Cannot open EAM potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read and broadcast header
// extract element names from nelements line
int n;
if (me == 0) {
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
n = strlen(line) + 1;
}
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
sscanf(line,"%d",&file->nelements);
int nwords = atom->count_words(line);
if (nwords != file->nelements + 1)
- error->all("Incorrect element names in EAM potential file");
+ error->all(FLERR,"Incorrect element names in EAM potential file");
char **words = new char*[file->nelements+1];
nwords = 0;
strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
file->elements = new char*[file->nelements];
for (int i = 0; i < file->nelements; i++) {
n = strlen(words[i]) + 1;
file->elements[i] = new char[n];
strcpy(file->elements[i],words[i]);
}
delete [] words;
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg %d %lg %lg",
&file->nrho,&file->drho,&file->nr,&file->dr,&file->cut);
}
MPI_Bcast(&file->nrho,1,MPI_INT,0,world);
MPI_Bcast(&file->drho,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->nr,1,MPI_INT,0,world);
MPI_Bcast(&file->dr,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->cut,1,MPI_DOUBLE,0,world);
file->mass = new double[file->nelements];
memory->create(file->frho,file->nelements,file->nrho+1,
"pair:frho");
memory->create(file->rhor,file->nelements,file->nelements,
file->nr+1,"pair:rhor");
memory->create(file->z2r,file->nelements,file->nelements,
file->nr+1,"pair:z2r");
int i,j,tmp;
for (i = 0; i < file->nelements; i++) {
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg",&tmp,&file->mass[i]);
}
MPI_Bcast(&file->mass[i],1,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nrho,&file->frho[i][1]);
MPI_Bcast(&file->frho[i][1],file->nrho,MPI_DOUBLE,0,world);
for (j = 0; j < file->nelements; j++) {
if (me == 0) grab(fptr,file->nr,&file->rhor[i][j][1]);
MPI_Bcast(&file->rhor[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
}
for (i = 0; i < file->nelements; i++)
for (j = 0; j <= i; j++) {
if (me == 0) grab(fptr,file->nr,&file->z2r[i][j][1]);
MPI_Bcast(&file->z2r[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
// close the potential file
if (me == 0) fclose(fptr);
}
/* ----------------------------------------------------------------------
copy read-in setfl potential to standard array format
------------------------------------------------------------------------- */
void PairEAMFS::file2array()
{
int i,j,m,n;
int ntypes = atom->ntypes;
// set function params directly from fs file
nrho = fs->nrho;
nr = fs->nr;
drho = fs->drho;
dr = fs->dr;
// ------------------------------------------------------------------
// setup frho arrays
// ------------------------------------------------------------------
// allocate frho arrays
// nfrho = # of fs elements + 1 for zero array
nfrho = fs->nelements + 1;
memory->destroy(frho);
memory->create(frho,nfrho,nrho+1,"pair:frho");
// copy each element's frho to global frho
for (i = 0; i < fs->nelements; i++)
for (m = 1; m <= nrho; m++) frho[i][m] = fs->frho[i][m];
// add extra frho of zeroes for non-EAM types to point to (pair hybrid)
// this is necessary b/c fp is still computed for non-EAM atoms
for (m = 1; m <= nrho; m++) frho[nfrho-1][m] = 0.0;
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
// if atom type doesn't point to element (non-EAM atom in pair hybrid)
// then map it to last frho array of zeroes
for (i = 1; i <= ntypes; i++)
if (map[i] >= 0) type2frho[i] = map[i];
else type2frho[i] = nfrho-1;
// ------------------------------------------------------------------
// setup rhor arrays
// ------------------------------------------------------------------
// allocate rhor arrays
// nrhor = square of # of fs elements
nrhor = fs->nelements * fs->nelements;
memory->destroy(rhor);
memory->create(rhor,nrhor,nr+1,"pair:rhor");
// copy each element pair rhor to global rhor
n = 0;
for (i = 0; i < fs->nelements; i++)
for (j = 0; j < fs->nelements; j++) {
for (m = 1; m <= nr; m++) rhor[n][m] = fs->rhor[i][j][m];
n++;
}
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
// for fs files, there is a full NxN set of rhor arrays
// OK if map = -1 (non-EAM atom in pair hybrid) b/c type2rhor not used
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++)
type2rhor[i][j] = map[i] * fs->nelements + map[j];
// ------------------------------------------------------------------
// setup z2r arrays
// ------------------------------------------------------------------
// allocate z2r arrays
// nz2r = N*(N+1)/2 where N = # of fs elements
nz2r = fs->nelements * (fs->nelements+1) / 2;
memory->destroy(z2r);
memory->create(z2r,nz2r,nr+1,"pair:z2r");
// copy each element pair z2r to global z2r, only for I >= J
n = 0;
for (i = 0; i < fs->nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) z2r[n][m] = fs->z2r[i][j][m];
n++;
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// if map = -1 (non-EAM atom in pair hybrid):
// type2z2r is not used by non-opt
// but set type2z2r to 0 since accessed by opt
int irow,icol;
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2z2r[i][j] = 0;
continue;
}
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2z2r[i][j] = n;
}
}
}
diff --git a/src/MANYBODY/pair_eim.cpp b/src/MANYBODY/pair_eim.cpp
index 07c2706c0..c8b324d26 100644
--- a/src/MANYBODY/pair_eim.cpp
+++ b/src/MANYBODY/pair_eim.cpp
@@ -1,1171 +1,1168 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Xiaowang Zhou (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_eim.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairEIM::PairEIM(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
setfl = NULL;
nmax = 0;
rho = NULL;
fp = NULL;
nelements = 0;
elements = NULL;
negativity = NULL;
q0 = NULL;
cutforcesq = NULL;
Fij = NULL;
Gij = NULL;
phiij = NULL;
Fij_spline = NULL;
Gij_spline = NULL;
phiij_spline = NULL;
// set comm size needed by this Pair
comm_forward = 1;
comm_reverse = 1;
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairEIM::~PairEIM()
{
memory->destroy(rho);
memory->destroy(fp);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
memory->destroy(type2Fij);
memory->destroy(type2Gij);
memory->destroy(type2phiij);
}
for (int i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
deallocate_setfl();
delete [] negativity;
delete [] q0;
memory->destroy(cutforcesq);
memory->destroy(Fij);
memory->destroy(Gij);
memory->destroy(phiij);
memory->destroy(Fij_spline);
memory->destroy(Gij_spline);
memory->destroy(phiij_spline);
}
/* ---------------------------------------------------------------------- */
void PairEIM::compute(int eflag, int vflag)
{
int i,j,ii,jj,m,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,p,rhoip,rhojp,phip,phi,coul,coulp,recip,psip;
double *coeff;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = eflag_atom = 0;
// grow energy array if necessary
if (atom->nmax > nmax) {
memory->destroy(rho);
memory->destroy(fp);
nmax = atom->nmax;
memory->create(rho,nmax,"pair:rho");
memory->create(fp,nmax,"pair:fp");
}
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// zero out density
if (newton_pair) {
m = nlocal + atom->nghost;
for (i = 0; i < m; i++) {
rho[i] = 0.0;
fp[i] = 0.0;
}
} else {
for (i = 0; i < nlocal; i++) {
rho[i] = 0.0;
fp[i] = 0.0;
}
}
// rho = density at each atom
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = type[j];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutforcesq[itype][jtype]) {
p = sqrt(rsq)*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
coeff = Fij_spline[type2Fij[itype][jtype]][m];
rho[i] += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
if (newton_pair || j < nlocal) {
coeff = Fij_spline[type2Fij[jtype][itype]][m];
rho[j] += ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
}
}
}
}
// communicate and sum densities
rhofp = 1;
if (newton_pair) comm->reverse_comm_pair(this);
comm->forward_comm_pair(this);
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = type[j];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutforcesq[itype][jtype]) {
p = sqrt(rsq)*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
coeff = Gij_spline[type2Gij[itype][jtype]][m];
fp[i] += rho[j]*(((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6]);
if (newton_pair || j < nlocal) {
fp[j] += rho[i]*(((coeff[3]*p + coeff[4])*p + coeff[5])*p +
coeff[6]);
}
}
}
}
// communicate and sum modified densities
rhofp = 2;
if (newton_pair) comm->reverse_comm_pair(this);
comm->forward_comm_pair(this);
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
if (eflag) {
phi = 0.5*rho[i]*fp[i];
if (eflag_global) eng_vdwl += phi;
if (eflag_atom) eatom[i] += phi;
}
}
// compute forces on each atom
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = type[j];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutforcesq[itype][jtype]) {
r = sqrt(rsq);
p = r*rdr + 1.0;
m = static_cast<int> (p);
m = MIN(m,nr-1);
p -= m;
p = MIN(p,1.0);
// rhoip = derivative of (density at atom j due to atom i)
// rhojp = derivative of (density at atom i due to atom j)
// phi = pair potential energy
// phip = phi'
coeff = Fij_spline[type2Fij[jtype][itype]][m];
rhoip = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = Fij_spline[type2Fij[itype][jtype]][m];
rhojp = (coeff[0]*p + coeff[1])*p + coeff[2];
coeff = phiij_spline[type2phiij[itype][jtype]][m];
phip = (coeff[0]*p + coeff[1])*p + coeff[2];
phi = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
coeff = Gij_spline[type2Gij[itype][jtype]][m];
coul = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
coulp = (coeff[0]*p + coeff[1])*p + coeff[2];
psip = phip + (rho[i]*rho[j]-q0[itype]*q0[jtype])*coulp +
fp[i]*rhojp + fp[j]*rhoip;
recip = 1.0/r;
fpair = -psip*recip;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) evdwl = phi-q0[itype]*q0[jtype]*coul;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairEIM::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
for (int i = 1; i <= n; i++) map[i] = -1;
memory->create(type2Fij,n+1,n+1,"pair:type2Fij");
memory->create(type2Gij,n+1,n+1,"pair:type2Gij");
memory->create(type2phiij,n+1,n+1,"pair:type2phiij");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairEIM::settings(int narg, char **arg)
{
- if (narg > 0) error->all("Illegal pair_style command");
+ if (narg > 0) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs from set file
------------------------------------------------------------------------- */
void PairEIM::coeff(int narg, char **arg)
{
int i,j,m,n;
if (!allocated) allocate();
- if (narg < 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 5) error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read EIM element names before filename
// nelements = # of EIM elements to read from file
// elements = list of unique element names
if (nelements) {
for (i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
}
nelements = narg - 3 - atom->ntypes;
- if (nelements < 1) error->all("Incorrect args for pair coefficients");
+ if (nelements < 1) error->all(FLERR,"Incorrect args for pair coefficients");
elements = new char*[nelements];
for (i = 0; i < nelements; i++) {
n = strlen(arg[i+2]) + 1;
elements[i] = new char[n];
strcpy(elements[i],arg[i+2]);
}
// read EIM file
deallocate_setfl();
setfl = new Setfl();
read_file(arg[2+nelements]);
// read args that map atom types to elements in potential file
// map[i] = which element the Ith atom type is, -1 if NULL
for (i = 3 + nelements; i < narg; i++) {
m = i - (3+nelements) + 1;
for (j = 0; j < nelements; j++)
if (strcmp(arg[i],elements[j]) == 0) break;
if (j < nelements) map[m] = j;
else if (strcmp(arg[i],"NULL") == 0) map[m] = -1;
- else error->all("Incorrect args for pair coefficients");
+ else error->all(FLERR,"Incorrect args for pair coefficients");
}
// clear setflag since coeff() called once with I,J = * *
n = atom->ntypes;
for (i = 1; i <= n; i++)
for (j = i; j <= n; j++)
setflag[i][j] = 0;
// set setflag i,j for type pairs where both are mapped to elements
// set mass of atom type if i = j
int count = 0;
for (i = 1; i <= n; i++)
for (j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
if (i == j) atom->set_mass(i,setfl->mass[map[i]]);
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairEIM::init_style()
{
// convert read-in file(s) to arrays and spline them
file2array();
array2spline();
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairEIM::init_one(int i, int j)
{
cutmax = sqrt(cutforcesq[i][j]);
return cutmax;
}
/* ----------------------------------------------------------------------
read potential values from a set file
------------------------------------------------------------------------- */
void PairEIM::read_file(char *filename)
{
// open potential file
int me = comm->me;
FILE *fptr;
if (me == 0) {
fptr = fopen(filename,"r");
if (fptr == NULL) {
char str[128];
sprintf(str,"Cannot open EIM potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
}
int npair = nelements*(nelements+1)/2;
setfl->ielement = new int[nelements];
setfl->mass = new double[nelements];
setfl->negativity = new double[nelements];
setfl->ra = new double[nelements];
setfl->ri = new double[nelements];
setfl->Ec = new double[nelements];
setfl->q0 = new double[nelements];
setfl->rcutphiA = new double[npair];
setfl->rcutphiR = new double[npair];
setfl->Eb = new double[npair];
setfl->r0 = new double[npair];
setfl->alpha = new double[npair];
setfl->beta = new double[npair];
setfl->rcutq = new double[npair];
setfl->Asigma = new double[npair];
setfl->rq = new double[npair];
setfl->rcutsigma = new double[npair];
setfl->Ac = new double[npair];
setfl->zeta = new double[npair];
setfl->rs = new double[npair];
setfl->tp = new int[npair];
if (me == 0)
if (!grabglobal(fptr))
- error->one("Could not grab global entry from EIM potential file");
+ error->one(FLERR,"Could not grab global entry from EIM potential file");
MPI_Bcast(&setfl->division,1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->rbig,1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->rsmall,1,MPI_DOUBLE,0,world);
for (int i = 0; i < nelements; i++) {
if (me == 0)
if (!grabsingle(fptr,i))
- error->one("Could not grab element entry from EIM potential file");
+ error->one(FLERR,"Could not grab element entry from EIM potential file");
MPI_Bcast(&setfl->ielement[i],1,MPI_INT,0,world);
MPI_Bcast(&setfl->mass[i],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->negativity[i],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->ra[i],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->ri[i],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->Ec[i],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->q0[i],1,MPI_DOUBLE,0,world);
}
for (int i = 0; i < nelements; i++) {
for (int j = i; j < nelements; j++) {
int ij;
if (i == j) ij = i;
else if (i < j) ij = nelements*(i+1) - (i+1)*(i+2)/2 + j;
else ij = nelements*(j+1) - (j+1)*(j+2)/2 + i;
if (me == 0)
if (grabpair(fptr,i,j) == 0)
- error->one("Could not grab pair entry from EIM potential file");
+ error->one(FLERR,"Could not grab pair entry from EIM potential file");
MPI_Bcast(&setfl->rcutphiA[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->rcutphiR[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->Eb[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->r0[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->alpha[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->beta[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->rcutq[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->Asigma[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->rq[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->rcutsigma[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->Ac[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->zeta[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->rs[ij],1,MPI_DOUBLE,0,world);
MPI_Bcast(&setfl->tp[ij],1,MPI_INT,0,world);
}
}
setfl->nr = 5000;
setfl->cut = 0.0;
for (int i = 0; i < npair; i++) {
if (setfl->cut < setfl->rcutphiA[i]) setfl->cut = setfl->rcutphiA[i];
if (setfl->cut < setfl->rcutphiR[i]) setfl->cut = setfl->rcutphiR[i];
if (setfl->cut < setfl->rcutq[i]) setfl->cut = setfl->rcutq[i];
if (setfl->cut < setfl->rcutsigma[i]) setfl->cut = setfl->rcutsigma[i];
}
setfl->dr = setfl->cut/(setfl->nr-1.0);
memory->create(setfl->cuts,nelements,nelements,"pair:cuts");
for (int i = 0; i < nelements; i++) {
for (int j = 0; j < nelements; j++) {
if (i > j) {
setfl->cuts[i][j] = setfl->cuts[j][i];
} else {
int ij;
if (i == j) {
ij = i;
} else {
ij = nelements*(i+1) - (i+1)*(i+2)/2 + j;
}
setfl->cuts[i][j] = setfl->rcutphiA[ij];
if (setfl->cuts[i][j] < setfl->rcutphiR[ij])
setfl->cuts[i][j] = setfl->rcutphiR[ij];
if (setfl->cuts[i][j] < setfl->rcutq[ij])
setfl->cuts[i][j] = setfl->rcutq[ij];
if (setfl->cuts[i][j] < setfl->rcutsigma[ij])
setfl->cuts[i][j] = setfl->rcutsigma[ij];
}
}
}
memory->create(setfl->Fij,nelements,nelements,setfl->nr+1,"pair:Fij");
memory->create(setfl->Gij,nelements,nelements,setfl->nr+1,"pair:Gij");
memory->create(setfl->phiij,nelements,nelements,setfl->nr+1,"pair:phiij");
for (int i = 0; i < nelements; i++)
for (int j = 0; j < nelements; j++) {
for (int k = 0; k < setfl->nr; k++) {
if (i > j) {
setfl->phiij[i][j][k+1] = setfl->phiij[j][i][k+1];
} else {
double r = k*setfl->dr;
setfl->phiij[i][j][k+1] = funcphi(i,j,r);
}
}
}
for (int i = 0; i < nelements; i++)
for (int j = 0; j < nelements; j++) {
for (int k = 0; k < setfl->nr; k++) {
double r = k*setfl->dr;
setfl->Fij[i][j][k+1] = funcsigma(i,j,r);
}
}
for (int i = 0; i < nelements; i++)
for (int j = 0; j < nelements; j++) {
for (int k = 0; k < setfl->nr; k++) {
if (i > j) {
setfl->Gij[i][j][k+1] = setfl->Gij[j][i][k+1];
} else {
double r = k*setfl->dr;
setfl->Gij[i][j][k+1] = funccoul(i,j,r);
}
}
}
// close the potential file
if (me == 0) fclose(fptr);
}
/* ----------------------------------------------------------------------
deallocate data associated with setfl file
------------------------------------------------------------------------- */
void PairEIM::deallocate_setfl()
{
if (!setfl) return;
delete [] setfl->ielement;
delete [] setfl->mass;
delete [] setfl->negativity;
delete [] setfl->ra;
delete [] setfl->ri;
delete [] setfl->Ec;
delete [] setfl->q0;
delete [] setfl->rcutphiA;
delete [] setfl->rcutphiR;
delete [] setfl->Eb;
delete [] setfl->r0;
delete [] setfl->alpha;
delete [] setfl->beta;
delete [] setfl->rcutq;
delete [] setfl->Asigma;
delete [] setfl->rq;
delete [] setfl->rcutsigma;
delete [] setfl->Ac;
delete [] setfl->zeta;
delete [] setfl->rs;
delete [] setfl->tp;
memory->destroy(setfl->cuts);
memory->destroy(setfl->Fij);
memory->destroy(setfl->Gij);
memory->destroy(setfl->phiij);
delete setfl;
}
/* ----------------------------------------------------------------------
convert read-in potentials to standard array format
interpolate all file values to a single grid and cutoff
------------------------------------------------------------------------- */
void PairEIM::file2array()
{
int i,j,m,n;
int irow,icol;
int ntypes = atom->ntypes;
delete [] negativity;
delete [] q0;
delete [] cutforcesq;
negativity = new double[ntypes+1];
q0 = new double[ntypes+1];
memory->create(cutforcesq,ntypes+1,ntypes+1,"pair:cutforcesq");
for (i = 1; i <= ntypes; i++) {
if (map[i] == -1) {
negativity[i]=0.0;
q0[i]=0.0;
} else {
negativity[i]=setfl->negativity[map[i]];
q0[i]=setfl->q0[map[i]];
}
}
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++) {
if (map[i] == -1 || map[j] == -1) {
cutforcesq[i][j] = setfl->cut;
cutforcesq[i][j] = cutforcesq[i][j]*cutforcesq[i][j];
} else {
cutforcesq[i][j] = setfl->cuts[map[i]][map[j]];
cutforcesq[i][j] = cutforcesq[i][j]*cutforcesq[i][j];
}
}
nr = setfl->nr;
dr = setfl->dr;
// ------------------------------------------------------------------
// setup Fij arrays
// ------------------------------------------------------------------
nFij = nelements*nelements + 1;
memory->destroy(Fij);
memory->create(Fij,nFij,nr+1,"pair:Fij");
// copy each element's Fij to global Fij
n=0;
for (i = 0; i < nelements; i++)
for (j = 0; j < nelements; j++) {
for (m = 1; m <= nr; m++) Fij[n][m] = setfl->Fij[i][j][m];
n++;
}
// add extra Fij of zeroes for non-EIM types to point to (pair hybrid)
for (m = 1; m <= nr; m++) Fij[nFij-1][m] = 0.0;
// type2Fij[i][j] = which Fij array (0 to nFij-1) each type pair maps to
// setfl of Fij arrays
// value = n = sum over rows of matrix until reach irow,icol
// if atom type doesn't point to element (non-EIM atom in pair hybrid)
// then map it to last Fij array of zeroes
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2Fij[i][j] = nFij-1;
} else {
n = 0;
for (m = 0; m < irow; m++) n += nelements;
n += icol;
type2Fij[i][j] = n;
}
}
}
// ------------------------------------------------------------------
// setup Gij arrays
// ------------------------------------------------------------------
nGij = nelements * (nelements+1) / 2 + 1;
memory->destroy(Gij);
memory->create(Gij,nGij,nr+1,"pair:Gij");
// copy each element's Gij to global Gij, only for I >= J
n=0;
for (i = 0; i < nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) Gij[n][m] = setfl->Gij[i][j][m];
n++;
}
// add extra Gij of zeroes for non-EIM types to point to (pair hybrid)
for (m = 1; m <= nr; m++) Gij[nGij-1][m] = 0.0;
// type2Gij[i][j] = which Gij array (0 to nGij-1) each type pair maps to
// setfl of Gij arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// if atom type doesn't point to element (non-EIM atom in pair hybrid)
// then map it to last Gij array of zeroes
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2Gij[i][j] = nGij-1;
} else {
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2Gij[i][j] = n;
}
}
}
// ------------------------------------------------------------------
// setup phiij arrays
// ------------------------------------------------------------------
nphiij = nelements * (nelements+1) / 2 + 1;
memory->destroy(phiij);
memory->create(phiij,nphiij,nr+1,"pair:phiij");
// copy each element pair phiij to global phiij, only for I >= J
n = 0;
for (i = 0; i < nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) phiij[n][m] = setfl->phiij[i][j][m];
n++;
}
// add extra phiij of zeroes for non-EIM types to point to (pair hybrid)
for (m = 1; m <= nr; m++) phiij[nphiij-1][m] = 0.0;
// type2phiij[i][j] = which phiij array (0 to nphiij-1)
// each type pair maps to
// setfl of phiij arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// if atom type doesn't point to element (non-EIM atom in pair hybrid)
// then map it to last phiij array of zeroes
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2phiij[i][j] = nphiij-1;
} else {
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2phiij[i][j] = n;
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairEIM::array2spline()
{
rdr = 1.0/dr;
memory->destroy(Fij_spline);
memory->destroy(Gij_spline);
memory->destroy(phiij_spline);
memory->create(Fij_spline,nFij,nr+1,7,"pair:Fij");
memory->create(Gij_spline,nGij,nr+1,7,"pair:Gij");
memory->create(phiij_spline,nphiij,nr+1,7,"pair:phiij");
for (int i = 0; i < nFij; i++)
interpolate(nr,dr,Fij[i],Fij_spline[i],0.0);
for (int i = 0; i < nGij; i++)
interpolate(nr,dr,Gij[i],Gij_spline[i],0.0);
for (int i = 0; i < nphiij; i++)
interpolate(nr,dr,phiij[i],phiij_spline[i],0.0);
}
/* ---------------------------------------------------------------------- */
void PairEIM::interpolate(int n, double delta, double *f,
double **spline, double origin)
{
for (int m = 1; m <= n; m++) spline[m][6] = f[m];
spline[1][5] = spline[2][6] - spline[1][6];
spline[2][5] = 0.5 * (spline[3][6]-spline[1][6]);
spline[n-1][5] = 0.5 * (spline[n][6]-spline[n-2][6]);
spline[n][5] = 0.0;
for (int m = 3; m <= n-2; m++)
spline[m][5] = ((spline[m-2][6]-spline[m+2][6]) +
8.0*(spline[m+1][6]-spline[m-1][6])) / 12.0;
for (int m = 1; m <= n-1; m++) {
spline[m][4] = 3.0*(spline[m+1][6]-spline[m][6]) -
2.0*spline[m][5] - spline[m+1][5];
spline[m][3] = spline[m][5] + spline[m+1][5] -
2.0*(spline[m+1][6]-spline[m][6]);
}
spline[n][4] = 0.0;
spline[n][3] = 0.0;
for (int m = 1; m <= n; m++) {
spline[m][2] = spline[m][5]/delta;
spline[m][1] = 2.0*spline[m][4]/delta;
spline[m][0] = 3.0*spline[m][3]/delta;
}
}
/* ----------------------------------------------------------------------
grab global line from file and store info in setfl
return 0 if error
------------------------------------------------------------------------- */
int PairEIM::grabglobal(FILE *fptr)
{
char line[MAXLINE];
char *pch = NULL, *data = NULL;
while (pch == NULL) {
if (fgets(line,MAXLINE,fptr) == NULL) break;
pch = strstr(line,"global");
if (pch != NULL) {
data = strtok (line," \t\n\r\f");
data = strtok (NULL,"?");
sscanf(data,"%lg %lg %lg",&setfl->division,&setfl->rbig,&setfl->rsmall);
}
}
if (pch == NULL) return 0;
return 1;
}
/* ----------------------------------------------------------------------
grab elemental line from file and store info in setfl
return 0 if error
------------------------------------------------------------------------- */
int PairEIM::grabsingle(FILE *fptr, int i)
{
char line[MAXLINE];
rewind(fptr);
char *pch1 = NULL, *pch2 = NULL, *data = NULL;
while (pch1 == NULL || pch2 == NULL) {
if (fgets(line,MAXLINE,fptr) == NULL) break;
pch1 = strtok (line," \t\n\r\f");
pch1 = strstr(pch1,"element:");
if (pch1 != NULL) {
pch2 = strtok(NULL, " \t\n\r\f");
if (pch2 != NULL) data = strtok (NULL, "?");
if (strcmp(pch2,elements[i]) == 0) {
sscanf(data,"%d %lg %lg %lg %lg %lg %lg",&setfl->ielement[i],
&setfl->mass[i],&setfl->negativity[i],&setfl->ra[i],
&setfl->ri[i],&setfl->Ec[i],&setfl->q0[i]);
} else {
pch2 = NULL;
}
}
}
if (pch1 == NULL || pch2 == NULL) return 0;
return 1;
}
/* ----------------------------------------------------------------------
grab pair line from file and store info in setfl
return 0 if error
------------------------------------------------------------------------- */
int PairEIM::grabpair(FILE *fptr, int i, int j)
{
char line[MAXLINE];
rewind(fptr);
int ij;
if (i == j) ij = i;
else if (i < j) ij = nelements*(i+1) - (i+1)*(i+2)/2 + j;
else ij = nelements*(j+1) - (j+1)*(j+2)/2 + i;
char *pch1 = NULL, *pch2 = NULL, *pch3 = NULL, *data = NULL;
while (pch1 == NULL || pch2 == NULL || pch3 == NULL) {
if (fgets(line,MAXLINE,fptr) == NULL) break;
pch1 = strtok (line," \t\n\r\f");
pch1 = strstr(pch1,"pair:");
if (pch1 != NULL) {
pch2 = strtok (NULL, " \t\n\r\f");
if (pch2 != NULL) pch3 = strtok (NULL, " \t\n\r\f");
if (pch3 != NULL) data = strtok (NULL, "?");
if ((strcmp(pch2,elements[i]) == 0 &&
strcmp(pch3,elements[j]) == 0) ||
(strcmp(pch2,elements[j]) == 0 &&
strcmp(pch3,elements[i]) == 0)) {
sscanf(data,"%lg %lg %lg %lg %lg",
&setfl->rcutphiA[ij],&setfl->rcutphiR[ij],
&setfl->Eb[ij],&setfl->r0[ij],&setfl->alpha[ij]);
fgets(line,MAXLINE,fptr);
sscanf(line,"%lg %lg %lg %lg %lg",
&setfl->beta[ij],&setfl->rcutq[ij],&setfl->Asigma[ij],
&setfl->rq[ij],&setfl->rcutsigma[ij]);
fgets(line,MAXLINE,fptr);
sscanf(line,"%lg %lg %lg %d",
&setfl->Ac[ij],&setfl->zeta[ij],&setfl->rs[ij],
&setfl->tp[ij]);
} else {
pch1 = NULL;
pch2 = NULL;
pch3 = NULL;
}
}
}
if (pch1 == NULL || pch2 == NULL || pch3 == NULL) return 0;
return 1;
}
/* ----------------------------------------------------------------------
cutoff function
------------------------------------------------------------------------- */
double PairEIM::funccutoff(double rp, double rc, double r)
{
double rbig = setfl->rbig;
double rsmall = setfl->rsmall;
double a = (rsmall-rbig)/(rc-rp)*(r-rp)+rbig;
a = erfc(a);
double b = erfc(rbig);
double c = erfc(rsmall);
return (a-c)/(b-c);
}
/* ----------------------------------------------------------------------
pair interaction function phi
------------------------------------------------------------------------- */
double PairEIM::funcphi(int i, int j, double r)
{
int ij;
double value = 0.0;
if (i == j) ij = i;
else if (i < j) ij = nelements*(i+1) - (i+1)*(i+2)/2 + j;
else ij = nelements*(j+1) - (j+1)*(j+2)/2 + i;
if (r < 0.2) r = 0.2;
if (setfl->tp[ij] == 1) {
double a = setfl->Eb[ij]*setfl->alpha[ij] /
(setfl->beta[ij]-setfl->alpha[ij]);
double b = setfl->Eb[ij]*setfl->beta[ij] /
(setfl->beta[ij]-setfl->alpha[ij]);
if (r < setfl->rcutphiA[ij]) {
value -= a*exp(-setfl->beta[ij]*(r/setfl->r0[ij]-1.0))*
funccutoff(setfl->r0[ij],setfl->rcutphiA[ij],r);
}
if (r < setfl-> rcutphiR[ij]) {
value += b*exp(-setfl->alpha[ij]*(r/setfl->r0[ij]-1.0))*
funccutoff(setfl->r0[ij],setfl->rcutphiR[ij],r);
}
} else if (setfl->tp[ij] == 2) {
double a=setfl->Eb[ij]*setfl->alpha[ij]*pow(setfl->r0[ij],setfl->beta[ij])/
(setfl->beta[ij]-setfl->alpha[ij]);
double b=a*setfl->beta[ij]/setfl->alpha[ij]*
pow(setfl->r0[ij],setfl->alpha[ij]-setfl->beta[ij]);
if (r < setfl->rcutphiA[ij]) {
value -= a/pow(r,setfl->beta[ij])*
funccutoff(setfl->r0[ij],setfl->rcutphiA[ij],r);
}
if (r < setfl-> rcutphiR[ij]) {
value += b/pow(r,setfl->alpha[ij])*
funccutoff(setfl->r0[ij],setfl->rcutphiR[ij],r);
}
}
return value;
}
/* ----------------------------------------------------------------------
ion propensity function sigma
------------------------------------------------------------------------- */
double PairEIM::funcsigma(int i, int j, double r)
{
int ij;
double value = 0.0;
if (i == j) ij = i;
else if (i < j) ij = nelements*(i+1) - (i+1)*(i+2)/2 + j;
else ij = nelements*(j+1) - (j+1)*(j+2)/2 + i;
if (r < 0.2) r = 0.2;
if (r < setfl->rcutq[ij]) {
value = setfl->Asigma[ij]*(setfl->negativity[j]-setfl->negativity[i]) *
funccutoff(setfl->rq[ij],setfl->rcutq[ij],r);
}
return value;
}
/* ----------------------------------------------------------------------
charge-charge interaction function sigma
------------------------------------------------------------------------- */
double PairEIM::funccoul(int i, int j, double r)
{
int ij;
double value = 0.0;
if (i == j) ij = i;
else if (i < j) ij = nelements*(i+1) - (i+1)*(i+2)/2 + j;
else ij = nelements*(j+1) - (j+1)*(j+2)/2 + i;
if (r < 0.2) r = 0.2;
if (r < setfl->rcutsigma[ij]) {
value = setfl->Ac[ij]*exp(-setfl->zeta[ij]*r)*
funccutoff(setfl->rs[ij],setfl->rcutsigma[ij],r);
}
return value;
}
/* ---------------------------------------------------------------------- */
int PairEIM::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
if (rhofp == 1) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = rho[j];
}
}
if (rhofp == 2) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = fp[j];
}
}
return 1;
}
/* ---------------------------------------------------------------------- */
void PairEIM::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (rhofp == 1) {
for (i = first; i < last; i++) rho[i] = buf[m++];
}
if (rhofp == 2) {
for (i = first; i < last; i++) fp[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int PairEIM::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (rhofp == 1) {
for (i = first; i < last; i++) buf[m++] = rho[i];
}
if (rhofp == 2) {
for (i = first; i < last; i++) buf[m++] = fp[i];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void PairEIM::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
if (rhofp == 1) {
for (i = 0; i < n; i++) {
j = list[i];
rho[j] += buf[m++];
}
}
if (rhofp == 2) {
for (i = 0; i < n; i++) {
j = list[i];
fp[j] += buf[m++];
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairEIM::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
bytes += 2 * nmax * sizeof(double);
return bytes;
}
diff --git a/src/MANYBODY/pair_rebo.cpp b/src/MANYBODY/pair_rebo.cpp
index 5a73f7bda..efda8c2c9 100644
--- a/src/MANYBODY/pair_rebo.cpp
+++ b/src/MANYBODY/pair_rebo.cpp
@@ -1,34 +1,34 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "pair_rebo.h"
#include "force.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairREBO::PairREBO(LAMMPS *lmp) : PairAIREBO(lmp) {}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairREBO::settings(int narg, char **arg)
{
- if (narg != 0) error->all("Illegal pair_style command");
+ if (narg != 0) error->all(FLERR,"Illegal pair_style command");
cutlj = 0.0;
ljflag = torflag = 0;
}
diff --git a/src/MANYBODY/pair_sw.cpp b/src/MANYBODY/pair_sw.cpp
index c0661cc1a..1c708564a 100755
--- a/src/MANYBODY/pair_sw.cpp
+++ b/src/MANYBODY/pair_sw.cpp
@@ -1,602 +1,602 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_sw.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "force.h"
#include "comm.h"
#include "memory.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
#define DELTA 4
/* ---------------------------------------------------------------------- */
PairSW::PairSW(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
nelements = 0;
elements = NULL;
nparams = maxparam = 0;
params = NULL;
elem2param = NULL;
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairSW::~PairSW()
{
if (elements)
for (int i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
memory->destroy(params);
memory->destroy(elem2param);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
}
}
/* ---------------------------------------------------------------------- */
void PairSW::compute(int eflag, int vflag)
{
int i,j,k,ii,jj,kk,inum,jnum,jnumm1,itag,jtag;
int itype,jtype,ktype,ijparam,ikparam,ijkparam;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,rsq1,rsq2;
double delr1[3],delr2[3],fj[3],fk[3];
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *tag = atom->tag;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over full neighbor list of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
itype = map[type[i]];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// two-body interactions, skip half of them
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
jtype = map[type[j]];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
ijparam = elem2param[itype][jtype][jtype];
if (rsq > params[ijparam].cutsq) continue;
twobody(&params[ijparam],rsq,fpair,eflag,evdwl);
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
jnumm1 = jnum - 1;
for (jj = 0; jj < jnumm1; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = map[type[j]];
ijparam = elem2param[itype][jtype][jtype];
delr1[0] = x[j][0] - xtmp;
delr1[1] = x[j][1] - ytmp;
delr1[2] = x[j][2] - ztmp;
rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2];
if (rsq1 > params[ijparam].cutsq) continue;
for (kk = jj+1; kk < jnum; kk++) {
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
ikparam = elem2param[itype][ktype][ktype];
ijkparam = elem2param[itype][jtype][ktype];
delr2[0] = x[k][0] - xtmp;
delr2[1] = x[k][1] - ytmp;
delr2[2] = x[k][2] - ztmp;
rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
if (rsq2 > params[ikparam].cutsq) continue;
threebody(&params[ijparam],&params[ikparam],&params[ijkparam],
rsq1,rsq2,delr1,delr2,fj,fk,eflag,evdwl);
f[i][0] -= fj[0] + fk[0];
f[i][1] -= fj[1] + fk[1];
f[i][2] -= fj[2] + fk[2];
f[j][0] += fj[0];
f[j][1] += fj[1];
f[j][2] += fj[2];
f[k][0] += fk[0];
f[k][1] += fk[1];
f[k][2] += fk[2];
if (evflag) ev_tally3(i,j,k,evdwl,0.0,fj,fk,delr1,delr2);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairSW::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSW::settings(int narg, char **arg)
{
- if (narg != 0) error->all("Illegal pair_style command");
+ if (narg != 0) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSW::coeff(int narg, char **arg)
{
int i,j,n;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// 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;
}
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++;
}
}
// read potential file and initialize potential parameters
read_file(arg[2]);
setup();
// 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;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairSW::init_style()
{
if (atom->tag_enable == 0)
- error->all("Pair style Stillinger-Weber requires atom IDs");
+ error->all(FLERR,"Pair style Stillinger-Weber requires atom IDs");
if (force->newton_pair == 0)
- error->all("Pair style Stillinger-Weber requires newton pair on");
+ error->all(FLERR,"Pair style Stillinger-Weber requires newton pair on");
// need a full neighbor list
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSW::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
return cutmax;
}
/* ---------------------------------------------------------------------- */
void PairSW::read_file(char *file)
{
int params_per_line = 14;
char **words = new char*[params_per_line+1];
memory->sfree(params);
params = NULL;
nparams = maxparam = 0;
// open file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open Stillinger-Weber potential file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read each set of params from potential file
// one set of params can span multiple lines
// store params if all 3 element tags are in element list
int n,nwords,ielement,jelement,kelement;
char line[MAXLINE],*ptr;
int eof = 0;
while (1) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
if (nwords == 0) continue;
// concatenate additional lines until have params_per_line words
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n],MAXLINE-n,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
}
if (nwords != params_per_line)
- error->all("Incorrect format in Stillinger-Weber potential file");
+ error->all(FLERR,"Incorrect format in Stillinger-Weber potential file");
// words = ptrs to all words in line
nwords = 0;
words[nwords++] = strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next entry in file
for (ielement = 0; ielement < nelements; ielement++)
if (strcmp(words[0],elements[ielement]) == 0) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (strcmp(words[1],elements[jelement]) == 0) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (strcmp(words[2],elements[kelement]) == 0) break;
if (kelement == nelements) continue;
// load up parameter settings and error check their values
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].epsilon = atof(words[3]);
params[nparams].sigma = atof(words[4]);
params[nparams].littlea = atof(words[5]);
params[nparams].lambda = atof(words[6]);
params[nparams].gamma = atof(words[7]);
params[nparams].costheta = atof(words[8]);
params[nparams].biga = atof(words[9]);
params[nparams].bigb = atof(words[10]);
params[nparams].powerp = atof(words[11]);
params[nparams].powerq = atof(words[12]);
params[nparams].tol = atof(words[13]);
if (params[nparams].epsilon < 0.0 || params[nparams].sigma < 0.0 ||
params[nparams].littlea < 0.0 || params[nparams].lambda < 0.0 ||
params[nparams].gamma < 0.0 || params[nparams].biga < 0.0 ||
params[nparams].bigb < 0.0 || params[nparams].powerp < 0.0 ||
params[nparams].powerq < 0.0 || params[nparams].tol < 0.0)
- error->all("Illegal Stillinger-Weber parameter");
+ error->all(FLERR,"Illegal Stillinger-Weber parameter");
nparams++;
}
delete [] words;
}
/* ---------------------------------------------------------------------- */
void PairSW::setup()
{
int i,j,k,m,n;
double rtmp;
// set elem2param for all triplet combinations
// must be a single exact match to lines read from file
// do not allow for ACB in place of ABC
memory->destroy(elem2param);
memory->create(elem2param,nelements,nelements,nelements,"pair:elem2param");
for (i = 0; i < nelements; i++)
for (j = 0; j < nelements; j++)
for (k = 0; k < nelements; k++) {
n = -1;
for (m = 0; m < nparams; m++) {
if (i == params[m].ielement && j == params[m].jelement &&
k == params[m].kelement) {
- if (n >= 0) error->all("Potential file has duplicate entry");
+ if (n >= 0) error->all(FLERR,"Potential file has duplicate entry");
n = m;
}
}
- if (n < 0) error->all("Potential file is missing an entry");
+ if (n < 0) error->all(FLERR,"Potential file is missing an entry");
elem2param[i][j][k] = n;
}
// compute parameter values derived from inputs
// set cutsq using shortcut to reduce neighbor list for accelerated
// calculations. cut must remain unchanged as it is a potential parameter
// (cut = a*sigma)
for (m = 0; m < nparams; m++) {
params[m].cut = params[m].sigma*params[m].littlea;
rtmp = params[m].cut;
if (params[m].tol > 0.0) {
if (params[m].tol > 0.01) params[m].tol = 0.01;
if (params[m].gamma < 1.0)
rtmp = rtmp +
params[m].gamma * params[m].sigma / log(params[m].tol);
else rtmp = rtmp +
params[m].sigma / log(params[m].tol);
}
params[m].cutsq = rtmp * rtmp;
params[m].sigma_gamma = params[m].sigma*params[m].gamma;
params[m].lambda_epsilon = params[m].lambda*params[m].epsilon;
params[m].lambda_epsilon2 = 2.0*params[m].lambda*params[m].epsilon;
params[m].c1 = params[m].biga*params[m].epsilon *
params[m].powerp*params[m].bigb *
pow(params[m].sigma,params[m].powerp);
params[m].c2 = params[m].biga*params[m].epsilon*params[m].powerq *
pow(params[m].sigma,params[m].powerq);
params[m].c3 = params[m].biga*params[m].epsilon*params[m].bigb *
pow(params[m].sigma,params[m].powerp+1.0);
params[m].c4 = params[m].biga*params[m].epsilon *
pow(params[m].sigma,params[m].powerq+1.0);
params[m].c5 = params[m].biga*params[m].epsilon*params[m].bigb *
pow(params[m].sigma,params[m].powerp);
params[m].c6 = params[m].biga*params[m].epsilon *
pow(params[m].sigma,params[m].powerq);
}
// set cutmax to max of all params
cutmax = 0.0;
for (m = 0; m < nparams; m++) {
rtmp = sqrt(params[m].cutsq);
if (rtmp > cutmax) cutmax = rtmp;
}
}
/* ---------------------------------------------------------------------- */
void PairSW::twobody(Param *param, double rsq, double &fforce,
int eflag, double &eng)
{
double r,rinvsq,rp,rq,rainv,rainvsq,expsrainv;
r = sqrt(rsq);
rinvsq = 1.0/rsq;
rp = pow(r,-param->powerp);
rq = pow(r,-param->powerq);
rainv = 1.0 / (r - param->cut);
rainvsq = rainv*rainv*r;
expsrainv = exp(param->sigma * rainv);
fforce = (param->c1*rp - param->c2*rq +
(param->c3*rp -param->c4*rq) * rainvsq) * expsrainv * rinvsq;
if (eflag) eng = (param->c5*rp - param->c6*rq) * expsrainv;
}
/* ---------------------------------------------------------------------- */
void PairSW::threebody(Param *paramij, Param *paramik, Param *paramijk,
double rsq1, double rsq2,
double *delr1, double *delr2,
double *fj, double *fk, int eflag, double &eng)
{
double r1,rinvsq1,rainv1,gsrainv1,gsrainvsq1,expgsrainv1;
double r2,rinvsq2,rainv2,gsrainv2,gsrainvsq2,expgsrainv2;
double rinv12,cs,delcs,delcssq,facexp,facrad,frad1,frad2;
double facang,facang12,csfacang,csfac1,csfac2;
r1 = sqrt(rsq1);
rinvsq1 = 1.0/rsq1;
rainv1 = 1.0/(r1 - paramij->cut);
gsrainv1 = paramij->sigma_gamma * rainv1;
gsrainvsq1 = gsrainv1*rainv1/r1;
expgsrainv1 = exp(gsrainv1);
r2 = sqrt(rsq2);
rinvsq2 = 1.0/rsq2;
rainv2 = 1.0/(r2 - paramik->cut);
gsrainv2 = paramik->sigma_gamma * rainv2;
gsrainvsq2 = gsrainv2*rainv2/r2;
expgsrainv2 = exp(gsrainv2);
rinv12 = 1.0/(r1*r2);
cs = (delr1[0]*delr2[0] + delr1[1]*delr2[1] + delr1[2]*delr2[2]) * rinv12;
delcs = cs - paramijk->costheta;
delcssq = delcs*delcs;
facexp = expgsrainv1*expgsrainv2;
// facrad = sqrt(paramij->lambda_epsilon*paramik->lambda_epsilon) *
// facexp*delcssq;
facrad = paramijk->lambda_epsilon * facexp*delcssq;
frad1 = facrad*gsrainvsq1;
frad2 = facrad*gsrainvsq2;
facang = paramijk->lambda_epsilon2 * facexp*delcs;
facang12 = rinv12*facang;
csfacang = cs*facang;
csfac1 = rinvsq1*csfacang;
fj[0] = delr1[0]*(frad1+csfac1)-delr2[0]*facang12;
fj[1] = delr1[1]*(frad1+csfac1)-delr2[1]*facang12;
fj[2] = delr1[2]*(frad1+csfac1)-delr2[2]*facang12;
csfac2 = rinvsq2*csfacang;
fk[0] = delr2[0]*(frad2+csfac2)-delr1[0]*facang12;
fk[1] = delr2[1]*(frad2+csfac2)-delr1[1]*facang12;
fk[2] = delr2[2]*(frad2+csfac2)-delr1[2]*facang12;
if (eflag) eng = facrad;
}
diff --git a/src/MANYBODY/pair_tersoff.cpp b/src/MANYBODY/pair_tersoff.cpp
index b6e881940..bd50ec9bd 100755
--- a/src/MANYBODY/pair_tersoff.cpp
+++ b/src/MANYBODY/pair_tersoff.cpp
@@ -1,797 +1,797 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_tersoff.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
#define DELTA 4
/* ---------------------------------------------------------------------- */
PairTersoff::PairTersoff(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
PI = 4.0*atan(1.0);
PI2 = 2.0*atan(1.0);
PI4 = atan(1.0);
nelements = 0;
elements = NULL;
nparams = maxparam = 0;
params = NULL;
elem2param = NULL;
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairTersoff::~PairTersoff()
{
if (elements)
for (int i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
memory->destroy(params);
memory->destroy(elem2param);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
}
}
/* ---------------------------------------------------------------------- */
void PairTersoff::compute(int eflag, int vflag)
{
int i,j,k,ii,jj,kk,inum,jnum;
int itag,jtag,itype,jtype,ktype,iparam_ij,iparam_ijk;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,rsq1,rsq2;
double delr1[3],delr2[3],fi[3],fj[3],fk[3];
double zeta_ij,prefactor;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = vflag_atom = 0;
double **x = atom->x;
double **f = atom->f;
int *tag = atom->tag;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over full neighbor list of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itag = tag[i];
itype = map[type[i]];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// two-body interactions, skip half of them
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < x[i][2]) continue;
if (x[j][2] == ztmp && x[j][1] < ytmp) continue;
if (x[j][2] == ztmp && x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
jtype = map[type[j]];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
iparam_ij = elem2param[itype][jtype][jtype];
if (rsq > params[iparam_ij].cutsq) continue;
repulsive(&params[iparam_ij],rsq,fpair,eflag,evdwl);
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
// three-body interactions
// skip immediately if I-J is not within cutoff
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = map[type[j]];
iparam_ij = elem2param[itype][jtype][jtype];
delr1[0] = x[j][0] - xtmp;
delr1[1] = x[j][1] - ytmp;
delr1[2] = x[j][2] - ztmp;
rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2];
if (rsq1 > params[iparam_ij].cutsq) continue;
// accumulate bondorder zeta for each i-j interaction via loop over k
zeta_ij = 0.0;
for (kk = 0; kk < jnum; kk++) {
if (jj == kk) continue;
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
iparam_ijk = elem2param[itype][jtype][ktype];
delr2[0] = x[k][0] - xtmp;
delr2[1] = x[k][1] - ytmp;
delr2[2] = x[k][2] - ztmp;
rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
if (rsq2 > params[iparam_ijk].cutsq) continue;
zeta_ij += zeta(&params[iparam_ijk],rsq1,rsq2,delr1,delr2);
}
// pairwise force due to zeta
force_zeta(&params[iparam_ij],rsq1,zeta_ij,fpair,prefactor,eflag,evdwl);
f[i][0] += delr1[0]*fpair;
f[i][1] += delr1[1]*fpair;
f[i][2] += delr1[2]*fpair;
f[j][0] -= delr1[0]*fpair;
f[j][1] -= delr1[1]*fpair;
f[j][2] -= delr1[2]*fpair;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,-fpair,-delr1[0],-delr1[1],-delr1[2]);
// attractive term via loop over k
for (kk = 0; kk < jnum; kk++) {
if (jj == kk) continue;
k = jlist[kk];
k &= NEIGHMASK;
ktype = map[type[k]];
iparam_ijk = elem2param[itype][jtype][ktype];
delr2[0] = x[k][0] - xtmp;
delr2[1] = x[k][1] - ytmp;
delr2[2] = x[k][2] - ztmp;
rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
if (rsq2 > params[iparam_ijk].cutsq) continue;
attractive(&params[iparam_ijk],prefactor,
rsq1,rsq2,delr1,delr2,fi,fj,fk);
f[i][0] += fi[0];
f[i][1] += fi[1];
f[i][2] += fi[2];
f[j][0] += fj[0];
f[j][1] += fj[1];
f[j][2] += fj[2];
f[k][0] += fk[0];
f[k][1] += fk[1];
f[k][2] += fk[2];
if (vflag_atom) v_tally3(i,j,k,fj,fk,delr1,delr2);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairTersoff::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairTersoff::settings(int narg, char **arg)
{
- if (narg != 0) error->all("Illegal pair_style command");
+ if (narg != 0) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairTersoff::coeff(int narg, char **arg)
{
int i,j,n;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// 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;
}
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++;
}
}
// read potential file and initialize potential parameters
read_file(arg[2]);
setup();
// 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;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairTersoff::init_style()
{
if (atom->tag_enable == 0)
- error->all("Pair style Tersoff requires atom IDs");
+ error->all(FLERR,"Pair style Tersoff requires atom IDs");
if (force->newton_pair == 0)
- error->all("Pair style Tersoff requires newton pair on");
+ error->all(FLERR,"Pair style Tersoff requires newton pair on");
// need a full neighbor list
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairTersoff::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
return cutmax;
}
/* ---------------------------------------------------------------------- */
void PairTersoff::read_file(char *file)
{
int params_per_line = 17;
char **words = new char*[params_per_line+1];
memory->sfree(params);
params = NULL;
nparams = maxparam = 0;
// open file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open Tersoff potential file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read each line out of file, skipping blank lines or leading '#'
// store line of params if all 3 element tags are in element list
int n,nwords,ielement,jelement,kelement;
char line[MAXLINE],*ptr;
int eof = 0;
while (1) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
if (nwords == 0) continue;
// concatenate additional lines until have params_per_line words
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n],MAXLINE-n,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
}
if (nwords != params_per_line)
- error->all("Incorrect format in Tersoff potential file");
+ error->all(FLERR,"Incorrect format in Tersoff potential file");
// words = ptrs to all words in line
nwords = 0;
words[nwords++] = strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next line
for (ielement = 0; ielement < nelements; ielement++)
if (strcmp(words[0],elements[ielement]) == 0) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (strcmp(words[1],elements[jelement]) == 0) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (strcmp(words[2],elements[kelement]) == 0) break;
if (kelement == nelements) continue;
// load up parameter settings and error check their values
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].powerm = atof(words[3]);
params[nparams].gamma = atof(words[4]);
params[nparams].lam3 = atof(words[5]);
params[nparams].c = atof(words[6]);
params[nparams].d = atof(words[7]);
params[nparams].h = atof(words[8]);
params[nparams].powern = atof(words[9]);
params[nparams].beta = atof(words[10]);
params[nparams].lam2 = atof(words[11]);
params[nparams].bigb = atof(words[12]);
params[nparams].bigr = atof(words[13]);
params[nparams].bigd = atof(words[14]);
params[nparams].lam1 = atof(words[15]);
params[nparams].biga = atof(words[16]);
// currently only allow m exponent of 1 or 3
params[nparams].powermint = int(params[nparams].powerm);
if (params[nparams].c < 0.0 || params[nparams].d < 0.0 ||
params[nparams].powern < 0.0 || params[nparams].beta < 0.0 ||
params[nparams].lam2 < 0.0 || params[nparams].bigb < 0.0 ||
params[nparams].bigr < 0.0 ||params[nparams].bigd < 0.0 ||
params[nparams].bigd > params[nparams].bigr ||
params[nparams].lam1 < 0.0 || params[nparams].biga < 0.0 ||
params[nparams].powerm - params[nparams].powermint != 0.0 ||
(params[nparams].powermint != 3 && params[nparams].powermint != 1) ||
params[nparams].gamma < 0.0)
- error->all("Illegal Tersoff parameter");
+ error->all(FLERR,"Illegal Tersoff parameter");
nparams++;
}
delete [] words;
}
/* ---------------------------------------------------------------------- */
void PairTersoff::setup()
{
int i,j,k,m,n;
// set elem2param for all element triplet combinations
// must be a single exact match to lines read from file
// do not allow for ACB in place of ABC
memory->destroy(elem2param);
memory->create(elem2param,nelements,nelements,nelements,"pair:elem2param");
for (i = 0; i < nelements; i++)
for (j = 0; j < nelements; j++)
for (k = 0; k < nelements; k++) {
n = -1;
for (m = 0; m < nparams; m++) {
if (i == params[m].ielement && j == params[m].jelement &&
k == params[m].kelement) {
- if (n >= 0) error->all("Potential file has duplicate entry");
+ if (n >= 0) error->all(FLERR,"Potential file has duplicate entry");
n = m;
}
}
- if (n < 0) error->all("Potential file is missing an entry");
+ if (n < 0) error->all(FLERR,"Potential file is missing an entry");
elem2param[i][j][k] = n;
}
// compute parameter values derived from inputs
for (m = 0; m < nparams; m++) {
params[m].cut = params[m].bigr + params[m].bigd;
params[m].cutsq = params[m].cut*params[m].cut;
params[m].c1 = pow(2.0*params[m].powern*1.0e-16,-1.0/params[m].powern);
params[m].c2 = pow(2.0*params[m].powern*1.0e-8,-1.0/params[m].powern);
params[m].c3 = 1.0/params[m].c2;
params[m].c4 = 1.0/params[m].c1;
}
// set cutmax to max of all params
cutmax = 0.0;
for (m = 0; m < nparams; m++)
if (params[m].cut > cutmax) cutmax = params[m].cut;
}
/* ---------------------------------------------------------------------- */
void PairTersoff::repulsive(Param *param, double rsq, double &fforce,
int eflag, double &eng)
{
double r,tmp_fc,tmp_fc_d,tmp_exp;
r = sqrt(rsq);
tmp_fc = ters_fc(r,param);
tmp_fc_d = ters_fc_d(r,param);
tmp_exp = exp(-param->lam1 * r);
fforce = -param->biga * tmp_exp * (tmp_fc_d - tmp_fc*param->lam1) / r;
if (eflag) eng = tmp_fc * param->biga * tmp_exp;
}
/* ---------------------------------------------------------------------- */
double PairTersoff::zeta(Param *param, double rsqij, double rsqik,
double *delrij, double *delrik)
{
double rij,rik,costheta,arg,ex_delr;
rij = sqrt(rsqij);
rik = sqrt(rsqik);
costheta = (delrij[0]*delrik[0] + delrij[1]*delrik[1] +
delrij[2]*delrik[2]) / (rij*rik);
if (param->powermint == 3) arg = pow(param->lam3 * (rij-rik),3.0);
else arg = param->lam3 * (rij-rik);
if (arg > 69.0776) ex_delr = 1.e30;
else if (arg < -69.0776) ex_delr = 0.0;
else ex_delr = exp(arg);
return ters_fc(rik,param) * ters_gijk(costheta,param) * ex_delr;
}
/* ---------------------------------------------------------------------- */
void PairTersoff::force_zeta(Param *param, double rsq, double zeta_ij,
double &fforce, double &prefactor,
int eflag, double &eng)
{
double r,fa,fa_d,bij;
r = sqrt(rsq);
fa = ters_fa(r,param);
fa_d = ters_fa_d(r,param);
bij = ters_bij(zeta_ij,param);
fforce = 0.5*bij*fa_d / r;
prefactor = -0.5*fa * ters_bij_d(zeta_ij,param);
if (eflag) eng = 0.5*bij*fa;
}
/* ----------------------------------------------------------------------
attractive term
use param_ij cutoff for rij test
use param_ijk cutoff for rik test
------------------------------------------------------------------------- */
void PairTersoff::attractive(Param *param, double prefactor,
double rsqij, double rsqik,
double *delrij, double *delrik,
double *fi, double *fj, double *fk)
{
double rij_hat[3],rik_hat[3];
double rij,rijinv,rik,rikinv;
rij = sqrt(rsqij);
rijinv = 1.0/rij;
vec3_scale(rijinv,delrij,rij_hat);
rik = sqrt(rsqik);
rikinv = 1.0/rik;
vec3_scale(rikinv,delrik,rik_hat);
ters_zetaterm_d(prefactor,rij_hat,rij,rik_hat,rik,fi,fj,fk,param);
}
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_fc(double r, Param *param)
{
double ters_R = param->bigr;
double ters_D = param->bigd;
if (r < ters_R-ters_D) return 1.0;
if (r > ters_R+ters_D) return 0.0;
return 0.5*(1.0 - sin(PI2*(r - ters_R)/ters_D));
}
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_fc_d(double r, Param *param)
{
double ters_R = param->bigr;
double ters_D = param->bigd;
if (r < ters_R-ters_D) return 0.0;
if (r > ters_R+ters_D) return 0.0;
return -(PI4/ters_D) * cos(PI2*(r - ters_R)/ters_D);
}
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_fa(double r, Param *param)
{
if (r > param->bigr + param->bigd) return 0.0;
return -param->bigb * exp(-param->lam2 * r) * ters_fc(r,param);
}
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_fa_d(double r, Param *param)
{
if (r > param->bigr + param->bigd) return 0.0;
return param->bigb * exp(-param->lam2 * r) *
(param->lam2 * ters_fc(r,param) - ters_fc_d(r,param));
}
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_bij(double zeta, Param *param)
{
double tmp = param->beta * zeta;
if (tmp > param->c1) return 1.0/sqrt(tmp);
if (tmp > param->c2)
return (1.0 - pow(tmp,-param->powern) / (2.0*param->powern))/sqrt(tmp);
if (tmp < param->c4) return 1.0;
if (tmp < param->c3)
return 1.0 - pow(tmp,param->powern)/(2.0*param->powern);
return pow(1.0 + pow(tmp,param->powern), -1.0/(2.0*param->powern));
}
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_bij_d(double zeta, Param *param)
{
double tmp = param->beta * zeta;
if (tmp > param->c1) return param->beta * -0.5*pow(tmp,-1.5);
if (tmp > param->c2)
return param->beta * (-0.5*pow(tmp,-1.5) *
(1.0 - 0.5*(1.0 + 1.0/(2.0*param->powern)) *
pow(tmp,-param->powern)));
if (tmp < param->c4) return 0.0;
if (tmp < param->c3)
return -0.5*param->beta * pow(tmp,param->powern-1.0);
double tmp_n = pow(tmp,param->powern);
return -0.5 * pow(1.0+tmp_n, -1.0-(1.0/(2.0*param->powern)))*tmp_n / zeta;
}
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_gijk(double costheta, Param *param)
{
double ters_c = param->c;
double ters_d = param->d;
return param->gamma*(1.0 + pow(ters_c/ters_d,2.0) -
pow(ters_c,2.0) / (pow(ters_d,2.0) + pow(param->h - costheta,2.0)));
};
/* ---------------------------------------------------------------------- */
double PairTersoff::ters_gijk_d(double costheta, Param *param)
{
double numerator = -2.0 * pow(param->c,2) * (param->h - costheta);
double denominator = pow(pow(param->d,2.0) +
pow(param->h - costheta,2.0),2.0);
return param->gamma*numerator/denominator;
}
/* ---------------------------------------------------------------------- */
void PairTersoff::ters_zetaterm_d(double prefactor,
double *rij_hat, double rij,
double *rik_hat, double rik,
double *dri, double *drj, double *drk,
Param *param)
{
double gijk,gijk_d,ex_delr,ex_delr_d,fc,dfc,cos_theta,tmp;
double dcosdri[3],dcosdrj[3],dcosdrk[3];
fc = ters_fc(rik,param);
dfc = ters_fc_d(rik,param);
if (param->powermint == 3) tmp = pow(param->lam3 * (rij-rik),3.0);
else tmp = param->lam3 * (rij-rik);
if (tmp > 69.0776) ex_delr = 1.e30;
else if (tmp < -69.0776) ex_delr = 0.0;
else ex_delr = exp(tmp);
if (param->powermint == 3)
ex_delr_d = 3.0*pow(param->lam3,3.0) * pow(rij-rik,2.0)*ex_delr;
else ex_delr_d = param->lam3 * ex_delr;
cos_theta = vec3_dot(rij_hat,rik_hat);
gijk = ters_gijk(cos_theta,param);
gijk_d = ters_gijk_d(cos_theta,param);
costheta_d(rij_hat,rij,rik_hat,rik,dcosdri,dcosdrj,dcosdrk);
// compute the derivative wrt Ri
// dri = -dfc*gijk*ex_delr*rik_hat;
// dri += fc*gijk_d*ex_delr*dcosdri;
// dri += fc*gijk*ex_delr_d*(rik_hat - rij_hat);
vec3_scale(-dfc*gijk*ex_delr,rik_hat,dri);
vec3_scaleadd(fc*gijk_d*ex_delr,dcosdri,dri,dri);
vec3_scaleadd(fc*gijk*ex_delr_d,rik_hat,dri,dri);
vec3_scaleadd(-fc*gijk*ex_delr_d,rij_hat,dri,dri);
vec3_scale(prefactor,dri,dri);
// compute the derivative wrt Rj
// drj = fc*gijk_d*ex_delr*dcosdrj;
// drj += fc*gijk*ex_delr_d*rij_hat;
vec3_scale(fc*gijk_d*ex_delr,dcosdrj,drj);
vec3_scaleadd(fc*gijk*ex_delr_d,rij_hat,drj,drj);
vec3_scale(prefactor,drj,drj);
// compute the derivative wrt Rk
// drk = dfc*gijk*ex_delr*rik_hat;
// drk += fc*gijk_d*ex_delr*dcosdrk;
// drk += -fc*gijk*ex_delr_d*rik_hat;
vec3_scale(dfc*gijk*ex_delr,rik_hat,drk);
vec3_scaleadd(fc*gijk_d*ex_delr,dcosdrk,drk,drk);
vec3_scaleadd(-fc*gijk*ex_delr_d,rik_hat,drk,drk);
vec3_scale(prefactor,drk,drk);
}
/* ---------------------------------------------------------------------- */
void PairTersoff::costheta_d(double *rij_hat, double rij,
double *rik_hat, double rik,
double *dri, double *drj, double *drk)
{
// first element is devative wrt Ri, second wrt Rj, third wrt Rk
double cos_theta = vec3_dot(rij_hat,rik_hat);
vec3_scaleadd(-cos_theta,rij_hat,rik_hat,drj);
vec3_scale(1.0/rij,drj,drj);
vec3_scaleadd(-cos_theta,rik_hat,rij_hat,drk);
vec3_scale(1.0/rik,drk,drk);
vec3_add(drj,drk,dri);
vec3_scale(-1.0,dri,dri);
};
diff --git a/src/MANYBODY/pair_tersoff_zbl.cpp b/src/MANYBODY/pair_tersoff_zbl.cpp
index dfa0da021..90ccfd9c1 100644
--- a/src/MANYBODY/pair_tersoff_zbl.cpp
+++ b/src/MANYBODY/pair_tersoff_zbl.cpp
@@ -1,285 +1,285 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL) - original Tersoff implementation
David Farrell (NWU) - ZBL addition
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_tersoff_zbl.h"
#include "atom.h"
#include "update.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
#define DELTA 4
/* ---------------------------------------------------------------------- */
PairTersoffZBL::PairTersoffZBL(LAMMPS *lmp) : PairTersoff(lmp)
{
// hard-wired constants in metal or real units
// a0 = Bohr radius
// epsilon0 = permittivity of vacuum = q / energy-distance units
// e = unit charge
// 1 Kcal/mole = 0.043365121 eV
if (strcmp(update->unit_style,"metal") == 0) {
global_a_0 = 0.529;
global_epsilon_0 = 0.00552635;
global_e = 1.0;
} else if (strcmp(update->unit_style,"real") == 0) {
global_a_0 = 0.529;
global_epsilon_0 = 0.00552635 * 0.043365121;
global_e = 1.0;
- } else error->all("Pair tersoff/zbl requires metal or real units");
+ } else error->all(FLERR,"Pair tersoff/zbl requires metal or real units");
}
/* ---------------------------------------------------------------------- */
void PairTersoffZBL::read_file(char *file)
{
int params_per_line = 21;
char **words = new char*[params_per_line+1];
delete [] params;
params = NULL;
nparams = 0;
// open file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open Tersoff potential file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read each line out of file, skipping blank lines or leading '#'
// store line of params if all 3 element tags are in element list
int n,nwords,ielement,jelement,kelement;
char line[MAXLINE],*ptr;
int eof = 0;
while (1) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
if (nwords == 0) continue;
// concatenate additional lines until have params_per_line words
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n],MAXLINE-n,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
}
if (nwords != params_per_line)
- error->all("Incorrect format in Tersoff potential file");
+ error->all(FLERR,"Incorrect format in Tersoff potential file");
// words = ptrs to all words in line
nwords = 0;
words[nwords++] = strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next line
for (ielement = 0; ielement < nelements; ielement++)
if (strcmp(words[0],elements[ielement]) == 0) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (strcmp(words[1],elements[jelement]) == 0) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (strcmp(words[2],elements[kelement]) == 0) break;
if (kelement == nelements) continue;
// load up parameter settings and error check their values
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].powerm = atof(words[3]);
params[nparams].gamma = atof(words[4]);
params[nparams].lam3 = atof(words[5]);
params[nparams].c = atof(words[6]);
params[nparams].d = atof(words[7]);
params[nparams].h = atof(words[8]);
params[nparams].powern = atof(words[9]);
params[nparams].beta = atof(words[10]);
params[nparams].lam2 = atof(words[11]);
params[nparams].bigb = atof(words[12]);
params[nparams].bigr = atof(words[13]);
params[nparams].bigd = atof(words[14]);
params[nparams].lam1 = atof(words[15]);
params[nparams].biga = atof(words[16]);
params[nparams].Z_i = atof(words[17]);
params[nparams].Z_j = atof(words[18]);
params[nparams].ZBLcut = atof(words[19]);
params[nparams].ZBLexpscale = atof(words[20]);
// currently only allow m exponent of 1 or 3
params[nparams].powermint = int(params[nparams].powerm);
if (
params[nparams].lam3 < 0.0 || params[nparams].c < 0.0 ||
params[nparams].d < 0.0 || params[nparams].powern < 0.0 ||
params[nparams].beta < 0.0 || params[nparams].lam2 < 0.0 ||
params[nparams].bigb < 0.0 || params[nparams].bigr < 0.0 ||
params[nparams].bigd < 0.0 ||
params[nparams].bigd > params[nparams].bigr ||
params[nparams].lam3 < 0.0 || params[nparams].biga < 0.0 ||
params[nparams].powerm - params[nparams].powermint != 0.0 ||
(params[nparams].powermint != 3 && params[nparams].powermint != 1) ||
params[nparams].gamma < 0.0 ||
params[nparams].Z_i < 1.0 || params[nparams].Z_j < 1.0 ||
params[nparams].ZBLcut < 0.0 || params[nparams].ZBLexpscale < 0.0)
- error->all("Illegal Tersoff parameter");
+ error->all(FLERR,"Illegal Tersoff parameter");
nparams++;
}
delete [] words;
}
/* ---------------------------------------------------------------------- */
void PairTersoffZBL::repulsive(Param *param, double rsq, double &fforce,
int eflag, double &eng)
{
double r,tmp_fc,tmp_fc_d,tmp_exp;
// Tersoff repulsive portion
r = sqrt(rsq);
tmp_fc = ters_fc(r,param);
tmp_fc_d = ters_fc_d(r,param);
tmp_exp = exp(-param->lam1 * r);
double fforce_ters = param->biga * tmp_exp * (tmp_fc_d - tmp_fc*param->lam1);
double eng_ters = tmp_fc * param->biga * tmp_exp;
// ZBL repulsive portion
double esq = pow(global_e,2.0);
double a_ij = (0.8854*global_a_0) /
(pow(param->Z_i,0.23) + pow(param->Z_j,0.23));
double premult = (param->Z_i * param->Z_j * esq)/(4.0*PI*global_epsilon_0);
double r_ov_a = r/a_ij;
double phi = 0.1818*exp(-3.2*r_ov_a) + 0.5099*exp(-0.9423*r_ov_a) +
0.2802*exp(-0.4029*r_ov_a) + 0.02817*exp(-0.2016*r_ov_a);
double dphi = (1.0/a_ij) * (-3.2*0.1818*exp(-3.2*r_ov_a) -
0.9423*0.5099*exp(-0.9423*r_ov_a) -
0.4029*0.2802*exp(-0.4029*r_ov_a) -
0.2016*0.02817*exp(-0.2016*r_ov_a));
double fforce_ZBL = premult*-pow(r,-2.0)* phi + premult*pow(r,-1.0)*dphi;
double eng_ZBL = premult*(1.0/r)*phi;
// combine two parts with smoothing by Fermi-like function
fforce = -(-F_fermi_d(r,param) * eng_ZBL +
(1.0 - F_fermi(r,param))*fforce_ZBL +
F_fermi_d(r,param)*eng_ters + F_fermi(r,param)*fforce_ters) / r;
if (eflag)
eng = (1.0 - F_fermi(r,param))*eng_ZBL + F_fermi(r,param)*eng_ters;
}
/* ---------------------------------------------------------------------- */
double PairTersoffZBL::ters_fa(double r, Param *param)
{
if (r > param->bigr + param->bigd) return 0.0;
return -param->bigb * exp(-param->lam2 * r) * ters_fc(r,param) *
F_fermi(r,param);
}
/* ---------------------------------------------------------------------- */
double PairTersoffZBL::ters_fa_d(double r, Param *param)
{
if (r > param->bigr + param->bigd) return 0.0;
return param->bigb * exp(-param->lam2 * r) *
(param->lam2 * ters_fc(r,param) * F_fermi(r,param) -
ters_fc_d(r,param) * F_fermi(r,param) - ters_fc(r,param) *
F_fermi_d(r,param));
}
/* ----------------------------------------------------------------------
Fermi-like smoothing function
------------------------------------------------------------------------- */
double PairTersoffZBL::F_fermi(double r, Param *param)
{
return 1.0 / (1.0 + exp(-param->ZBLexpscale*(r-param->ZBLcut)));
}
/* ----------------------------------------------------------------------
Fermi-like smoothing function derivative with respect to r
------------------------------------------------------------------------- */
double PairTersoffZBL::F_fermi_d(double r, Param *param)
{
return param->ZBLexpscale*exp(-param->ZBLexpscale*(r-param->ZBLcut)) /
pow(1.0 + exp(-param->ZBLexpscale*(r-param->ZBLcut)),2.0);
}
diff --git a/src/MC/fix_bond_break.cpp b/src/MC/fix_bond_break.cpp
index a4c44338d..888c247da 100755
--- a/src/MC/fix_bond_break.cpp
+++ b/src/MC/fix_bond_break.cpp
@@ -1,392 +1,389 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "fix_bond_break.h"
#include "update.h"
#include "respa.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixBondBreak::FixBondBreak(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix bond/break command");
+ if (narg < 6) error->all(FLERR,"Illegal fix bond/break command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix bond/break command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix bond/break command");
force_reneighbor = 1;
next_reneighbor = -1;
vector_flag = 1;
size_vector = 2;
global_freq = 1;
extvector = 0;
btype = atoi(arg[4]);
double cutoff = atof(arg[5]);
if (btype < 1 || btype > atom->nbondtypes)
- error->all("Invalid bond type in fix bond/break command");
- if (cutoff < 0.0) error->all("Illegal fix bond/break command");
+ error->all(FLERR,"Invalid bond type in fix bond/break command");
+ if (cutoff < 0.0) error->all(FLERR,"Illegal fix bond/break command");
cutsq = cutoff*cutoff;
// optional keywords
fraction = 1.0;
int seed = 12345;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"prob") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix bond/break command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix bond/break command");
fraction = atof(arg[iarg+1]);
seed = atoi(arg[iarg+2]);
if (fraction < 0.0 || fraction > 1.0)
- error->all("Illegal fix bond/break command");
- if (seed <= 0) error->all("Illegal fix bond/break command");
+ error->all(FLERR,"Illegal fix bond/break command");
+ if (seed <= 0) error->all(FLERR,"Illegal fix bond/break command");
iarg += 3;
- } else error->all("Illegal fix bond/break command");
+ } else error->all(FLERR,"Illegal fix bond/break command");
}
// error check
if (atom->molecular == 0)
- error->all("Cannot use fix bond/break with non-molecular systems");
+ error->all(FLERR,"Cannot use fix bond/break with non-molecular systems");
// initialize Marsaglia RNG with processor-unique seed
random = new RanMars(lmp,seed + me);
// set comm sizes needed by this fix
comm_forward = 2;
comm_reverse = 2;
// allocate arrays local to this fix
nmax = 0;
partner = NULL;
distsq = NULL;
// zero out stats
breakcount = 0;
breakcounttotal = 0;
}
/* ---------------------------------------------------------------------- */
FixBondBreak::~FixBondBreak()
{
delete random;
// delete locally stored arrays
memory->destroy(partner);
memory->destroy(distsq);
}
/* ---------------------------------------------------------------------- */
int FixBondBreak::setmask()
{
int mask = 0;
mask |= POST_INTEGRATE;
mask |= POST_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixBondBreak::init()
{
// require special bonds = 0,1,1
int flag = 0;
if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 ||
force->special_lj[3] != 1.0) flag = 1;
if (force->special_coul[1] != 0.0 || force->special_coul[2] != 1.0 ||
force->special_coul[3] != 1.0) flag = 1;
- if (flag) error->all("Fix bond/break requires special_bonds = 0,1,1");
+ if (flag) error->all(FLERR,"Fix bond/break requires special_bonds = 0,1,1");
// warn if angles, dihedrals, impropers are being used
if (force->angle || force->dihedral || force->improper) {
if (me == 0)
- error->warning("Broken bonds will not alter angles, "
+ error->warning(FLERR,"Broken bonds will not alter angles, "
"dihedrals, or impropers");
}
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixBondBreak::post_integrate()
{
int i,j,k,m,n,i1,i2,n1,n3,type;
double delx,dely,delz,rsq,min,max;
int *slist;
if (update->ntimestep % nevery) return;
// need updated ghost atom positions
comm->forward_comm();
// resize bond partner list and initialize it
// probability array overlays distsq array
// needs to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(partner);
memory->destroy(distsq);
nmax = atom->nmax;
memory->create(partner,nmax,"bond/break:partner");
memory->create(distsq,nmax,"bond/break:distsq");
probability = distsq;
}
int nlocal = atom->nlocal;
int nall = atom->nlocal + atom->nghost;
for (i = 0; i < nall; i++) {
partner[i] = 0;
distsq[i] = 0.0;
}
// loop over bond list
// setup possible partner list of bonds to break
double **x = atom->x;
int *tag = atom->tag;
int *mask = atom->mask;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
if (!(mask[i1] & groupbit)) continue;
if (!(mask[i2] & groupbit)) continue;
if (type != btype) continue;
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutsq) continue;
if (rsq > distsq[i1]) {
partner[i1] = tag[i2];
distsq[i1] = rsq;
}
if (rsq > distsq[i2]) {
partner[i2] = tag[i1];
distsq[i2] = rsq;
}
}
// reverse comm of partner info
if (force->newton_bond) comm->reverse_comm_fix(this);
// each atom now knows its winning partner
// for prob check, generate random value for each atom with a bond partner
// forward comm of partner and random value, so ghosts have it
if (fraction < 1.0) {
for (i = 0; i < nlocal; i++)
if (partner[i]) probability[i] = random->uniform();
}
comm->forward_comm_fix(this);
// break bonds
// if both atoms list each other as winning bond partner
// and probability constraint is satisfied
int **bond_type = atom->bond_type;
int **bond_atom = atom->bond_atom;
int *num_bond = atom->num_bond;
int **nspecial = atom->nspecial;
int **special = atom->special;
int nbreak = 0;
for (i = 0; i < nlocal; i++) {
if (partner[i] == 0) continue;
j = atom->map(partner[i]);
if (partner[j] != tag[i]) continue;
// apply probability constraint
// MIN,MAX insures values are added in same order on different procs
if (fraction < 1.0) {
min = MIN(probability[i],probability[j]);
max = MAX(probability[i],probability[j]);
if (0.5*(min+max) >= fraction) continue;
}
// delete bond from atom I if I stores it
// atom J will also do this
for (m = 0; m < num_bond[i]; m++) {
if (bond_atom[i][m] == partner[i]) {
for (k = m; k < num_bond[i]-1; k++) {
bond_atom[i][k] = bond_atom[i][k+1];
bond_type[i][k] = bond_type[i][k+1];
}
num_bond[i]--;
break;
}
}
// remove J from special bond list for atom I
// atom J will also do this
slist = special[i];
n1 = nspecial[i][0];
n3 = nspecial[i][2];
for (m = 0; m < n1; m++)
if (slist[m] == partner[i]) break;
for (; m < n3-1; m++) slist[m] = slist[m+1];
nspecial[i][0]--;
nspecial[i][1]--;
nspecial[i][2]--;
// count the broken bond once
if (tag[i] < tag[j]) nbreak++;
}
// tally stats
MPI_Allreduce(&nbreak,&breakcount,1,MPI_INT,MPI_SUM,world);
breakcounttotal += breakcount;
atom->nbonds -= breakcount;
// trigger reneighboring if any bonds were formed
if (breakcount) next_reneighbor = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void FixBondBreak::post_integrate_respa(int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_integrate();
}
/* ---------------------------------------------------------------------- */
int FixBondBreak::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = partner[j];
buf[m++] = probability[j];
}
return 2;
}
/* ---------------------------------------------------------------------- */
void FixBondBreak::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
partner[i] = static_cast<int> (buf[m++]);
probability[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int FixBondBreak::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = partner[i];
buf[m++] = distsq[i];
}
return 2;
}
/* ---------------------------------------------------------------------- */
void FixBondBreak::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
if (buf[m+1] > distsq[j]) {
partner[j] = static_cast<int> (buf[m++]);
distsq[j] = buf[m++];
} else m += 2;
}
}
/* ---------------------------------------------------------------------- */
double FixBondBreak::compute_vector(int n)
{
if (n == 1) return (double) breakcount;
return (double) breakcounttotal;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixBondBreak::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int);
bytes += nmax * sizeof(double);
return bytes;
}
diff --git a/src/MC/fix_bond_create.cpp b/src/MC/fix_bond_create.cpp
index 295f04981..042ff80db 100755
--- a/src/MC/fix_bond_create.cpp
+++ b/src/MC/fix_bond_create.cpp
@@ -1,617 +1,614 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "fix_bond_create.h"
#include "update.h"
#include "respa.h"
#include "atom.h"
#include "force.h"
#include "pair.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixBondCreate::FixBondCreate(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 8) error->all("Illegal fix bond/create command");
+ if (narg < 8) error->all(FLERR,"Illegal fix bond/create command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix bond/create command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix bond/create command");
force_reneighbor = 1;
next_reneighbor = -1;
vector_flag = 1;
size_vector = 2;
global_freq = 1;
extvector = 0;
iatomtype = atoi(arg[4]);
jatomtype = atoi(arg[5]);
double cutoff = atof(arg[6]);
btype = atoi(arg[7]);
if (iatomtype < 1 || iatomtype > atom->ntypes ||
jatomtype < 1 || jatomtype > atom->ntypes)
- error->all("Invalid atom type in fix bond/create command");
- if (cutoff < 0.0) error->all("Illegal fix bond/create command");
+ error->all(FLERR,"Invalid atom type in fix bond/create command");
+ if (cutoff < 0.0) error->all(FLERR,"Illegal fix bond/create command");
if (btype < 1 || btype > atom->nbondtypes)
- error->all("Invalid bond type in fix bond/create command");
+ error->all(FLERR,"Invalid bond type in fix bond/create command");
cutsq = cutoff*cutoff;
// optional keywords
imaxbond = 0;
inewtype = iatomtype;
jmaxbond = 0;
jnewtype = jatomtype;
fraction = 1.0;
int seed = 12345;
int iarg = 8;
while (iarg < narg) {
if (strcmp(arg[iarg],"iparam") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix bond/create command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix bond/create command");
imaxbond = atoi(arg[iarg+1]);
inewtype = atoi(arg[iarg+2]);
- if (imaxbond < 0) error->all("Illegal fix bond/create command");
+ if (imaxbond < 0) error->all(FLERR,"Illegal fix bond/create command");
if (inewtype < 1 || inewtype > atom->ntypes)
- error->all("Invalid atom type in fix bond/create command");
+ error->all(FLERR,"Invalid atom type in fix bond/create command");
iarg += 3;
} else if (strcmp(arg[iarg],"jparam") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix bond/create command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix bond/create command");
jmaxbond = atoi(arg[iarg+1]);
jnewtype = atoi(arg[iarg+2]);
- if (jmaxbond < 0) error->all("Illegal fix bond/create command");
+ if (jmaxbond < 0) error->all(FLERR,"Illegal fix bond/create command");
if (jnewtype < 1 || jnewtype > atom->ntypes)
- error->all("Invalid atom type in fix bond/create command");
+ error->all(FLERR,"Invalid atom type in fix bond/create command");
iarg += 3;
} else if (strcmp(arg[iarg],"prob") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix bond/create command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix bond/create command");
fraction = atof(arg[iarg+1]);
seed = atoi(arg[iarg+2]);
if (fraction < 0.0 || fraction > 1.0)
- error->all("Illegal fix bond/create command");
- if (seed <= 0) error->all("Illegal fix bond/create command");
+ error->all(FLERR,"Illegal fix bond/create command");
+ if (seed <= 0) error->all(FLERR,"Illegal fix bond/create command");
iarg += 3;
- } else error->all("Illegal fix bond/create command");
+ } else error->all(FLERR,"Illegal fix bond/create command");
}
// error check
if (atom->molecular == 0)
- error->all("Cannot use fix bond/create with non-molecular systems");
+ error->all(FLERR,"Cannot use fix bond/create with non-molecular systems");
if (iatomtype == jatomtype &&
((imaxbond != jmaxbond) || (inewtype != jnewtype)))
- error->all("Inconsistent iparam/jparam values in fix bond/create command");
+ error->all(FLERR,"Inconsistent iparam/jparam values in fix bond/create command");
// initialize Marsaglia RNG with processor-unique seed
random = new RanMars(lmp,seed + me);
// perform initial allocation of atom-based arrays
// register with Atom class
// bondcount values will be initialized in setup()
bondcount = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
countflag = 0;
// set comm sizes needed by this fix
comm_forward = 2;
comm_reverse = 2;
// allocate arrays local to this fix
nmax = 0;
partner = NULL;
distsq = NULL;
// zero out stats
createcount = 0;
createcounttotal = 0;
}
/* ---------------------------------------------------------------------- */
FixBondCreate::~FixBondCreate()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
delete random;
// delete locally stored arrays
memory->destroy(bondcount);
memory->destroy(partner);
memory->destroy(distsq);
}
/* ---------------------------------------------------------------------- */
int FixBondCreate::setmask()
{
int mask = 0;
mask |= POST_INTEGRATE;
mask |= POST_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixBondCreate::init()
{
// check cutoff for iatomtype,jatomtype
if (force->pair == NULL || cutsq > force->pair->cutsq[iatomtype][jatomtype])
- error->all("Fix bond/create cutoff is longer than pairwise cutoff");
+ error->all(FLERR,"Fix bond/create cutoff is longer than pairwise cutoff");
// require special bonds = 0,1,1
if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 ||
force->special_lj[3] != 1.0)
- error->all("Fix bond/create requires special_bonds lj = 0,1,1");
+ error->all(FLERR,"Fix bond/create requires special_bonds lj = 0,1,1");
if (atom->q_flag)
if (force->special_coul[1] != 0.0 || force->special_coul[2] != 1.0 ||
force->special_coul[3] != 1.0)
- error->all("Fix bond/create requires special_bonds coul = 0,1,1");
+ error->all(FLERR,"Fix bond/create requires special_bonds coul = 0,1,1");
// warn if angles, dihedrals, impropers are being used
if (force->angle || force->dihedral || force->improper) {
if (me == 0)
- error->warning("Created bonds will not create angles, "
+ error->warning(FLERR,"Created bonds will not create angles, "
"dihedrals, or impropers");
}
// need a half neighbor list, built when ever re-neighboring occurs
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixBondCreate::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void FixBondCreate::setup(int vflag)
{
int i,j,m;
// compute initial bondcount if this is first run
// can't do this earlier, like in constructor or init, b/c need ghost info
if (countflag) return;
countflag = 1;
// count bonds stored with each bond I own
// if newton bond is not set, just increment count on atom I
// if newton bond is set, also increment count on atom J even if ghost
// bondcount is long enough to tally ghost atom counts
int *num_bond = atom->num_bond;
int **bond_type = atom->bond_type;
int **bond_atom = atom->bond_atom;
int nlocal = atom->nlocal;
int nghost = atom->nghost;
int nall = nlocal + nghost;
int newton_bond = force->newton_bond;
for (i = 0; i < nall; i++) bondcount[i] = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < num_bond[i]; j++) {
if (bond_type[i][j] == btype) {
bondcount[i]++;
if (newton_bond) {
m = atom->map(bond_atom[i][j]);
if (m < 0)
- error->one("Could not count initial bonds in fix bond/create");
+ error->one(FLERR,"Could not count initial bonds in fix bond/create");
bondcount[m]++;
}
}
}
// if newton_bond is set, need to sum bondcount
commflag = 0;
if (newton_bond) comm->reverse_comm_fix(this);
}
/* ---------------------------------------------------------------------- */
void FixBondCreate::post_integrate()
{
int i,j,m,ii,jj,inum,jnum,itype,jtype,n1,n3,possible;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq,min,max;
int *ilist,*jlist,*numneigh,**firstneigh,*slist;
if (update->ntimestep % nevery) return;
// need updated ghost atom positions
comm->forward_comm();
// forward comm of bondcount, so ghosts have it
commflag = 0;
comm->forward_comm_fix(this);
// resize bond partner list and initialize it
// probability array overlays distsq array
// needs to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(partner);
memory->destroy(distsq);
nmax = atom->nmax;
memory->create(partner,nmax,"bond/create:partner");
memory->create(distsq,nmax,"bond/create:distsq");
probability = distsq;
}
int nlocal = atom->nlocal;
int nall = atom->nlocal + atom->nghost;
for (i = 0; i < nall; i++) {
partner[i] = 0;
distsq[i] = BIG;
}
// loop over neighbors of my atoms
// each atom sets one closest eligible partner atom ID to bond with
double **x = atom->x;
int *tag = atom->tag;
int *mask = atom->mask;
int *type = atom->type;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (!(mask[i] & groupbit)) continue;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
if (!(mask[j] & groupbit)) continue;
jtype = type[j];
possible = 0;
if (itype == iatomtype && jtype == jatomtype) {
if ((imaxbond == 0 || bondcount[i] < imaxbond) &&
(jmaxbond == 0 || bondcount[j] < jmaxbond))
possible = 1;
} else if (itype == jatomtype && jtype == iatomtype) {
if ((jmaxbond == 0 || bondcount[i] < jmaxbond) &&
(imaxbond == 0 || bondcount[j] < imaxbond))
possible = 1;
}
if (!possible) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq >= cutsq) continue;
if (rsq < distsq[i]) {
partner[i] = tag[j];
distsq[i] = rsq;
}
if (rsq < distsq[j]) {
partner[j] = tag[i];
distsq[j] = rsq;
}
}
}
// reverse comm of distsq and partner
// not needed if newton_pair off since I,J pair was seen by both procs
commflag = 1;
if (force->newton_pair) comm->reverse_comm_fix(this);
// each atom now knows its winning partner
// for prob check, generate random value for each atom with a bond partner
// forward comm of partner and random value, so ghosts have it
if (fraction < 1.0) {
for (i = 0; i < nlocal; i++)
if (partner[i]) probability[i] = random->uniform();
}
commflag = 1;
comm->forward_comm_fix(this);
// create bonds for atoms I own
// if other atom is owned by another proc, it should create same bond
// if both atoms list each other as winning bond partner
// and probability constraint is satisfied
int **bond_type = atom->bond_type;
int **bond_atom = atom->bond_atom;
int *num_bond = atom->num_bond;
int **nspecial = atom->nspecial;
int **special = atom->special;
int newton_bond = force->newton_bond;
int ncreate = 0;
for (i = 0; i < nlocal; i++) {
if (partner[i] == 0) continue;
j = atom->map(partner[i]);
if (partner[j] != tag[i]) continue;
// apply probability constraint
// MIN,MAX insures values are added in same order on different procs
if (fraction < 1.0) {
min = MIN(probability[i],probability[j]);
max = MAX(probability[i],probability[j]);
if (0.5*(min+max) >= fraction) continue;
}
// if newton_bond is set, only store with I or J
// if not newton_bond, store bond with both I and J
if (!newton_bond || tag[i] < tag[j]) {
if (num_bond[i] == atom->bond_per_atom)
- error->one("New bond exceeded bonds per atom in fix bond/create");
+ error->one(FLERR,"New bond exceeded bonds per atom in fix bond/create");
bond_type[i][num_bond[i]] = btype;
bond_atom[i][num_bond[i]] = tag[j];
num_bond[i]++;
}
// add a 1-2 neighbor to special bond list for atom I
// atom J will also do this
slist = special[i];
n1 = nspecial[i][0];
n3 = nspecial[i][2];
if (n3 == atom->maxspecial)
- error->one("New bond exceeded special list size in fix bond/create");
+ error->one(FLERR,"New bond exceeded special list size in fix bond/create");
for (m = n3; m > n1; m--) slist[m+1] = slist[m];
slist[n1] = tag[j];
nspecial[i][0]++;
nspecial[i][1]++;
nspecial[i][2]++;
// increment bondcount, convert atom to new type if limit reached
bondcount[i]++;
if (type[i] == iatomtype) {
if (bondcount[i] == imaxbond) type[i] = inewtype;
} else {
if (bondcount[i] == jmaxbond) type[i] = jnewtype;
}
// count the created bond once
if (tag[i] < tag[j]) ncreate++;
}
// tally stats
MPI_Allreduce(&ncreate,&createcount,1,MPI_INT,MPI_SUM,world);
createcounttotal += createcount;
atom->nbonds += createcount;
// trigger reneighboring if any bonds were formed
if (createcount) next_reneighbor = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void FixBondCreate::post_integrate_respa(int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_integrate();
}
/* ---------------------------------------------------------------------- */
int FixBondCreate::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
if (commflag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = bondcount[j];
}
return 1;
} else {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = partner[j];
buf[m++] = probability[j];
}
return 2;
}
}
/* ---------------------------------------------------------------------- */
void FixBondCreate::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (commflag == 0) {
for (i = first; i < last; i++)
bondcount[i] = static_cast<int> (buf[m++]);
} else {
for (i = first; i < last; i++) {
partner[i] = static_cast<int> (buf[m++]);
probability[i] = buf[m++];
}
}
}
/* ---------------------------------------------------------------------- */
int FixBondCreate::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (commflag == 0) {
for (i = first; i < last; i++)
buf[m++] = bondcount[i];
return 1;
} else {
for (i = first; i < last; i++) {
buf[m++] = distsq[i];
buf[m++] = partner[i];
}
return 2;
}
}
/* ---------------------------------------------------------------------- */
void FixBondCreate::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
if (commflag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
bondcount[j] += static_cast<int> (buf[m++]);
}
} else {
for (i = 0; i < n; i++) {
j = list[i];
if (buf[m] < distsq[j]) {
distsq[j] = buf[m++];
partner[j] = static_cast<int> (buf[m++]);
} else m += 2;
}
}
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixBondCreate::grow_arrays(int nmax)
{
memory->grow(bondcount,nmax,"bond/create:bondcount");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixBondCreate::copy_arrays(int i, int j)
{
bondcount[j] = bondcount[i];
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixBondCreate::pack_exchange(int i, double *buf)
{
buf[0] = bondcount[i];
return 1;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixBondCreate::unpack_exchange(int nlocal, double *buf)
{
bondcount[nlocal] = static_cast<int> (buf[0]);
return 1;
}
/* ---------------------------------------------------------------------- */
double FixBondCreate::compute_vector(int n)
{
if (n == 1) return (double) createcount;
return (double) createcounttotal;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixBondCreate::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax*2 * sizeof(int);
bytes += nmax * sizeof(double);
return bytes;
}
diff --git a/src/MC/fix_bond_swap.cpp b/src/MC/fix_bond_swap.cpp
index daf9b1350..1984f9f40 100644
--- a/src/MC/fix_bond_swap.cpp
+++ b/src/MC/fix_bond_swap.cpp
@@ -1,689 +1,689 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_bond_swap.h"
#include "atom.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "group.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "compute.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
#include "update.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixBondSwap::FixBondSwap(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal fix bond/swap command");
+ if (narg != 6) error->all(FLERR,"Illegal fix bond/swap command");
vector_flag = 1;
size_vector = 2;
global_freq = 1;
extvector = 0;
fraction = atof(arg[3]);
double cutoff = atof(arg[4]);
cutsq = cutoff*cutoff;
// initialize Marsaglia RNG with processor-unique seed
int seed = atoi(arg[5]);
random = new RanMars(lmp,seed + comm->me);
// create a new compute temp style
// id = fix-ID + temp, compute group = fix group
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = "all";
newarg[2] = "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// initialize atom list
nmax = 0;
alist = NULL;
naccept = foursome = 0;
}
/* ---------------------------------------------------------------------- */
FixBondSwap::~FixBondSwap()
{
delete random;
// delete temperature if fix created it
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
memory->destroy(alist);
}
/* ---------------------------------------------------------------------- */
int FixBondSwap::setmask()
{
int mask = 0;
mask |= PRE_NEIGHBOR;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixBondSwap::init()
{
// require an atom style with molecule IDs
if (atom->molecule == NULL)
- error->all("Must use atom style with molecule IDs with fix bond/swap");
+ error->all(FLERR,"Must use atom style with molecule IDs with fix bond/swap");
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix bond/swap does not exist");
+ error->all(FLERR,"Temperature ID for fix bond/swap does not exist");
temperature = modify->compute[icompute];
// pair and bonds must be defined
// no dihedral or improper potentials allowed
// special bonds must be 0 1 1
if (force->pair == NULL || force->bond == NULL)
- error->all("Fix bond/swap requires pair and bond styles");
+ error->all(FLERR,"Fix bond/swap requires pair and bond styles");
if (force->pair->single_enable == 0)
- error->all("Pair style does not support fix bond/swap");
+ error->all(FLERR,"Pair style does not support fix bond/swap");
if (force->angle == NULL && atom->nangles > 0 && comm->me == 0)
- error->warning("Fix bond/swap will ignore defined angles");
+ error->warning(FLERR,"Fix bond/swap will ignore defined angles");
if (force->dihedral || force->improper)
- error->all("Fix bond/swap cannot use dihedral or improper styles");
+ error->all(FLERR,"Fix bond/swap cannot use dihedral or improper styles");
if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 ||
force->special_lj[3] != 1.0)
- error->all("Fix bond/swap requires special_bonds = 0,1,1");
+ error->all(FLERR,"Fix bond/swap requires special_bonds = 0,1,1");
// need a half neighbor list, built when ever re-neighboring occurs
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
// zero out stats
naccept = foursome = 0;
angleflag = 0;
if (force->angle) angleflag = 1;
}
/* ---------------------------------------------------------------------- */
void FixBondSwap::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void FixBondSwap::pre_neighbor()
{
int i,j,ii,jj,m,inum,jnum;
int inext,iprev,ilast,jnext,jprev,jlast,ibond,iangle,jbond,jangle;
int itag,inexttag,iprevtag,ilasttag,jtag,jnexttag,jprevtag,jlasttag;
int ibondtype,jbondtype,iangletype,inextangletype,jangletype,jnextangletype;
int i1,i2,i3,j1,j2,j3,tmp;
int *ilist,*jlist,*numneigh,**firstneigh;
double delta,factor;
// compute current temp for Boltzmann factor test
double t_current = temperature->compute_scalar();
// local ptrs to atom arrays
int *tag = atom->tag;
int *mask = atom->mask;
int *molecule = atom->molecule;
int *num_bond = atom->num_bond;
int **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int *num_angle = atom->num_angle;
int **angle_atom1 = atom->angle_atom1;
int **angle_atom2 = atom->angle_atom2;
int **angle_atom3 = atom->angle_atom3;
int **angle_type = atom->angle_type;
int **nspecial = atom->nspecial;
int **special = atom->special;
int newton_bond = force->newton_bond;
int nlocal = atom->nlocal;
type = atom->type;
x = atom->x;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// randomize list of my owned atoms that are in fix group
// grow atom list if necessary
if (nlocal > nmax) {
memory->destroy(alist);
nmax = atom->nmax;
memory->create(alist,nmax,"bondswap:alist");
}
int neligible = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit)
alist[neligible++] = i;
}
for (i = 0; i < neligible; i++) {
j = static_cast<int> (random->uniform() * neligible);
tmp = alist[i];
alist[i] = alist[j];
alist[j] = tmp;
}
// examine ntest of my eligible atoms for potential swaps
// atom i is randomly selected via atom list
// look at all j neighbors of atom i
// atom j must be on-processor (j < nlocal)
// atom j must be in fix group
// i and j must be same distance from chain end (mol[i] = mol[j])
// NOTE: must use extra parens in if test on mask[j] & groupbit
int ntest = static_cast<int> (fraction * neligible);
int accept = 0;
for (int itest = 0; itest < ntest; itest++) {
i = alist[itest];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
if (j >= nlocal) continue;
if ((mask[j] & groupbit) == 0) continue;
if (molecule[i] != molecule[j]) continue;
// look at all bond partners of atoms i and j
// use num_bond for this, not special list, so also find bondtypes
// inext,jnext = bonded atoms
// inext,jnext must be on-processor (inext,jnext < nlocal)
// inext,jnext must be same dist from chain end (mol[inext] = mol[jnext])
// since swaps may occur between two ends of a single chain, insure
// the 4 atoms are unique (no duplicates): inext != jnext, inext != j
// all 4 old and new bonds must have length < cutoff
for (ibond = 0; ibond < num_bond[i]; ibond++) {
inext = atom->map(bond_atom[i][ibond]);
if (inext >= nlocal || inext < 0) continue;
ibondtype = bond_type[i][ibond];
for (jbond = 0; jbond < num_bond[j]; jbond++) {
jnext = atom->map(bond_atom[j][jbond]);
if (jnext >= nlocal || jnext < 0) continue;
jbondtype = bond_type[j][jbond];
if (molecule[inext] != molecule[jnext]) continue;
if (inext == jnext || inext == j) continue;
if (dist_rsq(i,inext) >= cutsq) continue;
if (dist_rsq(j,jnext) >= cutsq) continue;
if (dist_rsq(i,jnext) >= cutsq) continue;
if (dist_rsq(j,inext) >= cutsq) continue;
// if angles are enabled:
// find other atoms i,inext,j,jnext are in angles with
// and angletypes: i/j angletype, i/j nextangletype
// use num_angle for this, not special list, so also find angletypes
// 4 atoms consecutively along 1st chain: iprev,i,inext,ilast
// 4 atoms consecutively along 2nd chain: jprev,j,jnext,jlast
// prev or last atom can be non-existent at end of chain
// set prev/last = -1 in this case
// if newton bond = 0, then angles are stored by all 4 atoms
// so require that iprev,ilast,jprev,jlast be owned by this proc
// so all copies of angles can be updated if a swap takes place
if (angleflag) {
itag = tag[i];
inexttag = tag[inext];
jtag = tag[j];
jnexttag = tag[jnext];
iprev = -1;
for (iangle = 0; iangle < num_angle[i]; iangle++) {
i1 = angle_atom1[i][iangle];
i2 = angle_atom2[i][iangle];
i3 = angle_atom3[i][iangle];
if (i2 == itag && i3 == inexttag) iprev = atom->map(i1);
else if (i1 == inexttag && i2 == itag) iprev = atom->map(i3);
if (iprev >= 0) {
iangletype = angle_type[i][iangle];
break;
}
}
if (!newton_bond && iprev >= nlocal) continue;
ilast = -1;
for (iangle = 0; iangle < num_angle[inext]; iangle++) {
i1 = angle_atom1[inext][iangle];
i2 = angle_atom2[inext][iangle];
i3 = angle_atom3[inext][iangle];
if (i1 == itag && i2 == inexttag) ilast = atom->map(i3);
else if (i2 == inexttag && i3 == itag) ilast = atom->map(i1);
if (ilast >= 0) {
inextangletype = angle_type[inext][iangle];
break;
}
}
if (!newton_bond && ilast >= nlocal) continue;
jprev = -1;
for (jangle = 0; jangle < num_angle[j]; jangle++) {
j1 = angle_atom1[j][jangle];
j2 = angle_atom2[j][jangle];
j3 = angle_atom3[j][jangle];
if (j2 == jtag && j3 == jnexttag) jprev = atom->map(j1);
else if (j1 == jnexttag && j2 == jtag) jprev = atom->map(j3);
if (jprev >= 0) {
jangletype = angle_type[j][jangle];
break;
}
}
if (!newton_bond && jprev >= nlocal) continue;
jlast = -1;
for (jangle = 0; jangle < num_angle[jnext]; jangle++) {
j1 = angle_atom1[jnext][jangle];
j2 = angle_atom2[jnext][jangle];
j3 = angle_atom3[jnext][jangle];
if (j1 == jtag && j2 == jnexttag) jlast = atom->map(j3);
else if (j2 == jnexttag && j3 == jtag) jlast = atom->map(j1);
if (jlast >= 0) {
jnextangletype = angle_type[jnext][jangle];
break;
}
}
if (!newton_bond && jlast >= nlocal) continue;
}
// valid foursome found between 2 chains:
// chains = iprev-i-inext-ilast and jprev-j-jnext-jlast
// prev or last values are -1 if do not exist due to end of chain
// OK to call angle_eng with -1 atom, since just return 0.0
// current energy of foursome =
// E_nb(i,j) + E_nb(i,jnext) + E_nb(inext,j) + E_nb(inext,jnext) +
// E_bond(i,inext) + E_bond(j,jnext) +
// E_angle(iprev,i,inext) + E_angle(i,inext,ilast) +
// E_angle(jprev,j,jnext) + E_angle(j,jnext,jlast)
// new energy of foursome with swapped bonds =
// E_nb(i,j) + E_nb(i,inext) + E_nb(j,jnext) + E_nb(inext,jnext) +
// E_bond(i,jnext) + E_bond(j,inext) +
// E_angle(iprev,i,jnext) + E_angle(i,jnext,jlast) +
// E_angle(jprev,j,inext) + E_angle(j,inext,ilast)
// energy delta = add/subtract differing terms between 2 formulas
foursome++;
delta = pair_eng(i,inext) + pair_eng(j,jnext) -
pair_eng(i,jnext) - pair_eng(inext,j);
delta += bond_eng(ibondtype,i,jnext) + bond_eng(jbondtype,j,inext) -
bond_eng(ibondtype,i,inext) - bond_eng(jbondtype,j,jnext);
if (angleflag)
delta += angle_eng(iangletype,iprev,i,jnext) +
angle_eng(jnextangletype,i,jnext,jlast) +
angle_eng(jangletype,jprev,j,inext) +
angle_eng(inextangletype,j,inext,ilast) -
angle_eng(iangletype,iprev,i,inext) -
angle_eng(inextangletype,i,inext,ilast) -
angle_eng(jangletype,jprev,j,jnext) -
angle_eng(jnextangletype,j,jnext,jlast);
// if delta <= 0, accept swap
// if delta > 0, compute Boltzmann factor with current temperature
// only accept if greater than random value
// whether accept or not, exit test loop
if (delta < 0.0) accept = 1;
else {
factor = exp(-delta/force->boltz/t_current);
if (random->uniform() < factor) accept = 1;
}
goto done;
}
}
}
}
done:
if (!accept) return;
naccept++;
// change bond partners of affected atoms
// on atom i: bond i-inext changes to i-jnext
// on atom j: bond j-jnext changes to j-inext
// on atom inext: bond inext-i changes to inext-j
// on atom jnext: bond jnext-j changes to jnext-i
for (ibond = 0; ibond < num_bond[i]; ibond++)
if (bond_atom[i][ibond] == tag[inext]) bond_atom[i][ibond] = tag[jnext];
for (jbond = 0; jbond < num_bond[j]; jbond++)
if (bond_atom[j][jbond] == tag[jnext]) bond_atom[j][jbond] = tag[inext];
for (ibond = 0; ibond < num_bond[inext]; ibond++)
if (bond_atom[inext][ibond] == tag[i]) bond_atom[inext][ibond] = tag[j];
for (jbond = 0; jbond < num_bond[jnext]; jbond++)
if (bond_atom[jnext][jbond] == tag[j]) bond_atom[jnext][jbond] = tag[i];
// set global tags of 4 atoms in bonds
itag = tag[i];
inexttag = tag[inext];
jtag = tag[j];
jnexttag = tag[jnext];
// change 1st special neighbors of affected atoms: i,j,inext,jnext
// don't need to change 2nd/3rd special neighbors for any atom
// since special bonds = 0 1 1 means they are never used
for (m = 0; m < nspecial[i][0]; m++)
if (special[i][m] == inexttag) special[i][m] = jnexttag;
for (m = 0; m < nspecial[j][0]; m++)
if (special[j][m] == jnexttag) special[j][m] = inexttag;
for (m = 0; m < nspecial[inext][0]; m++)
if (special[inext][m] == itag) special[inext][m] = jtag;
for (m = 0; m < nspecial[jnext][0]; m++)
if (special[jnext][m] == jtag) special[jnext][m] = itag;
// done if no angles
if (!angleflag) return;
// set global tags of 4 additional atoms in angles, 0 if no angle
if (iprev >= 0) iprevtag = tag[iprev];
else iprevtag = 0;
if (ilast >= 0) ilasttag = tag[ilast];
else ilasttag = 0;
if (jprev >= 0) jprevtag = tag[jprev];
else jprevtag = 0;
if (jlast >= 0) jlasttag = tag[jlast];
else jlasttag = 0;
// change angle partners of affected atoms
// must check if each angle is stored as a-b-c or c-b-a
// on atom i:
// angle iprev-i-inext changes to iprev-i-jnext
// angle i-inext-ilast changes to i-jnext-jlast
// on atom j:
// angle jprev-j-jnext changes to jprev-j-inext
// angle j-jnext-jlast changes to j-inext-ilast
// on atom inext:
// angle iprev-i-inext changes to jprev-j-inext
// angle i-inext-ilast changes to j-inext-ilast
// on atom jnext:
// angle jprev-j-jnext changes to iprev-i-jnext
// angle j-jnext-jlast changes to i-jnext-jlast
for (iangle = 0; iangle < num_angle[i]; iangle++) {
i1 = angle_atom1[i][iangle];
i2 = angle_atom2[i][iangle];
i3 = angle_atom3[i][iangle];
if (i1 == iprevtag && i2 == itag && i3 == inexttag)
angle_atom3[i][iangle] = jnexttag;
else if (i1 == inexttag && i2 == itag && i3 == iprevtag)
angle_atom1[i][iangle] = jnexttag;
else if (i1 == itag && i2 == inexttag && i3 == ilasttag) {
angle_atom2[i][iangle] = jnexttag;
angle_atom3[i][iangle] = jlasttag;
} else if (i1 == ilasttag && i2 == inexttag && i3 == itag) {
angle_atom1[i][iangle] = jlasttag;
angle_atom2[i][iangle] = jnexttag;
}
}
for (jangle = 0; jangle < num_angle[j]; jangle++) {
j1 = angle_atom1[j][jangle];
j2 = angle_atom2[j][jangle];
j3 = angle_atom3[j][jangle];
if (j1 == jprevtag && j2 == jtag && j3 == jnexttag)
angle_atom3[j][jangle] = inexttag;
else if (j1 == jnexttag && j2 == jtag && j3 == jprevtag)
angle_atom1[j][jangle] = inexttag;
else if (j1 == jtag && j2 == jnexttag && j3 == jlasttag) {
angle_atom2[j][jangle] = inexttag;
angle_atom3[j][jangle] = ilasttag;
} else if (j1 == jlasttag && j2 == jnexttag && j3 == jtag) {
angle_atom1[j][jangle] = ilasttag;
angle_atom2[j][jangle] = inexttag;
}
}
for (iangle = 0; iangle < num_angle[inext]; iangle++) {
i1 = angle_atom1[inext][iangle];
i2 = angle_atom2[inext][iangle];
i3 = angle_atom3[inext][iangle];
if (i1 == iprevtag && i2 == itag && i3 == inexttag) {
angle_atom1[inext][iangle] = jprevtag;
angle_atom2[inext][iangle] = jtag;
} else if (i1 == inexttag && i2 == itag && i3 == iprevtag) {
angle_atom2[inext][iangle] = jtag;
angle_atom3[inext][iangle] = jprevtag;
} else if (i1 == itag && i2 == inexttag && i3 == ilasttag)
angle_atom1[inext][iangle] = jtag;
else if (i1 == ilasttag && i2 == inexttag && i3 == itag)
angle_atom3[inext][iangle] = jtag;
}
for (jangle = 0; jangle < num_angle[jnext]; jangle++) {
j1 = angle_atom1[jnext][jangle];
j2 = angle_atom2[jnext][jangle];
j3 = angle_atom3[jnext][jangle];
if (j1 == jprevtag && j2 == jtag && j3 == jnexttag) {
angle_atom1[jnext][jangle] = iprevtag;
angle_atom2[jnext][jangle] = itag;
} else if (j1 == jnexttag && j2 == jtag && j3 == jprevtag) {
angle_atom2[jnext][jangle] = itag;
angle_atom3[jnext][jangle] = iprevtag;
} else if (j1 == jtag && j2 == jnexttag && j3 == jlasttag)
angle_atom1[jnext][jangle] = itag;
else if (j1 == jlasttag && j2 == jnexttag && j3 == jtag)
angle_atom3[jnext][jangle] = itag;
}
// done if newton bond set
if (newton_bond) return;
// change angles stored by iprev,ilast,jprev,jlast
// on atom iprev: angle iprev-i-inext changes to iprev-i-jnext
// on atom jprev: angle jprev-j-jnext changes to jprev-j-inext
// on atom ilast: angle i-inext-ilast changes to j-inext-ilast
// on atom jlast: angle j-jnext-jlast changes to i-jnext-jlast
for (iangle = 0; iangle < num_angle[iprev]; iangle++) {
i1 = angle_atom1[iprev][iangle];
i2 = angle_atom2[iprev][iangle];
i3 = angle_atom3[iprev][iangle];
if (i1 == iprevtag && i2 == itag && i3 == inexttag)
angle_atom3[iprev][iangle] = jnexttag;
else if (i1 == inexttag && i2 == itag && i3 == iprevtag)
angle_atom1[iprev][iangle] = jnexttag;
}
for (jangle = 0; jangle < num_angle[jprev]; jangle++) {
j1 = angle_atom1[jprev][jangle];
j2 = angle_atom2[jprev][jangle];
j3 = angle_atom3[jprev][jangle];
if (j1 == jprevtag && j2 == jtag && j3 == jnexttag)
angle_atom3[jprev][jangle] = inexttag;
else if (j1 == jnexttag && j2 == jtag && j3 == jprevtag)
angle_atom1[jprev][jangle] = inexttag;
}
for (iangle = 0; iangle < num_angle[ilast]; iangle++) {
i1 = angle_atom1[ilast][iangle];
i2 = angle_atom2[ilast][iangle];
i3 = angle_atom3[ilast][iangle];
if (i1 == itag && i2 == inexttag && i3 == ilasttag)
angle_atom1[ilast][iangle] = jtag;
else if (i1 == ilasttag && i2 == inexttag && i3 == itag)
angle_atom3[ilast][iangle] = jtag;
}
for (jangle = 0; jangle < num_angle[jlast]; jangle++) {
j1 = angle_atom1[jlast][jangle];
j2 = angle_atom2[jlast][jangle];
j3 = angle_atom3[jlast][jangle];
if (j1 == jtag && j2 == jnexttag && j3 == jlasttag)
angle_atom1[jlast][jangle] = itag;
else if (j1 == jlasttag && j2 == jnexttag && j3 == jtag)
angle_atom3[jlast][jangle] = itag;
}
}
/* ---------------------------------------------------------------------- */
int FixBondSwap::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
return 2;
}
return 0;
}
/* ----------------------------------------------------------------------
compute squared distance between atoms I,J
must use minimum_image since J was found thru atom->map()
------------------------------------------------------------------------- */
double FixBondSwap::dist_rsq(int i, int j)
{
double delx = x[i][0] - x[j][0];
double dely = x[i][1] - x[j][1];
double delz = x[i][2] - x[j][2];
domain->minimum_image(delx,dely,delz);
return (delx*delx + dely*dely + delz*delz);
}
/* ----------------------------------------------------------------------
return pairwise interaction energy between atoms I,J
will always be full non-bond interaction, so factors = 1 in single() call
------------------------------------------------------------------------- */
double FixBondSwap::pair_eng(int i, int j)
{
double tmp;
double rsq = dist_rsq(i,j);
return force->pair->single(i,j,type[i],type[j],rsq,1.0,1.0,tmp);
}
/* ---------------------------------------------------------------------- */
double FixBondSwap::bond_eng(int btype, int i, int j)
{
double rsq = dist_rsq(i,j);
return force->bond->single(btype,rsq,i,j);
}
/* ---------------------------------------------------------------------- */
double FixBondSwap::angle_eng(int atype, int i, int j, int k)
{
// test for non-existent angle at end of chain
if (i == -1 || k == -1) return 0.0;
return force->angle->single(atype,i,j,k);
}
/* ----------------------------------------------------------------------
return bond swapping stats
n = 1 is # of swaps
n = 2 is # of attempted swaps
------------------------------------------------------------------------- */
double FixBondSwap::compute_vector(int n)
{
double one,all;
if (n == 0) one = naccept;
else one = foursome;
MPI_Allreduce(&one,&all,1,MPI_DOUBLE,MPI_SUM,world);
return all;
}
/* ----------------------------------------------------------------------
memory usage of alist
------------------------------------------------------------------------- */
double FixBondSwap::memory_usage()
{
double bytes = nmax * sizeof(int);
return bytes;
}
diff --git a/src/MC/fix_gcmc.cpp b/src/MC/fix_gcmc.cpp
index 9f3dfc5e8..9016a26b2 100644
--- a/src/MC/fix_gcmc.cpp
+++ b/src/MC/fix_gcmc.cpp
@@ -1,562 +1,562 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_gcmc.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "comm.h"
#include "group.h"
#include "domain.h"
#include "random_park.h"
#include "force.h"
#include "pair.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixGCMC::FixGCMC(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 11) error->all("Illegal fix GCMC command");
+ if (narg < 11) error->all(FLERR,"Illegal fix GCMC command");
vector_flag = 1;
size_vector = 6;
global_freq = 1;
extvector = 0;
restart_global = 1;
time_depend = 1;
// required args
nevery = atoi(arg[3]);
nexchanges = atoi(arg[4]);
nmcmoves = atoi(arg[5]);
ntype = atoi(arg[6]);
seed = atoi(arg[7]);
reservoir_temperature = atof(arg[8]);
chemical_potential = atof(arg[9]);
displace = atof(arg[10]);
if (ntype <= 0 || ntype > atom->ntypes)
- error->all("Invalid atom type in fix GCMC command");
- if (nexchanges < 0) error->all("Illegal fix GCMC command");
- if (nmcmoves < 0) error->all("Illegal fix GCMC command");
- if (seed <= 0) error->all("Illegal fix GCMC command");
- if (reservoir_temperature < 0.0) error->all("Illegal fix GCMC command");
- if (displace < 0.0) error->all("Illegal fix GCMC command");
+ error->all(FLERR,"Invalid atom type in fix GCMC command");
+ if (nexchanges < 0) error->all(FLERR,"Illegal fix GCMC command");
+ if (nmcmoves < 0) error->all(FLERR,"Illegal fix GCMC command");
+ if (seed <= 0) error->all(FLERR,"Illegal fix GCMC command");
+ if (reservoir_temperature < 0.0) error->all(FLERR,"Illegal fix GCMC command");
+ if (displace < 0.0) error->all(FLERR,"Illegal fix GCMC command");
// compute beta, lambda, sigma, and the zz factor
beta = 1.0/(force->boltz*reservoir_temperature);
double PI = 4.0*atan(1.0);
double gas_mass = atom->mass[ntype];
double lambda = sqrt(force->hplanck*force->hplanck/
(2.0*PI*gas_mass*force->mvv2e*
force->boltz*reservoir_temperature));
sigma = sqrt(force->boltz*reservoir_temperature/gas_mass/force->mvv2e);
zz = exp(beta*chemical_potential)/(pow(lambda,3));
// set defaults
molflag = 0;
// read options from end of input line
options(narg-11,&arg[11]);
// random number generator, same for all procs
random_equal = new RanPark(lmp,seed);
// random number generator, not the same for all procs
random_unequal = new RanPark(lmp,seed);
// compute the number of MC cycles that occur nevery timesteps
ncycles = nexchanges + nmcmoves;
// set up reneighboring
force_reneighbor = 1;
next_reneighbor = update->ntimestep + 1;
// zero out counters
nmove_attempts = 0.0;
nmove_successes = 0.0;
ndel_attempts = 0.0;
ndel_successes = 0.0;
ninsert_attempts = 0.0;
ninsert_successes = 0.0;
nmax = 0;
local_gas_list = NULL;
}
/* ---------------------------------------------------------------------- */
FixGCMC::~FixGCMC()
{
delete random_equal;
delete random_unequal;
memory->sfree(local_gas_list);
}
/* ---------------------------------------------------------------------- */
int FixGCMC::setmask()
{
int mask = 0;
mask |= PRE_EXCHANGE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixGCMC::init()
{
// check that no deletable atoms are in atom->firstgroup
// deleting such an atom would not leave firstgroup atoms first
int *type = atom->type;
if (atom->firstgroup >= 0) {
int *mask = atom->mask;
int nlocal = atom->nlocal;
int firstgroupbit = group->bitmask[atom->firstgroup];
int flag = 0;
for (int i = 0; i < nlocal; i++)
if ((type[i] == ntype) && (mask[i] && firstgroupbit)) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall)
- error->all("Cannot do GCMC on atoms in atom_modify first group");
+ error->all(FLERR,"Cannot do GCMC on atoms in atom_modify first group");
}
// if molflag not set, warn if any deletable atom has a mol ID
if (molflag == 0 && atom->molecule_flag) {
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int flag = 0;
for (int i = 0; i < nlocal; i++)
if (type[i] == ntype)
if (molecule[i]) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall && comm->me == 0)
- error->warning("Fix GCMC may delete atom with non-zero molecule ID");
+ error->warning(FLERR,"Fix GCMC may delete atom with non-zero molecule ID");
}
if (molflag && atom->molecule_flag == 0)
- error->all("Fix GCMC molecule command requires atom attribute molecule");
+ error->all(FLERR,"Fix GCMC molecule command requires atom attribute molecule");
- if (molflag != 0) error->all("Fix GCMC molecule feature does not yet work");
+ if (molflag != 0) error->all(FLERR,"Fix GCMC molecule feature does not yet work");
if (force->pair->single_enable == 0)
- error->all("Fix GCMC incompatible with given pair_style");
+ error->all(FLERR,"Fix GCMC incompatible with given pair_style");
}
/* ----------------------------------------------------------------------
attempt particle insertions and deletions
done before exchange, borders, reneighbor
so that ghost atoms and neighbor lists will be correct
------------------------------------------------------------------------- */
void FixGCMC::pre_exchange()
{
// just return if should not be called on this timestep
if (next_reneighbor != update->ntimestep) return;
if (domain->triclinic == 0) {
xlo = domain->boxlo[0];
xhi = domain->boxhi[0];
ylo = domain->boxlo[1];
yhi = domain->boxhi[1];
zlo = domain->boxlo[2];
zhi = domain->boxhi[2];
sublo = domain->sublo;
subhi = domain->subhi;
} else {
xlo = domain->boxlo_bound[0];
xhi = domain->boxhi_bound[0];
ylo = domain->boxlo_bound[1];
yhi = domain->boxhi_bound[1];
zlo = domain->boxlo_bound[2];
zhi = domain->boxhi_bound[2];
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
volume = domain->xprd * domain->yprd * domain->zprd;
// grow local_gas_list array if necessary
if (atom->nlocal > nmax) {
memory->sfree(local_gas_list);
nmax = atom->nmax;
local_gas_list = (int *) memory->smalloc(nmax*sizeof(int),
"GCMC:local_gas_list");
}
int *type = atom->type;
ngas_local = 0;
for (int i = 0; i < atom->nlocal; i++)
if (type[i] == ntype)
local_gas_list[ngas_local++] = i;
MPI_Allreduce(&ngas_local,&ngas,1,MPI_INT,MPI_SUM,world);
MPI_Scan(&ngas_local,&ngas_before,1,MPI_INT,MPI_SUM,world);
ngas_before -= ngas_local;
// perform ncycles MC cycles
for (int i = 0; i < ncycles; i++) {
int random_int_fraction =
static_cast<int>(random_equal->uniform()*ncycles) + 1;
if (random_int_fraction <= nmcmoves) {
attempt_move();
} else {
if (random_equal->uniform() < 0.5) attempt_deletion();
else attempt_insertion();
}
}
next_reneighbor = update->ntimestep + nevery;
}
/* ----------------------------------------------------------------------
choose particle randomly across all procs and attempt displacement
------------------------------------------------------------------------- */
void FixGCMC::attempt_move()
{
int i,iwhichglobal,iwhichlocal;
double rx,ry,rz;
double coord[3];
double **x = atom->x;
nmove_attempts += 1.0;
int success = 0;
iwhichglobal = static_cast<int> (ngas*random_equal->uniform());
if ((iwhichglobal >= ngas_before) &&
(iwhichglobal < ngas_before + ngas_local)) {
iwhichlocal = iwhichglobal - ngas_before;
i = local_gas_list[iwhichlocal];
double energy_before = energy(i,x[i]);
double rsq = 1.1;
while (rsq > 1.0) {
rx = 2*random_unequal->uniform() - 1.0;
ry = 2*random_unequal->uniform() - 1.0;
if (domain->dimension == 3) rz = 2*random_unequal->uniform() - 1.0;
else rz = 0.0;
rsq = rx*rx + ry*ry + rz*rz;
}
coord[0] = x[i][0] + displace*rx;
coord[1] = x[i][1] + displace*ry;
coord[2] = x[i][2] + displace*rz;
double energy_after = energy(i,coord);
if (random_unequal->uniform() < exp(-beta*(energy_after - energy_before))) {
x[i][0] = coord[0];
x[i][1] = coord[1];
x[i][2] = coord[2];
success = 1;
}
}
int success_all = 0;
MPI_Allreduce(&success,&success_all,1,MPI_INT,MPI_MAX,world);
if (success_all) {
nmove_successes += 1.0;
comm->borders();
}
}
/* ----------------------------------------------------------------------
attempt particle deletion
------------------------------------------------------------------------- */
void FixGCMC::attempt_deletion()
{
ndel_attempts += 1.0;
if (ngas == 0) return;
int i,iwhichglobal,iwhichlocal;
AtomVec *avec = atom->avec;
// choose particle randomly across all procs and delete it
// keep ngas, ngas_local, ngas_before, and local_gas_list current
// after each deletion
int success = 0;
iwhichglobal = static_cast<int> (ngas*random_equal->uniform());
if ((iwhichglobal >= ngas_before) &&
(iwhichglobal < ngas_before + ngas_local)) {
iwhichlocal = iwhichglobal - ngas_before;
i = local_gas_list[iwhichlocal];
double deletion_energy = energy(i,atom->x[i]);
if (random_unequal->uniform() <
ngas*exp(beta*deletion_energy)/(zz*volume)) {
avec->copy(atom->nlocal-1,i,1);
atom->nlocal--;
local_gas_list[iwhichlocal] = local_gas_list[ngas_local-1];
ngas_local--;
success = 1;
}
}
int success_all = 0;
MPI_Allreduce(&success,&success_all,1,MPI_INT,MPI_MAX,world);
if (success_all) {
ngas--;
ndel_successes += 1.0;
atom->natoms--;
if (iwhichglobal < ngas_before) ngas_before--;
comm->borders();
if (atom->tag_enable) {
atom->tag_extend();
if (atom->map_style) {
atom->map_init();
atom->map_set();
}
}
}
}
/* ----------------------------------------------------------------------
attempt particle insertion
------------------------------------------------------------------------- */
void FixGCMC::attempt_insertion()
{
int flag,success;
double coord[3],lamda[3];
double *newcoord;
ninsert_attempts += 1.0;
// choose random position for new atom within box
coord[0] = xlo + random_equal->uniform() * (xhi-xlo);
coord[1] = ylo + random_equal->uniform() * (yhi-ylo);
coord[2] = zlo + random_equal->uniform() * (zhi-zlo);
// check if new atom is in my sub-box or above it if I'm highest proc
// if so, add to my list via create_atom()
// initialize info about the atoms
// set group mask to "all" plus fix group
if (domain->triclinic) {
domain->x2lamda(coord,lamda);
newcoord = lamda;
} else newcoord = coord;
flag = 0;
if (newcoord[0] >= sublo[0] && newcoord[0] < subhi[0] &&
newcoord[1] >= sublo[1] && newcoord[1] < subhi[1] &&
newcoord[2] >= sublo[2] && newcoord[2] < subhi[2]) flag = 1;
success = 0;
if (flag) {
int nall = atom->nlocal + atom->nghost;
double insertion_energy = energy(nall,coord);
if (random_unequal->uniform() <
zz*volume*exp(-beta*insertion_energy)/(ngas+1)) {
atom->avec->create_atom(ntype,coord);
int m = atom->nlocal - 1;
atom->type[m] = ntype;
atom->mask[m] = 1 | groupbit;
atom->v[m][0] = random_unequal->gaussian()*sigma;
atom->v[m][1] = random_unequal->gaussian()*sigma;
atom->v[m][2] = random_unequal->gaussian()*sigma;
int nfix = modify->nfix;
Fix **fix = modify->fix;
for (int j = 0; j < nfix; j++)
if (fix[j]->create_attribute) fix[j]->set_arrays(m);
if (atom->nlocal > nmax) {
nmax = atom->nmax;
local_gas_list = (int *)
memory->srealloc(local_gas_list,nmax*sizeof(int),
"GCMC:local_gas_list");
}
local_gas_list[ngas_local] = atom->nlocal;
ngas_local++;
success = 1;
}
}
int success_all = 0;
MPI_Allreduce(&success,&success_all,1,MPI_INT,MPI_MAX,world);
if (success_all) {
ngas++;
ninsert_successes += 1.0;
MPI_Scan(&ngas_local,&ngas_before,1,MPI_INT,MPI_SUM,world);
ngas_before -= ngas_local;
comm->borders();
if (atom->tag_enable) {
atom->natoms++;
atom->tag_extend();
if (atom->map_style) {
atom->map_init();
atom->map_set();
}
}
}
}
/* ----------------------------------------------------------------------
compute particle's interaction energy with the rest of the system
------------------------------------------------------------------------- */
double FixGCMC::energy(int i, double *coord)
{
double delx,dely,delz,rsq;
double **x = atom->x;
int *type = atom->type;
int nall = atom->nlocal + atom->nghost;
pair = force->pair;
cutsq = force->pair->cutsq;
double fpair = 0.0;
double factor_coul = 1.0;
double factor_lj = 1.0;
double total_energy = 0.0;
for (int j = 0; j < nall; j++) {
if (i == j) continue;
delx = coord[0] - x[j][0];
dely = coord[1] - x[j][1];
delz = coord[2] - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
int jtype = type[j];
if (rsq < cutsq[ntype][jtype])
total_energy +=
pair->single(i,j,ntype,jtype,rsq,factor_coul,factor_lj,fpair);
}
return total_energy;
}
/* ----------------------------------------------------------------------
parse optional parameters at end of input line
------------------------------------------------------------------------- */
void FixGCMC::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal fix GCMC command");
+ if (narg < 0) error->all(FLERR,"Illegal fix GCMC command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"molecule") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix GCMC command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix GCMC command");
if (strcmp(arg[iarg+1],"no") == 0) molflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) molflag = 1;
- else error->all("Illegal fix evaporate command");
+ else error->all(FLERR,"Illegal fix evaporate command");
iarg += 2;
- } else error->all("Illegal fix GCMC command");
+ } else error->all(FLERR,"Illegal fix GCMC command");
}
}
/* ----------------------------------------------------------------------
return acceptance ratios
------------------------------------------------------------------------- */
double FixGCMC::compute_vector(int n)
{
if (n == 0) return nmove_attempts;
if (n == 1) return nmove_successes;
if (n == 2) return ndel_attempts;
if (n == 3) return ndel_successes;
if (n == 4) return ninsert_attempts;
if (n == 5) return ninsert_successes;
return 0.0;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixGCMC::memory_usage()
{
double bytes = nmax * sizeof(int);
return bytes;
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixGCMC::write_restart(FILE *fp)
{
int n = 0;
double list[4];
list[n++] = random_equal->state();
list[n++] = random_unequal->state();
list[n++] = next_reneighbor;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),n,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixGCMC::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
seed = static_cast<int> (list[n++]);
random_equal->reset(seed);
seed = static_cast<int> (list[n++]);
random_unequal->reset(seed);
next_reneighbor = static_cast<int> (list[n++]);
}
diff --git a/src/MC/pair_dsmc.cpp b/src/MC/pair_dsmc.cpp
index b04dd8f6d..39a0f5013 100644
--- a/src/MC/pair_dsmc.cpp
+++ b/src/MC/pair_dsmc.cpp
@@ -1,525 +1,522 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_dsmc.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
#include "domain.h"
#include "update.h"
#include "random_mars.h"
#include "limits.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairDSMC::PairDSMC(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
total_number_of_collisions = 0;
max_particles = max_particle_list = 0;
next_particle = NULL;
random = NULL;
}
/* ---------------------------------------------------------------------- */
PairDSMC::~PairDSMC()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(sigma);
memory->destroy(cut);
memory->destroy(V_sigma_max);
memory->destroy(particle_list);
memory->destroy(first);
memory->destroy(number);
}
delete [] next_particle;
delete random;
}
/* ---------------------------------------------------------------------- */
void PairDSMC::compute(int eflag, int vflag)
{
double **x = atom->x;
double *mass = atom->mass;
int *type = atom->type;
int nlocal = atom->nlocal;
for (int i = 1; i <= atom->ntypes; ++i)
for (int j = 0; j < total_ncells; ++j) {
first[i][j] = -1;
number[i][j] = 0;
}
if (atom->nmax > max_particles) {
delete [] next_particle;
max_particles = atom->nmax;
next_particle = new int[max_particles];
}
// find each particle's cell and sort by type
// assume a constant volume and shape simulation domain
// skip particle if outside processor domain
for (int i = 0; i < nlocal; ++i) {
int xcell = static_cast<int>((x[i][0] - domain->boxlo[0])/cellx);
int ycell = static_cast<int>((x[i][1] - domain->boxlo[1])/celly);
int zcell = static_cast<int>((x[i][2] - domain->boxlo[2])/cellz);
if ((xcell < 0) or (xcell > ncellsx-1) or
(ycell < 0) or (ycell > ncellsy-1) or
(zcell < 0) or (zcell > ncellsz-1)) continue;
int icell = xcell + ycell*ncellsx + zcell*ncellsx*ncellsy;
itype = type[i];
next_particle[i] = first[itype][icell];
first[itype][icell] = i;
number[itype][icell]++;
}
for (int icell = 0; icell < total_ncells; ++icell) {
for (itype = 1; itype <= atom->ntypes; ++itype) {
number_of_A = number[itype][icell];
if (number_of_A > max_particle_list) {
max_particle_list = number_of_A;
memory->grow(particle_list,atom->ntypes+1,max_particle_list,
"pair:particle_list");
}
int m = first[itype][icell];
for (int k = 0; k < number_of_A; k++) {
particle_list[itype][k] = m;
m = next_particle[m];
}
}
for (itype = 1; itype <= atom->ntypes; ++itype) {
imass = mass[itype];
number_of_A = number[itype][icell];
for (jtype = itype; jtype <= atom->ntypes; ++jtype) {
jmass = mass[jtype];
number_of_B = number[jtype][icell];
reduced_mass = imass*jmass/(imass + jmass);
total_mass = imass + jmass;
jmass_tmass = jmass/total_mass;
imass_tmass = imass/total_mass;
// if necessary, recompute V_sigma_max values
if (recompute_vsigmamax_stride &&
(update->ntimestep % recompute_vsigmamax_stride == 0))
recompute_V_sigma_max(icell);
// # of collisions to perform for itype-jtype pairs
double &Vs_max = V_sigma_max[itype][jtype];
double num_of_collisions_double = number_of_A * number_of_B *
weighting * Vs_max * update->dt / vol;
if ((itype == jtype) and number_of_B)
num_of_collisions_double *=
0.5 * double(number_of_B - 1) / double(number_of_B);
int num_of_collisions =
convert_double_to_equivalent_int(num_of_collisions_double);
if (num_of_collisions > number_of_A)
- error->warning("Pair dsmc: num_of_collisions > number_of_A",0);
+ error->warning(FLERR,"Pair dsmc: num_of_collisions > number_of_A",0);
if (num_of_collisions > number_of_B)
- error->warning("Pair dsmc: num_of_collisions > number_of_B",0);
+ error->warning(FLERR,"Pair dsmc: num_of_collisions > number_of_B",0);
// perform collisions on pairs of particles in icell
for (int k = 0; k < num_of_collisions; k++) {
if ((number_of_A < 1) or (number_of_B < 1)) break;
int ith_A = static_cast<int>(random->uniform()*number_of_A);
int jth_B = static_cast<int>(random->uniform()*number_of_B);
int i = particle_list[itype][ith_A];
int j = particle_list[jtype][jth_B];
if (i == j) {
k--;
continue;
}
double probability = V_sigma(i,j)/Vs_max;
if (probability > random->uniform()) scatter_random(i,j,icell);
}
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairDSMC::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(V_sigma_max,n+1,n+1,"pair:V_sigma_max");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairDSMC::settings(int narg, char **arg)
{
- if (narg != 6) error->all("Illegal pair_style command");
+ if (narg != 6) error->all(FLERR,"Illegal pair_style command");
cut_global = 0.0;
max_cell_size = force->numeric(arg[0]);
seed = force->inumeric(arg[1]);
weighting = force->numeric(arg[2]);
T_ref = force->numeric(arg[3]);
recompute_vsigmamax_stride = force->inumeric(arg[4]);
vsigmamax_samples = force->inumeric(arg[5]);
// initialize Marsaglia RNG with processor-unique seed
- if (max_cell_size <= 0.0) error->all("Illegal pair_style command");
- if (seed <= 0) error->all("Illegal pair_style command");
+ if (max_cell_size <= 0.0) error->all(FLERR,"Illegal pair_style command");
+ if (seed <= 0) error->all(FLERR,"Illegal pair_style command");
if (random) delete random;
random = new RanMars(lmp,seed + comm->me);
kT_ref = force->boltz*T_ref;
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairDSMC::coeff(int narg, char **arg)
{
- if (narg < 3 || narg > 4) error->all("Incorrect args for pair coefficients");
+ if (narg < 3 || narg > 4) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double sigma_one = force->numeric(arg[2]);
double cut_one = cut_global;
if (narg == 4) cut_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
sigma[i][j] = sigma_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairDSMC::init_style()
{
ncellsx = ncellsy = ncellsz = 1;
while (((domain->boxhi[0] - domain->boxlo[0])/ncellsx) > max_cell_size)
ncellsx++;
while (((domain->boxhi[1] - domain->boxlo[1])/ncellsy) > max_cell_size)
ncellsy++;
while (((domain->boxhi[2] - domain->boxlo[2])/ncellsz) > max_cell_size)
ncellsz++;
cellx = (domain->boxhi[0] - domain->boxlo[0])/ncellsx;
celly = (domain->boxhi[1] - domain->boxlo[1])/ncellsy;
cellz = (domain->boxhi[2] - domain->boxlo[2])/ncellsz;
if (comm->me == 0) {
if (screen) fprintf(screen,"DSMC cell size = %g x %g x %g\n",
cellx,celly,cellz);
if (logfile) fprintf(logfile,"DSMC cell size = %g x %g x %g\n",
cellx,celly,cellz);
}
total_ncells = ncellsx*ncellsy*ncellsz;
vol = cellx*celly*cellz;
memory->create(particle_list,atom->ntypes+1,0,"pair:particle_list");
memory->create(first,atom->ntypes+1,total_ncells,"pair:first");
memory->create(number,atom->ntypes+1,total_ncells,"pair:number");
for (int i = 1; i <= atom->ntypes; i++)
for (int j = 1; j <= atom->ntypes; j++)
V_sigma_max[i][j] = 0.0;
two_pi = 8.0*atan(1.0);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairDSMC::init_one(int i, int j)
{
if (setflag[i][j] == 0) cut[i][j] = 0.0;
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDSMC::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDSMC::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDSMC::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&max_cell_size,sizeof(double),1,fp);
fwrite(&seed,sizeof(int),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDSMC::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&max_cell_size,sizeof(double),1,fp);
fread(&seed,sizeof(int),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&max_cell_size,1,MPI_DOUBLE,0,world);
MPI_Bcast(&seed,1,MPI_INT,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
// initialize Marsaglia RNG with processor-unique seed
// same seed that pair_style command initially specified
if (random) delete random;
random = new RanMars(lmp,seed + comm->me);
}
/*-------------------------------------------------------------------------
rezero and recompute the V_sigma_max values this timestep for use during
the next nrezero timesteps
-------------------------------------------------------------------------*/
void PairDSMC::recompute_V_sigma_max(int icell)
{
int i,j,k;
double Vsigma_max = 0;
if (number_of_A && number_of_B) {
for (k = 0; k < vsigmamax_samples; k++) {
i = particle_list[itype]
[static_cast<int>(random->uniform()*number_of_A)];
j = particle_list[jtype]
[static_cast<int>(random->uniform()*number_of_B)];
if (i == j) continue;
Vsigma_max = MAX(Vsigma_max,V_sigma(i,j));
}
}
V_sigma_max[itype][jtype] = Vsigma_max;
}
/*-------------------------------------------------------------------------
VHS model
compute the velocity vector difference between i and j and multiply by
their combined collision cross section, sigma, for neutral-neutral
collisions using the Variable Hard Sphere model
-------------------------------------------------------------------------*/
double PairDSMC::V_sigma(int i, int j)
{
double relative_velocity_sq,relative_velocity,pair_sigma;
double delv[3];
double *vi = atom->v[i];
double *vj = atom->v[j];
subtract3d(vi,vj,delv);
relative_velocity_sq = dot3d(delv,delv);
relative_velocity = sqrt(relative_velocity_sq);
// from Bird eq 4.63, and omega=0.67
// (omega - 0.5) = 0.17
// 1/GAMMA(2.5 - omega) = 1.06418029298371
if (relative_velocity_sq != 0.0)
pair_sigma = sigma[itype][jtype]*
pow(kT_ref/(0.5*reduced_mass*relative_velocity_sq),0.17) *
1.06418029298371;
else
pair_sigma = 0.0;
return relative_velocity*pair_sigma;
}
/*-------------------------------------------------------------------------
generate new velocities for collided particles
-------------------------------------------------------------------------*/
void PairDSMC::scatter_random(int i, int j, int icell)
{
double mag_delv,cos_phi,cos_squared,r,theta;
double delv[3],vcm[3];
double *vi = atom->v[i];
double *vj = atom->v[j];
subtract3d(vi,vj,delv);
if (itype == jtype) mag_delv = sqrt(dot3d(delv,delv))*0.5;
else mag_delv = sqrt(dot3d(delv,delv));
cos_phi = 1.0 - (2.0*random->uniform());
cos_squared = MIN(1.0,cos_phi*cos_phi);
r = sqrt(1.0 - cos_squared);
delv[0] = cos_phi*mag_delv;
theta = two_pi*random->uniform();
delv[1] = r*mag_delv*cos(theta);
delv[2] = r*mag_delv*sin(theta);
if (itype == jtype) {
vcm[0] = (vi[0]+vj[0])*0.5;
vcm[1] = (vi[1]+vj[1])*0.5;
vcm[2] = (vi[2]+vj[2])*0.5;
vi[0] = vcm[0] + delv[0];
vi[1] = vcm[1] + delv[1];
vi[2] = vcm[2] + delv[2];
vj[0] = vcm[0] - delv[0];
vj[1] = vcm[1] - delv[1];
vj[2] = vcm[2] - delv[2];
} else {
vcm[0] = vi[0]*imass_tmass + vj[0]*jmass_tmass;
vcm[1] = vi[1]*imass_tmass + vj[1]*jmass_tmass;
vcm[2] = vi[2]*imass_tmass + vj[2]*jmass_tmass;
vi[0] = vcm[0] + delv[0]*jmass_tmass;
vi[1] = vcm[1] + delv[1]*jmass_tmass;
vi[2] = vcm[2] + delv[2]*jmass_tmass;
vj[0] = vcm[0] - delv[0]*imass_tmass;
vj[1] = vcm[1] - delv[1]*imass_tmass;
vj[2] = vcm[2] - delv[2]*imass_tmass;
}
total_number_of_collisions++;
}
/* ----------------------------------------------------------------------
This method converts the double supplied by the calling function into
an int, which is returned. By adding a random number between 0 and 1
to the double before converting it to an int, we ensure that,
statistically, we round down with probability identical to the
remainder and up the rest of the time. So even though we're using an
integer, we're statistically matching the exact expression represented
by the double.
------------------------------------------------------------------------- */
int PairDSMC::convert_double_to_equivalent_int(double input_double)
{
if (input_double > INT_MAX)
- error->all("Tried to convert a double to int, but input_double > INT_MAX");
+ error->all(FLERR,"Tried to convert a double to int, but input_double > INT_MAX");
int output_int = static_cast<int>(input_double + random->uniform());
return output_int;
}
diff --git a/src/MEAM/pair_meam.cpp b/src/MEAM/pair_meam.cpp
index 7c6fd9dbb..370a719a2 100644
--- a/src/MEAM/pair_meam.cpp
+++ b/src/MEAM/pair_meam.cpp
@@ -1,946 +1,943 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Greg Wagner (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_meam.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "memory.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define MAXLINE 1024
enum{FCC,BCC,HCP,DIM,DIAMOND,B1,C11,L12,B2};
int nkeywords = 21;
char *keywords[] = {"Ec","alpha","rho0","delta","lattce",
"attrac","repuls","nn2","Cmin","Cmax","rc","delr",
"augt1","gsmooth_factor","re","ialloy","mixture_ref_t",
"erose_form","zbl","emb_lin_neg","bkgd_dyn"};
/* ---------------------------------------------------------------------- */
PairMEAM::PairMEAM(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
nmax = 0;
rho = rho0 = rho1 = rho2 = rho3 = frhop = NULL;
gamma = dgamma1 = dgamma2 = dgamma3 = arho2b = NULL;
arho1 = arho2 = arho3 = arho3b = t_ave = tsq_ave = NULL;
maxneigh = 0;
scrfcn = dscrfcn = fcpair = NULL;
nelements = 0;
elements = NULL;
mass = NULL;
// set comm size needed by this Pair
comm_forward = 38;
comm_reverse = 30;
}
/* ----------------------------------------------------------------------
free all arrays
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairMEAM::~PairMEAM()
{
meam_cleanup_();
memory->destroy(rho);
memory->destroy(rho0);
memory->destroy(rho1);
memory->destroy(rho2);
memory->destroy(rho3);
memory->destroy(frhop);
memory->destroy(gamma);
memory->destroy(dgamma1);
memory->destroy(dgamma2);
memory->destroy(dgamma3);
memory->destroy(arho2b);
memory->destroy(arho1);
memory->destroy(arho2);
memory->destroy(arho3);
memory->destroy(arho3b);
memory->destroy(t_ave);
memory->destroy(tsq_ave);
memory->destroy(scrfcn);
memory->destroy(dscrfcn);
memory->destroy(fcpair);
for (int i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
delete [] mass;
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
delete [] fmap;
}
}
/* ---------------------------------------------------------------------- */
void PairMEAM::compute(int eflag, int vflag)
{
int i,j,ii,n,inum_half,errorflag;
double evdwl;
int *ilist_half,*numneigh_half,**firstneigh_half;
int *numneigh_full,**firstneigh_full;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = vflag_global =
eflag_atom = vflag_atom = 0;
// grow local arrays if necessary
if (atom->nmax > nmax) {
memory->destroy(rho);
memory->destroy(rho0);
memory->destroy(rho1);
memory->destroy(rho2);
memory->destroy(rho3);
memory->destroy(frhop);
memory->destroy(gamma);
memory->destroy(dgamma1);
memory->destroy(dgamma2);
memory->destroy(dgamma3);
memory->destroy(arho2b);
memory->destroy(arho1);
memory->destroy(arho2);
memory->destroy(arho3);
memory->destroy(arho3b);
memory->destroy(t_ave);
memory->destroy(tsq_ave);
nmax = atom->nmax;
memory->create(rho,nmax,"pair:rho");
memory->create(rho0,nmax,"pair:rho0");
memory->create(rho1,nmax,"pair:rho1");
memory->create(rho2,nmax,"pair:rho2");
memory->create(rho3,nmax,"pair:rho3");
memory->create(frhop,nmax,"pair:frhop");
memory->create(gamma,nmax,"pair:gamma");
memory->create(dgamma1,nmax,"pair:dgamma1");
memory->create(dgamma2,nmax,"pair:dgamma2");
memory->create(dgamma3,nmax,"pair:dgamma3");
memory->create(arho2b,nmax,"pair:arho2b");
memory->create(arho1,nmax,3,"pair:arho1");
memory->create(arho2,nmax,6,"pair:arho2");
memory->create(arho3,nmax,10,"pair:arho3");
memory->create(arho3b,nmax,3,"pair:arho3b");
memory->create(t_ave,nmax,3,"pair:t_ave");
memory->create(tsq_ave,nmax,3,"pair:tsq_ave");
}
// neighbor list info
inum_half = listhalf->inum;
ilist_half = listhalf->ilist;
numneigh_half = listhalf->numneigh;
firstneigh_half = listhalf->firstneigh;
numneigh_full = listfull->numneigh;
firstneigh_full = listfull->firstneigh;
// strip neighbor lists of any special bond flags before using with MEAM
// necessary before doing neigh_f2c and neigh_c2f conversions each step
if (neighbor->ago == 0) {
neigh_strip(inum_half,ilist_half,numneigh_half,firstneigh_half);
neigh_strip(inum_half,ilist_half,numneigh_full,firstneigh_full);
}
// check size of scrfcn based on half neighbor list
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
n = 0;
for (ii = 0; ii < inum_half; ii++) n += numneigh_half[ilist_half[ii]];
if (n > maxneigh) {
memory->destroy(scrfcn);
memory->destroy(dscrfcn);
memory->destroy(fcpair);
maxneigh = n;
memory->create(scrfcn,maxneigh,"pair:scrfcn");
memory->create(dscrfcn,maxneigh,"pair:dscrfcn");
memory->create(fcpair,maxneigh,"pair:fcpair");
}
// zero out local arrays
for (i = 0; i < nall; i++) {
rho0[i] = 0.0;
arho2b[i] = 0.0;
arho1[i][0] = arho1[i][1] = arho1[i][2] = 0.0;
for (j = 0; j < 6; j++) arho2[i][j] = 0.0;
for (j = 0; j < 10; j++) arho3[i][j] = 0.0;
arho3b[i][0] = arho3b[i][1] = arho3b[i][2] = 0.0;
t_ave[i][0] = t_ave[i][1] = t_ave[i][2] = 0.0;
tsq_ave[i][0] = tsq_ave[i][1] = tsq_ave[i][2] = 0.0;
}
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int ntype = atom->ntypes;
// change neighbor list indices to Fortran indexing
neigh_c2f(inum_half,ilist_half,numneigh_half,firstneigh_half);
neigh_c2f(inum_half,ilist_half,numneigh_full,firstneigh_full);
// 3 stages of MEAM calculation
// loop over my atoms followed by communication
int ifort;
int offset = 0;
errorflag = 0;
for (ii = 0; ii < inum_half; ii++) {
i = ilist_half[ii];
ifort = i+1;
meam_dens_init_(&ifort,&nmax,&ntype,type,fmap,&x[0][0],
&numneigh_half[i],firstneigh_half[i],
&numneigh_full[i],firstneigh_full[i],
&scrfcn[offset],&dscrfcn[offset],&fcpair[offset],
rho0,&arho1[0][0],&arho2[0][0],arho2b,
&arho3[0][0],&arho3b[0][0],&t_ave[0][0],&tsq_ave[0][0],
&errorflag);
if (errorflag) {
char str[128];
sprintf(str,"MEAM library error %d",errorflag);
- error->one(str);
+ error->one(FLERR,str);
}
offset += numneigh_half[i];
}
comm->reverse_comm_pair(this);
meam_dens_final_(&nlocal,&nmax,&eflag_either,&eflag_global,&eflag_atom,
&eng_vdwl,eatom,&ntype,type,fmap,
&arho1[0][0],&arho2[0][0],arho2b,&arho3[0][0],
&arho3b[0][0],&t_ave[0][0],&tsq_ave[0][0],gamma,dgamma1,
dgamma2,dgamma3,rho,rho0,rho1,rho2,rho3,frhop,&errorflag);
if (errorflag) {
char str[128];
sprintf(str,"MEAM library error %d",errorflag);
- error->one(str);
+ error->one(FLERR,str);
}
comm->forward_comm_pair(this);
offset = 0;
// vptr is first value in vatom if it will be used by meam_force()
// else vatom may not exist, so pass dummy ptr
double *vptr;
if (vflag_atom) vptr = &vatom[0][0];
else vptr = &cutmax;
for (ii = 0; ii < inum_half; ii++) {
i = ilist_half[ii];
ifort = i+1;
meam_force_(&ifort,&nmax,&eflag_either,&eflag_global,&eflag_atom,
&vflag_atom,&eng_vdwl,eatom,&ntype,type,fmap,&x[0][0],
&numneigh_half[i],firstneigh_half[i],
&numneigh_full[i],firstneigh_full[i],
&scrfcn[offset],&dscrfcn[offset],&fcpair[offset],
dgamma1,dgamma2,dgamma3,rho0,rho1,rho2,rho3,frhop,
&arho1[0][0],&arho2[0][0],arho2b,&arho3[0][0],&arho3b[0][0],
&t_ave[0][0],&tsq_ave[0][0],&f[0][0],vptr,&errorflag);
if (errorflag) {
char str[128];
sprintf(str,"MEAM library error %d",errorflag);
- error->one(str);
+ error->one(FLERR,str);
}
offset += numneigh_half[i];
}
// change neighbor list indices back to C indexing
neigh_f2c(inum_half,ilist_half,numneigh_half,firstneigh_half);
neigh_f2c(inum_half,ilist_half,numneigh_full,firstneigh_full);
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairMEAM::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
fmap = new int[n];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairMEAM::settings(int narg, char **arg)
{
- if (narg != 0) error->all("Illegal pair_style command");
+ if (narg != 0) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairMEAM::coeff(int narg, char **arg)
{
int i,j,m,n;
if (!allocated) allocate();
- if (narg < 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 6) error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read MEAM element names between 2 filenames
// nelements = # of MEAM elements
// elements = list of unique element names
if (nelements) {
for (i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
delete [] mass;
}
nelements = narg - 4 - atom->ntypes;
- if (nelements < 1) error->all("Incorrect args for pair coefficients");
+ if (nelements < 1) error->all(FLERR,"Incorrect args for pair coefficients");
elements = new char*[nelements];
mass = new double[nelements];
for (i = 0; i < nelements; i++) {
n = strlen(arg[i+3]) + 1;
elements[i] = new char[n];
strcpy(elements[i],arg[i+3]);
}
// read MEAM library and parameter files
// pass all parameters to MEAM package
// tell MEAM package that setup is done
read_files(arg[2],arg[2+nelements+1]);
meam_setup_done_(&cutmax);
// read args that map atom types to MEAM elements
// map[i] = which element the Ith atom type is, -1 if not mapped
for (i = 4 + nelements; i < narg; i++) {
m = i - (4+nelements) + 1;
for (j = 0; j < nelements; j++)
if (strcmp(arg[i],elements[j]) == 0) break;
if (j < nelements) map[m] = j;
else if (strcmp(arg[i],"NULL") == 0) map[m] = -1;
- else error->all("Incorrect args for pair coefficients");
+ else error->all(FLERR,"Incorrect args for pair coefficients");
}
// 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
// set mass for i,i in atom class
int count = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
if (i == j) atom->set_mass(i,mass[map[i]]);
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairMEAM::init_style()
{
if (force->newton_pair == 0)
- error->all("Pair style MEAM requires newton pair on");
+ error->all(FLERR,"Pair style MEAM requires newton pair on");
// need full and half neighbor list
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);
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;
// setup Fortran-style mapping array needed by MEAM package
// fmap is indexed from 1:ntypes by Fortran and stores a Fortran index
// if type I is not a MEAM atom, fmap stores a 0
for (int i = 1; i <= atom->ntypes; i++) fmap[i-1] = map[i] + 1;
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
half or full
------------------------------------------------------------------------- */
void PairMEAM::init_list(int id, NeighList *ptr)
{
if (id == 1) listfull = ptr;
else if (id == 2) listhalf = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairMEAM::init_one(int i, int j)
{
return cutmax;
}
/* ---------------------------------------------------------------------- */
void PairMEAM::read_files(char *globalfile, char *userfile)
{
// open global meamf file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = fopen(globalfile,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open MEAM potential file %s",globalfile);
- error->one(str);
+ error->one(FLERR,str);
}
}
// allocate parameter arrays
int params_per_line = 19;
int *lat = new int[nelements];
int *ielement = new int[nelements];
int *ibar = new int[nelements];
double *z = new double[nelements];
double *atwt = new double[nelements];
double *alpha = new double[nelements];
double *b0 = new double[nelements];
double *b1 = new double[nelements];
double *b2 = new double[nelements];
double *b3 = new double[nelements];
double *alat = new double[nelements];
double *esub = new double[nelements];
double *asub = new double[nelements];
double *t0 = new double[nelements];
double *t1 = new double[nelements];
double *t2 = new double[nelements];
double *t3 = new double[nelements];
double *rozero = new double[nelements];
bool *found = new bool[nelements];
for (int i = 0; i < nelements; i++) found[i] = false;
// read each set of params from global MEAM file
// one set of params can span multiple lines
// store params if element name is in element list
// if element name appears multiple times, only store 1st entry
int i,n,nwords;
char **words = new char*[params_per_line+1];
char line[MAXLINE],*ptr;
int eof = 0;
int nset = 0;
while (1) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
if (nwords == 0) continue;
// concatenate additional lines until have params_per_line words
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n],MAXLINE-n,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
if (ptr = strchr(line,'#')) *ptr = '\0';
nwords = atom->count_words(line);
}
if (nwords != params_per_line)
- error->all("Incorrect format in MEAM potential file");
+ error->all(FLERR,"Incorrect format in MEAM potential file");
// words = ptrs to all words in line
// strip single and double quotes from words
nwords = 0;
words[nwords++] = strtok(line,"' \t\n\r\f");
while (words[nwords++] = strtok(NULL,"' \t\n\r\f")) continue;
// skip if element name isn't in element list
for (i = 0; i < nelements; i++)
if (strcmp(words[0],elements[i]) == 0) break;
if (i == nelements) continue;
// skip if element already appeared
if (found[i] == true) continue;
found[i] = true;
// map lat string to an integer
if (strcmp(words[1],"fcc") == 0) lat[i] = FCC;
else if (strcmp(words[1],"bcc") == 0) lat[i] = BCC;
else if (strcmp(words[1],"hcp") == 0) lat[i] = HCP;
else if (strcmp(words[1],"dim") == 0) lat[i] = DIM;
else if (strcmp(words[1],"dia") == 0) lat[i] = DIAMOND;
- else error->all("Unrecognized lattice type in MEAM file 1");
+ else error->all(FLERR,"Unrecognized lattice type in MEAM file 1");
// store parameters
z[i] = atof(words[2]);
ielement[i] = atoi(words[3]);
atwt[i] = atof(words[4]);
alpha[i] = atof(words[5]);
b0[i] = atof(words[6]);
b1[i] = atof(words[7]);
b2[i] = atof(words[8]);
b3[i] = atof(words[9]);
alat[i] = atof(words[10]);
esub[i] = atof(words[11]);
asub[i] = atof(words[12]);
t0[i] = atof(words[13]);
t1[i] = atof(words[14]);
t2[i] = atof(words[15]);
t3[i] = atof(words[16]);
rozero[i] = atof(words[17]);
ibar[i] = atoi(words[18]);
nset++;
}
// error if didn't find all elements in file
if (nset != nelements)
- error->all("Did not find all elements in MEAM library file");
+ error->all(FLERR,"Did not find all elements in MEAM library file");
// pass element parameters to MEAM package
meam_setup_global_(&nelements,lat,z,ielement,atwt,alpha,b0,b1,b2,b3,
alat,esub,asub,t0,t1,t2,t3,rozero,ibar);
// set element masses
for (i = 0; i < nelements; i++) mass[i] = atwt[i];
// clean-up memory
delete [] words;
delete [] lat;
delete [] ielement;
delete [] ibar;
delete [] z;
delete [] atwt;
delete [] alpha;
delete [] b0;
delete [] b1;
delete [] b2;
delete [] b3;
delete [] alat;
delete [] esub;
delete [] asub;
delete [] t0;
delete [] t1;
delete [] t2;
delete [] t3;
delete [] rozero;
delete [] found;
// done if user param file is NULL
if (strcmp(userfile,"NULL") == 0) return;
// open user param file on proc 0
if (comm->me == 0) {
fp = fopen(userfile,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open MEAM potential file %s",userfile);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read settings
// pass them one at a time to MEAM package
// match strings to list of corresponding ints
int which;
double value;
int nindex,index[3];
int maxparams = 6;
char **params = new char*[maxparams];
int nparams;
eof = 0;
while (1) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if (ptr = strchr(line,'#')) *ptr = '\0';
nparams = atom->count_words(line);
if (nparams == 0) continue;
// words = ptrs to all words in line
nparams = 0;
params[nparams++] = strtok(line,"=(), '\t\n\r\f");
while (nparams < maxparams &&
(params[nparams++] = strtok(NULL,"=(), '\t\n\r\f")))
continue;
nparams--;
for (which = 0; which < nkeywords; which++)
if (strcmp(params[0],keywords[which]) == 0) break;
if (which == nkeywords) {
char str[128];
sprintf(str,"Keyword %s in MEAM parameter file not recognized",
params[0]);
- error->all(str);
+ error->all(FLERR,str);
}
nindex = nparams - 2;
for (i = 0; i < nindex; i++) index[i] = atoi(params[i+1]);
// map lattce_meam value to an integer
if (which == 4) {
if (strcmp(params[nparams-1],"fcc") == 0) value = FCC;
else if (strcmp(params[nparams-1],"bcc") == 0) value = BCC;
else if (strcmp(params[nparams-1],"hcp") == 0) value = HCP;
else if (strcmp(params[nparams-1],"dim") == 0) value = DIM;
else if (strcmp(params[nparams-1],"dia") == 0) value = DIAMOND;
else if (strcmp(params[nparams-1],"b1") == 0) value = B1;
else if (strcmp(params[nparams-1],"c11") == 0) value = C11;
else if (strcmp(params[nparams-1],"l12") == 0) value = L12;
else if (strcmp(params[nparams-1],"b2") == 0) value = B2;
- else error->all("Unrecognized lattice type in MEAM file 2");
+ else error->all(FLERR,"Unrecognized lattice type in MEAM file 2");
}
else value = atof(params[nparams-1]);
// pass single setting to MEAM package
int errorflag = 0;
meam_setup_param_(&which,&value,&nindex,index,&errorflag);
if (errorflag) {
char str[128];
sprintf(str,"MEAM library error %d",errorflag);
- error->all(str);
+ error->all(FLERR,str);
}
}
delete [] params;
}
/* ---------------------------------------------------------------------- */
int PairMEAM::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,k,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = rho0[j];
buf[m++] = rho1[j];
buf[m++] = rho2[j];
buf[m++] = rho3[j];
buf[m++] = frhop[j];
buf[m++] = gamma[j];
buf[m++] = dgamma1[j];
buf[m++] = dgamma2[j];
buf[m++] = dgamma3[j];
buf[m++] = arho2b[j];
buf[m++] = arho1[j][0];
buf[m++] = arho1[j][1];
buf[m++] = arho1[j][2];
buf[m++] = arho2[j][0];
buf[m++] = arho2[j][1];
buf[m++] = arho2[j][2];
buf[m++] = arho2[j][3];
buf[m++] = arho2[j][4];
buf[m++] = arho2[j][5];
for (k = 0; k < 10; k++) buf[m++] = arho3[j][k];
buf[m++] = arho3b[j][0];
buf[m++] = arho3b[j][1];
buf[m++] = arho3b[j][2];
buf[m++] = t_ave[j][0];
buf[m++] = t_ave[j][1];
buf[m++] = t_ave[j][2];
buf[m++] = tsq_ave[j][0];
buf[m++] = tsq_ave[j][1];
buf[m++] = tsq_ave[j][2];
}
return comm_forward;
}
/* ---------------------------------------------------------------------- */
void PairMEAM::unpack_comm(int n, int first, double *buf)
{
int i,k,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
rho0[i] = buf[m++];
rho1[i] = buf[m++];
rho2[i] = buf[m++];
rho3[i] = buf[m++];
frhop[i] = buf[m++];
gamma[i] = buf[m++];
dgamma1[i] = buf[m++];
dgamma2[i] = buf[m++];
dgamma3[i] = buf[m++];
arho2b[i] = buf[m++];
arho1[i][0] = buf[m++];
arho1[i][1] = buf[m++];
arho1[i][2] = buf[m++];
arho2[i][0] = buf[m++];
arho2[i][1] = buf[m++];
arho2[i][2] = buf[m++];
arho2[i][3] = buf[m++];
arho2[i][4] = buf[m++];
arho2[i][5] = buf[m++];
for (k = 0; k < 10; k++) arho3[i][k] = buf[m++];
arho3b[i][0] = buf[m++];
arho3b[i][1] = buf[m++];
arho3b[i][2] = buf[m++];
t_ave[i][0] = buf[m++];
t_ave[i][1] = buf[m++];
t_ave[i][2] = buf[m++];
tsq_ave[i][0] = buf[m++];
tsq_ave[i][1] = buf[m++];
tsq_ave[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int PairMEAM::pack_reverse_comm(int n, int first, double *buf)
{
int i,k,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = rho0[i];
buf[m++] = arho2b[i];
buf[m++] = arho1[i][0];
buf[m++] = arho1[i][1];
buf[m++] = arho1[i][2];
buf[m++] = arho2[i][0];
buf[m++] = arho2[i][1];
buf[m++] = arho2[i][2];
buf[m++] = arho2[i][3];
buf[m++] = arho2[i][4];
buf[m++] = arho2[i][5];
for (k = 0; k < 10; k++) buf[m++] = arho3[i][k];
buf[m++] = arho3b[i][0];
buf[m++] = arho3b[i][1];
buf[m++] = arho3b[i][2];
buf[m++] = t_ave[i][0];
buf[m++] = t_ave[i][1];
buf[m++] = t_ave[i][2];
buf[m++] = tsq_ave[i][0];
buf[m++] = tsq_ave[i][1];
buf[m++] = tsq_ave[i][2];
}
return comm_reverse;
}
/* ---------------------------------------------------------------------- */
void PairMEAM::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,k,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
rho0[j] += buf[m++];
arho2b[j] += buf[m++];
arho1[j][0] += buf[m++];
arho1[j][1] += buf[m++];
arho1[j][2] += buf[m++];
arho2[j][0] += buf[m++];
arho2[j][1] += buf[m++];
arho2[j][2] += buf[m++];
arho2[j][3] += buf[m++];
arho2[j][4] += buf[m++];
arho2[j][5] += buf[m++];
for (k = 0; k < 10; k++) arho3[j][k] += buf[m++];
arho3b[j][0] += buf[m++];
arho3b[j][1] += buf[m++];
arho3b[j][2] += buf[m++];
t_ave[j][0] += buf[m++];
t_ave[j][1] += buf[m++];
t_ave[j][2] += buf[m++];
tsq_ave[j][0] += buf[m++];
tsq_ave[j][1] += buf[m++];
tsq_ave[j][2] += buf[m++];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairMEAM::memory_usage()
{
double bytes = 11 * nmax * sizeof(double);
bytes += (3 + 6 + 10 + 3 + 3 + 3) * nmax * sizeof(double);
bytes += 3 * maxneigh * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
strip special bond flags from neighbor list entries
are not used with MEAM
need to do here so Fortran lib doesn't see them
done once per reneighbor so that neigh_f2c and neigh_c2f don't see them
------------------------------------------------------------------------- */
void PairMEAM::neigh_strip(int inum, int *ilist,
int *numneigh, int **firstneigh)
{
int i,j,ii,jnum;
int *jlist;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
jlist = firstneigh[i];
jnum = numneigh[i];
for (j = 0; j < jnum; j++) jlist[j] &= NEIGHMASK;
}
}
/* ----------------------------------------------------------------------
toggle neighbor list indices between zero- and one-based values
needed for access by MEAM Fortran library
------------------------------------------------------------------------- */
void PairMEAM::neigh_f2c(int inum, int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jnum;
int *jlist;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
jlist = firstneigh[i];
jnum = numneigh[i];
for (j = 0; j < jnum; j++) jlist[j]--;
}
}
void PairMEAM::neigh_c2f(int inum, int *ilist, int *numneigh, int **firstneigh)
{
int i,j,ii,jnum;
int *jlist;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
jlist = firstneigh[i];
jnum = numneigh[i];
for (j = 0; j < jnum; j++) jlist[j]++;
}
}
diff --git a/src/MOLECULE/angle_charmm.cpp b/src/MOLECULE/angle_charmm.cpp
index a0b0fc970..5dd81580c 100644
--- a/src/MOLECULE/angle_charmm.cpp
+++ b/src/MOLECULE/angle_charmm.cpp
@@ -1,298 +1,298 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_charmm.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleCharmm::AngleCharmm(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleCharmm::~AngleCharmm()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(theta0);
memory->destroy(k_ub);
memory->destroy(r_ub);
}
}
/* ---------------------------------------------------------------------- */
void AngleCharmm::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3];
double dtheta,tk;
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
double delxUB,delyUB,delzUB,rsqUB,rUB,dr,rk,forceUB;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// Urey-Bradley bond
delxUB = x[i3][0] - x[i1][0];
delyUB = x[i3][1] - x[i1][1];
delzUB = x[i3][2] - x[i1][2];
domain->minimum_image(delxUB,delyUB,delzUB);
rsqUB = delxUB*delxUB + delyUB*delyUB + delzUB*delzUB;
rUB = sqrt(rsqUB);
// Urey-Bradley force & energy
dr = rUB - r_ub[type];
rk = k_ub[type] * dr;
if (rUB > 0.0) forceUB = -2.0*rk/rUB;
else forceUB = 0.0;
if (eflag) eangle = rk*dr;
// angle (cos and sin)
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
s = 1.0/s;
// harmonic force & energy
dtheta = acos(c) - theta0[type];
tk = k[type] * dtheta;
if (eflag) eangle += tk*dtheta;
a = -2.0 * tk * s;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2 - delxUB*forceUB;
f1[1] = a11*dely1 + a12*dely2 - delyUB*forceUB;
f1[2] = a11*delz1 + a12*delz2 - delzUB*forceUB;
f3[0] = a22*delx2 + a12*delx1 + delxUB*forceUB;
f3[1] = a22*dely2 + a12*dely1 + delyUB*forceUB;
f3[2] = a22*delz2 + a12*delz1 + delzUB*forceUB;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleCharmm::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(k,n+1,"angle:k");
memory->create(theta0,n+1,"angle:theta0");
memory->create(k_ub,n+1,"angle:k_ub");
memory->create(r_ub,n+1,"angle:r_ub");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void AngleCharmm::coeff(int narg, char **arg)
{
- if (narg != 5) error->all("Incorrect args for angle coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double theta0_one = force->numeric(arg[2]);
double k_ub_one = force->numeric(arg[3]);
double r_ub_one = force->numeric(arg[4]);
// convert theta0 from degrees to radians
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
theta0[i] = theta0_one/180.0 * PI;
k_ub[i] = k_ub_one;
r_ub[i] = r_ub_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleCharmm::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleCharmm::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
fwrite(&k_ub[1],sizeof(double),atom->nangletypes,fp);
fwrite(&r_ub[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleCharmm::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nangletypes,fp);
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
fread(&k_ub[1],sizeof(double),atom->nangletypes,fp);
fread(&r_ub[1],sizeof(double),atom->nangletypes,fp);
}
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k_ub[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r_ub[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleCharmm::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double delxUB = x[i3][0] - x[i1][0];
double delyUB = x[i3][1] - x[i1][1];
double delzUB = x[i3][2] - x[i1][2];
domain->minimum_image(delxUB,delyUB,delzUB);
double rUB = sqrt(delxUB*delxUB + delyUB*delyUB + delzUB*delzUB);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double dtheta = acos(c) - theta0[type];
double tk = k[type] * dtheta;
double dr = rUB - r_ub[type];
double rk = k_ub[type] * dr;
return (tk*dtheta + rk*dr);
}
diff --git a/src/MOLECULE/angle_cosine.cpp b/src/MOLECULE/angle_cosine.cpp
index 771093af6..6c6fa4fc8 100644
--- a/src/MOLECULE/angle_cosine.cpp
+++ b/src/MOLECULE/angle_cosine.cpp
@@ -1,227 +1,227 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_cosine.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleCosine::AngleCosine(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleCosine::~AngleCosine()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosine::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3];
double rsq1,rsq2,r1,r2,c,a,a11,a12,a22;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// c = cosine of angle
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// force & energy
if (eflag) eangle = k[type]*(1.0+c);
a = k[type];
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosine::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(k,n+1,"angle:k");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void AngleCosine::coeff(int narg, char **arg)
{
- if (narg != 2) error->all("Incorrect args for angle coefficients");
+ if (narg != 2) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleCosine::equilibrium_angle(int i)
{
return PI;
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleCosine::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleCosine::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) fread(&k[1],sizeof(double),atom->nangletypes,fp);
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleCosine::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
return k[type]*(1.0+c);
}
diff --git a/src/MOLECULE/angle_cosine_periodic.cpp b/src/MOLECULE/angle_cosine_periodic.cpp
index 4d2bd5891..d401c1fff 100644
--- a/src/MOLECULE/angle_cosine_periodic.cpp
+++ b/src/MOLECULE/angle_cosine_periodic.cpp
@@ -1,288 +1,288 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Tod A Pascal (Caltech)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_cosine_periodic.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleCosinePeriodic::AngleCosinePeriodic(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleCosinePeriodic::~AngleCosinePeriodic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(b);
memory->destroy(multiplicity);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosinePeriodic::compute(int eflag, int vflag)
{
int i,i1,i2,i3,n,m,type,b_factor;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3];
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
double tn,tn_1,tn_2,un,un_1,un_2;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// c = cosine of angle
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
m = multiplicity[type];
b_factor = b[type];
// cos(n*x) = Tn(cos(x))
// Tn(x) = Chebyshev polynomials of the first kind: T_0 = 1, T_1 = x, ...
// recurrence relationship:
// Tn(x) = 2*x*T[n-1](x) - T[n-2](x) where T[-1](x) = 0
// also, dTn(x)/dx = n*U[n-1](x)
// where Un(x) = 2*x*U[n-1](x) - U[n-2](x) and U[-1](x) = 0
// finally need to handle special case for n = 1
tn = 1.0;
tn_1 = 1.0;
tn_2 = 0.0;
un = 1.0;
un_1 = 2.0;
un_2 = 0.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
s = 1.0/s;
// force & energy
tn_2 = c;
for (i = 1; i <= m; i++) {
tn = 2*c*tn_1 - tn_2;
tn_2 = tn_1;
tn_1 = tn;
}
for (i = 2; i <= m; i++) {
un = 2*c*un_1 - un_2;
un_2 = un_1;
un_1 = un;
}
tn = b_factor*pow((-1),m)*tn;
un = b_factor*pow((-1),m)*m*un;
if (eflag) eangle = 2*k[type]*(1.0 - tn);
a = -k[type]*un;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosinePeriodic::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(k,n+1,"angle:k");
memory->create(multiplicity,n+1,"angle:multiplicity");
memory->create(b,n+1,"angle:b");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void AngleCosinePeriodic::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for angle coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double c_one = atof(arg[1]);
int b_one = atoi(arg[2]);
int n_one = atoi(arg[3]);
- if (n_one <= 0) error->all("Incorrect args for angle coefficients");
+ if (n_one <= 0) error->all(FLERR,"Incorrect args for angle coefficients");
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = c_one/(n_one*n_one);
b[i] = b_one;
multiplicity[i] = n_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleCosinePeriodic::equilibrium_angle(int i)
{
return PI;
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleCosinePeriodic::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
fwrite(&b[1],sizeof(int),atom->nangletypes,fp);
fwrite(&multiplicity[1],sizeof(int),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleCosinePeriodic::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nangletypes,fp);
fread(&b[1],sizeof(int),atom->nangletypes,fp);
fread(&multiplicity[1],sizeof(int),atom->nangletypes,fp);
}
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&b[1],atom->nangletypes,MPI_INT,0,world);
MPI_Bcast(&multiplicity[1],atom->nangletypes,MPI_INT,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleCosinePeriodic::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
c = cos(acos(c)*multiplicity[type]);
return k[type]*(1.0-b[type]*pow(-1,multiplicity[type])*c);
}
diff --git a/src/MOLECULE/angle_cosine_squared.cpp b/src/MOLECULE/angle_cosine_squared.cpp
index caaf44db5..926270067 100644
--- a/src/MOLECULE/angle_cosine_squared.cpp
+++ b/src/MOLECULE/angle_cosine_squared.cpp
@@ -1,250 +1,250 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Naveen Michaud-Agrawal (Johns Hopkins U)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_cosine_squared.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleCosineSquared::AngleCosineSquared(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleCosineSquared::~AngleCosineSquared()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(theta0);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosineSquared::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3];
double dcostheta,tk;
double rsq1,rsq2,r1,r2,c,a,a11,a12,a22;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// force & energy
dcostheta = c - cos(theta0[type]);
tk = k[type] * dcostheta;
if (eflag) eangle = tk*dcostheta;
a = 2.0 * tk;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosineSquared::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(k,n+1,"angle:k");
memory->create(theta0,n+1,"angle:theta0");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void AngleCosineSquared::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Incorrect args for angle coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double theta0_one = force->numeric(arg[2]);
// convert theta0 from degrees to radians
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
theta0[i] = theta0_one/180.0 * PI;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleCosineSquared::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleCosineSquared::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleCosineSquared::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nangletypes,fp);
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
}
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleCosineSquared::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double dcostheta = c - cos(theta0[type]);
double tk = k[type] * dcostheta;
return tk*dcostheta;
}
diff --git a/src/MOLECULE/angle_harmonic.cpp b/src/MOLECULE/angle_harmonic.cpp
index 20fa892ce..e3def9749 100644
--- a/src/MOLECULE/angle_harmonic.cpp
+++ b/src/MOLECULE/angle_harmonic.cpp
@@ -1,250 +1,250 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_harmonic.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleHarmonic::AngleHarmonic(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleHarmonic::~AngleHarmonic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(theta0);
}
}
/* ---------------------------------------------------------------------- */
void AngleHarmonic::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3];
double dtheta,tk;
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
s = 1.0/s;
// force & energy
dtheta = acos(c) - theta0[type];
tk = k[type] * dtheta;
if (eflag) eangle = tk*dtheta;
a = -2.0 * tk * s;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleHarmonic::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(k,n+1,"angle:k");
memory->create(theta0,n+1,"angle:theta0");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void AngleHarmonic::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Incorrect args for angle coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double theta0_one = force->numeric(arg[2]);
// convert theta0 from degrees to radians
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
theta0[i] = theta0_one/180.0 * PI;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleHarmonic::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleHarmonic::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleHarmonic::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nangletypes,fp);
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
}
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleHarmonic::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double dtheta = acos(c) - theta0[type];
double tk = k[type] * dtheta;
return tk*dtheta;
}
diff --git a/src/MOLECULE/angle_hybrid.cpp b/src/MOLECULE/angle_hybrid.cpp
index ac3b8a28a..a71d87da1 100644
--- a/src/MOLECULE/angle_hybrid.cpp
+++ b/src/MOLECULE/angle_hybrid.cpp
@@ -1,354 +1,355 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "ctype.h"
#include "angle_hybrid.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define EXTRA 1000
/* ---------------------------------------------------------------------- */
AngleHybrid::AngleHybrid(LAMMPS *lmp) : Angle(lmp)
{
nstyles = 0;
}
/* ---------------------------------------------------------------------- */
AngleHybrid::~AngleHybrid()
{
if (nstyles) {
for (int i = 0; i < nstyles; i++) delete styles[i];
delete [] styles;
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(map);
delete [] nanglelist;
delete [] maxangle;
for (int i = 0; i < nstyles; i++)
memory->destroy(anglelist[i]);
delete [] anglelist;
}
}
/* ---------------------------------------------------------------------- */
void AngleHybrid::compute(int eflag, int vflag)
{
int i,j,m,n;
// save ptrs to original anglelist
int nanglelist_orig = neighbor->nanglelist;
int **anglelist_orig = neighbor->anglelist;
// if this is re-neighbor step, create sub-style anglelists
// nanglelist[] = length of each sub-style list
// realloc sub-style anglelist if necessary
// load sub-style anglelist with 4 values from original anglelist
if (neighbor->ago == 0) {
for (m = 0; m < nstyles; m++) nanglelist[m] = 0;
for (i = 0; i < nanglelist_orig; i++) {
m = map[anglelist_orig[i][3]];
if (m >= 0) nanglelist[m]++;
}
for (m = 0; m < nstyles; m++) {
if (nanglelist[m] > maxangle[m]) {
memory->destroy(anglelist[m]);
maxangle[m] = nanglelist[m] + EXTRA;
memory->create(anglelist[m],maxangle[m],4,"angle_hybrid:anglelist");
}
nanglelist[m] = 0;
}
for (i = 0; i < nanglelist_orig; i++) {
m = map[anglelist_orig[i][3]];
if (m < 0) continue;
n = nanglelist[m];
anglelist[m][n][0] = anglelist_orig[i][0];
anglelist[m][n][1] = anglelist_orig[i][1];
anglelist[m][n][2] = anglelist_orig[i][2];
anglelist[m][n][3] = anglelist_orig[i][3];
nanglelist[m]++;
}
}
// call each sub-style's compute function
// set neighbor->anglelist to sub-style anglelist before call
// accumulate sub-style global/peratom energy/virial in hybrid
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
for (m = 0; m < nstyles; m++) {
neighbor->nanglelist = nanglelist[m];
neighbor->anglelist = anglelist[m];
styles[m]->compute(eflag,vflag);
if (eflag_global) energy += styles[m]->energy;
if (vflag_global)
for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double *eatom_substyle = styles[m]->eatom;
for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i];
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double **vatom_substyle = styles[m]->vatom;
for (i = 0; i < n; i++)
for (j = 0; j < 6; j++)
vatom[i][j] += vatom_substyle[i][j];
}
}
// restore ptrs to original anglelist
neighbor->nanglelist = nanglelist_orig;
neighbor->anglelist = anglelist_orig;
}
/* ---------------------------------------------------------------------- */
void AngleHybrid::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(map,n+1,"angle:map");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
nanglelist = new int[nstyles];
maxangle = new int[nstyles];
anglelist = new int**[nstyles];
for (int m = 0; m < nstyles; m++) maxangle[m] = 0;
for (int m = 0; m < nstyles; m++) anglelist[m] = NULL;
}
/* ----------------------------------------------------------------------
create one angle style for each arg in list
------------------------------------------------------------------------- */
void AngleHybrid::settings(int narg, char **arg)
{
int i,m,istyle;
- if (narg < 1) error->all("Illegal angle_style command");
+ if (narg < 1) error->all(FLERR,"Illegal angle_style command");
// delete old lists, since cannot just change settings
if (nstyles) {
for (int i = 0; i < nstyles; i++) delete styles[i];
delete [] styles;
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(map);
delete [] nanglelist;
delete [] maxangle;
for (int i = 0; i < nstyles; i++)
memory->destroy(anglelist[i]);
delete [] anglelist;
}
allocated = 0;
// count sub-styles by skipping numeric args
// one exception is 1st arg of style "table", which is non-numeric word
// need a better way to skip these exceptions
nstyles = 0;
i = 0;
while (i < narg) {
if (strcmp(arg[i],"table") == 0) i++;
i++;
while (i < narg && !isalpha(arg[i][0])) i++;
nstyles++;
}
// allocate list of sub-styles
styles = new Angle*[nstyles];
keywords = new char*[nstyles];
// allocate each sub-style and call its settings() with subset of args
// define subset of args for a sub-style by skipping numeric args
// one exception is 1st arg of style "table", which is non-numeric
// need a better way to skip these exceptions
nstyles = 0;
i = 0;
while (i < narg) {
for (m = 0; m < nstyles; m++)
if (strcmp(arg[i],keywords[m]) == 0)
- error->all("Angle style hybrid cannot use same pair style twice");
+ error->all(FLERR,"Angle style hybrid cannot use same pair style twice");
if (strcmp(arg[i],"hybrid") == 0)
- error->all("Angle style hybrid cannot have hybrid as an argument");
+ error->all(FLERR,"Angle style hybrid cannot have hybrid as an argument");
if (strcmp(arg[i],"none") == 0)
- error->all("Angle style hybrid cannot have none as an argument");
+ error->all(FLERR,"Angle style hybrid cannot have none as an argument");
styles[nstyles] = force->new_angle(arg[i]);
keywords[nstyles] = new char[strlen(arg[i])+1];
strcpy(keywords[nstyles],arg[i]);
istyle = i;
if (strcmp(arg[i],"table") == 0) i++;
i++;
while (i < narg && !isalpha(arg[i][0])) i++;
styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]);
nstyles++;
}
}
/* ----------------------------------------------------------------------
set coeffs for one type
---------------------------------------------------------------------- */
void AngleHybrid::coeff(int narg, char **arg)
{
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
// 2nd arg = angle sub-style name
// allow for "none" or "skip" as valid sub-style name
int m;
for (m = 0; m < nstyles; m++)
if (strcmp(arg[1],keywords[m]) == 0) break;
int none = 0;
int skip = 0;
if (m == nstyles) {
if (strcmp(arg[1],"none") == 0) none = 1;
else if (strcmp(arg[1],"skip") == 0) none = skip = 1;
- else error->all("Angle coeff for hybrid has invalid style");
+ else error->all(FLERR,"Angle coeff for hybrid has invalid style");
}
// move 1st arg to 2nd arg
// just copy ptrs, since arg[] points into original input line
arg[1] = arg[0];
// invoke sub-style coeff() starting with 1st arg
if (!none) styles[m]->coeff(narg-1,&arg[1]);
// set setflag and which type maps to which sub-style
// if sub-style is skip: auxiliary class2 setting in data file so ignore
// if sub-style is none: set hybrid setflag, wipe out map
for (int i = ilo; i <= ihi; i++) {
if (skip) continue;
else if (none) {
setflag[i] = 1;
map[i] = -1;
} else {
setflag[i] = styles[m]->setflag[i];
map[i] = m;
}
}
}
/* ----------------------------------------------------------------------
return an equilbrium angle length
------------------------------------------------------------------------- */
double AngleHybrid::equilibrium_angle(int i)
{
- if (map[i] < 0) error->one("Invoked angle equil angle on angle style none");
+ if (map[i] < 0)
+ error->one(FLERR,"Invoked angle equil angle on angle style none");
return styles[map[i]]->equilibrium_angle(i);
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void AngleHybrid::write_restart(FILE *fp)
{
fwrite(&nstyles,sizeof(int),1,fp);
int n;
for (int m = 0; m < nstyles; m++) {
n = strlen(keywords[m]) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(keywords[m],sizeof(char),n,fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void AngleHybrid::read_restart(FILE *fp)
{
int me = comm->me;
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
styles = new Angle*[nstyles];
keywords = new char*[nstyles];
allocate();
int n;
for (int m = 0; m < nstyles; m++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
keywords[m] = new char[n];
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
styles[m] = force->new_angle(keywords[m]);
}
}
/* ---------------------------------------------------------------------- */
double AngleHybrid::single(int type, int i1, int i2, int i3)
{
- if (map[type] < 0) error->one("Invoked angle single on angle style none");
+ if (map[type] < 0) error->one(FLERR,"Invoked angle single on angle style none");
return styles[map[type]]->single(type,i1,i2,i3);
}
/* ----------------------------------------------------------------------
memory usage
------------------------------------------------------------------------- */
double AngleHybrid::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
for (int m = 0; m < nstyles; m++) bytes += maxangle[m]*4 * sizeof(int);
for (int m = 0; m < nstyles; m++)
if (styles[m]) bytes += styles[m]->memory_usage();
return bytes;
}
diff --git a/src/MOLECULE/angle_table.cpp b/src/MOLECULE/angle_table.cpp
index c47309c50..4395c2041 100644
--- a/src/MOLECULE/angle_table.cpp
+++ b/src/MOLECULE/angle_table.cpp
@@ -1,663 +1,660 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Chuanfu Luo (luochuanfu@gmail.com)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "angle_table.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
enum{LINEAR,SPLINE};
#define MAXLINE 1024
#define SMALL 0.001
#define TINY 1.E-10
/* ---------------------------------------------------------------------- */
AngleTable::AngleTable(LAMMPS *lmp) : Angle(lmp)
{
ntables = 0;
tables = NULL;
}
/* ---------------------------------------------------------------------- */
AngleTable::~AngleTable()
{
for (int m = 0; m < ntables; m++) free_table(&tables[m]);
memory->sfree(tables);
if (allocated) {
memory->destroy(setflag);
memory->destroy(theta0);
memory->destroy(tabindex);
}
}
/* ---------------------------------------------------------------------- */
void AngleTable::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double eangle,f1[3],f3[3];
double delx1,dely1,delz1,delx2,dely2,delz2;
double rsq1,rsq2,r1,r2,c,s,a,a11,a12,a22;
double theta,u,mdu; //mdu: minus du, -du/dx=f
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
s = 1.0/s;
// tabulated force & energy
theta = acos(c);
uf_lookup(type,theta,u,mdu);
if (eflag) eangle = u;
a = mdu * s;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleTable::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(theta0,n+1,"angle:theta0");
memory->create(tabindex,n+1,"angle:tabindex");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void AngleTable::settings(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal angle_style command");
+ if (narg != 2) error->all(FLERR,"Illegal angle_style command");
if (strcmp(arg[0],"linear") == 0) tabstyle = LINEAR;
else if (strcmp(arg[0],"spline") == 0) tabstyle = SPLINE;
- else error->all("Unknown table style in angle style table");
+ else error->all(FLERR,"Unknown table style in angle style table");
tablength = force->inumeric(arg[1]);
- if (tablength < 2) error->all("Illegal number of angle table entries");
+ if (tablength < 2) error->all(FLERR,"Illegal number of angle table entries");
// delete old tables, since cannot just change settings
for (int m = 0; m < ntables; m++) free_table(&tables[m]);
memory->sfree(tables);
if (allocated) {
memory->destroy(setflag);
memory->destroy(tabindex);
}
allocated = 0;
ntables = 0;
tables = NULL;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void AngleTable::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Illegal angle_coeff command");
+ if (narg != 3) error->all(FLERR,"Illegal angle_coeff command");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
int me;
MPI_Comm_rank(world,&me);
tables = (Table *)
memory->srealloc(tables,(ntables+1)*sizeof(Table),"angle:tables");
Table *tb = &tables[ntables];
null_table(tb);
if (me == 0) read_table(tb,arg[1],arg[2]);
bcast_table(tb);
// error check on table parameters
- if (tb->ninput <= 1) error->one("Invalid angle table length");
+ if (tb->ninput <= 1) error->one(FLERR,"Invalid angle table length");
double alo,ahi;
alo = tb->afile[0];
ahi = tb->afile[tb->ninput-1];
if (fabs(alo-0.0) > TINY || fabs(ahi-180.0) > TINY)
- error->all("Angle table must range from 0 to 180 degrees");
+ error->all(FLERR,"Angle table must range from 0 to 180 degrees");
// convert theta from degrees to radians
for (int i = 0; i < tb->ninput; i++){
tb->afile[i] *= PI/180.0;
tb->ffile[i] *= 180.0/PI;
}
// spline read-in and compute a,e,f vectors within table
spline_table(tb);
compute_table(tb);
// store ptr to table in tabindex
int count = 0;
for (int i = ilo; i <= ihi; i++) {
tabindex[i] = ntables;
setflag[i] = 1;
theta0[i] = tb->theta0;
count++;
}
ntables++;
- if (count == 0) error->all("Illegal angle_coeff command");
+ if (count == 0) error->all(FLERR,"Illegal angle_coeff command");
}
/* ----------------------------------------------------------------------
return an equilbrium angle length
should not be used, since don't know minimum of tabulated function
------------------------------------------------------------------------- */
double AngleTable::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void AngleTable::write_restart(FILE *fp)
{
fwrite(&tabstyle,sizeof(int),1,fp);
fwrite(&tablength,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void AngleTable::read_restart(FILE *fp)
{
if (comm->me == 0) {
fread(&tabstyle,sizeof(int),1,fp);
fread(&tablength,sizeof(int),1,fp);
}
MPI_Bcast(&tabstyle,1,MPI_DOUBLE,0,world);
MPI_Bcast(&tablength,1,MPI_INT,0,world);
allocate();
}
/* ---------------------------------------------------------------------- */
double AngleTable::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double theta = acos(c);
double u;
u_lookup(type,theta,u);
return u;
}
/* ---------------------------------------------------------------------- */
void AngleTable::null_table(Table *tb)
{
tb->afile = tb->efile = tb->ffile = NULL;
tb->e2file = tb->f2file = NULL;
tb->ang = tb->e = tb->de = NULL;
tb->f = tb->df = tb->e2 = tb->f2 = NULL;
}
/* ---------------------------------------------------------------------- */
void AngleTable::free_table(Table *tb)
{
memory->destroy(tb->afile);
memory->destroy(tb->efile);
memory->destroy(tb->ffile);
memory->destroy(tb->e2file);
memory->destroy(tb->f2file);
memory->destroy(tb->ang);
memory->destroy(tb->e);
memory->destroy(tb->de);
memory->destroy(tb->f);
memory->destroy(tb->df);
memory->destroy(tb->e2);
memory->destroy(tb->f2);
}
/* ----------------------------------------------------------------------
read table file, only called by proc 0
------------------------------------------------------------------------- */
void AngleTable::read_table(Table *tb, char *file, char *keyword)
{
char line[MAXLINE];
// open file
FILE *fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
// loop until section found with matching keyword
while (1) {
if (fgets(line,MAXLINE,fp) == NULL)
- error->one("Did not find keyword in table file");
+ error->one(FLERR,"Did not find keyword in table file");
if (strspn(line," \t\n") == strlen(line)) continue; // blank line
if (line[0] == '#') continue; // comment
if (strstr(line,keyword) == line) break; // matching keyword
fgets(line,MAXLINE,fp); // no match, skip section
param_extract(tb,line);
fgets(line,MAXLINE,fp);
for (int i = 0; i < tb->ninput; i++) fgets(line,MAXLINE,fp);
}
// read args on 2nd line of section
// allocate table arrays for file values
fgets(line,MAXLINE,fp);
param_extract(tb,line);
memory->create(tb->afile,tb->ninput,"angle:afile");
memory->create(tb->efile,tb->ninput,"angle:efile");
memory->create(tb->ffile,tb->ninput,"angle:ffile");
// read a,e,f table values from file
int itmp;
fgets(line,MAXLINE,fp);
for (int i = 0; i < tb->ninput; i++) {
fgets(line,MAXLINE,fp);
sscanf(line,"%d %lg %lg %lg",
&itmp,&tb->afile[i],&tb->efile[i],&tb->ffile[i]);
}
fclose(fp);
}
/* ----------------------------------------------------------------------
build spline representation of e,f over entire range of read-in table
this function sets these values in e2file,f2file
------------------------------------------------------------------------- */
void AngleTable::spline_table(Table *tb)
{
memory->create(tb->e2file,tb->ninput,"angle:e2file");
memory->create(tb->f2file,tb->ninput,"angle:f2file");
double ep0 = - tb->ffile[0];
double epn = - tb->ffile[tb->ninput-1];
spline(tb->afile,tb->efile,tb->ninput,ep0,epn,tb->e2file);
if (tb->fpflag == 0) {
tb->fplo = (tb->ffile[1] - tb->ffile[0]) / (tb->afile[1] - tb->afile[0]);
tb->fphi = (tb->ffile[tb->ninput-1] - tb->ffile[tb->ninput-2]) /
(tb->afile[tb->ninput-1] - tb->afile[tb->ninput-2]);
}
double fp0 = tb->fplo;
double fpn = tb->fphi;
spline(tb->afile,tb->ffile,tb->ninput,fp0,fpn,tb->f2file);
}
/* ----------------------------------------------------------------------
compute a,e,f vectors from splined values
------------------------------------------------------------------------- */
void AngleTable::compute_table(Table *tb)
{
// delta = table spacing in angle for N-1 bins
int tlm1 = tablength-1;
tb->delta = PI/ tlm1;
tb->invdelta = 1.0/tb->delta;
tb->deltasq6 = tb->delta*tb->delta / 6.0;
// N-1 evenly spaced bins in angle from 0 to PI
// ang,e,f = value at lower edge of bin
// de,df values = delta values of e,f
// ang,e,f are N in length so de,df arrays can compute difference
memory->create(tb->ang,tablength,"angle:ang");
memory->create(tb->e,tablength,"angle:e");
memory->create(tb->de,tlm1,"angle:de");
memory->create(tb->f,tablength,"angle:f");
memory->create(tb->df,tlm1,"angle:df");
memory->create(tb->e2,tablength,"angle:e2");
memory->create(tb->f2,tablength,"angle:f2");
double a;
for (int i = 0; i < tablength; i++) {
a = i*tb->delta;
tb->ang[i] = a;
tb->e[i] = splint(tb->afile,tb->efile,tb->e2file,tb->ninput,a);
tb->f[i] = splint(tb->afile,tb->ffile,tb->f2file,tb->ninput,a);
}
for (int i = 0; i < tlm1; i++) {
tb->de[i] = tb->e[i+1] - tb->e[i];
tb->df[i] = tb->f[i+1] - tb->f[i];
}
double ep0 = - tb->f[0];
double epn = - tb->f[tlm1];
spline(tb->ang,tb->e,tablength,ep0,epn,tb->e2);
spline(tb->ang,tb->f,tablength,tb->fplo,tb->fphi,tb->f2);
}
/* ----------------------------------------------------------------------
extract attributes from parameter line in table section
format of line: N value FP fplo fphi EQ theta0
N is required, other params are optional
------------------------------------------------------------------------- */
void AngleTable::param_extract(Table *tb, char *line)
{
tb->ninput = 0;
tb->fpflag = 0;
tb->theta0 = 180.0;
char *word = strtok(line," \t\n\r\f");
while (word) {
if (strcmp(word,"N") == 0) {
word = strtok(NULL," \t\n\r\f");
tb->ninput = atoi(word);
} else if (strcmp(word,"FP") == 0) {
tb->fpflag = 1;
word = strtok(NULL," \t\n\r\f");
tb->fplo = atof(word);
word = strtok(NULL," \t\n\r\f");
tb->fphi = atof(word);
tb->fplo *= (180.0/PI)*(180.0/PI);
tb->fphi *= (180.0/PI)*(180.0/PI);
} else if (strcmp(word,"EQ") == 0) {
word = strtok(NULL," \t\n\r\f");
tb->theta0 = atof(word);
} else {
- error->one("Invalid keyword in angle table parameters");
+ error->one(FLERR,"Invalid keyword in angle table parameters");
}
word = strtok(NULL," \t\n\r\f");
}
- if (tb->ninput == 0) error->one("Angle table parameters did not set N");
+ if (tb->ninput == 0) error->one(FLERR,"Angle table parameters did not set N");
}
/* ----------------------------------------------------------------------
broadcast read-in table info from proc 0 to other procs
this function communicates these values in Table:
ninput,afile,efile,ffile,fpflag,fplo,fphi,theta0
------------------------------------------------------------------------- */
void AngleTable::bcast_table(Table *tb)
{
MPI_Bcast(&tb->ninput,1,MPI_INT,0,world);
int me;
MPI_Comm_rank(world,&me);
if (me > 0) {
memory->create(tb->afile,tb->ninput,"angle:afile");
memory->create(tb->efile,tb->ninput,"angle:efile");
memory->create(tb->ffile,tb->ninput,"angle:ffile");
}
MPI_Bcast(tb->afile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(tb->efile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(tb->ffile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(&tb->fpflag,1,MPI_INT,0,world);
if (tb->fpflag) {
MPI_Bcast(&tb->fplo,1,MPI_DOUBLE,0,world);
MPI_Bcast(&tb->fphi,1,MPI_DOUBLE,0,world);
}
MPI_Bcast(&tb->theta0,1,MPI_DOUBLE,0,world);
}
/* ----------------------------------------------------------------------
spline and splint routines modified from Numerical Recipes
------------------------------------------------------------------------- */
void AngleTable::spline(double *x, double *y, int n,
double yp1, double ypn, double *y2)
{
int i,k;
double p,qn,sig,un;
double *u = new double[n];
if (yp1 > 0.99e30) y2[0] = u[0] = 0.0;
else {
y2[0] = -0.5;
u[0] = (3.0/(x[1]-x[0])) * ((y[1]-y[0]) / (x[1]-x[0]) - yp1);
}
for (i = 1; i < n-1; i++) {
sig = (x[i]-x[i-1]) / (x[i+1]-x[i-1]);
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 (ypn > 0.99e30) qn = un = 0.0;
else {
qn = 0.5;
un = (3.0/(x[n-1]-x[n-2])) * (ypn - (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 (k = n-2; k >= 0; k--) y2[k] = y2[k]*y2[k+1] + u[k];
delete [] u;
}
/* ---------------------------------------------------------------------- */
double AngleTable::splint(double *xa, double *ya, double *y2a, int n, double x)
{
int klo,khi,k;
double h,b,a,y;
klo = 0;
khi = n-1;
while (khi-klo > 1) {
k = (khi+klo) >> 1;
if (xa[k] > x) khi = k;
else klo = k;
}
h = xa[khi]-xa[klo];
a = (xa[khi]-x) / h;
b = (x-xa[klo]) / h;
y = a*ya[klo] + b*ya[khi] +
((a*a*a-a)*y2a[klo] + (b*b*b-b)*y2a[khi]) * (h*h)/6.0;
return y;
}
/* ----------------------------------------------------------------------
calculate potential u and force f at angle x
------------------------------------------------------------------------- */
void AngleTable::uf_lookup(int type, double x, double &u, double &f)
{
int itable;
double fraction,a,b;
Table *tb = &tables[tabindex[type]];
if (tabstyle == LINEAR) {
itable = static_cast<int> ( x * tb->invdelta);
fraction = (x - tb->ang[itable]) * tb->invdelta;
u = tb->e[itable] + fraction*tb->de[itable];
f = tb->f[itable] + fraction*tb->df[itable];
} else if (tabstyle == SPLINE) {
itable = static_cast<int> ( x * tb->invdelta);
fraction = (x - tb->ang[itable]) * tb->invdelta;
b = (x - tb->ang[itable]) * tb->invdelta;
a = 1.0 - b;
u = a * tb->e[itable] + b * tb->e[itable+1] +
((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) *
tb->deltasq6;
f = a * tb->f[itable] + b * tb->f[itable+1] +
((a*a*a-a)*tb->f2[itable] + (b*b*b-b)*tb->f2[itable+1]) *
tb->deltasq6;
}
}
/* ----------------------------------------------------------------------
calculate potential u at angle x
------------------------------------------------------------------------- */
void AngleTable::u_lookup(int type, double x, double &u)
{
int itable;
double fraction,a,b;
Table *tb = &tables[tabindex[type]];
if (tabstyle == LINEAR) {
itable = static_cast<int> ( x * tb->invdelta);
fraction = (x - tb->ang[itable]) * tb->invdelta;
u = tb->e[itable] + fraction*tb->de[itable];
} else if (tabstyle == SPLINE) {
itable = static_cast<int> ( x * tb->invdelta);
fraction = (x - tb->ang[itable]) * tb->invdelta;
b = (x - tb->ang[itable]) * tb->invdelta;
a = 1.0 - b;
u = a * tb->e[itable] + b * tb->e[itable+1] +
((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) *
tb->deltasq6;
}
}
diff --git a/src/MOLECULE/atom_vec_angle.cpp b/src/MOLECULE/atom_vec_angle.cpp
index 72afefb8d..46478bac0 100644
--- a/src/MOLECULE/atom_vec_angle.cpp
+++ b/src/MOLECULE/atom_vec_angle.cpp
@@ -1,843 +1,840 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "atom_vec_angle.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecAngle::AtomVecAngle(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 1;
bonds_allow = angles_allow = 1;
mass_type = 1;
comm_x_only = comm_f_only = 1;
size_forward = 3;
size_reverse = 3;
size_border = 7;
size_velocity = 3;
size_data_atom = 6;
size_data_vel = 4;
xcol_data = 4;
atom->molecule_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecAngle::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
molecule = memory->grow(atom->molecule,nmax,"atom:molecule");
nspecial = memory->grow(atom->nspecial,nmax,3,"atom:nspecial");
special = memory->grow(atom->special,nmax,atom->maxspecial,"atom:special");
num_bond = memory->grow(atom->num_bond,nmax,"atom:num_bond");
bond_type = memory->grow(atom->bond_type,nmax,atom->bond_per_atom,
"atom:bond_type");
bond_atom = memory->grow(atom->bond_atom,nmax,atom->bond_per_atom,
"atom:bond_atom");
num_angle = memory->grow(atom->num_angle,nmax,"atom:num_angle");
angle_type = memory->grow(atom->angle_type,nmax,atom->angle_per_atom,
"atom:angle_type");
angle_atom1 = memory->grow(atom->angle_atom1,nmax,atom->angle_per_atom,
"atom:angle_atom1");
angle_atom2 = memory->grow(atom->angle_atom2,nmax,atom->angle_per_atom,
"atom:angle_atom2");
angle_atom3 = memory->grow(atom->angle_atom3,nmax,atom->angle_per_atom,
"atom:angle_atom3");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecAngle::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
molecule = atom->molecule;
nspecial = atom->nspecial; special = atom->special;
num_bond = atom->num_bond; bond_type = atom->bond_type;
bond_atom = atom->bond_atom;
num_angle = atom->num_angle; angle_type = atom->angle_type;
angle_atom1 = atom->angle_atom1; angle_atom2 = atom->angle_atom2;
angle_atom3 = atom->angle_atom3;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecAngle::copy(int i, int j, int delflag)
{
int k;
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
molecule[j] = molecule[i];
num_bond[j] = num_bond[i];
for (k = 0; k < num_bond[j]; k++) {
bond_type[j][k] = bond_type[i][k];
bond_atom[j][k] = bond_atom[i][k];
}
num_angle[j] = num_angle[i];
for (k = 0; k < num_angle[j]; k++) {
angle_type[j][k] = angle_type[i][k];
angle_atom1[j][k] = angle_atom1[i][k];
angle_atom2[j][k] = angle_atom2[i][k];
angle_atom3[j][k] = angle_atom3[i][k];
}
nspecial[j][0] = nspecial[i][0];
nspecial[j][1] = nspecial[i][1];
nspecial[j][2] = nspecial[i][2];
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAngle::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecAngle::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAngle::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
} else {
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = molecule[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAngle::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
molecule[i] = static_cast<int> (buf[m++]);
}
}
/* ---------------------------------------------------------------------- */
void AtomVecAngle::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
molecule[i] = static_cast<int> (buf[m++]);
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
molecule[i] = static_cast<int> (buf[m++]);
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecAngle::pack_exchange(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = bond_type[i][k];
buf[m++] = bond_atom[i][k];
}
buf[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf[m++] = angle_type[i][k];
buf[m++] = angle_atom1[i][k];
buf[m++] = angle_atom2[i][k];
buf[m++] = angle_atom3[i][k];
}
buf[m++] = nspecial[i][0];
buf[m++] = nspecial[i][1];
buf[m++] = nspecial[i][2];
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAngle::unpack_exchange(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
num_angle[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[nlocal]; k++) {
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
}
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
for (k = 0; k < nspecial[nlocal][2]; k++)
special[nlocal][k] = static_cast<int> (buf[m++]);
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecAngle::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 0;
for (i = 0; i < nlocal; i++)
n += 14 + 2*num_bond[i] + 4*num_angle[i];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecAngle::pack_restart(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = MAX(bond_type[i][k],-bond_type[i][k]);
buf[m++] = bond_atom[i][k];
}
buf[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf[m++] = MAX(angle_type[i][k],-angle_type[i][k]);
buf[m++] = angle_atom1[i][k];
buf[m++] = angle_atom2[i][k];
buf[m++] = angle_atom3[i][k];
}
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecAngle::unpack_restart(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
num_angle[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[nlocal]; k++) {
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
}
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecAngle::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
molecule[nlocal] = 0;
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
nspecial[nlocal][0] = nspecial[nlocal][1] = nspecial[nlocal][2] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecAngle::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
molecule[nlocal] = atoi(values[1]);
type[nlocal] = atoi(values[2]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecAngle::data_atom_hybrid(int nlocal, char **values)
{
molecule[nlocal] = atoi(values[0]);
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
return 1;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecAngle::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("molecule")) bytes += memory->usage(molecule,nmax);
if (atom->memcheck("nspecial")) bytes += memory->usage(nspecial,nmax,3);
if (atom->memcheck("special"))
bytes += memory->usage(special,nmax,atom->maxspecial);
if (atom->memcheck("num_bond")) bytes += memory->usage(num_bond,nmax);
if (atom->memcheck("bond_type"))
bytes += memory->usage(bond_type,nmax,atom->bond_per_atom);
if (atom->memcheck("bond_atom"))
bytes += memory->usage(bond_atom,nmax,atom->bond_per_atom);
if (atom->memcheck("num_angle")) bytes += memory->usage(num_angle,nmax);
if (atom->memcheck("angle_type"))
bytes += memory->usage(angle_type,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom1"))
bytes += memory->usage(angle_atom1,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom2"))
bytes += memory->usage(angle_atom2,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom3"))
bytes += memory->usage(angle_atom3,nmax,atom->angle_per_atom);
return bytes;
}
diff --git a/src/MOLECULE/atom_vec_bond.cpp b/src/MOLECULE/atom_vec_bond.cpp
index fb0a3e058..700eb275a 100644
--- a/src/MOLECULE/atom_vec_bond.cpp
+++ b/src/MOLECULE/atom_vec_bond.cpp
@@ -1,791 +1,788 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "atom_vec_bond.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecBond::AtomVecBond(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 1;
bonds_allow = 1;
mass_type = 1;
comm_x_only = comm_f_only = 1;
size_forward = 3;
size_reverse = 3;
size_border = 7;
size_velocity = 3;
size_data_atom = 6;
size_data_vel = 4;
xcol_data = 4;
atom->molecule_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecBond::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
molecule = memory->grow(atom->molecule,nmax,"atom:molecule");
nspecial = memory->grow(atom->nspecial,nmax,3,"atom:nspecial");
special = memory->grow(atom->special,nmax,atom->maxspecial,"atom:special");
num_bond = memory->grow(atom->num_bond,nmax,"atom:num_bond");
bond_type = memory->grow(atom->bond_type,nmax,atom->bond_per_atom,
"atom:bond_type");
bond_atom = memory->grow(atom->bond_atom,nmax,atom->bond_per_atom,
"atom:bond_atom");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecBond::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
molecule = atom->molecule;
nspecial = atom->nspecial; special = atom->special;
num_bond = atom->num_bond; bond_type = atom->bond_type;
bond_atom = atom->bond_atom;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecBond::copy(int i, int j, int delflag)
{
int k;
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
molecule[j] = molecule[i];
num_bond[j] = num_bond[i];
for (k = 0; k < num_bond[j]; k++) {
bond_type[j][k] = bond_type[i][k];
bond_atom[j][k] = bond_atom[i][k];
}
nspecial[j][0] = nspecial[i][0];
nspecial[j][1] = nspecial[i][1];
nspecial[j][2] = nspecial[i][2];
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecBond::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecBond::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecBond::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = molecule[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecBond::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
molecule[i] = static_cast<int> (buf[m++]);
}
}
/* ---------------------------------------------------------------------- */
void AtomVecBond::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
molecule[i] = static_cast<int> (buf[m++]);
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
molecule[i] = static_cast<int> (buf[m++]);
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecBond::pack_exchange(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = bond_type[i][k];
buf[m++] = bond_atom[i][k];
}
buf[m++] = nspecial[i][0];
buf[m++] = nspecial[i][1];
buf[m++] = nspecial[i][2];
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecBond::unpack_exchange(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
for (k = 0; k < nspecial[nlocal][2]; k++)
special[nlocal][k] = static_cast<int> (buf[m++]);
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecBond::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 0;
for (i = 0; i < nlocal; i++)
n += 13 + 2*num_bond[i];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecBond::pack_restart(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = MAX(bond_type[i][k],-bond_type[i][k]);
buf[m++] = bond_atom[i][k];
}
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecBond::unpack_restart(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecBond::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
molecule[nlocal] = 0;
num_bond[nlocal] = 0;
nspecial[nlocal][0] = nspecial[nlocal][1] = nspecial[nlocal][2] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecBond::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
molecule[nlocal] = atoi(values[1]);
type[nlocal] = atoi(values[2]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
num_bond[nlocal] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecBond::data_atom_hybrid(int nlocal, char **values)
{
molecule[nlocal] = atoi(values[0]);
num_bond[nlocal] = 0;
return 1;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecBond::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("molecule")) bytes += memory->usage(molecule,nmax);
if (atom->memcheck("nspecial")) bytes += memory->usage(nspecial,nmax,3);
if (atom->memcheck("special"))
bytes += memory->usage(special,nmax,atom->maxspecial);
if (atom->memcheck("num_bond")) bytes += memory->usage(num_bond,nmax);
if (atom->memcheck("bond_type"))
bytes += memory->usage(bond_type,nmax,atom->bond_per_atom);
if (atom->memcheck("bond_atom"))
bytes += memory->usage(bond_atom,nmax,atom->bond_per_atom);
return bytes;
}
diff --git a/src/MOLECULE/atom_vec_full.cpp b/src/MOLECULE/atom_vec_full.cpp
index 15b3c3a84..5a14488fd 100644
--- a/src/MOLECULE/atom_vec_full.cpp
+++ b/src/MOLECULE/atom_vec_full.cpp
@@ -1,1038 +1,1035 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "atom_vec_full.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecFull::AtomVecFull(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 1;
bonds_allow = angles_allow = dihedrals_allow = impropers_allow = 1;
mass_type = 1;
comm_x_only = comm_f_only = 1;
size_forward = 3;
size_reverse = 3;
size_border = 8;
size_velocity = 3;
size_data_atom = 7;
size_data_vel = 4;
xcol_data = 5;
atom->molecule_flag = atom->q_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecFull::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
q = memory->grow(atom->q,nmax,"atom:q");
molecule = memory->grow(atom->molecule,nmax,"atom:molecule");
nspecial = memory->grow(atom->nspecial,nmax,3,"atom:nspecial");
special = memory->grow(atom->special,nmax,atom->maxspecial,"atom:special");
num_bond = memory->grow(atom->num_bond,nmax,"atom:num_bond");
bond_type = memory->grow(atom->bond_type,nmax,atom->bond_per_atom,
"atom:bond_type");
bond_atom = memory->grow(atom->bond_atom,nmax,atom->bond_per_atom,
"atom:bond_atom");
num_angle = memory->grow(atom->num_angle,nmax,"atom:num_angle");
angle_type = memory->grow(atom->angle_type,nmax,atom->angle_per_atom,
"atom:angle_type");
angle_atom1 = memory->grow(atom->angle_atom1,nmax,atom->angle_per_atom,
"atom:angle_atom1");
angle_atom2 = memory->grow(atom->angle_atom2,nmax,atom->angle_per_atom,
"atom:angle_atom2");
angle_atom3 = memory->grow(atom->angle_atom3,nmax,atom->angle_per_atom,
"atom:angle_atom3");
num_dihedral = memory->grow(atom->num_dihedral,nmax,"atom:num_dihedral");
dihedral_type = memory->grow(atom->dihedral_type,nmax,
atom->dihedral_per_atom,"atom:dihedral_type");
dihedral_atom1 =
memory->grow(atom->dihedral_atom1,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom1");
dihedral_atom2 =
memory->grow(atom->dihedral_atom2,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom2");
dihedral_atom3 =
memory->grow(atom->dihedral_atom3,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom3");
dihedral_atom4 =
memory->grow(atom->dihedral_atom4,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom4");
num_improper = memory->grow(atom->num_improper,nmax,"atom:num_improper");
improper_type =
memory->grow(atom->improper_type,nmax,atom->improper_per_atom,
"atom:improper_type");
improper_atom1 =
memory->grow(atom->improper_atom1,nmax,atom->improper_per_atom,
"atom:improper_atom1");
improper_atom2 =
memory->grow(atom->improper_atom2,nmax,atom->improper_per_atom,
"atom:improper_atom2");
improper_atom3 =
memory->grow(atom->improper_atom3,nmax,atom->improper_per_atom,
"atom:improper_atom3");
improper_atom4 =
memory->grow(atom->improper_atom4,nmax,atom->improper_per_atom,
"atom:improper_atom4");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecFull::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
q = atom->q; molecule = atom->molecule;
nspecial = atom->nspecial; special = atom->special;
num_bond = atom->num_bond; bond_type = atom->bond_type;
bond_atom = atom->bond_atom;
num_angle = atom->num_angle; angle_type = atom->angle_type;
angle_atom1 = atom->angle_atom1; angle_atom2 = atom->angle_atom2;
angle_atom3 = atom->angle_atom3;
num_dihedral = atom->num_dihedral; dihedral_type = atom->dihedral_type;
dihedral_atom1 = atom->dihedral_atom1; dihedral_atom2 = atom->dihedral_atom2;
dihedral_atom3 = atom->dihedral_atom3; dihedral_atom4 = atom->dihedral_atom4;
num_improper = atom->num_improper; improper_type = atom->improper_type;
improper_atom1 = atom->improper_atom1; improper_atom2 = atom->improper_atom2;
improper_atom3 = atom->improper_atom3; improper_atom4 = atom->improper_atom4;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecFull::copy(int i, int j, int delflag)
{
int k;
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
q[j] = q[i];
molecule[j] = molecule[i];
num_bond[j] = num_bond[i];
for (k = 0; k < num_bond[j]; k++) {
bond_type[j][k] = bond_type[i][k];
bond_atom[j][k] = bond_atom[i][k];
}
num_angle[j] = num_angle[i];
for (k = 0; k < num_angle[j]; k++) {
angle_type[j][k] = angle_type[i][k];
angle_atom1[j][k] = angle_atom1[i][k];
angle_atom2[j][k] = angle_atom2[i][k];
angle_atom3[j][k] = angle_atom3[i][k];
}
num_dihedral[j] = num_dihedral[i];
for (k = 0; k < num_dihedral[j]; k++) {
dihedral_type[j][k] = dihedral_type[i][k];
dihedral_atom1[j][k] = dihedral_atom1[i][k];
dihedral_atom2[j][k] = dihedral_atom2[i][k];
dihedral_atom3[j][k] = dihedral_atom3[i][k];
dihedral_atom4[j][k] = dihedral_atom4[i][k];
}
num_improper[j] = num_improper[i];
for (k = 0; k < num_improper[j]; k++) {
improper_type[j][k] = improper_type[i][k];
improper_atom1[j][k] = improper_atom1[i][k];
improper_atom2[j][k] = improper_atom2[i][k];
improper_atom3[j][k] = improper_atom3[i][k];
improper_atom4[j][k] = improper_atom4[i][k];
}
nspecial[j][0] = nspecial[i][0];
nspecial[j][1] = nspecial[i][1];
nspecial[j][2] = nspecial[i][2];
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecFull::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecFull::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecFull::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = molecule[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = molecule[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = molecule[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = molecule[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = molecule[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = q[j];
buf[m++] = molecule[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecFull::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
molecule[i] = static_cast<int> (buf[m++]);
}
}
/* ---------------------------------------------------------------------- */
void AtomVecFull::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
molecule[i] = static_cast<int> (buf[m++]);
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
q[i] = buf[m++];
molecule[i] = static_cast<int> (buf[m++]);
}
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecFull::pack_exchange(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = q[i];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = bond_type[i][k];
buf[m++] = bond_atom[i][k];
}
buf[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf[m++] = angle_type[i][k];
buf[m++] = angle_atom1[i][k];
buf[m++] = angle_atom2[i][k];
buf[m++] = angle_atom3[i][k];
}
buf[m++] = num_dihedral[i];
for (k = 0; k < num_dihedral[i]; k++) {
buf[m++] = dihedral_type[i][k];
buf[m++] = dihedral_atom1[i][k];
buf[m++] = dihedral_atom2[i][k];
buf[m++] = dihedral_atom3[i][k];
buf[m++] = dihedral_atom4[i][k];
}
buf[m++] = num_improper[i];
for (k = 0; k < num_improper[i]; k++) {
buf[m++] = improper_type[i][k];
buf[m++] = improper_atom1[i][k];
buf[m++] = improper_atom2[i][k];
buf[m++] = improper_atom3[i][k];
buf[m++] = improper_atom4[i][k];
}
buf[m++] = nspecial[i][0];
buf[m++] = nspecial[i][1];
buf[m++] = nspecial[i][2];
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecFull::unpack_exchange(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
q[nlocal] = buf[m++];
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
num_angle[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[nlocal]; k++) {
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
}
num_dihedral[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_dihedral[nlocal]; k++) {
dihedral_type[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom1[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom2[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom3[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
num_improper[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_improper[nlocal]; k++) {
improper_type[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom1[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom2[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom3[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
for (k = 0; k < nspecial[nlocal][2]; k++)
special[nlocal][k] = static_cast<int> (buf[m++]);
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecFull::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 0;
for (i = 0; i < nlocal; i++)
n += 17 + 2*num_bond[i] + 4*num_angle[i] +
5*num_dihedral[i] + 5*num_improper[i];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecFull::pack_restart(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = q[i];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = MAX(bond_type[i][k],-bond_type[i][k]);
buf[m++] = bond_atom[i][k];
}
buf[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf[m++] = MAX(angle_type[i][k],-angle_type[i][k]);
buf[m++] = angle_atom1[i][k];
buf[m++] = angle_atom2[i][k];
buf[m++] = angle_atom3[i][k];
}
buf[m++] = num_dihedral[i];
for (k = 0; k < num_dihedral[i]; k++) {
buf[m++] = MAX(dihedral_type[i][k],-dihedral_type[i][k]);
buf[m++] = dihedral_atom1[i][k];
buf[m++] = dihedral_atom2[i][k];
buf[m++] = dihedral_atom3[i][k];
buf[m++] = dihedral_atom4[i][k];
}
buf[m++] = num_improper[i];
for (k = 0; k < num_improper[i]; k++) {
buf[m++] = MAX(improper_type[i][k],-improper_type[i][k]);
buf[m++] = improper_atom1[i][k];
buf[m++] = improper_atom2[i][k];
buf[m++] = improper_atom3[i][k];
buf[m++] = improper_atom4[i][k];
}
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecFull::unpack_restart(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
q[nlocal] = buf[m++];
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
num_angle[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[nlocal]; k++) {
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
}
num_dihedral[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_dihedral[nlocal]; k++) {
dihedral_type[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom1[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom2[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom3[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
num_improper[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_improper[nlocal]; k++) {
improper_type[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom1[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom2[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom3[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecFull::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
q[nlocal] = 0.0;
molecule[nlocal] = 0;
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
num_dihedral[nlocal] = 0;
num_improper[nlocal] = 0;
nspecial[nlocal][0] = nspecial[nlocal][1] = nspecial[nlocal][2] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecFull::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
molecule[nlocal] = atoi(values[1]);
type[nlocal] = atoi(values[2]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
q[nlocal] = atof(values[3]);
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
num_dihedral[nlocal] = 0;
num_improper[nlocal] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecFull::data_atom_hybrid(int nlocal, char **values)
{
molecule[nlocal] = atoi(values[1]);
q[nlocal] = atof(values[3]);
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
num_dihedral[nlocal] = 0;
num_improper[nlocal] = 0;
return 2;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecFull::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("q")) bytes += memory->usage(q,nmax);
if (atom->memcheck("molecule")) bytes += memory->usage(molecule,nmax);
if (atom->memcheck("nspecial")) bytes += memory->usage(nspecial,nmax,3);
if (atom->memcheck("special"))
bytes += memory->usage(special,nmax,atom->maxspecial);
if (atom->memcheck("num_bond")) bytes += memory->usage(num_bond,nmax);
if (atom->memcheck("bond_type"))
bytes += memory->usage(bond_type,nmax,atom->bond_per_atom);
if (atom->memcheck("bond_atom"))
bytes += memory->usage(bond_atom,nmax,atom->bond_per_atom);
if (atom->memcheck("num_angle")) bytes += memory->usage(num_angle,nmax);
if (atom->memcheck("angle_type"))
bytes += memory->usage(angle_type,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom1"))
bytes += memory->usage(angle_atom1,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom2"))
bytes += memory->usage(angle_atom2,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom3"))
bytes += memory->usage(angle_atom3,nmax,atom->angle_per_atom);
if (atom->memcheck("num_dihedral")) bytes += memory->usage(num_dihedral,nmax);
if (atom->memcheck("dihedral_type"))
bytes += memory->usage(dihedral_type,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom1"))
bytes += memory->usage(dihedral_atom1,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom2"))
bytes += memory->usage(dihedral_atom2,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom3"))
bytes += memory->usage(dihedral_atom3,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom4"))
bytes += memory->usage(dihedral_atom4,nmax,atom->dihedral_per_atom);
if (atom->memcheck("num_improper")) bytes += memory->usage(num_improper,nmax);
if (atom->memcheck("improper_type"))
bytes += memory->usage(improper_type,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom1"))
bytes += memory->usage(improper_atom1,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom2"))
bytes += memory->usage(improper_atom2,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom3"))
bytes += memory->usage(improper_atom3,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom4"))
bytes += memory->usage(improper_atom4,nmax,atom->improper_per_atom);
return bytes;
}
diff --git a/src/MOLECULE/atom_vec_molecular.cpp b/src/MOLECULE/atom_vec_molecular.cpp
index 75c7df86c..1672541b6 100644
--- a/src/MOLECULE/atom_vec_molecular.cpp
+++ b/src/MOLECULE/atom_vec_molecular.cpp
@@ -1,1017 +1,1014 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "atom_vec_molecular.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecMolecular::AtomVecMolecular(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 1;
bonds_allow = angles_allow = dihedrals_allow = impropers_allow = 1;
mass_type = 1;
comm_x_only = comm_f_only = 1;
size_forward = 3;
size_reverse = 3;
size_border = 7;
size_velocity = 3;
size_data_atom = 6;
size_data_vel = 4;
xcol_data = 4;
atom->molecule_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecMolecular::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
molecule = memory->grow(atom->molecule,nmax,"atom:molecule");
nspecial = memory->grow(atom->nspecial,nmax,3,"atom:nspecial");
special = memory->grow(atom->special,nmax,atom->maxspecial,"atom:special");
num_bond = memory->grow(atom->num_bond,nmax,"atom:num_bond");
bond_type = memory->grow(atom->bond_type,nmax,atom->bond_per_atom,
"atom:bond_type");
bond_atom = memory->grow(atom->bond_atom,nmax,atom->bond_per_atom,
"atom:bond_atom");
num_angle = memory->grow(atom->num_angle,nmax,"atom:num_angle");
angle_type = memory->grow(atom->angle_type,nmax,atom->angle_per_atom,
"atom:angle_type");
angle_atom1 = memory->grow(atom->angle_atom1,nmax,atom->angle_per_atom,
"atom:angle_atom1");
angle_atom2 = memory->grow(atom->angle_atom2,nmax,atom->angle_per_atom,
"atom:angle_atom2");
angle_atom3 = memory->grow(atom->angle_atom3,nmax,atom->angle_per_atom,
"atom:angle_atom3");
num_dihedral = memory->grow(atom->num_dihedral,nmax,"atom:num_dihedral");
dihedral_type = memory->grow(atom->dihedral_type,nmax,
atom->dihedral_per_atom,"atom:dihedral_type");
dihedral_atom1 =
memory->grow(atom->dihedral_atom1,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom1");
dihedral_atom2 =
memory->grow(atom->dihedral_atom2,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom2");
dihedral_atom3 =
memory->grow(atom->dihedral_atom3,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom3");
dihedral_atom4 =
memory->grow(atom->dihedral_atom4,nmax,atom->dihedral_per_atom,
"atom:dihedral_atom4");
num_improper = memory->grow(atom->num_improper,nmax,"atom:num_improper");
improper_type =
memory->grow(atom->improper_type,nmax,atom->improper_per_atom,
"atom:improper_type");
improper_atom1 =
memory->grow(atom->improper_atom1,nmax,atom->improper_per_atom,
"atom:improper_atom1");
improper_atom2 =
memory->grow(atom->improper_atom2,nmax,atom->improper_per_atom,
"atom:improper_atom2");
improper_atom3 =
memory->grow(atom->improper_atom3,nmax,atom->improper_per_atom,
"atom:improper_atom3");
improper_atom4 =
memory->grow(atom->improper_atom4,nmax,atom->improper_per_atom,
"atom:improper_atom4");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecMolecular::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
molecule = atom->molecule;
nspecial = atom->nspecial; special = atom->special;
num_bond = atom->num_bond; bond_type = atom->bond_type;
bond_atom = atom->bond_atom;
num_angle = atom->num_angle; angle_type = atom->angle_type;
angle_atom1 = atom->angle_atom1; angle_atom2 = atom->angle_atom2;
angle_atom3 = atom->angle_atom3;
num_dihedral = atom->num_dihedral; dihedral_type = atom->dihedral_type;
dihedral_atom1 = atom->dihedral_atom1; dihedral_atom2 = atom->dihedral_atom2;
dihedral_atom3 = atom->dihedral_atom3; dihedral_atom4 = atom->dihedral_atom4;
num_improper = atom->num_improper; improper_type = atom->improper_type;
improper_atom1 = atom->improper_atom1; improper_atom2 = atom->improper_atom2;
improper_atom3 = atom->improper_atom3; improper_atom4 = atom->improper_atom4;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecMolecular::copy(int i, int j, int delflag)
{
int k;
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
molecule[j] = molecule[i];
num_bond[j] = num_bond[i];
for (k = 0; k < num_bond[j]; k++) {
bond_type[j][k] = bond_type[i][k];
bond_atom[j][k] = bond_atom[i][k];
}
num_angle[j] = num_angle[i];
for (k = 0; k < num_angle[j]; k++) {
angle_type[j][k] = angle_type[i][k];
angle_atom1[j][k] = angle_atom1[i][k];
angle_atom2[j][k] = angle_atom2[i][k];
angle_atom3[j][k] = angle_atom3[i][k];
}
num_dihedral[j] = num_dihedral[i];
for (k = 0; k < num_dihedral[j]; k++) {
dihedral_type[j][k] = dihedral_type[i][k];
dihedral_atom1[j][k] = dihedral_atom1[i][k];
dihedral_atom2[j][k] = dihedral_atom2[i][k];
dihedral_atom3[j][k] = dihedral_atom3[i][k];
dihedral_atom4[j][k] = dihedral_atom4[i][k];
}
num_improper[j] = num_improper[i];
for (k = 0; k < num_improper[j]; k++) {
improper_type[j][k] = improper_type[i][k];
improper_atom1[j][k] = improper_atom1[i][k];
improper_atom2[j][k] = improper_atom2[i][k];
improper_atom3[j][k] = improper_atom3[i][k];
improper_atom4[j][k] = improper_atom4[i][k];
}
nspecial[j][0] = nspecial[i][0];
nspecial[j][1] = nspecial[i][1];
nspecial[j][2] = nspecial[i][2];
for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecMolecular::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecMolecular::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecMolecular::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = molecule[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = molecule[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecMolecular::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
molecule[i] = static_cast<int> (buf[m++]);
}
}
/* ---------------------------------------------------------------------- */
void AtomVecMolecular::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
molecule[i] = static_cast<int> (buf[m++]);
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
molecule[i] = static_cast<int> (buf[m++]);
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecMolecular::pack_exchange(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = bond_type[i][k];
buf[m++] = bond_atom[i][k];
}
buf[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf[m++] = angle_type[i][k];
buf[m++] = angle_atom1[i][k];
buf[m++] = angle_atom2[i][k];
buf[m++] = angle_atom3[i][k];
}
buf[m++] = num_dihedral[i];
for (k = 0; k < num_dihedral[i]; k++) {
buf[m++] = dihedral_type[i][k];
buf[m++] = dihedral_atom1[i][k];
buf[m++] = dihedral_atom2[i][k];
buf[m++] = dihedral_atom3[i][k];
buf[m++] = dihedral_atom4[i][k];
}
buf[m++] = num_improper[i];
for (k = 0; k < num_improper[i]; k++) {
buf[m++] = improper_type[i][k];
buf[m++] = improper_atom1[i][k];
buf[m++] = improper_atom2[i][k];
buf[m++] = improper_atom3[i][k];
buf[m++] = improper_atom4[i][k];
}
buf[m++] = nspecial[i][0];
buf[m++] = nspecial[i][1];
buf[m++] = nspecial[i][2];
for (k = 0; k < nspecial[i][2]; k++) buf[m++] = special[i][k];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMolecular::unpack_exchange(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
num_angle[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[nlocal]; k++) {
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
}
num_dihedral[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_dihedral[nlocal]; k++) {
dihedral_type[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom1[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom2[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom3[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
num_improper[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_improper[nlocal]; k++) {
improper_type[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom1[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom2[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom3[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
nspecial[nlocal][0] = static_cast<int> (buf[m++]);
nspecial[nlocal][1] = static_cast<int> (buf[m++]);
nspecial[nlocal][2] = static_cast<int> (buf[m++]);
for (k = 0; k < nspecial[nlocal][2]; k++)
special[nlocal][k] = static_cast<int> (buf[m++]);
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecMolecular::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 0;
for (i = 0; i < nlocal; i++)
n += 16 + 2*num_bond[i] + 4*num_angle[i] +
5*num_dihedral[i] + 5*num_improper[i];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecMolecular::pack_restart(int i, double *buf)
{
int k;
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = molecule[i];
buf[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf[m++] = MAX(bond_type[i][k],-bond_type[i][k]);
buf[m++] = bond_atom[i][k];
}
buf[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf[m++] = MAX(angle_type[i][k],-angle_type[i][k]);
buf[m++] = angle_atom1[i][k];
buf[m++] = angle_atom2[i][k];
buf[m++] = angle_atom3[i][k];
}
buf[m++] = num_dihedral[i];
for (k = 0; k < num_dihedral[i]; k++) {
buf[m++] = MAX(dihedral_type[i][k],-dihedral_type[i][k]);
buf[m++] = dihedral_atom1[i][k];
buf[m++] = dihedral_atom2[i][k];
buf[m++] = dihedral_atom3[i][k];
buf[m++] = dihedral_atom4[i][k];
}
buf[m++] = num_improper[i];
for (k = 0; k < num_improper[i]; k++) {
buf[m++] = MAX(improper_type[i][k],-improper_type[i][k]);
buf[m++] = improper_atom1[i][k];
buf[m++] = improper_atom2[i][k];
buf[m++] = improper_atom3[i][k];
buf[m++] = improper_atom4[i][k];
}
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecMolecular::unpack_restart(double *buf)
{
int k;
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
molecule[nlocal] = static_cast<int> (buf[m++]);
num_bond[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[nlocal]; k++) {
bond_type[nlocal][k] = static_cast<int> (buf[m++]);
bond_atom[nlocal][k] = static_cast<int> (buf[m++]);
}
num_angle[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[nlocal]; k++) {
angle_type[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom1[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom2[nlocal][k] = static_cast<int> (buf[m++]);
angle_atom3[nlocal][k] = static_cast<int> (buf[m++]);
}
num_dihedral[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_dihedral[nlocal]; k++) {
dihedral_type[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom1[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom2[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom3[nlocal][k] = static_cast<int> (buf[m++]);
dihedral_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
num_improper[nlocal] = static_cast<int> (buf[m++]);
for (k = 0; k < num_improper[nlocal]; k++) {
improper_type[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom1[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom2[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom3[nlocal][k] = static_cast<int> (buf[m++]);
improper_atom4[nlocal][k] = static_cast<int> (buf[m++]);
}
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecMolecular::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
molecule[nlocal] = 0;
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
num_dihedral[nlocal] = 0;
num_improper[nlocal] = 0;
nspecial[nlocal][0] = nspecial[nlocal][1] = nspecial[nlocal][2] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecMolecular::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
molecule[nlocal] = atoi(values[1]);
type[nlocal] = atoi(values[2]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
num_dihedral[nlocal] = 0;
num_improper[nlocal] = 0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecMolecular::data_atom_hybrid(int nlocal, char **values)
{
molecule[nlocal] = atoi(values[0]);
num_bond[nlocal] = 0;
num_angle[nlocal] = 0;
num_dihedral[nlocal] = 0;
num_improper[nlocal] = 0;
return 1;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecMolecular::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("molecule")) bytes += memory->usage(molecule,nmax);
if (atom->memcheck("nspecial")) bytes += memory->usage(nspecial,nmax,3);
if (atom->memcheck("special"))
bytes += memory->usage(special,nmax,atom->maxspecial);
if (atom->memcheck("num_bond")) bytes += memory->usage(num_bond,nmax);
if (atom->memcheck("bond_type"))
bytes += memory->usage(bond_type,nmax,atom->bond_per_atom);
if (atom->memcheck("bond_atom"))
bytes += memory->usage(bond_atom,nmax,atom->bond_per_atom);
if (atom->memcheck("num_angle")) bytes += memory->usage(num_angle,nmax);
if (atom->memcheck("angle_type"))
bytes += memory->usage(angle_type,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom1"))
bytes += memory->usage(angle_atom1,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom2"))
bytes += memory->usage(angle_atom2,nmax,atom->angle_per_atom);
if (atom->memcheck("angle_atom3"))
bytes += memory->usage(angle_atom3,nmax,atom->angle_per_atom);
if (atom->memcheck("num_dihedral")) bytes += memory->usage(num_dihedral,nmax);
if (atom->memcheck("dihedral_type"))
bytes += memory->usage(dihedral_type,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom1"))
bytes += memory->usage(dihedral_atom1,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom2"))
bytes += memory->usage(dihedral_atom2,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom3"))
bytes += memory->usage(dihedral_atom3,nmax,atom->dihedral_per_atom);
if (atom->memcheck("dihedral_atom4"))
bytes += memory->usage(dihedral_atom4,nmax,atom->dihedral_per_atom);
if (atom->memcheck("num_improper")) bytes += memory->usage(num_improper,nmax);
if (atom->memcheck("improper_type"))
bytes += memory->usage(improper_type,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom1"))
bytes += memory->usage(improper_atom1,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom2"))
bytes += memory->usage(improper_atom2,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom3"))
bytes += memory->usage(improper_atom3,nmax,atom->improper_per_atom);
if (atom->memcheck("improper_atom4"))
bytes += memory->usage(improper_atom4,nmax,atom->improper_per_atom);
return bytes;
}
diff --git a/src/MOLECULE/bond_fene.cpp b/src/MOLECULE/bond_fene.cpp
index 26a8454db..571ace987 100644
--- a/src/MOLECULE/bond_fene.cpp
+++ b/src/MOLECULE/bond_fene.cpp
@@ -1,263 +1,263 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "bond_fene.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "update.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondFENE::BondFENE(LAMMPS *lmp) : Bond(lmp)
{
TWO_1_3 = pow(2.0,(1.0/3.0));
}
/* ---------------------------------------------------------------------- */
BondFENE::~BondFENE()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(r0);
memory->destroy(epsilon);
memory->destroy(sigma);
}
}
/* ---------------------------------------------------------------------- */
void BondFENE::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r0sq,rlogarg,sr2,sr6;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
// force from log term
rsq = delx*delx + dely*dely + delz*delz;
r0sq = r0[type] * r0[type];
rlogarg = 1.0 - rsq/r0sq;
// if r -> r0, then rlogarg < 0.0 which is an error
// issue a warning and reset rlogarg = epsilon
// if r > 2*r0 something serious is wrong, abort
if (rlogarg < 0.1) {
char str[128];
sprintf(str,"FENE bond too long: " BIGINT_FORMAT " %d %d %g",
update->ntimestep,atom->tag[i1],atom->tag[i2],sqrt(rsq));
- error->warning(str,0);
- if (rlogarg <= -3.0) error->one("Bad FENE bond");
+ error->warning(FLERR,str,0);
+ if (rlogarg <= -3.0) error->one(FLERR,"Bad FENE bond");
rlogarg = 0.1;
}
fbond = -k[type]/rlogarg;
// force from LJ term
if (rsq < TWO_1_3*sigma[type]*sigma[type]) {
sr2 = sigma[type]*sigma[type]/rsq;
sr6 = sr2*sr2*sr2;
fbond += 48.0*epsilon[type]*sr6*(sr6-0.5)/rsq;
}
// energy
if (eflag) {
ebond = -0.5 * k[type]*r0sq*log(rlogarg);
if (rsq < TWO_1_3*sigma[type]*sigma[type])
ebond += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type];
}
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondFENE::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(k,n+1,"bond:k");
memory->create(r0,n+1,"bond:r0");
memory->create(epsilon,n+1,"bond:epsilon");
memory->create(sigma,n+1,"bond:sigma");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void BondFENE::coeff(int narg, char **arg)
{
- if (narg != 5) error->all("Incorrect args for bond coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double r0_one = force->numeric(arg[2]);
double epsilon_one = force->numeric(arg[3]);
double sigma_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
r0[i] = r0_one;
epsilon[i] = epsilon_one;
sigma[i] = sigma_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
check if special_bond settings are valid
------------------------------------------------------------------------- */
void BondFENE::init_style()
{
// special bonds should be 0 1 1
if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 ||
force->special_lj[3] != 1.0) {
if (comm->me == 0)
- error->warning("Use special bonds = 0,1,1 with bond style fene");
+ error->warning(FLERR,"Use special bonds = 0,1,1 with bond style fene");
}
}
/* ---------------------------------------------------------------------- */
double BondFENE::equilibrium_distance(int i)
{
return 0.97*sigma[i];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void BondFENE::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&sigma[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void BondFENE::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
fread(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
fread(&sigma[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&epsilon[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondFENE::single(int type, double rsq, int i, int j)
{
double r0sq = r0[type] * r0[type];
double rlogarg = 1.0 - rsq/r0sq;
// if r -> r0, then rlogarg < 0.0 which is an error
// issue a warning and reset rlogarg = epsilon
// if r > 2*r0 something serious is wrong, abort
if (rlogarg < 0.1) {
char str[128];
sprintf(str,"FENE bond too long: " BIGINT_FORMAT " %g",
update->ntimestep,sqrt(rsq));
- error->warning(str,0);
- if (rlogarg <= -3.0) error->one("Bad FENE bond");
+ error->warning(FLERR,str,0);
+ if (rlogarg <= -3.0) error->one(FLERR,"Bad FENE bond");
rlogarg = 0.1;
}
double eng = -0.5 * k[type]*r0sq*log(rlogarg);
if (rsq < TWO_1_3*sigma[type]*sigma[type]) {
double sr2,sr6;
sr2 = sigma[type]*sigma[type]/rsq;
sr6 = sr2*sr2*sr2;
eng += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type];
}
return eng;
}
diff --git a/src/MOLECULE/bond_fene_expand.cpp b/src/MOLECULE/bond_fene_expand.cpp
index 560179bea..a466ca4db 100644
--- a/src/MOLECULE/bond_fene_expand.cpp
+++ b/src/MOLECULE/bond_fene_expand.cpp
@@ -1,277 +1,277 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "bond_fene_expand.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "update.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondFENEExpand::BondFENEExpand(LAMMPS *lmp) : Bond(lmp)
{
TWO_1_3 = pow(2.0,(1.0/3.0));
}
/* ---------------------------------------------------------------------- */
BondFENEExpand::~BondFENEExpand()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(r0);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(shift);
}
}
/* ---------------------------------------------------------------------- */
void BondFENEExpand::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r0sq,rlogarg,sr2,sr6;
double r,rshift,rshiftsq;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
// force from log term
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
rshift = r - shift[type];
rshiftsq = rshift*rshift;
r0sq = r0[type] * r0[type];
rlogarg = 1.0 - rshiftsq/r0sq;
// if r -> r0, then rlogarg < 0.0 which is an error
// issue a warning and reset rlogarg = epsilon
// if r > 2*r0 something serious is wrong, abort
if (rlogarg < 0.1) {
char str[128];
sprintf(str,"FENE bond too long: " BIGINT_FORMAT " %d %d %g",
update->ntimestep,atom->tag[i1],atom->tag[i2],sqrt(rsq));
- error->warning(str,0);
- if (rlogarg <= -3.0) error->one("Bad FENE bond");
+ error->warning(FLERR,str,0);
+ if (rlogarg <= -3.0) error->one(FLERR,"Bad FENE bond");
rlogarg = 0.1;
}
fbond = -k[type]*rshift/rlogarg/r;
// force from LJ term
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type]) {
sr2 = sigma[type]*sigma[type]/rshiftsq;
sr6 = sr2*sr2*sr2;
fbond += 48.0*epsilon[type]*sr6*(sr6-0.5)/rshift/r;
}
// energy
if (eflag) {
ebond = -0.5 * k[type]*r0sq*log(rlogarg);
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type])
ebond += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type];
}
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondFENEExpand::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(k,n+1,"bond:k");
memory->create(r0,n+1,"bond:r0");
memory->create(epsilon,n+1,"bond:epsilon");
memory->create(sigma,n+1,"bond:sigma");
memory->create(shift,n+1,"bond:shift");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void BondFENEExpand::coeff(int narg, char **arg)
{
- if (narg != 6) error->all("Incorrect args for bond coefficients");
+ if (narg != 6) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double r0_one = force->numeric(arg[2]);
double epsilon_one = force->numeric(arg[3]);
double sigma_one = force->numeric(arg[4]);
double shift_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
r0[i] = r0_one;
epsilon[i] = epsilon_one;
sigma[i] = sigma_one;
shift[i] = shift_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
check if special_bond settings are valid
------------------------------------------------------------------------- */
void BondFENEExpand::init_style()
{
// special bonds should be 0 1 1
if (force->special_lj[1] != 0.0 || force->special_lj[2] != 1.0 ||
force->special_lj[3] != 1.0) {
if (comm->me == 0)
- error->warning("Use special bonds = 0,1,1 with bond style fene/expand");
+ error->warning(FLERR,"Use special bonds = 0,1,1 with bond style fene/expand");
}
}
/* ---------------------------------------------------------------------- */
double BondFENEExpand::equilibrium_distance(int i)
{
return 0.97*sigma[i] + shift[i];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void BondFENEExpand::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&sigma[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&shift[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void BondFENEExpand::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
fread(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
fread(&sigma[1],sizeof(double),atom->nbondtypes,fp);
fread(&shift[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&epsilon[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&shift[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondFENEExpand::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
double rshift = r - shift[type];
double rshiftsq = rshift*rshift;
double r0sq = r0[type] * r0[type];
double rlogarg = 1.0 - rshiftsq/r0sq;
// if r -> r0, then rlogarg < 0.0 which is an error
// issue a warning and reset rlogarg = epsilon
// if r > 2*r0 something serious is wrong, abort
if (rlogarg < 0.1) {
char str[128];
sprintf(str,"FENE bond too long: " BIGINT_FORMAT " %g",
update->ntimestep,sqrt(rsq));
- error->warning(str,0);
- if (rlogarg <= -3.0) error->one("Bad FENE bond");
+ error->warning(FLERR,str,0);
+ if (rlogarg <= -3.0) error->one(FLERR,"Bad FENE bond");
rlogarg = 0.1;
}
double eng = -0.5 * k[type]*r0sq*log(rlogarg);
if (rshiftsq < TWO_1_3*sigma[type]*sigma[type]) {
double sr2,sr6;
sr2 = sigma[type]*sigma[type]/rshiftsq;
sr6 = sr2*sr2*sr2;
eng += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type];
}
return eng;
}
diff --git a/src/MOLECULE/bond_harmonic.cpp b/src/MOLECULE/bond_harmonic.cpp
index 9e4c2756a..63af84bf9 100644
--- a/src/MOLECULE/bond_harmonic.cpp
+++ b/src/MOLECULE/bond_harmonic.cpp
@@ -1,186 +1,186 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "bond_harmonic.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondHarmonic::BondHarmonic(LAMMPS *lmp) : Bond(lmp) {}
/* ---------------------------------------------------------------------- */
BondHarmonic::~BondHarmonic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(r0);
}
}
/* ---------------------------------------------------------------------- */
void BondHarmonic::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r,dr,rk;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
dr = r - r0[type];
rk = k[type] * dr;
// force & energy
if (r > 0.0) fbond = -2.0*rk/r;
else fbond = 0.0;
if (eflag) ebond = rk*dr;
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondHarmonic::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(k,n+1,"bond:k");
memory->create(r0,n+1,"bond:r0");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void BondHarmonic::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Incorrect args for bond coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double r0_one = force->numeric(arg[2]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
r0[i] = r0_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondHarmonic::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondHarmonic::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondHarmonic::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondHarmonic::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
double dr = r - r0[type];
double rk = k[type] * dr;
return rk*dr;
}
diff --git a/src/MOLECULE/bond_morse.cpp b/src/MOLECULE/bond_morse.cpp
index cd3fe47c9..135c6f8df 100644
--- a/src/MOLECULE/bond_morse.cpp
+++ b/src/MOLECULE/bond_morse.cpp
@@ -1,196 +1,196 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Jeff Greathouse (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "bond_morse.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondMorse::BondMorse(LAMMPS *lmp) : Bond(lmp) {}
/* ---------------------------------------------------------------------- */
BondMorse::~BondMorse()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(d0);
memory->destroy(alpha);
memory->destroy(r0);
}
}
/* ---------------------------------------------------------------------- */
void BondMorse::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r,dr,ralpha;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
dr = r - r0[type];
ralpha = exp(-alpha[type]*dr);
// force & energy
if (r > 0.0) fbond = -2.0*d0[type]*alpha[type]*(1-ralpha)*ralpha/r;
else fbond = 0.0;
if (eflag) ebond = d0[type]*(1-ralpha)*(1-ralpha);
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondMorse::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(d0,n+1,"bond:d0");
memory->create(alpha,n+1,"bond:alpha");
memory->create(r0,n+1,"bond:r0");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void BondMorse::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for bond coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double d0_one = force->numeric(arg[1]);
double alpha_one = force->numeric(arg[2]);
double r0_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
d0[i] = d0_one;
alpha[i] = alpha_one;
r0[i] = r0_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondMorse::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void BondMorse::write_restart(FILE *fp)
{
fwrite(&d0[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&alpha[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void BondMorse::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&d0[1],sizeof(double),atom->nbondtypes,fp);
fread(&alpha[1],sizeof(double),atom->nbondtypes,fp);
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&d0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&alpha[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondMorse::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
double dr = r - r0[type];
double ralpha = exp(-alpha[type]*dr);
return d0[type]*(1-ralpha)*(1-ralpha);
}
diff --git a/src/MOLECULE/bond_nonlinear.cpp b/src/MOLECULE/bond_nonlinear.cpp
index a848cce90..1a31b4c4b 100644
--- a/src/MOLECULE/bond_nonlinear.cpp
+++ b/src/MOLECULE/bond_nonlinear.cpp
@@ -1,193 +1,193 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "bond_nonlinear.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondNonlinear::BondNonlinear(LAMMPS *lmp) : Bond(lmp) {}
/* ---------------------------------------------------------------------- */
BondNonlinear::~BondNonlinear()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(epsilon);
memory->destroy(r0);
memory->destroy(lamda);
}
}
/* ---------------------------------------------------------------------- */
void BondNonlinear::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r,dr,drsq,lamdasq,denom,denomsq;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
dr = r - r0[type];
drsq = dr*dr;
lamdasq = lamda[type]*lamda[type];
denom = lamdasq - drsq;
denomsq = denom*denom;
// force & energy
fbond = -epsilon[type]/r * 2.0*dr*lamdasq/denomsq;
if (eflag) ebond = epsilon[type] * drsq / denom;
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondNonlinear::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(epsilon,n+1,"bond:epsilon");
memory->create(r0,n+1,"bond:r0");
memory->create(lamda,n+1,"bond:lamda");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void BondNonlinear::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for bond coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double epsilon_one = force->numeric(arg[1]);
double r0_one = force->numeric(arg[2]);
double lamda_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
epsilon[i] = epsilon_one;
r0[i] = r0_one;
lamda[i] = lamda_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ---------------------------------------------------------------------- */
double BondNonlinear::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void BondNonlinear::write_restart(FILE *fp)
{
fwrite(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&lamda[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void BondNonlinear::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&epsilon[1],sizeof(double),atom->nbondtypes,fp);
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
fread(&lamda[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&epsilon[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&lamda[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondNonlinear::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
double dr = r - r0[type];
double drsq = dr*dr;
double lamdasq = lamda[type]*lamda[type];
double denom = lamdasq - drsq;
return epsilon[type] * drsq / denom;
}
diff --git a/src/MOLECULE/bond_quartic.cpp b/src/MOLECULE/bond_quartic.cpp
index f9e5bd860..c8fc882d5 100755
--- a/src/MOLECULE/bond_quartic.cpp
+++ b/src/MOLECULE/bond_quartic.cpp
@@ -1,336 +1,336 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Chris Lorenz and Mark Stevens (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "bond_quartic.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondQuartic::BondQuartic(LAMMPS *lmp) : Bond(lmp)
{
TWO_1_3 = pow(2.0,(1.0/3.0));
}
/* ---------------------------------------------------------------------- */
BondQuartic::~BondQuartic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(b1);
memory->destroy(b2);
memory->destroy(rc);
memory->destroy(u0);
}
}
/* ---------------------------------------------------------------------- */
void BondQuartic::compute(int eflag, int vflag)
{
int i1,i2,n,m,type,itype,jtype;
double delx,dely,delz,ebond,fbond,evdwl,fpair;
double r,rsq,dr,r2,ra,rb,sr2,sr6;
ebond = evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
// insure pair->ev_tally() will use 1-4 virial contribution
if (vflag_global == 2)
force->pair->vflag_either = force->pair->vflag_global = 1;
double **cutsq = force->pair->cutsq;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
// skip bond if already broken
if (bondlist[n][2] <= 0) continue;
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
// if bond breaks, set type to 0
// both in temporary bondlist and permanent bond_type
// if this proc owns both atoms,
// negate bond_type twice if other atom stores it
// if other proc owns 2nd atom, other proc will also break bond
if (rsq > rc[type]*rc[type]) {
bondlist[n][2] = 0;
for (m = 0; m < atom->num_bond[i1]; m++)
if (atom->bond_atom[i1][m] == atom->tag[i2])
atom->bond_type[i1][m] = 0;
if (i2 < atom->nlocal)
for (m = 0; m < atom->num_bond[i2]; m++)
if (atom->bond_atom[i2][m] == atom->tag[i1])
atom->bond_type[i2][m] = 0;
continue;
}
// quartic bond
// 1st portion is from quartic term
// 2nd portion is from LJ term cut at 2^(1/6) with eps = sigma = 1.0
r = sqrt(rsq);
dr = r - rc[type];
r2 = dr*dr;
ra = dr - b1[type];
rb = dr - b2[type];
fbond = -k[type]/r * (r2*(ra+rb) + 2.0*dr*ra*rb);
if (rsq < TWO_1_3) {
sr2 = 1.0/rsq;
sr6 = sr2*sr2*sr2;
fbond += 48.0*sr6*(sr6-0.5)/rsq;
}
if (eflag) {
ebond = k[type]*r2*ra*rb + u0[type];
if (rsq < TWO_1_3) ebond += 4.0*sr6*(sr6-1.0) + 1.0;
}
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
// subtract out pairwise contribution from 2 atoms via pair->single()
// required since special_bond = 1,1,1
// tally energy/virial in pair, using newton_bond as newton flag
itype = atom->type[i1];
jtype = atom->type[i2];
if (rsq < cutsq[itype][jtype]) {
evdwl = -force->pair->single(i1,i2,itype,jtype,rsq,1.0,1.0,fpair);
fpair = -fpair;
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fpair;
f[i1][1] += dely*fpair;
f[i1][2] += delz*fpair;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fpair;
f[i2][1] -= dely*fpair;
f[i2][2] -= delz*fpair;
}
if (evflag) force->pair->ev_tally(i1,i2,nlocal,newton_bond,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
/* ---------------------------------------------------------------------- */
void BondQuartic::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(k,n+1,"bond:k");
memory->create(b1,n+1,"bond:b1");
memory->create(b2,n+1,"bond:b2");
memory->create(rc,n+1,"bond:rc");
memory->create(u0,n+1,"bond:u0");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void BondQuartic::coeff(int narg, char **arg)
{
- if (narg != 6) error->all("Incorrect args for bond coefficients");
+ if (narg != 6) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double b1_one = force->numeric(arg[2]);
double b2_one = force->numeric(arg[3]);
double rc_one = force->numeric(arg[4]);
double u0_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
b1[i] = b1_one;
b2[i] = b2_one;
rc[i] = rc_one;
u0[i] = u0_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
check if pair defined and special_bond settings are valid
------------------------------------------------------------------------- */
void BondQuartic::init_style()
{
if (force->pair == NULL || force->pair->single_enable == 0)
- error->all("Pair style does not support bond_style quartic");
+ error->all(FLERR,"Pair style does not support bond_style quartic");
if (force->angle)
- error->all("Bond style quartic cannot be used with 3,4-body interactions");
+ error->all(FLERR,"Bond style quartic cannot be used with 3,4-body interactions");
if (force->dihedral)
- error->all("Bond style quartic cannot be used with 3,4-body interactions");
+ error->all(FLERR,"Bond style quartic cannot be used with 3,4-body interactions");
if (force->improper)
- error->all("Bond style quartic cannot be used with 3,4-body interactions");
+ error->all(FLERR,"Bond style quartic cannot be used with 3,4-body interactions");
// special bonds must be 1 1 1
if (force->special_lj[1] != 1.0 || force->special_lj[2] != 1.0 ||
force->special_lj[3] != 1.0)
- error->all("Bond style quartic requires special_bonds = 1,1,1");
+ error->all(FLERR,"Bond style quartic requires special_bonds = 1,1,1");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondQuartic::equilibrium_distance(int i)
{
return 0.97;
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondQuartic::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&b1[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&b2[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&rc[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&u0[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondQuartic::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
fread(&b1[1],sizeof(double),atom->nbondtypes,fp);
fread(&b2[1],sizeof(double),atom->nbondtypes,fp);
fread(&rc[1],sizeof(double),atom->nbondtypes,fp);
fread(&u0[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&b1[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&b2[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&rc[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&u0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondQuartic::single(int type, double rsq, int i, int j)
{
double r,dr,r2,ra,rb,sr2,sr6;
if (type <= 0) return 0.0;
double eng = 0.0;
// subtract out pairwise contribution from 2 atoms via pair->single()
// required since special_bond = 1,1,1
int itype = atom->type[i];
int jtype = atom->type[j];
if (rsq < force->pair->cutsq[itype][jtype]) {
double tmp;
eng = -force->pair->single(i,j,itype,jtype,rsq,1.0,1.0,tmp);
}
// quartic bond
// 1st portion is from quartic term
// 2nd portion is from LJ term cut at 2^(1/6) with eps = sigma = 1.0
r = sqrt(rsq);
dr = r - rc[type];
r2 = dr*dr;
ra = dr - b1[type];
rb = dr - b2[type];
eng += k[type]*r2*ra*rb + u0[type];
if (rsq < TWO_1_3) {
sr2 = 1.0/rsq;
sr6 = sr2*sr2*sr2;
eng += 4.0*sr6*(sr6-1.0) + 1.0;
}
return eng;
}
diff --git a/src/MOLECULE/bond_table.cpp b/src/MOLECULE/bond_table.cpp
index 1e6abb88a..04743097e 100644
--- a/src/MOLECULE/bond_table.cpp
+++ b/src/MOLECULE/bond_table.cpp
@@ -1,593 +1,590 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Chuanfu Luo (luochuanfu@gmail.com)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "bond_table.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{LINEAR,SPLINE};
#define MAXLINE 1024
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
BondTable::BondTable(LAMMPS *lmp) : Bond(lmp)
{
ntables = 0;
tables = NULL;
}
/* ---------------------------------------------------------------------- */
BondTable::~BondTable()
{
for (int m = 0; m < ntables; m++) free_table(&tables[m]);
memory->sfree(tables);
if (allocated) {
memory->destroy(setflag);
memory->destroy(r0);
memory->destroy(tabindex);
}
}
/* ---------------------------------------------------------------------- */
void BondTable::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r;
double u,mdu;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
// force & energy
uf_lookup(type,r,u,mdu);
fbond = mdu/r;
ebond = u;
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondTable::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(tabindex,n+1,"bond:tabindex");
memory->create(r0,n+1,"bond:r0");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void BondTable::settings(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal bond_style command");
+ if (narg != 2) error->all(FLERR,"Illegal bond_style command");
if (strcmp(arg[0],"linear") == 0) tabstyle = LINEAR;
else if (strcmp(arg[0],"spline") == 0) tabstyle = SPLINE;
- else error->all("Unknown table style in bond style table");
+ else error->all(FLERR,"Unknown table style in bond style table");
tablength = force->inumeric(arg[1]);
- if (tablength < 2) error->all("Illegal number of bond table entries");
+ if (tablength < 2) error->all(FLERR,"Illegal number of bond table entries");
// delete old tables, since cannot just change settings
for (int m = 0; m < ntables; m++) free_table(&tables[m]);
memory->sfree(tables);
if (allocated) {
memory->destroy(setflag);
memory->destroy(tabindex);
}
allocated = 0;
ntables = 0;
tables = NULL;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void BondTable::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Illegal bond_coeff command");
+ if (narg != 3) error->all(FLERR,"Illegal bond_coeff command");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
int me;
MPI_Comm_rank(world,&me);
tables = (Table *)
memory->srealloc(tables,(ntables+1)*sizeof(Table),"bond:tables");
Table *tb = &tables[ntables];
null_table(tb);
if (me == 0) read_table(tb,arg[1],arg[2]);
bcast_table(tb);
// error check on table parameters
- if (tb->ninput <= 1) error->one("Invalid bond table length");
+ if (tb->ninput <= 1) error->one(FLERR,"Invalid bond table length");
tb->lo = tb->rfile[0];
tb->hi = tb->rfile[tb->ninput-1];
- if (tb->lo >= tb->hi) error->all("Bond table values are not increasing");
+ if (tb->lo >= tb->hi) error->all(FLERR,"Bond table values are not increasing");
// spline read-in and compute r,e,f vectors within table
spline_table(tb);
compute_table(tb);
// store ptr to table in tabindex
int count = 0;
for (int i = ilo; i <= ihi; i++) {
tabindex[i] = ntables;
r0[i] = tb->r0;
setflag[i] = 1;
count++;
}
ntables++;
- if (count == 0) error->all("Illegal bond_coeff command");
+ if (count == 0) error->all(FLERR,"Illegal bond_coeff command");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
should not be used, since don't know minimum of tabulated function
------------------------------------------------------------------------- */
double BondTable::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void BondTable::write_restart(FILE *fp)
{
fwrite(&tabstyle,sizeof(int),1,fp);
fwrite(&tablength,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void BondTable::read_restart(FILE *fp)
{
if (comm->me == 0) {
fread(&tabstyle,sizeof(int),1,fp);
fread(&tablength,sizeof(int),1,fp);
}
MPI_Bcast(&tabstyle,1,MPI_DOUBLE,0,world);
MPI_Bcast(&tablength,1,MPI_INT,0,world);
allocate();
}
/* ---------------------------------------------------------------------- */
double BondTable::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
double u;
u_lookup(type,r,u);
return u;
}
/* ---------------------------------------------------------------------- */
void BondTable::null_table(Table *tb)
{
tb->rfile = tb->efile = tb->ffile = NULL;
tb->e2file = tb->f2file = NULL;
tb->r = tb->e = tb->de = NULL;
tb->f = tb->df = tb->e2 = tb->f2 = NULL;
}
/* ---------------------------------------------------------------------- */
void BondTable::free_table(Table *tb)
{
memory->destroy(tb->rfile);
memory->destroy(tb->efile);
memory->destroy(tb->ffile);
memory->destroy(tb->e2file);
memory->destroy(tb->f2file);
memory->destroy(tb->r);
memory->destroy(tb->e);
memory->destroy(tb->de);
memory->destroy(tb->f);
memory->destroy(tb->df);
memory->destroy(tb->e2);
memory->destroy(tb->f2);
}
/* ----------------------------------------------------------------------
read table file, only called by proc 0
------------------------------------------------------------------------- */
void BondTable::read_table(Table *tb, char *file, char *keyword)
{
char line[MAXLINE];
// open file
FILE *fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
// loop until section found with matching keyword
while (1) {
if (fgets(line,MAXLINE,fp) == NULL)
- error->one("Did not find keyword in table file");
+ error->one(FLERR,"Did not find keyword in table file");
if (strspn(line," \t\n") == strlen(line)) continue; // blank line
if (line[0] == '#') continue; // comment
if (strstr(line,keyword) == line) break; // matching keyword
fgets(line,MAXLINE,fp); // no match, skip section
param_extract(tb,line);
fgets(line,MAXLINE,fp);
for (int i = 0; i < tb->ninput; i++) fgets(line,MAXLINE,fp);
}
// read args on 2nd line of section
// allocate table arrays for file values
fgets(line,MAXLINE,fp);
param_extract(tb,line);
memory->create(tb->rfile,tb->ninput,"bond:rfile");
memory->create(tb->efile,tb->ninput,"bond:efile");
memory->create(tb->ffile,tb->ninput,"bond:ffile");
// read r,e,f table values from file
int itmp;
fgets(line,MAXLINE,fp);
for (int i = 0; i < tb->ninput; i++) {
fgets(line,MAXLINE,fp);
sscanf(line,"%d %lg %lg %lg",
&itmp,&tb->rfile[i],&tb->efile[i],&tb->ffile[i]);
}
fclose(fp);
}
/* ----------------------------------------------------------------------
build spline representation of e,f over entire range of read-in table
this function sets these values in e2file,f2file
------------------------------------------------------------------------- */
void BondTable::spline_table(Table *tb)
{
memory->create(tb->e2file,tb->ninput,"bond:e2file");
memory->create(tb->f2file,tb->ninput,"bond:f2file");
double ep0 = - tb->ffile[0];
double epn = - tb->ffile[tb->ninput-1];
spline(tb->rfile,tb->efile,tb->ninput,ep0,epn,tb->e2file);
if (tb->fpflag == 0) {
tb->fplo = (tb->ffile[1] - tb->ffile[0]) / (tb->rfile[1] - tb->rfile[0]);
tb->fphi = (tb->ffile[tb->ninput-1] - tb->ffile[tb->ninput-2]) /
(tb->rfile[tb->ninput-1] - tb->rfile[tb->ninput-2]);
}
double fp0 = tb->fplo;
double fpn = tb->fphi;
spline(tb->rfile,tb->ffile,tb->ninput,fp0,fpn,tb->f2file);
}
/* ----------------------------------------------------------------------
compute r,e,f vectors from splined values
------------------------------------------------------------------------- */
void BondTable::compute_table(Table *tb)
{
// delta = table spacing for N-1 bins
int tlm1 = tablength-1;
tb->delta = (tb->hi - tb->lo)/ tlm1;
tb->invdelta = 1.0/tb->delta;
tb->deltasq6 = tb->delta*tb->delta / 6.0;
// N-1 evenly spaced bins in r from min to max
// r,e,f = value at lower edge of bin
// de,df values = delta values of e,f
// r,e,f are N in length so de,df arrays can compute difference
memory->create(tb->r,tablength,"bond:r");
memory->create(tb->e,tablength,"bond:e");
memory->create(tb->de,tlm1,"bond:de");
memory->create(tb->f,tablength,"bond:f");
memory->create(tb->df,tlm1,"bond:df");
memory->create(tb->e2,tablength,"bond:e2");
memory->create(tb->f2,tablength,"bond:f2");
double a;
for (int i = 0; i < tablength; i++) {
a = tb->lo + i*tb->delta;
tb->r[i] = a;
tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,a);
tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,a);
}
for (int i = 0; i < tlm1; i++) {
tb->de[i] = tb->e[i+1] - tb->e[i];
tb->df[i] = tb->f[i+1] - tb->f[i];
}
double ep0 = - tb->f[0];
double epn = - tb->f[tlm1];
spline(tb->r,tb->e,tablength,ep0,epn,tb->e2);
spline(tb->r,tb->f,tablength,tb->fplo,tb->fphi,tb->f2);
}
/* ----------------------------------------------------------------------
extract attributes from parameter line in table section
format of line: N value FP fplo fphi EQ r0
N is required, other params are optional
------------------------------------------------------------------------- */
void BondTable::param_extract(Table *tb, char *line)
{
tb->ninput = 0;
tb->fpflag = 0;
tb->r0 = 0.0;
char *word = strtok(line," \t\n\r\f");
while (word) {
if (strcmp(word,"N") == 0) {
word = strtok(NULL," \t\n\r\f");
tb->ninput = atoi(word);
} else if (strcmp(word,"FP") == 0) {
tb->fpflag = 1;
word = strtok(NULL," \t\n\r\f");
tb->fplo = atof(word);
word = strtok(NULL," \t\n\r\f");
tb->fphi = atof(word);
} else if (strcmp(word,"EQ") == 0) {
word = strtok(NULL," \t\n\r\f");
tb->r0 = atof(word);
} else {
- error->one("Invalid keyword in bond table parameters");
+ error->one(FLERR,"Invalid keyword in bond table parameters");
}
word = strtok(NULL," \t\n\r\f");
}
- if (tb->ninput == 0) error->one("Bond table parameters did not set N");
+ if (tb->ninput == 0) error->one(FLERR,"Bond table parameters did not set N");
}
/* ----------------------------------------------------------------------
broadcast read-in table info from proc 0 to other procs
this function communicates these values in Table:
ninput,rfile,efile,ffile,fpflag,fplo,fphi,r0
------------------------------------------------------------------------- */
void BondTable::bcast_table(Table *tb)
{
MPI_Bcast(&tb->ninput,1,MPI_INT,0,world);
MPI_Bcast(&tb->r0,1,MPI_INT,0,world);
int me;
MPI_Comm_rank(world,&me);
if (me > 0) {
memory->create(tb->rfile,tb->ninput,"angle:rfile");
memory->create(tb->efile,tb->ninput,"angle:efile");
memory->create(tb->ffile,tb->ninput,"angle:ffile");
}
MPI_Bcast(tb->rfile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(tb->efile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(tb->ffile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(&tb->fpflag,1,MPI_INT,0,world);
if (tb->fpflag) {
MPI_Bcast(&tb->fplo,1,MPI_DOUBLE,0,world);
MPI_Bcast(&tb->fphi,1,MPI_DOUBLE,0,world);
}
MPI_Bcast(&tb->r0,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
spline and splint routines modified from Numerical Recipes
------------------------------------------------------------------------- */
void BondTable::spline(double *x, double *y, int n,
double yp1, double ypn, double *y2)
{
int i,k;
double p,qn,sig,un;
double *u = new double[n];
if (yp1 > 0.99e30) y2[0] = u[0] = 0.0;
else {
y2[0] = -0.5;
u[0] = (3.0/(x[1]-x[0])) * ((y[1]-y[0]) / (x[1]-x[0]) - yp1);
}
for (i = 1; i < n-1; i++) {
sig = (x[i]-x[i-1]) / (x[i+1]-x[i-1]);
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 (ypn > 0.99e30) qn = un = 0.0;
else {
qn = 0.5;
un = (3.0/(x[n-1]-x[n-2])) * (ypn - (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 (k = n-2; k >= 0; k--) y2[k] = y2[k]*y2[k+1] + u[k];
delete [] u;
}
/* ---------------------------------------------------------------------- */
double BondTable::splint(double *xa, double *ya, double *y2a, int n, double x)
{
int klo,khi,k;
double h,b,a,y;
klo = 0;
khi = n-1;
while (khi-klo > 1) {
k = (khi+klo) >> 1;
if (xa[k] > x) khi = k;
else klo = k;
}
h = xa[khi]-xa[klo];
a = (xa[khi]-x) / h;
b = (x-xa[klo]) / h;
y = a*ya[klo] + b*ya[khi] +
((a*a*a-a)*y2a[klo] + (b*b*b-b)*y2a[khi]) * (h*h)/6.0;
return y;
}
/* ----------------------------------------------------------------------
calculate potential u and force f at distance x
insure x is between bond min/max
------------------------------------------------------------------------- */
void BondTable::uf_lookup(int type, double x, double &u, double &f)
{
int itable;
double fraction,a,b;
Table *tb = &tables[tabindex[type]];
x = MAX(x,tb->lo);
x = MIN(x,tb->hi);
if (tabstyle == LINEAR) {
itable = static_cast<int> ((x - tb->lo) * tb->invdelta);
fraction = (x - tb->r[itable]) * tb->invdelta;
u = tb->e[itable] + fraction*tb->de[itable];
f = tb->f[itable] + fraction*tb->df[itable];
} else if (tabstyle == SPLINE) {
itable = static_cast<int> ((x - tb->lo) * tb->invdelta);
fraction = (x - tb->r[itable]) * tb->invdelta;
b = (x - tb->r[itable]) * tb->invdelta;
a = 1.0 - b;
u = a * tb->e[itable] + b * tb->e[itable+1] +
((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) *
tb->deltasq6;
f = a * tb->f[itable] + b * tb->f[itable+1] +
((a*a*a-a)*tb->f2[itable] + (b*b*b-b)*tb->f2[itable+1]) *
tb->deltasq6;
}
}
/* ----------------------------------------------------------------------
calculate potential u at distance x
insure x is between bond min/max
------------------------------------------------------------------------- */
void BondTable::u_lookup(int type, double x, double &u)
{
int itable;
double fraction,a,b;
Table *tb = &tables[tabindex[type]];
x = MAX(x,tb->lo);
x = MIN(x,tb->hi);
if (tabstyle == LINEAR) {
itable = static_cast<int> ((x - tb->lo) * tb->invdelta);
fraction = (x - tb->r[itable]) * tb->invdelta;
u = tb->e[itable] + fraction*tb->de[itable];
} else if (tabstyle == SPLINE) {
itable = static_cast<int> ((x - tb->lo) * tb->invdelta);
fraction = (x - tb->r[itable]) * tb->invdelta;
b = (x - tb->r[itable]) * tb->invdelta;
a = 1.0 - b;
u = a * tb->e[itable] + b * tb->e[itable+1] +
((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) *
tb->deltasq6;
}
}
diff --git a/src/MOLECULE/dihedral_charmm.cpp b/src/MOLECULE/dihedral_charmm.cpp
index 5d29cab63..a40431115 100644
--- a/src/MOLECULE/dihedral_charmm.cpp
+++ b/src/MOLECULE/dihedral_charmm.cpp
@@ -1,429 +1,429 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "dihedral_charmm.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "force.h"
#include "pair.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define TOLERANCE 0.05
/* ---------------------------------------------------------------------- */
DihedralCharmm::DihedralCharmm(LAMMPS *lmp) : Dihedral(lmp) {}
/* ---------------------------------------------------------------------- */
DihedralCharmm::~DihedralCharmm()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(multiplicity);
memory->destroy(shift);
memory->destroy(cos_shift);
memory->destroy(sin_shift);
memory->destroy(weight);
}
}
/* ---------------------------------------------------------------------- */
void DihedralCharmm::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,i,m,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double edihedral,f1[3],f2[3],f3[3],f4[3];
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
double c,s,p,sx2,sy2,sz2;
int itype,jtype;
double delx,dely,delz,rsq,r2inv,r6inv;
double forcecoul,forcelj,fpair,ecoul,evdwl;
edihedral = evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
// insure pair->ev_tally() will use 1-4 virial contribution
if (weightflag && vflag_global == 2)
force->pair->vflag_either = force->pair->vflag_global = 1;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *atomtype = atom->type;
int **dihedrallist = neighbor->dihedrallist;
int ndihedrallist = neighbor->ndihedrallist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
double qqrd2e = force->qqrd2e;
for (n = 0; n < ndihedrallist; n++) {
i1 = dihedrallist[n][0];
i2 = dihedrallist[n][1];
i3 = dihedrallist[n][2];
i4 = dihedrallist[n][3];
type = dihedrallist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
ax = vb1y*vb2zm - vb1z*vb2ym;
ay = vb1z*vb2xm - vb1x*vb2zm;
az = vb1x*vb2ym - vb1y*vb2xm;
bx = vb3y*vb2zm - vb3z*vb2ym;
by = vb3z*vb2xm - vb3x*vb2zm;
bz = vb3x*vb2ym - vb3y*vb2xm;
rasq = ax*ax + ay*ay + az*az;
rbsq = bx*bx + by*by + bz*bz;
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
rg = sqrt(rgsq);
rginv = ra2inv = rb2inv = 0.0;
if (rg > 0) rginv = 1.0/rg;
if (rasq > 0) ra2inv = 1.0/rasq;
if (rbsq > 0) rb2inv = 1.0/rbsq;
rabinv = sqrt(ra2inv*rb2inv);
c = (ax*bx + ay*by + az*bz)*rabinv;
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
m = multiplicity[type];
p = 1.0;
df1 = 0.0;
for (i = 0; i < m; i++) {
ddf1 = p*c - df1*s;
df1 = p*s + df1*c;
p = ddf1;
}
p = p*cos_shift[type] + df1*sin_shift[type];
df1 = df1*cos_shift[type] - ddf1*sin_shift[type];
df1 *= -m;
p += 1.0;
if (m == 0) {
p = 1.0 + cos_shift[type];
df1 = 0.0;
}
if (eflag) edihedral = k[type] * p;
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
fga = fg*ra2inv*rginv;
hgb = hg*rb2inv*rginv;
gaa = -ra2inv*rg;
gbb = rb2inv*rg;
dtfx = gaa*ax;
dtfy = gaa*ay;
dtfz = gaa*az;
dtgx = fga*ax - hgb*bx;
dtgy = fga*ay - hgb*by;
dtgz = fga*az - hgb*bz;
dthx = gbb*bx;
dthy = gbb*by;
dthz = gbb*bz;
df = -k[type] * df1;
sx2 = df*dtgx;
sy2 = df*dtgy;
sz2 = df*dtgz;
f1[0] = df*dtfx;
f1[1] = df*dtfy;
f1[2] = df*dtfz;
f2[0] = sx2 - f1[0];
f2[1] = sy2 - f1[1];
f2[2] = sz2 - f1[2];
f4[0] = df*dthx;
f4[1] = df*dthy;
f4[2] = df*dthz;
f3[0] = -sx2 - f4[0];
f3[1] = -sy2 - f4[1];
f3[2] = -sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
// 1-4 LJ and Coulomb interactions
// tally energy/virial in pair, using newton_bond as newton flag
if (weight[type] > 0.0) {
itype = atomtype[i1];
jtype = atomtype[i4];
delx = x[i1][0] - x[i4][0];
dely = x[i1][1] - x[i4][1];
delz = x[i1][2] - x[i4][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
if (implicit) forcecoul = qqrd2e * q[i1]*q[i4]*r2inv;
else forcecoul = qqrd2e * q[i1]*q[i4]*sqrt(r2inv);
forcelj = r6inv * (lj14_1[itype][jtype]*r6inv - lj14_2[itype][jtype]);
fpair = weight[type] * (forcelj+forcecoul)*r2inv;
if (eflag) {
ecoul = weight[type] * forcecoul;
evdwl = r6inv * (lj14_3[itype][jtype]*r6inv - lj14_4[itype][jtype]);
evdwl *= weight[type];
}
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fpair;
f[i1][1] += dely*fpair;
f[i1][2] += delz*fpair;
}
if (newton_bond || i4 < nlocal) {
f[i4][0] -= delx*fpair;
f[i4][1] -= dely*fpair;
f[i4][2] -= delz*fpair;
}
if (evflag) force->pair->ev_tally(i1,i4,nlocal,newton_bond,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
/* ---------------------------------------------------------------------- */
void DihedralCharmm::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(k,n+1,"dihedral:k");
memory->create(multiplicity,n+1,"dihedral:k");
memory->create(shift,n+1,"dihedral:shift");
memory->create(cos_shift,n+1,"dihedral:cos_shift");
memory->create(sin_shift,n+1,"dihedral:sin_shift");
memory->create(weight,n+1,"dihedral:weight");
memory->create(setflag,n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void DihedralCharmm::coeff(int narg, char **arg)
{
- if (narg != 5) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for dihedral coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
// require integer values of shift for backwards compatibility
// arbitrary phase angle shift could be allowed, but would break
// backwards compatibility and is probably not needed
double k_one = force->numeric(arg[1]);
int multiplicity_one = force->inumeric(arg[2]);
int shift_one = force->inumeric(arg[3]);
double weight_one = force->numeric(arg[4]);
if (multiplicity_one < 0)
- error->all("Incorrect multiplicity arg for dihedral coefficients");
+ error->all(FLERR,"Incorrect multiplicity arg for dihedral coefficients");
if (weight_one < 0.0 || weight_one > 1.0)
- error->all("Incorrect weight arg for dihedral coefficients");
+ error->all(FLERR,"Incorrect weight arg for dihedral coefficients");
double PI = 4.0*atan(1.0);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
shift[i] = shift_one;
cos_shift[i] = cos(PI*shift_one/180.0);
sin_shift[i] = sin(PI*shift_one/180.0);
multiplicity[i] = multiplicity_one;
weight[i] = weight_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for dihedral coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
}
/* ----------------------------------------------------------------------
error check and initialize all values needed for force computation
------------------------------------------------------------------------- */
void DihedralCharmm::init_style()
{
// insure use of CHARMM pair_style if any weight factors are non-zero
// set local ptrs to LJ 14 arrays setup by Pair
weightflag = 0;
for (int i = 1; i <= atom->ndihedraltypes; i++)
if (weight[i] > 0.0) weightflag = 1;
if (weightflag) {
int itmp;
if (force->pair == NULL)
- error->all("Dihedral charmm is incompatible with Pair style");
+ error->all(FLERR,"Dihedral charmm is incompatible with Pair style");
lj14_1 = (double **) force->pair->extract("lj14_1",itmp);
lj14_2 = (double **) force->pair->extract("lj14_2",itmp);
lj14_3 = (double **) force->pair->extract("lj14_3",itmp);
lj14_4 = (double **) force->pair->extract("lj14_4",itmp);
int *ptr = (int *) force->pair->extract("implicit",itmp);
if (!lj14_1 || !lj14_2 || !lj14_3 || !lj14_4 || !ptr)
- error->all("Dihedral charmm is incompatible with Pair style");
+ error->all(FLERR,"Dihedral charmm is incompatible with Pair style");
implicit = *ptr;
}
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralCharmm::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
fwrite(&shift[1],sizeof(int),atom->ndihedraltypes,fp);
fwrite(&weight[1],sizeof(double),atom->ndihedraltypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralCharmm::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
fread(&shift[1],sizeof(int),atom->ndihedraltypes,fp);
fread(&weight[1],sizeof(double),atom->ndihedraltypes,fp);
}
MPI_Bcast(&k[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&multiplicity[1],atom->ndihedraltypes,MPI_INT,0,world);
MPI_Bcast(&shift[1],atom->ndihedraltypes,MPI_INT,0,world);
MPI_Bcast(&weight[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
double PI = 4.0*atan(1.0);
for (int i = 1; i <= atom->ndihedraltypes; i++) {
setflag[i] = 1;
cos_shift[i] = cos(PI*shift[i]/180.0);
sin_shift[i] = sin(PI*shift[i]/180.0);
}
}
diff --git a/src/MOLECULE/dihedral_harmonic.cpp b/src/MOLECULE/dihedral_harmonic.cpp
index cefd57d42..b88584d16 100644
--- a/src/MOLECULE/dihedral_harmonic.cpp
+++ b/src/MOLECULE/dihedral_harmonic.cpp
@@ -1,351 +1,351 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "dihedral_harmonic.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define TOLERANCE 0.05
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
DihedralHarmonic::DihedralHarmonic(LAMMPS *lmp) : Dihedral(lmp) {}
/* ---------------------------------------------------------------------- */
DihedralHarmonic::~DihedralHarmonic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(sign);
memory->destroy(multiplicity);
memory->destroy(cos_shift);
memory->destroy(sin_shift);
}
}
/* ---------------------------------------------------------------------- */
void DihedralHarmonic::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,i,m,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double edihedral,f1[3],f2[3],f3[3],f4[3];
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
double c,s,p,sx2,sy2,sz2;
edihedral = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **dihedrallist = neighbor->dihedrallist;
int ndihedrallist = neighbor->ndihedrallist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < ndihedrallist; n++) {
i1 = dihedrallist[n][0];
i2 = dihedrallist[n][1];
i3 = dihedrallist[n][2];
i4 = dihedrallist[n][3];
type = dihedrallist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// c,s calculation
ax = vb1y*vb2zm - vb1z*vb2ym;
ay = vb1z*vb2xm - vb1x*vb2zm;
az = vb1x*vb2ym - vb1y*vb2xm;
bx = vb3y*vb2zm - vb3z*vb2ym;
by = vb3z*vb2xm - vb3x*vb2zm;
bz = vb3x*vb2ym - vb3y*vb2xm;
rasq = ax*ax + ay*ay + az*az;
rbsq = bx*bx + by*by + bz*bz;
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
rg = sqrt(rgsq);
rginv = ra2inv = rb2inv = 0.0;
if (rg > 0) rginv = 1.0/rg;
if (rasq > 0) ra2inv = 1.0/rasq;
if (rbsq > 0) rb2inv = 1.0/rbsq;
rabinv = sqrt(ra2inv*rb2inv);
c = (ax*bx + ay*by + az*bz)*rabinv;
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
m = multiplicity[type];
p = 1.0;
df1 = 0.0;
for (i = 0; i < m; i++) {
ddf1 = p*c - df1*s;
df1 = p*s + df1*c;
p = ddf1;
}
p = p*cos_shift[type] + df1*sin_shift[type];
df1 = df1*cos_shift[type] - ddf1*sin_shift[type];
df1 *= -m;
p += 1.0;
if (m == 0) {
p = 1.0 + cos_shift[type];
df1 = 0.0;
}
if (eflag) edihedral = k[type] * p;
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
fga = fg*ra2inv*rginv;
hgb = hg*rb2inv*rginv;
gaa = -ra2inv*rg;
gbb = rb2inv*rg;
dtfx = gaa*ax;
dtfy = gaa*ay;
dtfz = gaa*az;
dtgx = fga*ax - hgb*bx;
dtgy = fga*ay - hgb*by;
dtgz = fga*az - hgb*bz;
dthx = gbb*bx;
dthy = gbb*by;
dthz = gbb*bz;
df = -k[type] * df1;
sx2 = df*dtgx;
sy2 = df*dtgy;
sz2 = df*dtgz;
f1[0] = df*dtfx;
f1[1] = df*dtfy;
f1[2] = df*dtfz;
f2[0] = sx2 - f1[0];
f2[1] = sy2 - f1[1];
f2[2] = sz2 - f1[2];
f4[0] = df*dthx;
f4[1] = df*dthy;
f4[2] = df*dthz;
f3[0] = -sx2 - f4[0];
f3[1] = -sy2 - f4[1];
f3[2] = -sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void DihedralHarmonic::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(k,n+1,"dihedral:k");
memory->create(sign,n+1,"dihedral:sign");
memory->create(multiplicity,n+1,"dihedral:multiplicity");
memory->create(cos_shift,n+1,"dihedral:cos_shift");
memory->create(sin_shift,n+1,"dihedral:sin_shift");
memory->create(setflag,n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void DihedralHarmonic::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for dihedral coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
int sign_one = force->inumeric(arg[2]);
int multiplicity_one = force->inumeric(arg[3]);
// require sign = +/- 1 for backwards compatibility
// arbitrary phase angle shift could be allowed, but would break
// backwards compatibility and is probably not needed
if (sign_one != -1 && sign_one != 1)
- error->all("Incorrect sign arg for dihedral coefficients");
+ error->all(FLERR,"Incorrect sign arg for dihedral coefficients");
if (multiplicity_one < 0)
- error->all("Incorrect multiplicity arg for dihedral coefficients");
+ error->all(FLERR,"Incorrect multiplicity arg for dihedral coefficients");
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
sign[i] = sign_one;
if (sign[i] == 1) {
cos_shift[i] = 1;
sin_shift[i] = 0;
} else {
cos_shift[i] = -1;
sin_shift[i] = 0;
}
multiplicity[i] = multiplicity_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for dihedral coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralHarmonic::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&sign[1],sizeof(int),atom->ndihedraltypes,fp);
fwrite(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralHarmonic::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&sign[1],sizeof(int),atom->ndihedraltypes,fp);
fread(&multiplicity[1],sizeof(int),atom->ndihedraltypes,fp);
}
MPI_Bcast(&k[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&sign[1],atom->ndihedraltypes,MPI_INT,0,world);
MPI_Bcast(&multiplicity[1],atom->ndihedraltypes,MPI_INT,0,world);
for (int i = 1; i <= atom->ndihedraltypes; i++) {
setflag[i] = 1;
if (sign[i] == 1) {
cos_shift[i] = 1;
sin_shift[i] = 0;
} else {
cos_shift[i] = -1;
sin_shift[i] = 0;
}
}
}
diff --git a/src/MOLECULE/dihedral_helix.cpp b/src/MOLECULE/dihedral_helix.cpp
index 639520e8a..7a50eb4fc 100644
--- a/src/MOLECULE/dihedral_helix.cpp
+++ b/src/MOLECULE/dihedral_helix.cpp
@@ -1,338 +1,335 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Naveen Michaud-Agrawal (Johns Hopkins U) and
Mark Stevens (Sandia)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "mpi.h"
#include "dihedral_helix.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define TOLERANCE 0.05
#define SMALL 0.001
#define SMALLER 0.00001
/* ---------------------------------------------------------------------- */
DihedralHelix::DihedralHelix(LAMMPS *lmp) : Dihedral(lmp) {}
/* ---------------------------------------------------------------------- */
DihedralHelix::~DihedralHelix()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(aphi);
memory->destroy(bphi);
memory->destroy(cphi);
}
}
/* ---------------------------------------------------------------------- */
void DihedralHelix::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double edihedral,f1[3],f2[3],f3[3],f4[3];
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
double c2mag,sc1,sc2,s1,s12,c,p,pd,a,a11,a22;
double a33,a12,a13,a23,sx2,sy2,sz2;
double s2,cx,cy,cz,cmag,dx,phi,si,siinv,sin2;
edihedral = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **dihedrallist = neighbor->dihedrallist;
int ndihedrallist = neighbor->ndihedrallist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < ndihedrallist; n++) {
i1 = dihedrallist[n][0];
i2 = dihedrallist[n][1];
i3 = dihedrallist[n][2];
i4 = dihedrallist[n][3];
type = dihedrallist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// c0 calculation
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
rb1 = sqrt(sb1);
rb3 = sqrt(sb3);
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
// 1st and 2nd angle
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
b1mag = sqrt(b1mag2);
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
b2mag = sqrt(b2mag2);
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
b3mag = sqrt(b3mag2);
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
r12c1 = 1.0 / (b1mag*b2mag);
c1mag = ctmp * r12c1;
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
r12c2 = 1.0 / (b2mag*b3mag);
c2mag = ctmp * r12c2;
// cos and sin of 2 angles and final c
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
sc1 = sqrt(sin2);
if (sc1 < SMALL) sc1 = SMALL;
sc1 = 1.0/sc1;
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
sc2 = sqrt(sin2);
if (sc2 < SMALL) sc2 = SMALL;
sc2 = 1.0/sc2;
s1 = sc1 * sc1;
s2 = sc2 * sc2;
s12 = sc1 * sc2;
c = (c0 + c1mag*c2mag) * s12;
cx = vb1y*vb2z - vb1z*vb2y;
cy = vb1z*vb2x - vb1x*vb2z;
cz = vb1x*vb2y - vb1y*vb2x;
cmag = sqrt(cx*cx + cy*cy + cz*cz);
dx = (cx*vb3x + cy*vb3y + cz*vb3z)/cmag/b3mag;
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
phi = acos(c);
if (dx < 0.0) phi *= -1.0;
si = sin(phi);
if (fabs(si) < SMALLER) si = SMALLER;
siinv = 1.0/si;
p = aphi[type]*(1.0 - c) + bphi[type]*(1.0 + cos(3.0*phi)) +
cphi[type]*(1.0 + cos(phi + 0.25*PI));
pd = -aphi[type] + 3.0*bphi[type]*sin(3.0*phi)*siinv +
cphi[type]*sin(phi + 0.25*PI)*siinv;
if (eflag) edihedral = p;
a = pd;
c = c * a;
s12 = s12 * a;
a11 = c*sb1*s1;
a22 = -sb2 * (2.0*c0*s12 - c*(s1+s2));
a33 = c*sb3*s2;
a12 = -r12c1 * (c1mag*c*s1 + c2mag*s12);
a13 = -rb1*rb3*s12;
a23 = r12c2 * (c2mag*c*s2 + c1mag*s12);
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
f2[0] = -sx2 - f1[0];
f2[1] = -sy2 - f1[1];
f2[2] = -sz2 - f1[2];
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
f3[0] = sx2 - f4[0];
f3[1] = sy2 - f4[1];
f3[2] = sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void DihedralHelix::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(aphi,n+1,"dihedral:aphi");
memory->create(bphi,n+1,"dihedral:bphi");
memory->create(cphi,n+1,"dihedral:cphi");
memory->create(setflag,n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs from one line in input script
------------------------------------------------------------------------- */
void DihedralHelix::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for dihedral coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
double aphi_one = force->numeric(arg[1]);
double bphi_one = force->numeric(arg[2]);
double cphi_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
aphi[i] = aphi_one;
bphi[i] = bphi_one;
cphi[i] = cphi_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for dihedral coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralHelix::write_restart(FILE *fp)
{
fwrite(&aphi[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&bphi[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&cphi[1],sizeof(double),atom->ndihedraltypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralHelix::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&aphi[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&bphi[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&cphi[1],sizeof(double),atom->ndihedraltypes,fp);
}
MPI_Bcast(&aphi[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&bphi[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&cphi[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
}
diff --git a/src/MOLECULE/dihedral_hybrid.cpp b/src/MOLECULE/dihedral_hybrid.cpp
index 2d17ea028..4b416281d 100644
--- a/src/MOLECULE/dihedral_hybrid.cpp
+++ b/src/MOLECULE/dihedral_hybrid.cpp
@@ -1,295 +1,295 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "dihedral_hybrid.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define EXTRA 1000
/* ---------------------------------------------------------------------- */
DihedralHybrid::DihedralHybrid(LAMMPS *lmp) : Dihedral(lmp)
{
nstyles = 0;
}
/* ---------------------------------------------------------------------- */
DihedralHybrid::~DihedralHybrid()
{
if (nstyles) {
for (int i = 0; i < nstyles; i++) delete styles[i];
delete [] styles;
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(map);
delete [] ndihedrallist;
delete [] maxdihedral;
for (int i = 0; i < nstyles; i++)
memory->destroy(dihedrallist[i]);
delete [] dihedrallist;
}
}
/* ---------------------------------------------------------------------- */
void DihedralHybrid::compute(int eflag, int vflag)
{
int i,j,m,n;
// save ptrs to original dihedrallist
int ndihedrallist_orig = neighbor->ndihedrallist;
int **dihedrallist_orig = neighbor->dihedrallist;
// if this is re-neighbor step, create sub-style dihedrallists
// ndihedrallist[] = length of each sub-style list
// realloc sub-style dihedrallist if necessary
// load sub-style dihedrallist with 5 values from original dihedrallist
if (neighbor->ago == 0) {
for (m = 0; m < nstyles; m++) ndihedrallist[m] = 0;
for (i = 0; i < ndihedrallist_orig; i++) {
m = map[dihedrallist_orig[i][4]];
if (m >= 0) ndihedrallist[m]++;
}
for (m = 0; m < nstyles; m++) {
if (ndihedrallist[m] > maxdihedral[m]) {
memory->destroy(dihedrallist[m]);
maxdihedral[m] = ndihedrallist[m] + EXTRA;
memory->create(dihedrallist[m],maxdihedral[m],5,
"dihedral_hybrid:dihedrallist");
}
ndihedrallist[m] = 0;
}
for (i = 0; i < ndihedrallist_orig; i++) {
m = map[dihedrallist_orig[i][4]];
if (m < 0) continue;
n = ndihedrallist[m];
dihedrallist[m][n][0] = dihedrallist_orig[i][0];
dihedrallist[m][n][1] = dihedrallist_orig[i][1];
dihedrallist[m][n][2] = dihedrallist_orig[i][2];
dihedrallist[m][n][3] = dihedrallist_orig[i][3];
dihedrallist[m][n][4] = dihedrallist_orig[i][4];
ndihedrallist[m]++;
}
}
// call each sub-style's compute function
// set neighbor->dihedrallist to sub-style dihedrallist before call
// accumulate sub-style global/peratom energy/virial in hybrid
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
for (m = 0; m < nstyles; m++) {
neighbor->ndihedrallist = ndihedrallist[m];
neighbor->dihedrallist = dihedrallist[m];
styles[m]->compute(eflag,vflag);
if (eflag_global) energy += styles[m]->energy;
if (vflag_global)
for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double *eatom_substyle = styles[m]->eatom;
for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i];
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double **vatom_substyle = styles[m]->vatom;
for (i = 0; i < n; i++)
for (j = 0; j < 6; j++)
vatom[i][j] += vatom_substyle[i][j];
}
}
// restore ptrs to original dihedrallist
neighbor->ndihedrallist = ndihedrallist_orig;
neighbor->dihedrallist = dihedrallist_orig;
}
/* ---------------------------------------------------------------------- */
void DihedralHybrid::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(map,n+1,"dihedral:map");
memory->create(setflag,n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
ndihedrallist = new int[nstyles];
maxdihedral = new int[nstyles];
dihedrallist = new int**[nstyles];
for (int m = 0; m < nstyles; m++) maxdihedral[m] = 0;
for (int m = 0; m < nstyles; m++) dihedrallist[m] = NULL;
}
/* ----------------------------------------------------------------------
create one dihedral style for each arg in list
------------------------------------------------------------------------- */
void DihedralHybrid::settings(int narg, char **arg)
{
nstyles = narg;
styles = new Dihedral*[nstyles];
keywords = new char*[nstyles];
for (int m = 0; m < nstyles; m++) {
for (int i = 0; i < m; i++)
if (strcmp(arg[m],arg[i]) == 0)
- error->all("Dihedral style hybrid cannot use "
+ error->all(FLERR,"Dihedral style hybrid cannot use "
"same dihedral style twice");
if (strcmp(arg[m],"hybrid") == 0)
- error->all("Dihedral style hybrid cannot have hybrid as an argument");
+ error->all(FLERR,"Dihedral style hybrid cannot have hybrid as an argument");
if (strcmp(arg[m],"none") == 0)
- error->all("Dihedral style hybrid cannot have none as an argument");
+ error->all(FLERR,"Dihedral style hybrid cannot have none as an argument");
styles[m] = force->new_dihedral(arg[m]);
keywords[m] = new char[strlen(arg[m])+1];
strcpy(keywords[m],arg[m]);
}
}
/* ----------------------------------------------------------------------
set coeffs for one type
---------------------------------------------------------------------- */
void DihedralHybrid::coeff(int narg, char **arg)
{
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
// 2nd arg = dihedral sub-style name
// allow for "none" or "skip" as valid sub-style name
int m;
for (m = 0; m < nstyles; m++)
if (strcmp(arg[1],keywords[m]) == 0) break;
int none = 0;
int skip = 0;
if (m == nstyles) {
if (strcmp(arg[1],"none") == 0) none = 1;
else if (strcmp(arg[1],"skip") == 0) none = skip = 1;
- else error->all("Dihedral coeff for hybrid has invalid style");
+ else error->all(FLERR,"Dihedral coeff for hybrid has invalid style");
}
// move 1st arg to 2nd arg
// just copy ptrs, since arg[] points into original input line
arg[1] = arg[0];
// invoke sub-style coeff() starting with 1st arg
if (!none) styles[m]->coeff(narg-1,&arg[1]);
// set setflag and which type maps to which sub-style
// if sub-style is skip: auxiliary class2 setting in data file so ignore
// if sub-style is none and not skip: set hybrid setflag, wipe out map
for (int i = ilo; i <= ihi; i++) {
if (skip) continue;
else if (none) {
setflag[i] = 1;
map[i] = -1;
} else {
setflag[i] = styles[m]->setflag[i];
map[i] = m;
}
}
}
/* ---------------------------------------------------------------------- */
void DihedralHybrid::init_style()
{
for (int m = 0; m < nstyles; m++)
if (styles[m]) styles[m]->init_style();
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void DihedralHybrid::write_restart(FILE *fp)
{
fwrite(&nstyles,sizeof(int),1,fp);
int n;
for (int m = 0; m < nstyles; m++) {
n = strlen(keywords[m]) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(keywords[m],sizeof(char),n,fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void DihedralHybrid::read_restart(FILE *fp)
{
int me = comm->me;
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
styles = new Dihedral*[nstyles];
keywords = new char*[nstyles];
allocate();
int n;
for (int m = 0; m < nstyles; m++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
keywords[m] = new char[n];
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
styles[m] = force->new_dihedral(keywords[m]);
}
}
/* ----------------------------------------------------------------------
memory usage
------------------------------------------------------------------------- */
double DihedralHybrid::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
for (int m = 0; m < nstyles; m++) bytes += maxdihedral[m]*5 * sizeof(int);
for (int m = 0; m < nstyles; m++)
if (styles[m]) bytes += styles[m]->memory_usage();
return bytes;
}
diff --git a/src/MOLECULE/dihedral_multi_harmonic.cpp b/src/MOLECULE/dihedral_multi_harmonic.cpp
index 291cea35e..ea0fd5532 100644
--- a/src/MOLECULE/dihedral_multi_harmonic.cpp
+++ b/src/MOLECULE/dihedral_multi_harmonic.cpp
@@ -1,339 +1,336 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mathias Puetz (SNL) and friends
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "dihedral_multi_harmonic.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define TOLERANCE 0.05
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
DihedralMultiHarmonic::DihedralMultiHarmonic(LAMMPS *lmp) : Dihedral(lmp) {}
/* ---------------------------------------------------------------------- */
DihedralMultiHarmonic::~DihedralMultiHarmonic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(a1);
memory->destroy(a2);
memory->destroy(a3);
memory->destroy(a4);
memory->destroy(a5);
}
}
/* ---------------------------------------------------------------------- */
void DihedralMultiHarmonic::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double edihedral,f1[3],f2[3],f3[3],f4[3];
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
double c2mag,sc1,sc2,s1,s12,c,p,pd,a,a11,a22;
double a33,a12,a13,a23,sx2,sy2,sz2;
double s2,sin2;
edihedral = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **dihedrallist = neighbor->dihedrallist;
int ndihedrallist = neighbor->ndihedrallist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < ndihedrallist; n++) {
i1 = dihedrallist[n][0];
i2 = dihedrallist[n][1];
i3 = dihedrallist[n][2];
i4 = dihedrallist[n][3];
type = dihedrallist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// c0 calculation
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
rb1 = sqrt(sb1);
rb3 = sqrt(sb3);
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
// 1st and 2nd angle
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
b1mag = sqrt(b1mag2);
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
b2mag = sqrt(b2mag2);
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
b3mag = sqrt(b3mag2);
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
r12c1 = 1.0 / (b1mag*b2mag);
c1mag = ctmp * r12c1;
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
r12c2 = 1.0 / (b2mag*b3mag);
c2mag = ctmp * r12c2;
// cos and sin of 2 angles and final c
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
sc1 = sqrt(sin2);
if (sc1 < SMALL) sc1 = SMALL;
sc1 = 1.0/sc1;
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
sc2 = sqrt(sin2);
if (sc2 < SMALL) sc2 = SMALL;
sc2 = 1.0/sc2;
s1 = sc1 * sc1;
s2 = sc2 * sc2;
s12 = sc1 * sc2;
c = (c0 + c1mag*c2mag) * s12;
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// force & energy
// p = sum (i=1,5) a_i * c**(i-1)
// pd = dp/dc
p = a1[type] + c*(a2[type] + c*(a3[type] + c*(a4[type] + c*a5[type])));
pd = a2[type] + c*(2.0*a3[type] + c*(3.0*a4[type] + c*4.0*a5[type]));
if (eflag) edihedral = p;
a = pd;
c = c * a;
s12 = s12 * a;
a11 = c*sb1*s1;
a22 = -sb2 * (2.0*c0*s12 - c*(s1+s2));
a33 = c*sb3*s2;
a12 = -r12c1*(c1mag*c*s1 + c2mag*s12);
a13 = -rb1*rb3*s12;
a23 = r12c2*(c2mag*c*s2 + c1mag*s12);
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
f2[0] = -sx2 - f1[0];
f2[1] = -sy2 - f1[1];
f2[2] = -sz2 - f1[2];
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
f3[0] = sx2 - f4[0];
f3[1] = sy2 - f4[1];
f3[2] = sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void DihedralMultiHarmonic::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(a1,n+1,"dihedral:a1");
memory->create(a2,n+1,"dihedral:a2");
memory->create(a3,n+1,"dihedral:a3");
memory->create(a4,n+1,"dihedral:a4");
memory->create(a5,n+1,"dihedral:a5");
memory->create(setflag,n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void DihedralMultiHarmonic::coeff(int narg, char **arg)
{
- if (narg != 6) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 6) error->all(FLERR,"Incorrect args for dihedral coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
double a1_one = force->numeric(arg[1]);
double a2_one = force->numeric(arg[2]);
double a3_one = force->numeric(arg[3]);
double a4_one = force->numeric(arg[4]);
double a5_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
a1[i] = a1_one;
a2[i] = a2_one;
a3[i] = a3_one;
a4[i] = a4_one;
a5[i] = a5_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for dihedral coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralMultiHarmonic::write_restart(FILE *fp)
{
fwrite(&a1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&a2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&a3[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&a4[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&a5[1],sizeof(double),atom->ndihedraltypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralMultiHarmonic::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&a1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&a2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&a3[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&a4[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&a5[1],sizeof(double),atom->ndihedraltypes,fp);
}
MPI_Bcast(&a1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&a2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&a3[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&a4[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&a5[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
}
diff --git a/src/MOLECULE/dihedral_opls.cpp b/src/MOLECULE/dihedral_opls.cpp
index 99bdd993e..4f4fd7588 100644
--- a/src/MOLECULE/dihedral_opls.cpp
+++ b/src/MOLECULE/dihedral_opls.cpp
@@ -1,349 +1,346 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mark Stevens (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "dihedral_opls.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define TOLERANCE 0.05
#define SMALL 0.001
#define SMALLER 0.00001
/* ---------------------------------------------------------------------- */
DihedralOPLS::DihedralOPLS(LAMMPS *lmp) : Dihedral(lmp) {}
/* ---------------------------------------------------------------------- */
DihedralOPLS::~DihedralOPLS()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k1);
memory->destroy(k2);
memory->destroy(k3);
memory->destroy(k4);
}
}
/* ---------------------------------------------------------------------- */
void DihedralOPLS::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double edihedral,f1[3],f2[3],f3[3],f4[3];
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
double c2mag,sc1,sc2,s1,s12,c,p,pd,a,a11,a22;
double a33,a12,a13,a23,sx2,sy2,sz2;
double s2,cx,cy,cz,cmag,dx,phi,si,siinv,sin2;
edihedral = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **dihedrallist = neighbor->dihedrallist;
int ndihedrallist = neighbor->ndihedrallist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < ndihedrallist; n++) {
i1 = dihedrallist[n][0];
i2 = dihedrallist[n][1];
i3 = dihedrallist[n][2];
i4 = dihedrallist[n][3];
type = dihedrallist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// c0 calculation
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
rb1 = sqrt(sb1);
rb3 = sqrt(sb3);
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
// 1st and 2nd angle
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
b1mag = sqrt(b1mag2);
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
b2mag = sqrt(b2mag2);
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
b3mag = sqrt(b3mag2);
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
r12c1 = 1.0 / (b1mag*b2mag);
c1mag = ctmp * r12c1;
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
r12c2 = 1.0 / (b2mag*b3mag);
c2mag = ctmp * r12c2;
// cos and sin of 2 angles and final c
sin2 = MAX(1.0 - c1mag*c1mag,0.0);
sc1 = sqrt(sin2);
if (sc1 < SMALL) sc1 = SMALL;
sc1 = 1.0/sc1;
sin2 = MAX(1.0 - c2mag*c2mag,0.0);
sc2 = sqrt(sin2);
if (sc2 < SMALL) sc2 = SMALL;
sc2 = 1.0/sc2;
s1 = sc1 * sc1;
s2 = sc2 * sc2;
s12 = sc1 * sc2;
c = (c0 + c1mag*c2mag) * s12;
cx = vb1y*vb2z - vb1z*vb2y;
cy = vb1z*vb2x - vb1x*vb2z;
cz = vb1x*vb2y - vb1y*vb2x;
cmag = sqrt(cx*cx + cy*cy + cz*cz);
dx = (cx*vb3x + cy*vb3y + cz*vb3z)/cmag/b3mag;
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// force & energy
// p = sum (i=1,4) k_i * (1 + (-1)**(i+1)*cos(i*phi) )
// pd = dp/dc
phi = acos(c);
if (dx < 0.0) phi *= -1.0;
si = sin(phi);
if (fabs(si) < SMALLER) si = SMALLER;
siinv = 1.0/si;
p = k1[type]*(1.0 + c) + k2[type]*(1.0 - cos(2.0*phi)) +
k3[type]*(1.0 + cos(3.0*phi)) + k4[type]*(1.0 - cos(4.0*phi)) ;
pd = k1[type] - 2.0*k2[type]*sin(2.0*phi)*siinv +
3.0*k3[type]*sin(3.0*phi)*siinv - 4.0*k4[type]*sin(4.0*phi)*siinv;
if (eflag) edihedral = p;
a = pd;
c = c * a;
s12 = s12 * a;
a11 = c*sb1*s1;
a22 = -sb2 * (2.0*c0*s12 - c*(s1+s2));
a33 = c*sb3*s2;
a12 = -r12c1 * (c1mag*c*s1 + c2mag*s12);
a13 = -rb1*rb3*s12;
a23 = r12c2 * (c2mag*c*s2 + c1mag*s12);
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
f2[0] = -sx2 - f1[0];
f2[1] = -sy2 - f1[1];
f2[2] = -sz2 - f1[2];
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
f3[0] = sx2 - f4[0];
f3[1] = sy2 - f4[1];
f3[2] = sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void DihedralOPLS::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(k1,n+1,"dihedral:k1");
memory->create(k2,n+1,"dihedral:k2");
memory->create(k3,n+1,"dihedral:k3");
memory->create(k4,n+1,"dihedral:k4");
memory->create(setflag,n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void DihedralOPLS::coeff(int narg, char **arg)
{
- if (narg != 5) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 5) error->all(FLERR,"Incorrect args for dihedral coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
double k1_one = force->numeric(arg[1]);
double k2_one = force->numeric(arg[2]);
double k3_one = force->numeric(arg[3]);
double k4_one = force->numeric(arg[4]);
// store 1/2 factor with prefactor
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k1[i] = 0.5*k1_one;
k2[i] = 0.5*k2_one;
k3[i] = 0.5*k3_one;
k4[i] = 0.5*k4_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for dihedral coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralOPLS::write_restart(FILE *fp)
{
fwrite(&k1[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&k2[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&k3[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&k4[1],sizeof(double),atom->ndihedraltypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralOPLS::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k1[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&k2[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&k3[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&k4[1],sizeof(double),atom->ndihedraltypes,fp);
}
MPI_Bcast(&k1[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k2[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k3[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&k4[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->ndihedraltypes; i++) setflag[i] = 1;
}
diff --git a/src/MOLECULE/improper_cvff.cpp b/src/MOLECULE/improper_cvff.cpp
index 2ea0b97f5..401bcad85 100644
--- a/src/MOLECULE/improper_cvff.cpp
+++ b/src/MOLECULE/improper_cvff.cpp
@@ -1,349 +1,349 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "improper_cvff.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define TOLERANCE 0.05
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
ImproperCvff::ImproperCvff(LAMMPS *lmp) : Improper(lmp) {}
/* ---------------------------------------------------------------------- */
ImproperCvff::~ImproperCvff()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(sign);
memory->destroy(multiplicity);
}
}
/* ---------------------------------------------------------------------- */
void ImproperCvff::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,m,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double eimproper,f1[3],f2[3],f3[3],f4[3];
double sb1,sb2,sb3,rb1,rb3,c0,b1mag2,b1mag,b2mag2;
double b2mag,b3mag2,b3mag,ctmp,r12c1,c1mag,r12c2;
double c2mag,sc1,sc2,s1,s2,s12,c,p,pd,rc2,a,a11,a22;
double a33,a12,a13,a23,sx2,sy2,sz2;
eimproper = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **improperlist = neighbor->improperlist;
int nimproperlist = neighbor->nimproperlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nimproperlist; n++) {
i1 = improperlist[n][0];
i2 = improperlist[n][1];
i3 = improperlist[n][2];
i4 = improperlist[n][3];
type = improperlist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// c0 calculation
sb1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
sb2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
sb3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
rb1 = sqrt(sb1);
rb3 = sqrt(sb3);
c0 = (vb1x*vb3x + vb1y*vb3y + vb1z*vb3z) * rb1*rb3;
// 1st and 2nd angle
b1mag2 = vb1x*vb1x + vb1y*vb1y + vb1z*vb1z;
b1mag = sqrt(b1mag2);
b2mag2 = vb2x*vb2x + vb2y*vb2y + vb2z*vb2z;
b2mag = sqrt(b2mag2);
b3mag2 = vb3x*vb3x + vb3y*vb3y + vb3z*vb3z;
b3mag = sqrt(b3mag2);
ctmp = vb1x*vb2x + vb1y*vb2y + vb1z*vb2z;
r12c1 = 1.0 / (b1mag*b2mag);
c1mag = ctmp * r12c1;
ctmp = vb2xm*vb3x + vb2ym*vb3y + vb2zm*vb3z;
r12c2 = 1.0 / (b2mag*b3mag);
c2mag = ctmp * r12c2;
// cos and sin of 2 angles and final c
sc1 = sqrt(1.0 - c1mag*c1mag);
if (sc1 < SMALL) sc1 = SMALL;
sc1 = 1.0/sc1;
sc2 = sqrt(1.0 - c2mag*c2mag);
if (sc2 < SMALL) sc2 = SMALL;
sc2 = 1.0/sc2;
s1 = sc1 * sc1;
s2 = sc2 * sc2;
s12 = sc1 * sc2;
c = (c0 + c1mag*c2mag) * s12;
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,
"Improper problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// force & energy
// p = 1 + cos(n*phi) for d = 1
// p = 1 - cos(n*phi) for d = -1
// pd = dp/dc / 2
m = multiplicity[type];
if (m == 2) {
p = 2.0*c*c;
pd = 2.0*c;
} else if (m == 3) {
rc2 = c*c;
p = (4.0*rc2-3.0)*c + 1.0;
pd = 6.0*rc2 - 1.5;
} else if (m == 4) {
rc2 = c*c;
p = 8.0*(rc2-1)*rc2 + 2.0;
pd = (16.0*rc2-8.0)*c;
} else if (m == 6) {
rc2 = c*c;
p = ((32.0*rc2-48.0)*rc2 + 18.0)*rc2;
pd = (96.0*(rc2-1.0)*rc2 + 18.0)*c;
} else if (m == 1) {
p = c + 1.0;
pd = 0.5;
} else if (m == 5) {
rc2 = c*c;
p = ((16.0*rc2-20.0)*rc2 + 5.0)*c + 1.0;
pd = (40.0*rc2-30.0)*rc2 + 2.5;
} else if (m == 0) {
p = 2.0;
pd = 0.0;
}
if (sign[type] == -1) {
p = 2.0 - p;
pd = -pd;
}
if (eflag) eimproper = k[type]*p;
a = 2.0 * k[type] * pd;
c = c * a;
s12 = s12 * a;
a11 = c*sb1*s1;
a22 = -sb2*(2.0*c0*s12 - c*(s1+s2));
a33 = c*sb3*s2;
a12 = -r12c1*(c1mag*c*s1 + c2mag*s12);
a13 = -rb1*rb3*s12;
a23 = r12c2*(c2mag*c*s2 + c1mag*s12);
sx2 = a12*vb1x + a22*vb2x + a23*vb3x;
sy2 = a12*vb1y + a22*vb2y + a23*vb3y;
sz2 = a12*vb1z + a22*vb2z + a23*vb3z;
f1[0] = a11*vb1x + a12*vb2x + a13*vb3x;
f1[1] = a11*vb1y + a12*vb2y + a13*vb3y;
f1[2] = a11*vb1z + a12*vb2z + a13*vb3z;
f2[0] = -sx2 - f1[0];
f2[1] = -sy2 - f1[1];
f2[2] = -sz2 - f1[2];
f4[0] = a13*vb1x + a23*vb2x + a33*vb3x;
f4[1] = a13*vb1y + a23*vb2y + a33*vb3y;
f4[2] = a13*vb1z + a23*vb2z + a33*vb3z;
f3[0] = sx2 - f4[0];
f3[1] = sy2 - f4[1];
f3[2] = sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,eimproper,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void ImproperCvff::allocate()
{
allocated = 1;
int n = atom->nimpropertypes;
memory->create(k,n+1,"improper:k");
memory->create(sign,n+1,"improper:sign");
memory->create(multiplicity,n+1,"improper:multiplicity");
memory->create(setflag,n+1,"improper:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void ImproperCvff::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for improper coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for improper coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
int sign_one = force->inumeric(arg[2]);
int multiplicity_one = force->inumeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
sign[i] = sign_one;
multiplicity[i] = multiplicity_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for improper coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for improper coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void ImproperCvff::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&sign[1],sizeof(int),atom->nimpropertypes,fp);
fwrite(&multiplicity[1],sizeof(int),atom->nimpropertypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void ImproperCvff::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nimpropertypes,fp);
fread(&sign[1],sizeof(int),atom->nimpropertypes,fp);
fread(&multiplicity[1],sizeof(int),atom->nimpropertypes,fp);
}
MPI_Bcast(&k[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&sign[1],atom->nimpropertypes,MPI_INT,0,world);
MPI_Bcast(&multiplicity[1],atom->nimpropertypes,MPI_INT,0,world);
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
}
diff --git a/src/MOLECULE/improper_harmonic.cpp b/src/MOLECULE/improper_harmonic.cpp
index 7e7db4d03..62d5cd54b 100644
--- a/src/MOLECULE/improper_harmonic.cpp
+++ b/src/MOLECULE/improper_harmonic.cpp
@@ -1,285 +1,285 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "improper_harmonic.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define TOLERANCE 0.05
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
ImproperHarmonic::ImproperHarmonic(LAMMPS *lmp) : Improper(lmp) {}
/* ---------------------------------------------------------------------- */
ImproperHarmonic::~ImproperHarmonic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(chi);
}
}
/* ---------------------------------------------------------------------- */
void ImproperHarmonic::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
double eimproper,f1[3],f2[3],f3[3],f4[3];
double ss1,ss2,ss3,r1,r2,r3,c0,c1,c2,s1,s2;
double s12,c,s,domega,a,a11,a22,a33,a12,a13,a23;
double sx2,sy2,sz2;
eimproper = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **improperlist = neighbor->improperlist;
int nimproperlist = neighbor->nimproperlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nimproperlist; n++) {
i1 = improperlist[n][0];
i2 = improperlist[n][1];
i3 = improperlist[n][2];
i4 = improperlist[n][3];
type = improperlist[n][4];
// geometry of 4-body
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
ss1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
ss2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
ss3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
r1 = sqrt(ss1);
r2 = sqrt(ss2);
r3 = sqrt(ss3);
// sin and cos of angle
c0 = (vb1x * vb3x + vb1y * vb3y + vb1z * vb3z) * r1 * r3;
c1 = (vb1x * vb2x + vb1y * vb2y + vb1z * vb2z) * r1 * r2;
c2 = -(vb3x * vb2x + vb3y * vb2y + vb3z * vb2z) * r3 * r2;
s1 = 1.0 - c1*c1;
if (s1 < SMALL) s1 = SMALL;
s1 = 1.0 / s1;
s2 = 1.0 - c2*c2;
if (s2 < SMALL) s2 = SMALL;
s2 = 1.0 / s2;
s12 = sqrt(s1*s2);
c = (c1*c2 + c0) * s12;
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,
"Improper problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
// force & energy
domega = acos(c) - chi[type];
a = k[type] * domega;
if (eflag) eimproper = a*domega;
a = -a * 2.0/s;
c = c * a;
s12 = s12 * a;
a11 = c*ss1*s1;
a22 = -ss2 * (2.0*c0*s12 - c*(s1+s2));
a33 = c*ss3*s2;
a12 = -r1*r2*(c1*c*s1 + c2*s12);
a13 = -r1*r3*s12;
a23 = r2*r3*(c2*c*s2 + c1*s12);
sx2 = a22*vb2x + a23*vb3x + a12*vb1x;
sy2 = a22*vb2y + a23*vb3y + a12*vb1y;
sz2 = a22*vb2z + a23*vb3z + a12*vb1z;
f1[0] = a12*vb2x + a13*vb3x + a11*vb1x;
f1[1] = a12*vb2y + a13*vb3y + a11*vb1y;
f1[2] = a12*vb2z + a13*vb3z + a11*vb1z;
f2[0] = -sx2 - f1[0];
f2[1] = -sy2 - f1[1];
f2[2] = -sz2 - f1[2];
f4[0] = a23*vb2x + a33*vb3x + a13*vb1x;
f4[1] = a23*vb2y + a33*vb3y + a13*vb1y;
f4[2] = a23*vb2z + a33*vb3z + a13*vb1z;
f3[0] = sx2 - f4[0];
f3[1] = sy2 - f4[1];
f3[2] = sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,eimproper,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void ImproperHarmonic::allocate()
{
allocated = 1;
int n = atom->nimpropertypes;
memory->create(k,n+1,"improper:k");
memory->create(chi,n+1,"improper:chi");
memory->create(setflag,n+1,"improper:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void ImproperHarmonic::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Incorrect args for improper coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for improper coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
double k_one = force->numeric(arg[1]);
double chi_one = force->numeric(arg[2]);
// convert chi from degrees to radians
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
chi[i] = chi_one/180.0 * PI;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for improper coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for improper coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void ImproperHarmonic::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&chi[1],sizeof(double),atom->nimpropertypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void ImproperHarmonic::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nimpropertypes,fp);
fread(&chi[1],sizeof(double),atom->nimpropertypes,fp);
}
MPI_Bcast(&k[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&chi[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
}
diff --git a/src/MOLECULE/improper_hybrid.cpp b/src/MOLECULE/improper_hybrid.cpp
index 767c12b93..645913e84 100644
--- a/src/MOLECULE/improper_hybrid.cpp
+++ b/src/MOLECULE/improper_hybrid.cpp
@@ -1,282 +1,282 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "improper_hybrid.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define EXTRA 1000
/* ---------------------------------------------------------------------- */
ImproperHybrid::ImproperHybrid(LAMMPS *lmp) : Improper(lmp)
{
nstyles = 0;
}
/* ---------------------------------------------------------------------- */
ImproperHybrid::~ImproperHybrid()
{
if (nstyles) {
for (int i = 0; i < nstyles; i++) delete styles[i];
delete [] styles;
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(map);
delete [] nimproperlist;
delete [] maximproper;
for (int i = 0; i < nstyles; i++)
memory->destroy(improperlist[i]);
delete [] improperlist;
}
}
/* ---------------------------------------------------------------------- */
void ImproperHybrid::compute(int eflag, int vflag)
{
int i,j,m,n;
// save ptrs to original improperlist
int nimproperlist_orig = neighbor->nimproperlist;
int **improperlist_orig = neighbor->improperlist;
// if this is re-neighbor step, create sub-style improperlists
// nimproperlist[] = length of each sub-style list
// realloc sub-style improperlist if necessary
// load sub-style improperlist with 5 values from original improperlist
if (neighbor->ago == 0) {
for (m = 0; m < nstyles; m++) nimproperlist[m] = 0;
for (i = 0; i < nimproperlist_orig; i++) {
m = map[improperlist_orig[i][4]];
nimproperlist[m]++;
}
for (m = 0; m < nstyles; m++) {
if (nimproperlist[m] > maximproper[m]) {
memory->destroy(improperlist[m]);
maximproper[m] = nimproperlist[m] + EXTRA;
memory->create(improperlist[m],maximproper[m],5,
"improper_hybrid:improperlist");
}
nimproperlist[m] = 0;
}
for (i = 0; i < nimproperlist_orig; i++) {
m = map[improperlist_orig[i][4]];
if (m < 0) continue;
n = nimproperlist[m];
improperlist[m][n][0] = improperlist_orig[i][0];
improperlist[m][n][1] = improperlist_orig[i][1];
improperlist[m][n][2] = improperlist_orig[i][2];
improperlist[m][n][3] = improperlist_orig[i][3];
improperlist[m][n][4] = improperlist_orig[i][4];
nimproperlist[m]++;
}
}
// call each sub-style's compute function
// set neighbor->improperlist to sub-style improperlist before call
// accumulate sub-style global/peratom energy/virial in hybrid
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
for (m = 0; m < nstyles; m++) {
neighbor->nimproperlist = nimproperlist[m];
neighbor->improperlist = improperlist[m];
styles[m]->compute(eflag,vflag);
if (eflag_global) energy += styles[m]->energy;
if (vflag_global)
for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double *eatom_substyle = styles[m]->eatom;
for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i];
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double **vatom_substyle = styles[m]->vatom;
for (i = 0; i < n; i++)
for (j = 0; j < 6; j++)
vatom[i][j] += vatom_substyle[i][j];
}
}
// restore ptrs to original improperlist
neighbor->nimproperlist = nimproperlist_orig;
neighbor->improperlist = improperlist_orig;
}
/* ---------------------------------------------------------------------- */
void ImproperHybrid::allocate()
{
allocated = 1;
int n = atom->nimpropertypes;
memory->create(map,n+1,"improper:map");
memory->create(setflag,n+1,"improper:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
nimproperlist = new int[nstyles];
maximproper = new int[nstyles];
improperlist = new int**[nstyles];
for (int m = 0; m < nstyles; m++) maximproper[m] = 0;
for (int m = 0; m < nstyles; m++) improperlist[m] = NULL;
}
/* ----------------------------------------------------------------------
create one improper style for each arg in list
------------------------------------------------------------------------- */
void ImproperHybrid::settings(int narg, char **arg)
{
nstyles = narg;
styles = new Improper*[nstyles];
keywords = new char*[nstyles];
for (int m = 0; m < nstyles; m++) {
for (int i = 0; i < m; i++)
if (strcmp(arg[m],arg[i]) == 0)
- error->all("Improper style hybrid cannot use same improper style twice");
+ error->all(FLERR,"Improper style hybrid cannot use same improper style twice");
if (strcmp(arg[m],"hybrid") == 0)
- error->all("Improper style hybrid cannot have hybrid as an argument");
+ error->all(FLERR,"Improper style hybrid cannot have hybrid as an argument");
if (strcmp(arg[m],"none") == 0)
- error->all("Improper style hybrid cannot have none as an argument");
+ error->all(FLERR,"Improper style hybrid cannot have none as an argument");
styles[m] = force->new_improper(arg[m]);
keywords[m] = new char[strlen(arg[m])+1];
strcpy(keywords[m],arg[m]);
}
}
/* ----------------------------------------------------------------------
set coeffs for one type
---------------------------------------------------------------------- */
void ImproperHybrid::coeff(int narg, char **arg)
{
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
// 2nd arg = improper sub-style name
// allow for "none" as valid sub-style name
int m;
for (m = 0; m < nstyles; m++)
if (strcmp(arg[1],keywords[m]) == 0) break;
int none = 0;
if (m == nstyles) {
if (strcmp(arg[1],"none") == 0) none = 1;
- else error->all("Improper coeff for hybrid has invalid style");
+ else error->all(FLERR,"Improper coeff for hybrid has invalid style");
}
// move 1st arg to 2nd arg
// just copy ptrs, since arg[] points into original input line
arg[1] = arg[0];
// invoke sub-style coeff() starting with 1st arg
if (!none) styles[m]->coeff(narg-1,&arg[1]);
// set setflag and which type maps to which sub-style
// if sub-style is none: set hybrid setflag, wipe out map
for (int i = ilo; i <= ihi; i++) {
if (none) {
setflag[i] = 1;
map[i] = -1;
} else {
setflag[i] = styles[m]->setflag[i];
map[i] = m;
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void ImproperHybrid::write_restart(FILE *fp)
{
fwrite(&nstyles,sizeof(int),1,fp);
int n;
for (int m = 0; m < nstyles; m++) {
n = strlen(keywords[m]) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(keywords[m],sizeof(char),n,fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void ImproperHybrid::read_restart(FILE *fp)
{
int me = comm->me;
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
styles = new Improper*[nstyles];
keywords = new char*[nstyles];
allocate();
int n;
for (int m = 0; m < nstyles; m++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
keywords[m] = new char[n];
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
styles[m] = force->new_improper(keywords[m]);
}
}
/* ----------------------------------------------------------------------
memory usage
------------------------------------------------------------------------- */
double ImproperHybrid::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
for (int m = 0; m < nstyles; m++) bytes += maximproper[m]*5 * sizeof(int);
for (int m = 0; m < nstyles; m++)
if (styles[m]) bytes += styles[m]->memory_usage();
return bytes;
}
diff --git a/src/MOLECULE/improper_umbrella.cpp b/src/MOLECULE/improper_umbrella.cpp
index 97cc1f65a..34fddf708 100644
--- a/src/MOLECULE/improper_umbrella.cpp
+++ b/src/MOLECULE/improper_umbrella.cpp
@@ -1,311 +1,311 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Tod A Pascal (Caltech)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "improper_umbrella.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define TOLERANCE 0.05
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
ImproperUmbrella::ImproperUmbrella(LAMMPS *lmp) : Improper(lmp) {}
/* ---------------------------------------------------------------------- */
ImproperUmbrella::~ImproperUmbrella()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(kw);
memory->destroy(w0);
memory->destroy(C);
}
}
/* ---------------------------------------------------------------------- */
void ImproperUmbrella::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,n,type;
double eimproper,f1[3],f2[3],f3[3],f4[3];
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
double domega,c,a,s,projhfg,dhax,dhay,dhaz,dahx,dahy,dahz,cotphi;
double ax,ay,az,ra2,rh2,ra,rh,rar,rhr,arx,ary,arz,hrx,hry,hrz;
eimproper = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **improperlist = neighbor->improperlist;
int nimproperlist = neighbor->nimproperlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nimproperlist; n++) {
i1 = improperlist[n][0];
i2 = improperlist[n][1];
i3 = improperlist[n][2];
i4 = improperlist[n][3];
type = improperlist[n][4];
// 1st bond
vb1x = x[i2][0] - x[i1][0];
vb1y = x[i2][1] - x[i1][1];
vb1z = x[i2][2] - x[i1][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i1][0];
vb2y = x[i3][1] - x[i1][1];
vb2z = x[i3][2] - x[i1][2];
domain->minimum_image(vb2x,vb2y,vb2z);
// 3rd bond
vb3x = x[i4][0] - x[i1][0];
vb3y = x[i4][1] - x[i1][1];
vb3z = x[i4][2] - x[i1][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// c0 calculation
// A = vb1 X vb2 is perpendicular to IJK plane
ax = vb1y*vb2z-vb1z*vb2y;
ay = vb1z*vb2x-vb1x*vb2z;
az = vb1x*vb2y-vb1y*vb2x;
ra2 = ax*ax+ay*ay+az*az;
rh2 = vb3x*vb3x+vb3y*vb3y+vb3z*vb3z;
ra = sqrt(ra2);
rh = sqrt(rh2);
if (ra < SMALL) ra = SMALL;
if (rh < SMALL) rh = SMALL;
rar = 1/ra;
rhr = 1/rh;
arx = ax*rar;
ary = ay*rar;
arz = az*rar;
hrx = vb3x*rhr;
hry = vb3y*rhr;
hrz = vb3z*rhr;
c = arx*hrx+ary*hry+arz*hrz;
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,
"Improper problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) s = 1.0;
if (c < -1.0) s = -1.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
cotphi = c/s;
projhfg = (vb3x*vb1x+vb3y*vb1y+vb3z*vb1z) /
sqrt(vb1x*vb1x+vb1y*vb1y+vb1z*vb1z);
projhfg += (vb3x*vb2x+vb3y*vb2y+vb3z*vb2z) /
sqrt(vb2x*vb2x+vb2y*vb2y+vb2z*vb2z);
if (projhfg > 0.0) {
s *= -1.0;
cotphi *= -1.0;
}
// force and energy
// if w0 = 0: E = k * (1 - cos w)
// if w0 != 0: E = 0.5 * C (cos w - cos w0)^2, C = k/(sin(w0)^2
if (w0[type] == 0.0) {
if (eflag) eimproper = kw[type] * (1.0-s);
a = -kw[type];
} else {
domega = s - cos(w0[type]);
a = 0.5 * C[type] * domega;
if (eflag) eimproper = a * domega;
a *= 2.0;
}
// dhax = diffrence between H and A in X direction, etc
a = a*cotphi;
dhax = hrx-c*arx;
dhay = hry-c*ary;
dhaz = hrz-c*arz;
dahx = arx-c*hrx;
dahy = ary-c*hry;
dahz = arz-c*hrz;
f2[0] = (dhay*vb1z - dhaz*vb1y)*rar;
f2[1] = (dhaz*vb1x - dhax*vb1z)*rar;
f2[2] = (dhax*vb1y - dhay*vb1x)*rar;
f3[0] = (-dhay*vb2z + dhaz*vb2y)*rar;
f3[1] = (-dhaz*vb2x + dhax*vb2z)*rar;
f3[2] = (-dhax*vb2y + dhay*vb2x)*rar;
f4[0] = dahx*rhr;
f4[1] = dahy*rhr;
f4[2] = dahz*rhr;
f1[0] = -(f2[0] + f3[0] + f4[0]);
f1[1] = -(f2[1] + f3[1] + f4[1]);
f1[2] = -(f2[2] + f3[2] + f4[2]);
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0]*a;
f[i1][1] += f1[1]*a;
f[i1][2] += f1[2]*a;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f3[0]*a;
f[i2][1] += f3[1]*a;
f[i2][2] += f3[2]*a;
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f2[0]*a;
f[i3][1] += f2[1]*a;
f[i3][2] += f2[2]*a;
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0]*a;
f[i4][1] += f4[1]*a;
f[i4][2] += f4[2]*a;
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,eimproper,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void ImproperUmbrella::allocate()
{
allocated = 1;
int n = atom->nimpropertypes;
memory->create(kw,n+1,"improper:kw");
memory->create(w0,n+1,"improper:w0");
memory->create(C,n+1,"improper:C");
memory->create(setflag,n+1,"improper:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void ImproperUmbrella::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Incorrect args for improper coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for improper coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nimpropertypes,ilo,ihi);
double k_one = atof(arg[1]);
double w_one = atof(arg[2]);
// convert w0 from degrees to radians
int count = 0;
for (int i = ilo; i <= ihi; i++) {
kw[i] = k_one;
w0[i] = w_one/180.0 * PI;
if (w_one == 0) C[i] = 1.0;
else C[i] = kw[i]/(pow(sin(w0[i]),2));
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for improper coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for improper coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void ImproperUmbrella::write_restart(FILE *fp)
{
fwrite(&kw[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&w0[1],sizeof(double),atom->nimpropertypes,fp);
fwrite(&C[1],sizeof(double),atom->nimpropertypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void ImproperUmbrella::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&kw[1],sizeof(double),atom->nimpropertypes,fp);
fread(&w0[1],sizeof(double),atom->nimpropertypes,fp);
fread(&C[1],sizeof(double),atom->nimpropertypes,fp);
}
MPI_Bcast(&kw[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&w0[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
MPI_Bcast(&C[1],atom->nimpropertypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nimpropertypes; i++) setflag[i] = 1;
}
diff --git a/src/MOLECULE/pair_hbond_dreiding_lj.cpp b/src/MOLECULE/pair_hbond_dreiding_lj.cpp
index 243e83721..cb5429b3f 100644
--- a/src/MOLECULE/pair_hbond_dreiding_lj.cpp
+++ b/src/MOLECULE/pair_hbond_dreiding_lj.cpp
@@ -1,536 +1,533 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Tod A Pascal (Caltech)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_hbond_dreiding_lj.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define SMALL 0.001
#define CHUNK 8
/* ---------------------------------------------------------------------- */
PairHbondDreidingLJ::PairHbondDreidingLJ(LAMMPS *lmp) : Pair(lmp)
{
// hbond cannot compute virial as F dot r
// due to using map() to find bonded H atoms which are not near donor atom
no_virial_fdotr_compute = 1;
PI = 4.0*atan(1.0);
nparams = maxparam = 0;
params = NULL;
nextra = 2;
pvector = new double[2];
}
/* ---------------------------------------------------------------------- */
PairHbondDreidingLJ::~PairHbondDreidingLJ()
{
memory->sfree(params);
delete [] pvector;
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] donor;
delete [] acceptor;
memory->destroy(type2param);
}
}
/* ---------------------------------------------------------------------- */
void PairHbondDreidingLJ::compute(int eflag, int vflag)
{
int i,j,k,m,ii,jj,kk,inum,jnum,knum,itype,jtype,ktype;
double delx,dely,delz,rsq,rsq1,rsq2,r1,r2;
double factor_hb,force_angle,force_kernel,evdwl,eng_lj;
double c,s,a,b,ac,a11,a12,a22,vx1,vx2,vy1,vy2,vz1,vz2;
double fi[3],fj[3],delr1[3],delr2[3];
double r2inv,r10inv;
double switch1,switch2;
int *ilist,*jlist,*klist,*numneigh,**firstneigh;
Param *pm;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int **special = atom->special;
int *type = atom->type;
int **nspecial = atom->nspecial;
double *special_lj = force->special_lj;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// ii = loop over donors
// jj = loop over acceptors
// kk = loop over hydrogens bonded to donor
int hbcount = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
if (!donor[itype]) continue;
klist = special[i];
knum = nspecial[i][0];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_hb = special_lj[sbmask(j)];
j &= NEIGHMASK;
jtype = type[j];
if (!acceptor[jtype]) continue;
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
for (kk = 0; kk < knum; kk++) {
k = atom->map(klist[kk]);
if (k < 0) continue;
ktype = type[k];
m = type2param[itype][jtype][ktype];
if (m < 0) continue;
pm = &params[m];
if (rsq < pm->cut_outersq) {
delr1[0] = x[i][0] - x[k][0];
delr1[1] = x[i][1] - x[k][1];
delr1[2] = x[i][2] - x[k][2];
domain->minimum_image(delr1);
rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2];
r1 = sqrt(rsq1);
delr2[0] = x[j][0] - x[k][0];
delr2[1] = x[j][1] - x[k][1];
delr2[2] = x[j][2] - x[k][2];
domain->minimum_image(delr2);
rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delr1[0]*delr2[0] + delr1[1]*delr2[1] + delr1[2]*delr2[2];
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
ac = acos(c);
if (ac > pm->cut_angle && ac < (2.0*PI - pm->cut_angle)) {
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
// LJ-specific kernel
r2inv = 1.0/rsq;
r10inv = r2inv*r2inv*r2inv*r2inv*r2inv;
force_kernel = r10inv*(pm->lj1*r2inv - pm->lj2)*r2inv *
pow(c,pm->ap);
force_angle = pm->ap * r10inv*(pm->lj3*r2inv - pm->lj4) *
pow(c,pm->ap-1)*s;
eng_lj = r10inv*(pm->lj3*r2inv - pm->lj4);
if (rsq > pm->cut_innersq) {
switch1 = (pm->cut_outersq-rsq) * (pm->cut_outersq-rsq) *
(pm->cut_outersq + 2.0*rsq - 3.0*pm->cut_innersq) /
pm->denom_vdw;
switch2 = 12.0*rsq * (pm->cut_outersq-rsq) *
(rsq-pm->cut_innersq) / pm->denom_vdw;
force_kernel = force_kernel*switch1 + eng_lj*switch2;
eng_lj *= switch1;
}
if (eflag) {
evdwl = eng_lj * pow(c,pm->ap);
evdwl *= factor_hb;
}
a = factor_hb*force_angle/s;
b = factor_hb*force_kernel;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
vx1 = a11*delr1[0] + a12*delr2[0];
vx2 = a22*delr2[0] + a12*delr1[0];
vy1 = a11*delr1[1] + a12*delr2[1];
vy2 = a22*delr2[1] + a12*delr1[1];
vz1 = a11*delr1[2] + a12*delr2[2];
vz2 = a22*delr2[2] + a12*delr1[2];
fi[0] = vx1 + b*delx;
fi[1] = vy1 + b*dely;
fi[2] = vz1 + b*delz;
fj[0] = vx2 - b*delx;
fj[1] = vy2 - b*dely;
fj[2] = vz2 - b*delz;
f[i][0] += fi[0];
f[i][1] += fi[1];
f[i][2] += fi[2];
f[j][0] += fj[0];
f[j][1] += fj[1];
f[j][2] += fj[2];
f[k][0] -= vx1 + vx2;
f[k][1] -= vy1 + vy2;
f[k][2] -= vz1 + vz2;
// KIJ instead of IJK b/c delr1/delr2 are both with respect to k
if (evflag) ev_tally3(k,i,j,evdwl,0.0,fi,fj,delr1,delr2);
hbcount++;
}
}
}
}
}
if (eflag_global) {
pvector[0] = hbcount;
pvector[1] = evdwl;
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairHbondDreidingLJ::allocate()
{
allocated = 1;
int n = atom->ntypes;
// mark all setflag as set, since don't require pair_coeff of all I,J
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 1;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
donor = new int[n+1];
acceptor = new int[n+1];
memory->create(type2param,n+1,n+1,n+1,"pair:type2param");
int i,j,k;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
for (k = 1; k <= n; k++)
type2param[i][j][k] = -1;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairHbondDreidingLJ::settings(int narg, char **arg)
{
- if (narg != 4) error->all("Illegal pair_style command");
+ if (narg != 4) error->all(FLERR,"Illegal pair_style command");
ap_global = force->inumeric(arg[0]);
cut_inner_global = force->numeric(arg[1]);
cut_outer_global = force->numeric(arg[2]);
cut_angle_global = force->numeric(arg[3]) * PI/180.0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairHbondDreidingLJ::coeff(int narg, char **arg)
{
if (narg < 6 || narg > 9)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi,klo,khi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
force->bounds(arg[2],atom->ntypes,klo,khi);
int donor_flag;
if (strcmp(arg[3],"i") == 0) donor_flag = 0;
else if (strcmp(arg[3],"j") == 0) donor_flag = 1;
- else error->all("Incorrect args for pair coefficients");
+ else error->all(FLERR,"Incorrect args for pair coefficients");
double epsilon_one = force->numeric(arg[4]);
double sigma_one = force->numeric(arg[5]);
int ap_one = ap_global;
if (narg > 6) ap_one = force->inumeric(arg[6]);
double cut_inner_one = cut_inner_global;
double cut_outer_one = cut_outer_global;
if (narg > 8) {
cut_inner_one = force->numeric(arg[7]);
cut_outer_one = force->numeric(arg[8]);
}
if (cut_inner_one>cut_outer_one)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
double cut_angle_one = cut_angle_global;
if (narg == 10) cut_angle_one = force->numeric(arg[9]) * PI/180.0;
// grow params array if necessary
if (nparams == maxparam) {
maxparam += CHUNK;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].epsilon = epsilon_one;
params[nparams].sigma = sigma_one;
params[nparams].ap = ap_one;
params[nparams].cut_inner = cut_inner_one;
params[nparams].cut_outer = cut_outer_one;
params[nparams].cut_innersq = cut_inner_one*cut_inner_one;
params[nparams].cut_outersq = cut_outer_one*cut_outer_one;
params[nparams].cut_angle = cut_angle_one;
params[nparams].denom_vdw =
(params[nparams].cut_outersq-params[nparams].cut_innersq) *
(params[nparams].cut_outersq-params[nparams].cut_innersq) *
(params[nparams].cut_outersq-params[nparams].cut_innersq);
// flag type2param with either i,j = D,A or j,i = D,A
int count = 0;
for (int i = ilo; i <= ihi; i++)
for (int j = MAX(jlo,i); j <= jhi; j++)
for (int k = klo; k <= khi; k++) {
if (donor_flag == 0) type2param[i][j][k] = nparams;
else type2param[j][i][k] = nparams;
count++;
}
nparams++;
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairHbondDreidingLJ::init_style()
{
// molecular system required to use special list to find H atoms
// tags required to use special list
// pair newton on required since are looping over D atoms
// and computing forces on A,H which may be on different procs
if (atom->molecular == 0)
- error->all("Pair style hbond/dreiding requires molecular system");
+ error->all(FLERR,"Pair style hbond/dreiding requires molecular system");
if (atom->tag_enable == 0)
- error->all("Pair style hbond/dreiding requires atom IDs");
+ error->all(FLERR,"Pair style hbond/dreiding requires atom IDs");
if (atom->map_style == 0)
- error->all("Pair style hbond/dreiding requires an atom map, "
+ error->all(FLERR,"Pair style hbond/dreiding requires an atom map, "
"see atom_modify");
if (force->newton_pair == 0)
- error->all("Pair style hbond/dreiding requires newton pair on");
+ error->all(FLERR,"Pair style hbond/dreiding requires newton pair on");
// set donor[M]/acceptor[M] if any atom of type M is a donor/acceptor
int anyflag = 0;
int n = atom->ntypes;
for (int m = 1; m <= n; m++) donor[m] = acceptor[m] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
if (type2param[i][j][k] >= 0) {
anyflag = 1;
donor[i] = 1;
acceptor[j] = 1;
}
- if (!anyflag) error->all("No pair hbond/dreiding coefficients set");
+ if (!anyflag) error->all(FLERR,"No pair hbond/dreiding coefficients set");
// set additional param values
// offset is for LJ only, angle term is not included
for (int m = 0; m < nparams; m++) {
params[m].lj1 = 60.0*params[m].epsilon*pow(params[m].sigma,12.0);
params[m].lj2 = 60.0*params[m].epsilon*pow(params[m].sigma,10.0);
params[m].lj3 = 5.0*params[m].epsilon*pow(params[m].sigma,12.0);
params[m].lj4 = 6.0*params[m].epsilon*pow(params[m].sigma,10.0);
/*
if (offset_flag) {
double ratio = params[m].sigma / params[m].cut_outer;
params[m].offset = params[m].epsilon *
((2.0*pow(ratio,9.0)) - (3.0*pow(ratio,6.0)));
} else params[m].offset = 0.0;
*/
}
// full neighbor list request
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairHbondDreidingLJ::init_one(int i, int j)
{
int m;
// return maximum cutoff for any K with I,J = D,A or J,I = D,A
// donor/acceptor is not symmetric, IJ interaction != JI interaction
double cut = 0.0;
for (int k = 1; k <= atom->ntypes; k++) {
m = type2param[i][j][k];
if (m >= 0) cut = MAX(cut,params[m].cut_outer);
m = type2param[j][i][k];
if (m >= 0) cut = MAX(cut,params[m].cut_outer);
}
return cut;
}
/* ---------------------------------------------------------------------- */
double PairHbondDreidingLJ::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
int k,kk,ktype,knum,m;
double eng,eng_lj,force_kernel,force_angle;
double rsq1,rsq2,r1,r2,c,s,ac,r2inv,r10inv,factor_hb;
double switch1,switch2;
double delr1[3],delr2[3];
int *klist;
Param *pm;
double **x = atom->x;
int **special = atom->special;
int *type = atom->type;
int **nspecial = atom->nspecial;
double *special_lj = force->special_lj;
eng = 0.0;
fforce = 0;
// sanity check
if (!donor[itype]) return 0.0;
if (!acceptor[jtype]) return 0.0;
klist = special[i];
knum = nspecial[i][0];
factor_hb = special_lj[sbmask(j)];
for (kk = 0; kk < knum; kk++) {
k = atom->map(klist[kk]);
if (k < 0) continue;
ktype = type[k];
m = type2param[itype][jtype][ktype];
if (m < 0) continue;
pm = &params[m];
delr1[0] = x[i][0] - x[k][0];
delr1[1] = x[i][1] - x[k][1];
delr1[2] = x[i][2] - x[k][2];
domain->minimum_image(delr1);
rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2];
r1 = sqrt(rsq1);
delr2[0] = x[j][0] - x[k][0];
delr2[1] = x[j][1] - x[k][1];
delr2[2] = x[j][2] - x[k][2];
domain->minimum_image(delr2);
rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delr1[0]*delr2[0] + delr1[1]*delr2[1] + delr1[2]*delr2[2];
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
ac = acos(c);
if (ac < pm->cut_angle || ac > (2.0*PI - pm->cut_angle)) return 0.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
// LJ-specific kernel
r2inv = 1.0/rsq;
r10inv = r2inv*r2inv*r2inv*r2inv*r2inv;
force_kernel = r10inv*(pm->lj1*r2inv - pm->lj2)*r2inv *
pow(c,pm->ap);
force_angle = pm->ap * r10inv*(pm->lj3*r2inv - pm->lj4) *
pow(c,pm->ap-1)*s;
// only lj part for now
eng_lj = r10inv*(pm->lj3*r2inv - pm->lj4);
if (rsq > pm->cut_innersq) {
switch1 = (pm->cut_outersq-rsq) * (pm->cut_outersq-rsq) *
(pm->cut_outersq + 2.0*rsq - 3.0*pm->cut_innersq) /
pm->denom_vdw;
switch2 = 12.0*rsq * (pm->cut_outersq-rsq) *
(rsq-pm->cut_innersq) / pm->denom_vdw;
force_kernel = force_kernel*switch1 + eng_lj*switch2;
eng_lj *= switch1;
}
fforce += force_kernel*pow(c,pm->ap) + eng_lj*force_angle;
eng += eng_lj * pow(c,pm->ap) * factor_hb;
}
return eng;
}
diff --git a/src/MOLECULE/pair_hbond_dreiding_morse.cpp b/src/MOLECULE/pair_hbond_dreiding_morse.cpp
index 62f75f0a1..2e70d928d 100644
--- a/src/MOLECULE/pair_hbond_dreiding_morse.cpp
+++ b/src/MOLECULE/pair_hbond_dreiding_morse.cpp
@@ -1,438 +1,435 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Tod A Pascal (Caltech)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_hbond_dreiding_morse.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define SMALL 0.001
#define CHUNK 8
/* ---------------------------------------------------------------------- */
PairHbondDreidingMorse::PairHbondDreidingMorse(LAMMPS *lmp) :
PairHbondDreidingLJ(lmp) {}
/* ---------------------------------------------------------------------- */
void PairHbondDreidingMorse::compute(int eflag, int vflag)
{
int i,j,k,m,ii,jj,kk,inum,jnum,knum,itype,jtype,ktype;
double delx,dely,delz,rsq,rsq1,rsq2,r1,r2;
double factor_hb,force_angle,force_kernel,evdwl;
double c,s,a,b,ac,a11,a12,a22,vx1,vx2,vy1,vy2,vz1,vz2;
double fi[3],fj[3],delr1[3],delr2[3];
double r,dr,dexp,eng_morse,switch1,switch2;
int *ilist,*jlist,*klist,*numneigh,**firstneigh;
Param *pm;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int **special = atom->special;
int *type = atom->type;
int **nspecial = atom->nspecial;
double *special_lj = force->special_lj;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// ii = loop over donors
// jj = loop over acceptors
// kk = loop over hydrogens bonded to donor
int hbcount = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
if (!donor[itype]) continue;
klist = special[i];
knum = nspecial[i][0];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_hb = special_lj[sbmask(j)];
j &= NEIGHMASK;
jtype = type[j];
if (!acceptor[jtype]) continue;
delx = x[i][0] - x[j][0];
dely = x[i][1] - x[j][1];
delz = x[i][2] - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
for (kk = 0; kk < knum; kk++) {
k = atom->map(klist[kk]);
if (k < 0) continue;
ktype = type[k];
m = type2param[itype][jtype][ktype];
if (m < 0) continue;
pm = &params[m];
if (rsq < pm->cut_outersq) {
delr1[0] = x[i][0] - x[k][0];
delr1[1] = x[i][1] - x[k][1];
delr1[2] = x[i][2] - x[k][2];
domain->minimum_image(delr1);
rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2];
r1 = sqrt(rsq1);
delr2[0] = x[j][0] - x[k][0];
delr2[1] = x[j][1] - x[k][1];
delr2[2] = x[j][2] - x[k][2];
domain->minimum_image(delr2);
rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delr1[0]*delr2[0] + delr1[1]*delr2[1] + delr1[2]*delr2[2];
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
ac = acos(c);
if (ac > pm->cut_angle && ac < (2.0*PI - pm->cut_angle)) {
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
// Morse-specific kernel
r = sqrt(rsq);
dr = r - pm->r0;
dexp = exp(-pm->alpha * dr);
force_kernel = pm->morse1*(dexp*dexp - dexp)/r * pow(c,pm->ap);
force_angle = pm->ap * eng_morse * pow(c,pm->ap-1)*s;
eng_morse = pm->d0 * (dexp*dexp - 2.0*dexp);
if (rsq > pm->cut_innersq) {
switch1 = (pm->cut_outersq-rsq) * (pm->cut_outersq-rsq) *
(pm->cut_outersq + 2.0*rsq - 3.0*pm->cut_innersq) /
pm->denom_vdw;
switch2 = 12.0*rsq * (pm->cut_outersq-rsq) *
(rsq-pm->cut_innersq) / pm->denom_vdw;
force_kernel = force_kernel*switch1 + eng_morse*switch2;
eng_morse *= switch1;
}
if (eflag) {
evdwl = eng_morse * pow(c,params[m].ap);
evdwl *= factor_hb;
}
a = factor_hb*force_angle/s;
b = factor_hb*force_kernel;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
vx1 = a11*delr1[0] + a12*delr2[0];
vx2 = a22*delr2[0] + a12*delr1[0];
vy1 = a11*delr1[1] + a12*delr2[1];
vy2 = a22*delr2[1] + a12*delr1[1];
vz1 = a11*delr1[2] + a12*delr2[2];
vz2 = a22*delr2[2] + a12*delr1[2];
fi[0] = vx1 + b*delx;
fi[1] = vy1 + b*dely;
fi[2] = vz1 + b*delz;
fj[0] = vx2 - b*delx;
fj[1] = vy2 - b*dely;
fj[2] = vz2 - b*delz;
f[i][0] += fi[0];
f[i][1] += fi[1];
f[i][2] += fi[2];
f[j][0] += fj[0];
f[j][1] += fj[1];
f[j][2] += fj[2];
f[k][0] -= vx1 + vx2;
f[k][1] -= vy1 + vy2;
f[k][2] -= vz1 + vz2;
// KIJ instead of IJK b/c delr1/delr2 are both with respect to k
if (evflag) ev_tally3(k,i,j,evdwl,0.0,fi,fj,delr1,delr2);
hbcount++;
}
}
}
}
}
if (eflag_global) {
pvector[0] = hbcount;
pvector[1] = evdwl;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairHbondDreidingMorse::coeff(int narg, char **arg)
{
if (narg < 8 || narg > 11)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi,klo,khi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
force->bounds(arg[2],atom->ntypes,klo,khi);
int donor_flag;
if (strcmp(arg[3],"i") == 0) donor_flag = 0;
else if (strcmp(arg[3],"j") == 0) donor_flag = 1;
- else error->all("Incorrect args for pair coefficients");
+ else error->all(FLERR,"Incorrect args for pair coefficients");
double d0_one = force->numeric(arg[4]);
double alpha_one = force->numeric(arg[5]);
double r0_one = force->numeric(arg[6]);
int ap_one = ap_global;
if (narg > 7) ap_one = force->inumeric(arg[7]);
double cut_inner_one = cut_inner_global;
double cut_outer_one = cut_outer_global;
if (narg > 9) {
cut_inner_one = force->numeric(arg[8]);
cut_outer_one = force->numeric(arg[9]);
}
if (cut_inner_one>cut_outer_one)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
double cut_angle_one = cut_angle_global;
if (narg > 10) cut_angle_one = force->numeric(arg[10]) * PI/180.0;
// grow params array if necessary
if (nparams == maxparam) {
maxparam += CHUNK;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].d0 = d0_one;
params[nparams].alpha = alpha_one;
params[nparams].r0 = r0_one;
params[nparams].ap = ap_one;
params[nparams].cut_inner = cut_inner_one;
params[nparams].cut_outer = cut_outer_one;
params[nparams].cut_innersq = cut_inner_one*cut_inner_one;
params[nparams].cut_outersq = cut_outer_one*cut_outer_one;
params[nparams].cut_angle = cut_angle_one;
params[nparams].denom_vdw =
(params[nparams].cut_outersq-params[nparams].cut_innersq) *
(params[nparams].cut_outersq-params[nparams].cut_innersq) *
(params[nparams].cut_outersq-params[nparams].cut_innersq);
// flag type2param with either i,j = D,A or j,i = D,A
int count = 0;
for (int i = ilo; i <= ihi; i++)
for (int j = MAX(jlo,i); j <= jhi; j++)
for (int k = klo; k <= khi; k++) {
if (donor_flag == 0) type2param[i][j][k] = nparams;
else type2param[j][i][k] = nparams;
count++;
}
nparams++;
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairHbondDreidingMorse::init_style()
{
// molecular system required to use special list to find H atoms
// tags required to use special list
// pair newton on required since are looping over D atoms
// and computing forces on A,H which may be on different procs
if (atom->molecular == 0)
- error->all("Pair style hbond/dreiding requires molecular system");
+ error->all(FLERR,"Pair style hbond/dreiding requires molecular system");
if (atom->tag_enable == 0)
- error->all("Pair style hbond/dreiding requires atom IDs");
+ error->all(FLERR,"Pair style hbond/dreiding requires atom IDs");
if (atom->map_style == 0)
- error->all("Pair style hbond/dreiding requires an atom map, "
+ error->all(FLERR,"Pair style hbond/dreiding requires an atom map, "
"see atom_modify");
if (force->newton_pair == 0)
- error->all("Pair style hbond/dreiding requires newton pair on");
+ error->all(FLERR,"Pair style hbond/dreiding requires newton pair on");
// set donor[M]/acceptor[M] if any atom of type M is a donor/acceptor
int anyflag = 0;
int n = atom->ntypes;
for (int m = 1; m <= n; m++) donor[m] = acceptor[m] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
if (type2param[i][j][k] >= 0) {
anyflag = 1;
donor[i] = 1;
acceptor[j] = 1;
}
- if (!anyflag) error->all("No pair hbond/dreiding coefficients set");
+ if (!anyflag) error->all(FLERR,"No pair hbond/dreiding coefficients set");
// set additional param values
// offset is for Morse only, angle term is not included
for (int m = 0; m < nparams; m++) {
params[m].morse1 = 2.0*params[m].d0*params[m].alpha;
/*
if (offset_flag) {
double alpha_dr = -params[m].alpha * (params[m].cut - params[m].r0);
params[m].offset = params[m].d0 *
((exp(2.0*alpha_dr)) - (2.0*exp(alpha_dr)));
} else params[m].offset = 0.0;
*/
}
// full neighbor list request
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ---------------------------------------------------------------------- */
double PairHbondDreidingMorse::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
int k,kk,ktype,knum,m;
double eng,eng_morse,force_kernel,force_angle;
double rsq1,rsq2,r1,r2,c,s,ac,r,dr,dexp,factor_hb;
double switch1,switch2;
double delr1[3],delr2[3];
int *klist;
Param *pm;
double **x = atom->x;
int **special = atom->special;
int *type = atom->type;
int **nspecial = atom->nspecial;
double *special_lj = force->special_lj;
eng = 0.0;
fforce = 0;
//sanity check
if (!donor[itype]) return 0.0;
if (!acceptor[jtype]) return 0.0;
klist = special[i];
knum = nspecial[i][0];
factor_hb = special_lj[sbmask(j)];
for (kk = 0; kk < knum; kk++) {
k = atom->map(klist[kk]);
if (k < 0) continue;
ktype = type[k];
m = type2param[itype][jtype][ktype];
if (m < 0) continue;
pm = &params[m];
delr1[0] = x[i][0] - x[k][0];
delr1[1] = x[i][1] - x[k][1];
delr1[2] = x[i][2] - x[k][2];
domain->minimum_image(delr1);
rsq1 = delr1[0]*delr1[0] + delr1[1]*delr1[1] + delr1[2]*delr1[2];
r1 = sqrt(rsq1);
delr2[0] = x[j][0] - x[k][0];
delr2[1] = x[j][1] - x[k][1];
delr2[2] = x[j][2] - x[k][2];
domain->minimum_image(delr2);
rsq2 = delr2[0]*delr2[0] + delr2[1]*delr2[1] + delr2[2]*delr2[2];
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delr1[0]*delr2[0] + delr1[1]*delr2[1] + delr1[2]*delr2[2];
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
ac = acos(c);
if (ac < pm->cut_angle || ac > (2.0*PI - pm->cut_angle)) return 0.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
// Morse-specific kernel
r = sqrt(rsq);
dr = r - pm->r0;
dexp = exp(-pm->alpha * dr);
force_kernel = pm->morse1*(dexp*dexp - dexp)/r * pow(c,pm->ap);
force_angle = pm->ap * eng_morse * pow(c,pm->ap-1)*s;
eng_morse = pm->d0 * (dexp*dexp - 2.0*dexp);
if (rsq > pm->cut_innersq) {
switch1 = (pm->cut_outersq-rsq) * (pm->cut_outersq-rsq) *
(pm->cut_outersq + 2.0*rsq - 3.0*pm->cut_innersq) /
pm->denom_vdw;
switch2 = 12.0*rsq * (pm->cut_outersq-rsq) *
(rsq-pm->cut_innersq) / pm->denom_vdw;
force_kernel = force_kernel*switch1 + eng_morse*switch2;
eng_morse *= switch1;
}
eng += eng_morse * pow(c,params[m].ap)* factor_hb;
fforce += force_kernel*pow(c,pm->ap) + eng_morse*force_angle;
}
return eng;
}
diff --git a/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp b/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp
index 3552f9e18..875f4c95a 100644
--- a/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp
+++ b/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp
@@ -1,510 +1,507 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_charmm_coul_charmm.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{GEOMETRIC,ARITHMETIC,SIXTHPOWER}; // same as in pair.cpp
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulCharmm::PairLJCharmmCoulCharmm(LAMMPS *lmp) : Pair(lmp)
{
implicit = 0;
mix_flag = ARITHMETIC;
}
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulCharmm::~PairLJCharmmCoulCharmm()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(eps14);
memory->destroy(sigma14);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(lj14_1);
memory->destroy(lj14_2);
memory->destroy(lj14_3);
memory->destroy(lj14_4);
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double philj,switch1,switch2;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_bothsq) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
if (rsq > cut_coul_innersq) {
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / denom_coul;
switch2 = 12.0*rsq * (cut_coulsq-rsq) *
(rsq-cut_coul_innersq) / denom_coul;
forcecoul *= switch1 + switch2;
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
} else forcelj = 0.0;
fpair = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
ecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
if (rsq > cut_coul_innersq) {
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) /
denom_coul;
ecoul *= switch1;
}
ecoul *= factor_coul;
} else ecoul = 0.0;
if (rsq < cut_ljsq) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
evdwl *= switch1;
}
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(eps14,n+1,n+1,"pair:eps14");
memory->create(sigma14,n+1,n+1,"pair:sigma14");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(lj14_1,n+1,n+1,"pair:lj14_1");
memory->create(lj14_2,n+1,n+1,"pair:lj14_2");
memory->create(lj14_3,n+1,n+1,"pair:lj14_3");
memory->create(lj14_4,n+1,n+1,"pair:lj14_4");
}
/* ----------------------------------------------------------------------
global settings
unlike other pair styles,
there are no individual pair settings that these override
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::settings(int narg, char **arg)
{
if (narg != 2 && narg != 4)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
cut_lj_inner = force->numeric(arg[0]);
cut_lj = force->numeric(arg[1]);
if (narg == 2) {
cut_coul_inner = cut_lj_inner;
cut_coul = cut_lj;
} else {
cut_coul_inner = force->numeric(arg[2]);
cut_coul = force->numeric(arg[3]);
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::coeff(int narg, char **arg)
{
if (narg != 4 && narg != 6)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double eps14_one = epsilon_one;
double sigma14_one = sigma_one;
if (narg == 6) {
eps14_one = force->numeric(arg[4]);
sigma14_one = force->numeric(arg[5]);
}
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
eps14[i][j] = eps14_one;
sigma14[i][j] = sigma14_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/charmm/coul/charmm requires atom attribute q");
+ error->all(FLERR,"Pair style lj/charmm/coul/charmm requires atom attribute q");
neighbor->request(this);
// require cut_lj_inner < cut_lj, cut_coul_inner < cut_coul
if (cut_lj_inner >= cut_lj || cut_coul_inner >= cut_coul)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coul_innersq = cut_coul_inner * cut_coul_inner;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) *
(cut_ljsq-cut_lj_innersq);
denom_coul = (cut_coulsq-cut_coul_innersq) * (cut_coulsq-cut_coul_innersq) *
(cut_coulsq-cut_coul_innersq);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJCharmmCoulCharmm::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
eps14[i][j] = mix_energy(eps14[i][i],eps14[j][j],
sigma14[i][i],sigma14[j][j]);
sigma14[i][j] = mix_distance(sigma14[i][i],sigma14[j][j]);
}
double cut = MAX(cut_lj,cut_coul);
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj14_1[i][j] = 48.0 * eps14[i][j] * pow(sigma14[i][j],12.0);
lj14_2[i][j] = 24.0 * eps14[i][j] * pow(sigma14[i][j],6.0);
lj14_3[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],12.0);
lj14_4[i][j] = 4.0 * eps14[i][j] * pow(sigma14[i][j],6.0);
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
lj14_1[j][i] = lj14_1[i][j];
lj14_2[j][i] = lj14_2[i][j];
lj14_3[j][i] = lj14_3[i][j];
lj14_4[j][i] = lj14_4[i][j];
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&eps14[i][j],sizeof(double),1,fp);
fwrite(&sigma14[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&eps14[i][j],sizeof(double),1,fp);
fread(&sigma14[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&eps14[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma14[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_inner,sizeof(double),1,fp);
fwrite(&cut_lj,sizeof(double),1,fp);
fwrite(&cut_coul_inner,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmm::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_inner,sizeof(double),1,fp);
fread(&cut_lj,sizeof(double),1,fp);
fread(&cut_coul_inner,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_inner,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_inner,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJCharmmCoulCharmm::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcecoul,forcelj,phicoul,philj;
double switch1,switch2;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
if (rsq > cut_coul_innersq) {
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / denom_coul;
switch2 = 12.0*rsq * (cut_coulsq-rsq) *
(rsq-cut_coul_innersq) / denom_coul;
forcecoul *= switch1 + switch2;
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) / denom_lj;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
forcelj = forcelj*switch1 + philj*switch2;
}
} else forcelj = 0.0;
fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq) {
phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
if (rsq > cut_coul_innersq) {
switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) *
(cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) /
denom_coul;
phicoul *= switch1;
}
eng += factor_coul*phicoul;
}
if (rsq < cut_ljsq) {
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj;
philj *= switch1;
}
eng += factor_lj*philj;
}
return eng;
}
/* ---------------------------------------------------------------------- */
void *PairLJCharmmCoulCharmm::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"lj14_1") == 0) return (void *) lj14_1;
if (strcmp(str,"lj14_2") == 0) return (void *) lj14_2;
if (strcmp(str,"lj14_3") == 0) return (void *) lj14_3;
if (strcmp(str,"lj14_4") == 0) return (void *) lj14_4;
dim = 0;
if (strcmp(str,"implicit") == 0) return (void *) &implicit;
return NULL;
}
diff --git a/src/Makefile b/src/Makefile
index c95e423ba..c0a9df822 100755
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,197 +1,201 @@
# LAMMPS multiple-machine Makefile
SHELL = /bin/bash
#.IGNORE:
# Definitions
ROOT = lmp
EXE = $(ROOT)_$@
SRC = $(wildcard *.cpp)
INC = $(wildcard *.h)
OBJ = $(SRC:.cpp=.o)
# Package variables
PACKAGE = asphere class2 colloid dipole gpu granular \
kspace manybody mc meam molecule opt peri poems reax replica \
shock srd xtc
PACKUSER = user-misc user-atc user-awpmd user-cg-cmm \
user-cuda user-eff user-ewaldn user-omp user-reaxc user-sph
PACKALL = $(PACKAGE) $(PACKUSER)
PACKAGEUC = $(shell echo $(PACKAGE) | tr a-z A-Z)
PACKUSERUC = $(shell echo $(PACKUSER) | tr a-z A-Z)
YESDIR = $(shell echo $(@:yes-%=%) | tr a-z A-Z)
NODIR = $(shell echo $(@:no-%=%) | tr a-z A-Z)
# List of all targets
help:
@echo ''
@echo 'make clean-all delete all object files'
@echo 'make clean-machine delete object files for one machine'
@echo 'make tar lmp_src.tar.gz of src dir and packages'
@echo 'make makelib update Makefile.lib for library build'
@echo 'make makelist update Makefile.list used by old makes'
@echo ''
@echo 'make package list available packages'
@echo 'make package-status status of all packages'
@echo 'make yes-package install a single package in src dir'
@echo 'make no-package remove a single package from src dir'
@echo 'make yes-all install all packages in src dir'
@echo 'make no-all remove all packages from src dir'
@echo 'make yes-standard install all standard packages'
@echo 'make no-standard remove all standard packages'
@echo 'make yes-user install all user packages'
@echo 'make no-user remove all user packages'
@echo ''
@echo 'make package-update replace src files with package files'
@echo 'make package-overwrite replace package files with src files'
@echo 'make package-diff diff src files against package files'
@echo ''
@echo 'make machine build LAMMPS where machine is one of:'
@echo ''
@files="`ls MAKE/Makefile.*`"; \
for file in $$files; do head -1 $$file; done
@echo ''
# Build the code
.DEFAULT:
@test -f MAKE/Makefile.$@
@if [ ! -d Obj_$@ ]; then mkdir Obj_$@; fi
@$(SHELL) Make.sh style
@cp -p *.cpp *.h Obj_$@
@cp MAKE/Makefile.$@ Obj_$@/Makefile
@if [ ! -e Makefile.package ]; \
then cp Makefile.package.empty Makefile.package; fi
@if [ ! -e Makefile.package.settings ]; \
then cp Makefile.package.settings.empty Makefile.package.settings; fi
@cp Makefile.package Makefile.package.settings Obj_$@
@cd Obj_$@; \
$(MAKE) $(MFLAGS) "OBJ = $(OBJ)" "INC = $(INC)" \
"EXE = ../$(EXE)" ../$(EXE)
@if [ -d Obj_$@ ]; then cd Obj_$@; rm -f $(SRC) $(INC) Makefile*; fi
# Remove machine-specific object files
clean:
@echo 'make clean-all delete all object files'
@echo 'make clean-machine delete object files for one machine'
clean-all:
rm -rf Obj_*
clean-%:
rm -rf Obj_$(@:clean-%=%)
# Create a tarball of src dir and packages
tar:
@cd STUBS; make clean
@cd ..; tar cvzf src/$(ROOT)_src.tar.gz \
src/Make* src/Package.sh src/MAKE src/*.cpp src/*.h src/STUBS \
$(patsubst %,src/%,$(PACKAGEUC)) $(patsubst %,src/%,$(PACKUSERUC)) \
--exclude=*/.svn
@cd STUBS; make
@echo "Created $(ROOT)_src.tar.gz"
# Make MPI STUBS lib
stubs:
@cd STUBS; make clean; make
# Update Makefile.lib and Makefile.list
makelib:
@$(SHELL) Make.sh style
@$(SHELL) Make.sh Makefile.lib
makelist:
@$(SHELL) Make.sh style
@$(SHELL) Make.sh Makefile.list
# Package management
package:
@echo 'Standard packages:' $(PACKAGE)
@echo ''
@echo 'User-contributed packages:' $(PACKUSER)
@echo ''
@echo 'make package list available packages'
@echo 'make package-status status of all packages'
@echo 'make yes-package install a single package in src dir'
@echo 'make no-package remove a single package from src dir'
@echo 'make yes-all install all packages in src dir'
@echo 'make no-all remove all packages from src dir'
@echo 'make yes-standard install all standard packages'
@echo 'make no-standard remove all standard packages'
@echo 'make yes-user install all user packages'
@echo 'make no-user remove all user packages'
@echo ''
@echo 'make package-update replace src files with package files'
@echo 'make package-overwrite replace package files with src files'
@echo 'make package-diff diff src files against package file'
yes-all:
@for p in $(PACKALL); do $(MAKE) yes-$$p; done
no-all:
@for p in $(PACKALL); do $(MAKE) no-$$p; done
yes-standard:
@for p in $(PACKAGE); do $(MAKE) yes-$$p; done
no-standard:
@for p in $(PACKAGE); do $(MAKE) no-$$p; done
yes-user:
@for p in $(PACKUSER); do $(MAKE) yes-$$p; done
no-user:
@for p in $(PACKUSER); do $(MAKE) no-$$p; done
yes-%:
+ @if [ ! -e Makefile.package ]; \
+ then cp Makefile.package.empty Makefile.package; fi
+ @if [ ! -e Makefile.package.settings ]; \
+ then cp Makefile.package.settings.empty Makefile.package.settings; fi
@if [ ! -e $(YESDIR) ]; then \
echo "Package $(@:yes-%=%) does not exist"; \
else \
echo "Installing package $(@:yes-%=%)"; \
cd $(YESDIR); $(SHELL) Install.sh 1; cd ..; $(SHELL) Depend.sh 1; \
fi;
no-%:
@if [ ! -e $(NODIR) ]; then \
echo "Package $(@:no-%=%) does not exist"; \
else \
echo "Uninstalling package $(@:no-%=%)"; \
cd $(NODIR); $(SHELL) Install.sh 0; cd ..; $(SHELL) Depend.sh 0; \
fi;
# status = list src files that differ from package files
# update = replace src files with newer package files
# overwrite = overwrite package files with newer src files
# diff = show differences between src and package files
package-status:
@for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p status; done
@echo ''
@for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p status; done
package-update:
@for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p update; done
@echo ''
@for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p update; done
package-overwrite:
@for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p overwrite; done
@echo ''
@for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p overwrite; done
package-diff:
@for p in $(PACKAGEUC); do $(SHELL) Package.sh $$p diff; done
@echo ''
@for p in $(PACKUSERUC); do $(SHELL) Package.sh $$p diff; done
diff --git a/src/Makefile.lib b/src/Makefile.lib
index 79e4d5693..10051e1c2 100644
--- a/src/Makefile.lib
+++ b/src/Makefile.lib
@@ -1,35 +1,39 @@
# LAMMPS library multiple-machine Makefile
SHELL = /bin/sh
# Definitions
ROOT = lmp
EXE = lib$(ROOT)_$@.a
SRC = angle.cpp angle_charmm.cpp angle_class2.cpp angle_cosine.cpp angle_cosine_delta.cpp angle_cosine_periodic.cpp angle_cosine_squared.cpp angle_harmonic.cpp angle_hybrid.cpp angle_table.cpp atom.cpp atom_vec.cpp atom_vec_angle.cpp atom_vec_atomic.cpp atom_vec_bond.cpp atom_vec_charge.cpp atom_vec_dipole.cpp atom_vec_ellipsoid.cpp atom_vec_full.cpp atom_vec_hybrid.cpp atom_vec_molecular.cpp atom_vec_peri.cpp atom_vec_sphere.cpp bond.cpp bond_class2.cpp bond_fene.cpp bond_fene_expand.cpp bond_harmonic.cpp bond_hybrid.cpp bond_morse.cpp bond_nonlinear.cpp bond_quartic.cpp bond_table.cpp change_box.cpp comm.cpp compute.cpp compute_angle_local.cpp compute_atom_molecule.cpp compute_bond_local.cpp compute_centro_atom.cpp compute_cluster_atom.cpp compute_cna_atom.cpp compute_com.cpp compute_com_molecule.cpp compute_coord_atom.cpp compute_damage_atom.cpp compute_dihedral_local.cpp compute_displace_atom.cpp compute_erotate_asphere.cpp compute_erotate_sphere.cpp compute_event_displace.cpp compute_group_group.cpp compute_gyration.cpp compute_gyration_molecule.cpp compute_heat_flux.cpp compute_improper_local.cpp compute_ke.cpp compute_ke_atom.cpp compute_msd.cpp compute_msd_molecule.cpp compute_pair.cpp compute_pair_local.cpp compute_pe.cpp compute_pe_atom.cpp compute_pressure.cpp compute_property_atom.cpp compute_property_local.cpp compute_property_molecule.cpp compute_rdf.cpp compute_reduce.cpp compute_reduce_region.cpp compute_slice.cpp compute_stress_atom.cpp compute_temp.cpp compute_temp_asphere.cpp compute_temp_com.cpp compute_temp_deform.cpp compute_temp_partial.cpp compute_temp_profile.cpp compute_temp_ramp.cpp compute_temp_region.cpp compute_temp_sphere.cpp compute_ti.cpp create_atoms.cpp create_box.cpp delete_atoms.cpp delete_bonds.cpp dihedral.cpp dihedral_charmm.cpp dihedral_class2.cpp dihedral_harmonic.cpp dihedral_helix.cpp dihedral_hybrid.cpp dihedral_multi_harmonic.cpp dihedral_opls.cpp displace_atoms.cpp displace_box.cpp domain.cpp dump.cpp dump_atom.cpp dump_cfg.cpp dump_custom.cpp dump_dcd.cpp dump_image.cpp dump_local.cpp dump_xtc.cpp dump_xyz.cpp error.cpp ewald.cpp fft3d.cpp fft3d_wrap.cpp finish.cpp fix.cpp fix_adapt.cpp fix_addforce.cpp fix_ave_atom.cpp fix_ave_correlate.cpp fix_ave_histo.cpp fix_ave_spatial.cpp fix_ave_time.cpp fix_aveforce.cpp fix_bond_break.cpp fix_bond_create.cpp fix_bond_swap.cpp fix_box_relax.cpp fix_deform.cpp fix_deposit.cpp fix_drag.cpp fix_dt_reset.cpp fix_efield.cpp fix_enforce2d.cpp fix_evaporate.cpp fix_event.cpp fix_event_prd.cpp fix_event_tad.cpp fix_external.cpp fix_freeze.cpp fix_gravity.cpp fix_heat.cpp fix_indent.cpp fix_langevin.cpp fix_lineforce.cpp fix_minimize.cpp fix_momentum.cpp fix_move.cpp fix_msst.cpp fix_neb.cpp fix_nh.cpp fix_nh_asphere.cpp fix_nh_sphere.cpp fix_nph.cpp fix_nph_asphere.cpp fix_nph_sphere.cpp fix_npt.cpp fix_npt_asphere.cpp fix_npt_sphere.cpp fix_nve.cpp fix_nve_asphere.cpp fix_nve_limit.cpp fix_nve_noforce.cpp fix_nve_sphere.cpp fix_nvt.cpp fix_nvt_asphere.cpp fix_nvt_sllod.cpp fix_nvt_sphere.cpp fix_orient_fcc.cpp fix_peri_neigh.cpp fix_planeforce.cpp fix_pour.cpp fix_press_berendsen.cpp fix_print.cpp fix_qeq_comb.cpp fix_read_restart.cpp fix_recenter.cpp fix_respa.cpp fix_rigid.cpp fix_rigid_nve.cpp fix_rigid_nvt.cpp fix_setforce.cpp fix_shake.cpp fix_shear_history.cpp fix_spring.cpp fix_spring_rg.cpp fix_spring_self.cpp fix_srd.cpp fix_store_force.cpp fix_store_state.cpp fix_temp_berendsen.cpp fix_temp_rescale.cpp fix_thermal_conductivity.cpp fix_tmd.cpp fix_ttm.cpp fix_viscosity.cpp fix_viscous.cpp fix_wall.cpp fix_wall_colloid.cpp fix_wall_gran.cpp fix_wall_harmonic.cpp fix_wall_lj126.cpp fix_wall_lj93.cpp fix_wall_reflect.cpp fix_wall_region.cpp fix_wall_srd.cpp force.cpp group.cpp improper.cpp improper_class2.cpp improper_cvff.cpp improper_harmonic.cpp improper_hybrid.cpp improper_umbrella.cpp input.cpp integrate.cpp irregular.cpp kspace.cpp lammps.cpp lattice.cpp library.cpp math_extra.cpp memory.cpp min.cpp min_cg.cpp min_fire.cpp min_hftn.cpp min_linesearch.cpp min_quickmin.cpp min_sd.cpp minimize.cpp modify.cpp neb.cpp neigh_bond.cpp neigh_derive.cpp neigh_full.cpp neigh_gran.cpp neigh_half_bin.cpp neigh_half_multi.cpp neigh_half_nsq.cpp neigh_list.cpp neigh_request.cpp neigh_respa.cpp neigh_stencil.cpp neighbor.cpp output.cpp pack.cpp pair.cpp pair_adp.cpp pair_airebo.cpp pair_born.cpp pair_born_coul_long.cpp pair_buck.cpp pair_buck_coul_cut.cpp pair_buck_coul_long.cpp pair_colloid.cpp pair_comb.cpp pair_coul_cut.cpp pair_coul_debye.cpp pair_coul_long.cpp pair_dipole_cut.cpp pair_dpd.cpp pair_dpd_tstat.cpp pair_dsmc.cpp pair_eam.cpp pair_eam_alloy.cpp pair_eam_fs.cpp pair_eim.cpp pair_gauss.cpp pair_gayberne.cpp pair_gran_hertz_history.cpp pair_gran_hooke.cpp pair_gran_hooke_history.cpp pair_hbond_dreiding_lj.cpp pair_hbond_dreiding_morse.cpp pair_hybrid.cpp pair_hybrid_overlay.cpp pair_lj96_cut.cpp pair_lj_charmm_coul_charmm.cpp pair_lj_charmm_coul_charmm_implicit.cpp pair_lj_charmm_coul_long.cpp pair_lj_class2.cpp pair_lj_class2_coul_cut.cpp pair_lj_class2_coul_long.cpp pair_lj_cut.cpp pair_lj_cut_coul_cut.cpp pair_lj_cut_coul_debye.cpp pair_lj_cut_coul_long.cpp pair_lj_cut_coul_long_tip4p.cpp pair_lj_cut_coul_long_tip4p2.cpp pair_lj_cut_coul_long_tip4p3.cpp pair_lj_expand.cpp pair_lj_gromacs.cpp pair_lj_gromacs_coul_gromacs.cpp pair_lj_smooth.cpp pair_lubricate.cpp pair_morse.cpp pair_peri_lps.cpp pair_peri_pmb.cpp pair_rebo.cpp pair_resquared.cpp pair_soft.cpp pair_sw.cpp pair_table.cpp pair_tersoff.cpp pair_tersoff_zbl.cpp pair_yukawa.cpp pair_yukawa_colloid.cpp pppm.cpp pppm2.cpp pppm_tip4p.cpp pppm_tip4p2.cpp prd.cpp random_mars.cpp random_park.cpp read_data.cpp read_restart.cpp region.cpp region_block.cpp region_cone.cpp region_cylinder.cpp region_intersect.cpp region_plane.cpp region_prism.cpp region_sphere.cpp region_union.cpp remap.cpp remap_wrap.cpp replicate.cpp respa.cpp run.cpp set.cpp special.cpp tad.cpp temper.cpp thermo.cpp timer.cpp universe.cpp update.cpp variable.cpp velocity.cpp verlet.cpp write_restart.cpp xdr_compat.cpp
INC = accelerator_cuda.h angle.h angle_charmm.h angle_class2.h angle_cosine.h angle_cosine_delta.h angle_cosine_periodic.h angle_cosine_squared.h angle_harmonic.h angle_hybrid.h angle_table.h atom.h atom_vec.h atom_vec_angle.h atom_vec_atomic.h atom_vec_bond.h atom_vec_charge.h atom_vec_dipole.h atom_vec_ellipsoid.h atom_vec_full.h atom_vec_hybrid.h atom_vec_molecular.h atom_vec_peri.h atom_vec_sphere.h bond.h bond_class2.h bond_fene.h bond_fene_expand.h bond_harmonic.h bond_hybrid.h bond_morse.h bond_nonlinear.h bond_quartic.h bond_table.h change_box.h comm.h compute.h compute_angle_local.h compute_atom_molecule.h compute_bond_local.h compute_centro_atom.h compute_cluster_atom.h compute_cna_atom.h compute_com.h compute_com_molecule.h compute_coord_atom.h compute_damage_atom.h compute_dihedral_local.h compute_displace_atom.h compute_erotate_asphere.h compute_erotate_sphere.h compute_event_displace.h compute_group_group.h compute_gyration.h compute_gyration_molecule.h compute_heat_flux.h compute_improper_local.h compute_ke.h compute_ke_atom.h compute_msd.h compute_msd_molecule.h compute_pair.h compute_pair_local.h compute_pe.h compute_pe_atom.h compute_pressure.h compute_property_atom.h compute_property_local.h compute_property_molecule.h compute_rdf.h compute_reduce.h compute_reduce_region.h compute_slice.h compute_stress_atom.h compute_temp.h compute_temp_asphere.h compute_temp_com.h compute_temp_deform.h compute_temp_partial.h compute_temp_profile.h compute_temp_ramp.h compute_temp_region.h compute_temp_sphere.h compute_ti.h create_atoms.h create_box.h delete_atoms.h delete_bonds.h dihedral.h dihedral_charmm.h dihedral_class2.h dihedral_harmonic.h dihedral_helix.h dihedral_hybrid.h dihedral_multi_harmonic.h dihedral_opls.h displace_atoms.h displace_box.h domain.h dump.h dump_atom.h dump_cfg.h dump_custom.h dump_dcd.h dump_image.h dump_local.h dump_xtc.h dump_xyz.h error.h ewald.h fft3d.h fft3d_wrap.h finish.h fix.h fix_adapt.h fix_addforce.h fix_ave_atom.h fix_ave_correlate.h fix_ave_histo.h fix_ave_spatial.h fix_ave_time.h fix_aveforce.h fix_bond_break.h fix_bond_create.h fix_bond_swap.h fix_box_relax.h fix_deform.h fix_deposit.h fix_drag.h fix_dt_reset.h fix_efield.h fix_enforce2d.h fix_evaporate.h fix_event.h fix_event_prd.h fix_event_tad.h fix_external.h fix_freeze.h fix_gravity.h fix_heat.h fix_indent.h fix_langevin.h fix_lineforce.h fix_minimize.h fix_momentum.h fix_move.h fix_msst.h fix_neb.h fix_nh.h fix_nh_asphere.h fix_nh_sphere.h fix_nph.h fix_nph_asphere.h fix_nph_sphere.h fix_npt.h fix_npt_asphere.h fix_npt_sphere.h fix_nve.h fix_nve_asphere.h fix_nve_limit.h fix_nve_noforce.h fix_nve_sphere.h fix_nvt.h fix_nvt_asphere.h fix_nvt_sllod.h fix_nvt_sphere.h fix_orient_fcc.h fix_peri_neigh.h fix_planeforce.h fix_pour.h fix_press_berendsen.h fix_print.h fix_qeq_comb.h fix_read_restart.h fix_recenter.h fix_respa.h fix_rigid.h fix_rigid_nve.h fix_rigid_nvt.h fix_setforce.h fix_shake.h fix_shear_history.h fix_spring.h fix_spring_rg.h fix_spring_self.h fix_srd.h fix_store_force.h fix_store_state.h fix_temp_berendsen.h fix_temp_rescale.h fix_thermal_conductivity.h fix_tmd.h fix_ttm.h fix_viscosity.h fix_viscous.h fix_wall.h fix_wall_colloid.h fix_wall_gran.h fix_wall_harmonic.h fix_wall_lj126.h fix_wall_lj93.h fix_wall_reflect.h fix_wall_region.h fix_wall_srd.h force.h group.h improper.h improper_class2.h improper_cvff.h improper_harmonic.h improper_hybrid.h improper_umbrella.h input.h integrate.h irregular.h kspace.h lammps.h lattice.h library.h lmptype.h lmpwindows.h math_extra.h memory.h min.h min_cg.h min_fire.h min_hftn.h min_linesearch.h min_quickmin.h min_sd.h minimize.h modify.h neb.h neigh_list.h neigh_request.h neighbor.h output.h pack.h pair.h pair_adp.h pair_airebo.h pair_born.h pair_born_coul_long.h pair_buck.h pair_buck_coul_cut.h pair_buck_coul_long.h pair_colloid.h pair_comb.h pair_coul_cut.h pair_coul_debye.h pair_coul_long.h pair_dipole_cut.h pair_dpd.h pair_dpd_tstat.h pair_dsmc.h pair_eam.h pair_eam_alloy.h pair_eam_fs.h pair_eim.h pair_gauss.h pair_gayberne.h pair_gran_hertz_history.h pair_gran_hooke.h pair_gran_hooke_history.h pair_hbond_dreiding_lj.h pair_hbond_dreiding_morse.h pair_hybrid.h pair_hybrid_overlay.h pair_lj96_cut.h pair_lj_charmm_coul_charmm.h pair_lj_charmm_coul_charmm_implicit.h pair_lj_charmm_coul_long.h pair_lj_class2.h pair_lj_class2_coul_cut.h pair_lj_class2_coul_long.h pair_lj_cut.h pair_lj_cut_coul_cut.h pair_lj_cut_coul_debye.h pair_lj_cut_coul_long.h pair_lj_cut_coul_long_tip4p.h pair_lj_cut_coul_long_tip4p2.h pair_lj_cut_coul_long_tip4p3.h pair_lj_expand.h pair_lj_gromacs.h pair_lj_gromacs_coul_gromacs.h pair_lj_smooth.h pair_lubricate.h pair_morse.h pair_peri_lps.h pair_peri_pmb.h pair_rebo.h pair_resquared.h pair_soft.h pair_sw.h pair_table.h pair_tersoff.h pair_tersoff_zbl.h pair_yukawa.h pair_yukawa_colloid.h pointers.h pppm.h pppm2.h pppm_tip4p.h pppm_tip4p2.h prd.h random_mars.h random_park.h read_data.h read_restart.h region.h region_block.h region_cone.h region_cylinder.h region_intersect.h region_plane.h region_prism.h region_sphere.h region_union.h remap.h remap_wrap.h replicate.h respa.h run.h set.h special.h style_angle.h style_atom.h style_bond.h style_command.h style_compute.h style_dihedral.h style_dump.h style_fix.h style_improper.h style_integrate.h style_kspace.h style_minimize.h style_pair.h style_region.h tad.h temper.h thermo.h timer.h universe.h update.h variable.h velocity.h verlet.h version.h write_restart.h xdr_compat.h
OBJ = $(SRC:.cpp=.o)
# Targets
help:
@echo 'Type "make target" where target is one of:'
@echo ''
@files="`ls MAKE/Makefile.*`"; \
for file in $$files; do head -1 $$file; done
clean:
rm -rf Obj_*
.DEFAULT:
@test -f MAKE/Makefile.$@
@if [ ! -d Obj_$@ ]; then mkdir Obj_$@; fi
@cp -p $(SRC) $(INC) Obj_$@
@cp MAKE/Makefile.$@ Obj_$@/Makefile
- @cp Makefile.package Obj_$@
+ @if [ ! -e Makefile.package ]; \
+ then cp Makefile.package.empty Makefile.package; fi
+ @if [ ! -e Makefile.package.settings ]; \
+ then cp Makefile.package.settings.empty Makefile.package.settings; fi
+ @cp Makefile.package Makefile.package.settings Obj_$@
@cd Obj_$@; \
$(MAKE) $(MFLAGS) "OBJ = $(OBJ)" "INC = $(INC)" "EXE = ../$(EXE)" lib
@if [ -d Obj_$@ ]; then cd Obj_$@; rm -f $(SRC) $(INC) Makefile*; fi
diff --git a/src/Makefile.list b/src/Makefile.list
index fe4b0a96c..5f755f6ec 100644
--- a/src/Makefile.list
+++ b/src/Makefile.list
@@ -1,35 +1,39 @@
# LAMMPS multiple-machine Makefile with explicit file list
SHELL = /bin/sh
# Definitions
ROOT = lmp
EXE = $(ROOT)_$@
SRC = angle.cpp angle_charmm.cpp angle_cosine.cpp angle_cosine_delta.cpp angle_cosine_squared.cpp angle_harmonic.cpp angle_hybrid.cpp angle_table.cpp atom.cpp atom_vec.cpp atom_vec_angle.cpp atom_vec_atomic.cpp atom_vec_bond.cpp atom_vec_charge.cpp atom_vec_full.cpp atom_vec_hybrid.cpp atom_vec_molecular.cpp bond.cpp bond_fene.cpp bond_fene_expand.cpp bond_harmonic.cpp bond_hybrid.cpp bond_morse.cpp bond_nonlinear.cpp bond_quartic.cpp bond_table.cpp change_box.cpp comm.cpp compute.cpp compute_angle_local.cpp compute_bond_local.cpp compute_centro_atom.cpp compute_cna_atom.cpp compute_com.cpp compute_com_molecule.cpp compute_coord_atom.cpp compute_dihedral_local.cpp compute_displace_atom.cpp compute_erotate_sphere.cpp compute_group_group.cpp compute_gyration.cpp compute_gyration_molecule.cpp compute_heat_flux.cpp compute_improper_local.cpp compute_ke.cpp compute_ke_atom.cpp compute_msd.cpp compute_msd_molecule.cpp compute_pair_local.cpp compute_pe.cpp compute_pe_atom.cpp compute_pressure.cpp compute_property_atom.cpp compute_property_local.cpp compute_property_molecule.cpp compute_rdf.cpp compute_reduce.cpp compute_reduce_region.cpp compute_stress_atom.cpp compute_temp.cpp compute_temp_com.cpp compute_temp_deform.cpp compute_temp_partial.cpp compute_temp_profile.cpp compute_temp_ramp.cpp compute_temp_region.cpp compute_temp_sphere.cpp create_atoms.cpp create_box.cpp delete_atoms.cpp delete_bonds.cpp dihedral.cpp dihedral_charmm.cpp dihedral_harmonic.cpp dihedral_helix.cpp dihedral_hybrid.cpp dihedral_multi_harmonic.cpp dihedral_opls.cpp displace_atoms.cpp displace_box.cpp domain.cpp dump.cpp dump_atom.cpp dump_cfg.cpp dump_custom.cpp dump_dcd.cpp dump_local.cpp dump_xyz.cpp error.cpp ewald.cpp fft3d.cpp fft3d_wrap.cpp finish.cpp fix.cpp fix_adapt.cpp fix_addforce.cpp fix_ave_atom.cpp fix_ave_correlate.cpp fix_ave_histo.cpp fix_ave_spatial.cpp fix_ave_time.cpp fix_aveforce.cpp fix_bond_break.cpp fix_bond_create.cpp fix_bond_swap.cpp fix_box_relax.cpp fix_deform.cpp fix_deposit.cpp fix_drag.cpp fix_dt_reset.cpp fix_efield.cpp fix_enforce2d.cpp fix_evaporate.cpp fix_gravity.cpp fix_heat.cpp fix_indent.cpp fix_langevin.cpp fix_lineforce.cpp fix_minimize.cpp fix_momentum.cpp fix_move.cpp fix_nh.cpp fix_nh_sphere.cpp fix_nph.cpp fix_nph_sphere.cpp fix_npt.cpp fix_npt_sphere.cpp fix_nve.cpp fix_nve_limit.cpp fix_nve_noforce.cpp fix_nve_sphere.cpp fix_nvt.cpp fix_nvt_sllod.cpp fix_nvt_sphere.cpp fix_orient_fcc.cpp fix_planeforce.cpp fix_press_berendsen.cpp fix_print.cpp fix_qeq_comb.cpp fix_recenter.cpp fix_respa.cpp fix_rigid.cpp fix_rigid_nve.cpp fix_rigid_nvt.cpp fix_setforce.cpp fix_shake.cpp fix_shear_history.cpp fix_spring.cpp fix_spring_rg.cpp fix_spring_self.cpp fix_store_force.cpp fix_store_state.cpp fix_temp_berendsen.cpp fix_temp_rescale.cpp fix_thermal_conductivity.cpp fix_tmd.cpp fix_ttm.cpp fix_viscosity.cpp fix_viscous.cpp fix_wall.cpp fix_wall_harmonic.cpp fix_wall_lj126.cpp fix_wall_lj93.cpp fix_wall_reflect.cpp fix_wall_region.cpp force.cpp group.cpp improper.cpp improper_cvff.cpp improper_harmonic.cpp improper_hybrid.cpp input.cpp integrate.cpp kspace.cpp lammps.cpp lattice.cpp library.cpp main.cpp memory.cpp min.cpp min_cg.cpp min_hftn.cpp min_linesearch.cpp min_sd.cpp minimize.cpp modify.cpp neigh_bond.cpp neigh_derive.cpp neigh_full.cpp neigh_gran.cpp neigh_half_bin.cpp neigh_half_multi.cpp neigh_half_nsq.cpp neigh_list.cpp neigh_request.cpp neigh_respa.cpp neigh_stencil.cpp neighbor.cpp output.cpp pack.cpp pair.cpp pair_airebo.cpp pair_born_coul_long.cpp pair_buck.cpp pair_buck_coul_cut.cpp pair_buck_coul_long.cpp pair_comb.cpp pair_coul_cut.cpp pair_coul_debye.cpp pair_coul_long.cpp pair_dpd.cpp pair_dpd_tstat.cpp pair_eam.cpp pair_eam_alloy.cpp pair_eam_fs.cpp pair_eim.cpp pair_hybrid.cpp pair_hybrid_overlay.cpp pair_lj96_cut.cpp pair_lj_charmm_coul_charmm.cpp pair_lj_charmm_coul_charmm_implicit.cpp pair_lj_charmm_coul_long.cpp pair_lj_cut.cpp pair_lj_cut_coul_cut.cpp pair_lj_cut_coul_debye.cpp pair_lj_cut_coul_long.cpp pair_lj_cut_coul_long_tip4p.cpp pair_lj_expand.cpp pair_lj_gromacs.cpp pair_lj_gromacs_coul_gromacs.cpp pair_lj_smooth.cpp pair_morse.cpp pair_soft.cpp pair_sw.cpp pair_table.cpp pair_tersoff.cpp pair_tersoff_zbl.cpp pair_yukawa.cpp pppm.cpp pppm_tip4p.cpp random_mars.cpp random_park.cpp read_data.cpp read_restart.cpp region.cpp region_block.cpp region_cone.cpp region_cylinder.cpp region_intersect.cpp region_plane.cpp region_prism.cpp region_sphere.cpp region_union.cpp remap.cpp remap_wrap.cpp replicate.cpp respa.cpp run.cpp set.cpp shell.cpp special.cpp temper.cpp thermo.cpp timer.cpp universe.cpp update.cpp variable.cpp velocity.cpp verlet.cpp write_restart.cpp
INC = angle.h angle_charmm.h angle_cosine.h angle_cosine_delta.h angle_cosine_squared.h angle_harmonic.h angle_hybrid.h angle_table.h atom.h atom_vec.h atom_vec_angle.h atom_vec_atomic.h atom_vec_bond.h atom_vec_charge.h atom_vec_full.h atom_vec_hybrid.h atom_vec_molecular.h bond.h bond_fene.h bond_fene_expand.h bond_harmonic.h bond_hybrid.h bond_morse.h bond_nonlinear.h bond_quartic.h bond_table.h change_box.h comm.h compute.h compute_angle_local.h compute_bond_local.h compute_centro_atom.h compute_cna_atom.h compute_com.h compute_com_molecule.h compute_coord_atom.h compute_dihedral_local.h compute_displace_atom.h compute_erotate_sphere.h compute_group_group.h compute_gyration.h compute_gyration_molecule.h compute_heat_flux.h compute_improper_local.h compute_ke.h compute_ke_atom.h compute_msd.h compute_msd_molecule.h compute_pair_local.h compute_pe.h compute_pe_atom.h compute_pressure.h compute_property_atom.h compute_property_local.h compute_property_molecule.h compute_rdf.h compute_reduce.h compute_reduce_region.h compute_stress_atom.h compute_temp.h compute_temp_com.h compute_temp_deform.h compute_temp_partial.h compute_temp_profile.h compute_temp_ramp.h compute_temp_region.h compute_temp_sphere.h create_atoms.h create_box.h delete_atoms.h delete_bonds.h dihedral.h dihedral_charmm.h dihedral_harmonic.h dihedral_helix.h dihedral_hybrid.h dihedral_multi_harmonic.h dihedral_opls.h displace_atoms.h displace_box.h domain.h dump.h dump_atom.h dump_cfg.h dump_custom.h dump_dcd.h dump_local.h dump_xyz.h error.h ewald.h fft3d.h fft3d_wrap.h finish.h fix.h fix_adapt.h fix_addforce.h fix_ave_atom.h fix_ave_correlate.h fix_ave_histo.h fix_ave_spatial.h fix_ave_time.h fix_aveforce.h fix_bond_break.h fix_bond_create.h fix_bond_swap.h fix_box_relax.h fix_deform.h fix_deposit.h fix_drag.h fix_dt_reset.h fix_efield.h fix_enforce2d.h fix_evaporate.h fix_gravity.h fix_heat.h fix_indent.h fix_langevin.h fix_lineforce.h fix_minimize.h fix_momentum.h fix_move.h fix_nh.h fix_nh_sphere.h fix_nph.h fix_nph_sphere.h fix_npt.h fix_npt_sphere.h fix_nve.h fix_nve_limit.h fix_nve_noforce.h fix_nve_sphere.h fix_nvt.h fix_nvt_sllod.h fix_nvt_sphere.h fix_orient_fcc.h fix_planeforce.h fix_press_berendsen.h fix_print.h fix_qeq_comb.h fix_recenter.h fix_respa.h fix_rigid.h fix_rigid_nve.h fix_rigid_nvt.h fix_setforce.h fix_shake.h fix_shear_history.h fix_spring.h fix_spring_rg.h fix_spring_self.h fix_store_force.h fix_store_state.h fix_temp_berendsen.h fix_temp_rescale.h fix_thermal_conductivity.h fix_tmd.h fix_ttm.h fix_viscosity.h fix_viscous.h fix_wall.h fix_wall_harmonic.h fix_wall_lj126.h fix_wall_lj93.h fix_wall_reflect.h fix_wall_region.h force.h group.h improper.h improper_cvff.h improper_harmonic.h improper_hybrid.h input.h integrate.h kspace.h lammps.h lattice.h library.h math_extra.h memory.h min.h min_cg.h min_hftn.h min_linesearch.h min_sd.h minimize.h modify.h neigh_list.h neigh_request.h neighbor.h output.h pack.h pair.h pair_airebo.h pair_born_coul_long.h pair_buck.h pair_buck_coul_cut.h pair_buck_coul_long.h pair_comb.h pair_coul_cut.h pair_coul_debye.h pair_coul_long.h pair_dpd.h pair_dpd_tstat.h pair_eam.h pair_eam_alloy.h pair_eam_fs.h pair_eim.h pair_hybrid.h pair_hybrid_overlay.h pair_lj96_cut.h pair_lj_charmm_coul_charmm.h pair_lj_charmm_coul_charmm_implicit.h pair_lj_charmm_coul_long.h pair_lj_cut.h pair_lj_cut_coul_cut.h pair_lj_cut_coul_debye.h pair_lj_cut_coul_long.h pair_lj_cut_coul_long_tip4p.h pair_lj_expand.h pair_lj_gromacs.h pair_lj_gromacs_coul_gromacs.h pair_lj_smooth.h pair_morse.h pair_soft.h pair_sw.h pair_table.h pair_tersoff.h pair_tersoff_zbl.h pair_yukawa.h pointers.h pppm.h pppm_tip4p.h random_mars.h random_park.h read_data.h read_restart.h region.h region_block.h region_cone.h region_cylinder.h region_intersect.h region_plane.h region_prism.h region_sphere.h region_union.h remap.h remap_wrap.h replicate.h respa.h run.h set.h shell.h special.h style_angle.h style_atom.h style_bond.h style_command.h style_compute.h style_dihedral.h style_dump.h style_fix.h style_improper.h style_integrate.h style_kspace.h style_minimize.h style_pair.h style_region.h temper.h thermo.h timer.h universe.h update.h variable.h velocity.h verlet.h version.h write_restart.h
OBJ = $(SRC:.cpp=.o)
# Targets
help:
@echo 'Type "make target" where target is one of:'
@echo ''
@files="`ls MAKE/Makefile.*`"; \
for file in $$files; do head -1 $$file; done
clean:
rm -rf Obj_*
.DEFAULT:
@test -f MAKE/Makefile.$@
@if [ ! -d Obj_$@ ]; then mkdir Obj_$@; fi
@cp -p $(SRC) $(INC) Obj_$@
@cp MAKE/Makefile.$@ Obj_$@/Makefile
- @cp Makefile.package Obj_$@
+ @if [ ! -e Makefile.package ]; \
+ then cp Makefile.package.empty Makefile.package; fi
+ @if [ ! -e Makefile.package.settings ]; \
+ then cp Makefile.package.settings.empty Makefile.package.settings; fi
+ @cp Makefile.package Makefile.package.settings Obj_$@
@cd Obj_$@; \
$(MAKE) $(MFLAGS) "OBJ = $(OBJ)" "INC = $(INC)" "EXE = ../$(EXE)" ../$(EXE)
@if [ -d Obj_$@ ]; then cd Obj_$@; rm -f $(SRC) $(INC) Makefile*; fi
diff --git a/src/OPT/pair_eam_opt.cpp b/src/OPT/pair_eam_opt.cpp
index 83a9580b9..616234b69 100644
--- a/src/OPT/pair_eam_opt.cpp
+++ b/src/OPT/pair_eam_opt.cpp
@@ -1,351 +1,348 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors:
James Fischer, High Performance Technologies, Inc.
Charles Cornwell, High Performance Technologies, Inc.
David Richie, Stone Ridge Technology
Vincent Natoli, Stone Ridge Technology
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_eam_opt.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairEAMOpt::PairEAMOpt(LAMMPS *lmp) : PairEAM(lmp) {}
/* ---------------------------------------------------------------------- */
void PairEAMOpt::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = eflag_atom = 0;
if (evflag) {
if (eflag) {
if (force->newton_pair) return eval<1,1,1>();
else return eval<1,1,0>();
} else {
if (force->newton_pair) return eval<1,0,1>();
else return eval<1,0,0>();
}
} else {
if (force->newton_pair) return eval<0,0,1>();
else return eval<0,0,0>();
}
}
/* ---------------------------------------------------------------------- */
template < int EVFLAG, int EFLAG, int NEWTON_PAIR >
void PairEAMOpt::eval()
{
typedef struct { double x,y,z; } vec3_t;
typedef struct {
double rhor0i,rhor1i,rhor2i,rhor3i;
double rhor0j,rhor1j,rhor2j,rhor3j;
} fast_alpha_t;
typedef struct {
double frho0,frho1,frho2,frho3,frho4,frho5,frho6;
double _pad[1];
} fast_beta_t;
typedef struct {
double rhor4i,rhor5i,rhor6i;
double rhor4j,rhor5j,rhor6j;
double z2r0,z2r1,z2r2,z2r3,z2r4,z2r5,z2r6;
double _pad[3];
} fast_gamma_t;
int i,j,ii,jj,inum,jnum,itype,jtype;
double evdwl = 0.0;
double* __restrict__ coeff;
// grow energy array if necessary
if (atom->nmax > nmax) {
memory->sfree(rho);
memory->sfree(fp);
nmax = atom->nmax;
rho = (double *) memory->smalloc(nmax*sizeof(double),"pair:rho");
fp = (double *) memory->smalloc(nmax*sizeof(double),"pair:fp");
}
double** __restrict__ x = atom->x;
double** __restrict__ f = atom->f;
int* __restrict__ type = atom->type;
int nlocal = atom->nlocal;
vec3_t* __restrict__ xx = (vec3_t*)x[0];
vec3_t* __restrict__ ff = (vec3_t*)f[0];
double tmp_cutforcesq = cutforcesq;
double tmp_rdr = rdr;
int nr2 = nr-2;
int nr1 = nr-1;
inum = list->inum;
int* __restrict__ ilist = list->ilist;
int** __restrict__ firstneigh = list->firstneigh;
int* __restrict__ numneigh = list->numneigh;
int ntypes = atom->ntypes;
int ntypes2 = ntypes*ntypes;
fast_alpha_t* __restrict__ fast_alpha =
(fast_alpha_t*) malloc(ntypes2*(nr+1)*sizeof(fast_alpha_t));
for (i = 0; i < ntypes; i++) for (j = 0; j < ntypes; j++) {
fast_alpha_t* __restrict__ tab = &fast_alpha[i*ntypes*nr+j*nr];
if (type2rhor[i+1][j+1] >= 0) {
for(int m = 1; m <= nr; m++) {
tab[m].rhor0i = rhor_spline[type2rhor[i+1][j+1]][m][6];
tab[m].rhor1i = rhor_spline[type2rhor[i+1][j+1]][m][5];
tab[m].rhor2i = rhor_spline[type2rhor[i+1][j+1]][m][4];
tab[m].rhor3i = rhor_spline[type2rhor[i+1][j+1]][m][3];
}
}
if (type2rhor[j+1][i+1] >= 0) {
for(int m = 1; m <= nr; m++) {
tab[m].rhor0j = rhor_spline[type2rhor[j+1][i+1]][m][6];
tab[m].rhor1j = rhor_spline[type2rhor[j+1][i+1]][m][5];
tab[m].rhor2j = rhor_spline[type2rhor[j+1][i+1]][m][4];
tab[m].rhor3j = rhor_spline[type2rhor[j+1][i+1]][m][3];
}
}
}
fast_alpha_t* __restrict__ tabeight = fast_alpha;
fast_gamma_t* __restrict__ fast_gamma =
(fast_gamma_t*) malloc(ntypes2*(nr+1)*sizeof(fast_gamma_t));
for (i = 0; i < ntypes; i++) for (j = 0; j < ntypes; j++) {
fast_gamma_t* __restrict__ tab = &fast_gamma[i*ntypes*nr+j*nr];
if (type2rhor[i+1][j+1] >= 0) {
for(int m = 1; m <= nr; m++) {
tab[m].rhor4i = rhor_spline[type2rhor[i+1][j+1]][m][2];
tab[m].rhor5i = rhor_spline[type2rhor[i+1][j+1]][m][1];
tab[m].rhor6i = rhor_spline[type2rhor[i+1][j+1]][m][0];
}
}
if (type2rhor[j+1][i+1] >= 0) {
for(int m = 1; m <= nr; m++) {
tab[m].rhor4j = rhor_spline[type2rhor[j+1][i+1]][m][2];
tab[m].rhor5j = rhor_spline[type2rhor[j+1][i+1]][m][1];
tab[m].rhor6j = rhor_spline[type2rhor[j+1][i+1]][m][0];
tab[m].z2r6 = z2r_spline[type2z2r[i+1][j+1]][m][0];
}
}
if (type2z2r[i+1][j+1] >= 0) {
for(int m = 1; m <= nr; m++) {
tab[m].z2r0 = z2r_spline[type2z2r[i+1][j+1]][m][6];
tab[m].z2r1 = z2r_spline[type2z2r[i+1][j+1]][m][5];
tab[m].z2r2 = z2r_spline[type2z2r[i+1][j+1]][m][4];
tab[m].z2r3 = z2r_spline[type2z2r[i+1][j+1]][m][3];
tab[m].z2r4 = z2r_spline[type2z2r[i+1][j+1]][m][2];
tab[m].z2r5 = z2r_spline[type2z2r[i+1][j+1]][m][1];
tab[m].z2r6 = z2r_spline[type2z2r[i+1][j+1]][m][0];
}
}
}
fast_gamma_t* __restrict__ tabss = fast_gamma;
// zero out density
if (NEWTON_PAIR) {
int m = nlocal + atom->nghost;
for (i = 0; i < m; i++) rho[i] = 0.0;
} else for (i = 0; i < nlocal; i++) rho[i] = 0.0;
// rho = density at each atom
// loop over neighbors of my atoms
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
double xtmp = xx[i].x;
double ytmp = xx[i].y;
double ztmp = xx[i].z;
itype = type[i] - 1;
int* __restrict__ jlist = firstneigh[i];
jnum = numneigh[i];
double tmprho = rho[i];
fast_alpha_t* __restrict__ tabeighti = &tabeight[itype*ntypes*nr];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
double delx = xtmp - xx[j].x;
double dely = ytmp - xx[j].y;
double delz = ztmp - xx[j].z;
double rsq = delx*delx + dely*dely + delz*delz;
if (rsq < tmp_cutforcesq) {
jtype = type[j] - 1;
double p = sqrt(rsq)*tmp_rdr;
if ( (int)p <= nr2 ) {
int m = (int)p + 1;
p -= (double)((int)p);
fast_alpha_t& a = tabeighti[jtype*nr+m];
tmprho += ((a.rhor3j*p+a.rhor2j)*p+a.rhor1j)*p+a.rhor0j;
if (NEWTON_PAIR || j < nlocal) {
rho[j] += ((a.rhor3i*p+a.rhor2i)*p+a.rhor1i)*p+a.rhor0i;
}
} else {
fast_alpha_t& a = tabeighti[jtype*nr+nr1];
tmprho += a.rhor3j+a.rhor2j+a.rhor1j+a.rhor0j;
if (NEWTON_PAIR || j < nlocal) {
rho[j] += a.rhor3i+a.rhor2i+a.rhor1i+a.rhor0i;
}
}
}
}
rho[i] = tmprho;
}
// communicate and sum densities
if (NEWTON_PAIR) comm->reverse_comm_pair(this);
// fp = derivative of embedding energy at each atom
// phi = embedding energy at each atom
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
double p = rho[i]*rdrho;
int m = MIN((int)p,nrho-2);
p -= (double)m;
++m;
coeff = frho_spline[type2frho[type[i]]][m];
fp[i] = (coeff[0]*p + coeff[1])*p + coeff[2];
if (EFLAG) {
double phi = ((coeff[3]*p + coeff[4])*p + coeff[5])*p + coeff[6];
if (eflag_global) eng_vdwl += phi;
if (eflag_atom) eatom[i] += phi;
}
}
// communicate derivative of embedding function
comm->forward_comm_pair(this);
// compute forces on each atom
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
double xtmp = xx[i].x;
double ytmp = xx[i].y;
double ztmp = xx[i].z;
int itype1 = type[i] - 1;
int* __restrict__ jlist = firstneigh[i];
jnum = numneigh[i];
double tmpfx = 0.0;
double tmpfy = 0.0;
double tmpfz = 0.0;
fast_gamma_t* __restrict__ tabssi = &tabss[itype1*ntypes*nr];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
double delx = xtmp - xx[j].x;
double dely = ytmp - xx[j].y;
double delz = ztmp - xx[j].z;
double rsq = delx*delx + dely*dely + delz*delz;
if (rsq < tmp_cutforcesq) {
jtype = type[j] - 1;
double r = sqrt(rsq);
double rhoip,rhojp,z2,z2p;
double p = r*tmp_rdr;
if ( (int)p <= nr2 ) {
int m = (int) p + 1;
p -= (double)((int) p);
fast_gamma_t& a = tabssi[jtype*nr+m];
rhoip = (a.rhor6i*p + a.rhor5i)*p + a.rhor4i;
rhojp = (a.rhor6j*p + a.rhor5j)*p + a.rhor4j;
z2 = ((a.z2r3*p + a.z2r2)*p + a.z2r1)*p + a.z2r0;
z2p = (a.z2r6*p + a.z2r5)*p + a.z2r4;
} else {
fast_gamma_t& a = tabssi[jtype*nr+nr1];
rhoip = a.rhor6i + a.rhor5i + a.rhor4i;
rhojp = a.rhor6j + a.rhor5j + a.rhor4j;
z2 = a.z2r3 + a.z2r2 + a.z2r1 + a.z2r0;
z2p = a.z2r6 + a.z2r5 + a.z2r4;
}
// rhoip = derivative of (density at atom j due to atom i)
// rhojp = derivative of (density at atom i due to atom j)
// phi = pair potential energy
// phip = phi'
// z2 = phi * r
// z2p = (phi * r)' = (phi' r) + phi
// psip needs both fp[i] and fp[j] terms since r_ij appears in two
// terms of embed eng: Fi(sum rho_ij) and Fj(sum rho_ji)
// hence embed' = Fi(sum rho_ij) rhojp + Fj(sum rho_ji) rhoip
double recip = 1.0/r;
double phi = z2*recip;
double phip = z2p*recip - phi*recip;
double psip = fp[i]*rhojp + fp[j]*rhoip + phip;
double fpair = -psip*recip;
tmpfx += delx*fpair;
tmpfy += dely*fpair;
tmpfz += delz*fpair;
if (NEWTON_PAIR || j < nlocal) {
ff[j].x -= delx*fpair;
ff[j].y -= dely*fpair;
ff[j].z -= delz*fpair;
}
if (EFLAG) evdwl = phi;
if (EVFLAG) ev_tally(i,j,nlocal,NEWTON_PAIR,
evdwl,0.0,fpair,delx,dely,delz);
}
}
ff[i].x += tmpfx;
ff[i].y += tmpfy;
ff[i].z += tmpfz;
}
free(fast_alpha); fast_alpha = 0;
free(fast_gamma); fast_gamma = 0;
if (vflag_fdotr) virial_fdotr_compute();
}
diff --git a/src/OPT/pair_lj_charmm_coul_long_opt.cpp b/src/OPT/pair_lj_charmm_coul_long_opt.cpp
index 6049eb2a3..49519d476 100644
--- a/src/OPT/pair_lj_charmm_coul_long_opt.cpp
+++ b/src/OPT/pair_lj_charmm_coul_long_opt.cpp
@@ -1,343 +1,340 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors:
James Fischer, High Performance Technologies, Inc.
David Richie, Stone Ridge Technology
Vincent Natoli, Stone Ridge Technology
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_lj_charmm_coul_long_opt.h"
#include "atom.h"
#include "force.h"
#include "neigh_list.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define EWALD_A1 0.254829592
#define EWALD_A2 -0.284496736
#define EWALD_A3 1.421413741
#define EWALD_A4 -1.453152027
#define EWALD_A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulLongOpt::PairLJCharmmCoulLongOpt(LAMMPS *lmp) :
PairLJCharmmCoulLong(lmp) {}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLongOpt::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
if (evflag) {
if (eflag) {
if (force->newton_pair) return eval<1,1,1>();
else return eval<1,1,0>();
} else {
if (force->newton_pair) return eval<1,0,1>();
else return eval<1,0,0>();
}
} else {
if (force->newton_pair) return eval<0,0,1>();
else return eval<0,0,0>();
}
}
/* ---------------------------------------------------------------------- */
template < int EVFLAG, int EFLAG, int NEWTON_PAIR >
void PairLJCharmmCoulLongOpt::eval()
{
typedef struct { double x,y,z; } vec3_t;
typedef struct {
double cutsq,lj1,lj2,lj3,lj4,offset;
double _pad[2];
} fast_alpha_t;
int i,j,ii,jj,inum,jnum,itype,jtype,itable,sbindex;
double fraction,table;
double r,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double grij,expm2,prefactor,t,erfc;
double philj,switch1,switch2;
double rsq;
double evdwl = 0.0;
double ecoul = 0.0;
double** __restrict__ x = atom->x;
double** __restrict__ f = atom->f;
double* __restrict__ q = atom->q;
int* __restrict__ type = atom->type;
int nlocal = atom->nlocal;
double* __restrict__ special_coul = force->special_coul;
double* __restrict__ special_lj = force->special_lj;
double qqrd2e = force->qqrd2e;
inum = list->inum;
int* __restrict__ ilist = list->ilist;
int** __restrict__ firstneigh = list->firstneigh;
int* __restrict__ numneigh = list->numneigh;
vec3_t* __restrict__ xx = (vec3_t*)x[0];
vec3_t* __restrict__ ff = (vec3_t*)f[0];
int ntypes = atom->ntypes;
int ntypes2 = ntypes*ntypes;
double tmp_coef1 = 1.0/denom_lj;
double tmp_coef2 = cut_ljsq - 3.0*cut_lj_innersq;
fast_alpha_t* __restrict__ fast_alpha =
(fast_alpha_t*)malloc(ntypes2*sizeof(fast_alpha_t));
for (i = 0; i < ntypes; i++) for (j = 0; j < ntypes; j++) {
fast_alpha_t& a = fast_alpha[i*ntypes+j];
a.cutsq = cutsq[i+1][j+1];
a.lj1 = lj1[i+1][j+1];
a.lj2 = lj2[i+1][j+1];
a.lj3 = lj3[i+1][j+1];
a.lj4 = lj4[i+1][j+1];
}
fast_alpha_t* __restrict__ tabsix = fast_alpha;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
double qtmp = q[i];
double xtmp = xx[i].x;
double ytmp = xx[i].y;
double ztmp = xx[i].z;
itype = type[i] - 1;
int* __restrict__ jlist = firstneigh[i];
jnum = numneigh[i];
double tmpfx = 0.0;
double tmpfy = 0.0;
double tmpfz = 0.0;
fast_alpha_t* __restrict__ tabsixi = (fast_alpha_t*) &tabsix[itype*ntypes];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
sbindex = sbmask(j);
if (sbindex == 0) {
double delx = xtmp - xx[j].x;
double dely = ytmp - xx[j].y;
double delz = ztmp - xx[j].z;
rsq = delx*delx + dely*dely + delz*delz;
double tmp_coef3 = qtmp*q[j];
if (rsq < cut_bothsq) {
r2inv = 1.0/rsq;
forcecoul = 0.0;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t *
(EWALD_A1+t*(EWALD_A2+t*(EWALD_A3+t*(EWALD_A4+t*EWALD_A5)))) *
expm2;
prefactor = qqrd2e * tmp_coef3/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = tmp_coef3 * table;
}
}
forcelj = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
jtype = type[j] - 1;
fast_alpha_t& a = tabsixi[jtype];
forcelj = r6inv * (a.lj1*r6inv - a.lj2);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(tmp_coef2 + 2.0*rsq) * tmp_coef1;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) * tmp_coef1;
philj = r6inv * (a.lj3*r6inv - a.lj4);
forcelj = forcelj*switch1 + philj*switch2;
}
}
double fpair = (forcecoul + forcelj) * r2inv;
tmpfx += delx*fpair;
tmpfy += dely*fpair;
tmpfz += delz*fpair;
if (NEWTON_PAIR || j < nlocal) {
ff[j].x -= delx*fpair;
ff[j].y -= dely*fpair;
ff[j].z -= delz*fpair;
}
if (EFLAG) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = tmp_coef3 * table;
}
} else ecoul = 0.0;
if (rsq < cut_ljsq) {
fast_alpha_t& a = tabsixi[jtype];
evdwl = r6inv*(a.lj3*r6inv-a.lj4);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(tmp_coef2 + 2.0*rsq) * tmp_coef1;
evdwl *= switch1;
}
} else evdwl = 0.0;
}
if (EVFLAG) ev_tally(i,j,nlocal,NEWTON_PAIR,
evdwl,ecoul,fpair,delx,dely,delz);
}
} else {
factor_lj = special_lj[sbindex];
factor_coul = special_coul[sbindex];
j &= NEIGHMASK;
double delx = xtmp - xx[j].x;
double dely = ytmp - xx[j].y;
double delz = ztmp - xx[j].z;
rsq = delx*delx + dely*dely + delz*delz;
double tmp_coef3 = qtmp*q[j];
if (rsq < cut_bothsq) {
r2inv = 1.0/rsq;
forcecoul = 0.0;
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq) {
r = sqrt(rsq);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
t = 1.0 / (1.0 + EWALD_P*grij);
erfc = t *
(EWALD_A1+t*(EWALD_A2+t*(EWALD_A3+t*(EWALD_A4+t*EWALD_A5)))) *
expm2;
prefactor = qqrd2e * tmp_coef3/r;
forcecoul = prefactor * (erfc + EWALD_F*grij*expm2);
if (factor_coul < 1.0) {
forcecoul -= (1.0-factor_coul)*prefactor;
}
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & ncoulmask;
itable >>= ncoulshiftbits;
fraction = (rsq_lookup.f - rtable[itable]) * drtable[itable];
table = ftable[itable] + fraction*dftable[itable];
forcecoul = tmp_coef3 * table;
if (factor_coul < 1.0) {
table = ctable[itable] + fraction*dctable[itable];
prefactor = tmp_coef3 * table;
forcecoul -= (1.0-factor_coul)*prefactor;
}
}
}
forcelj = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
jtype = type[j] - 1;
fast_alpha_t& a = tabsixi[jtype];
forcelj = r6inv * (a.lj1*r6inv - a.lj2);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(tmp_coef2 + 2.0*rsq) * tmp_coef1;
switch2 = 12.0*rsq * (cut_ljsq-rsq) *
(rsq-cut_lj_innersq) * tmp_coef1;
fast_alpha_t& a = tabsixi[jtype];
philj = r6inv * (a.lj3*r6inv - a.lj4);
forcelj = forcelj*switch1 + philj*switch2;
}
}
double fpair = (forcecoul + factor_lj*forcelj) * r2inv;
tmpfx += delx*fpair;
tmpfy += dely*fpair;
tmpfz += delz*fpair;
if (NEWTON_PAIR || j < nlocal) {
ff[j].x -= delx*fpair;
ff[j].y -= dely*fpair;
ff[j].z -= delz*fpair;
}
if (EFLAG) {
if (rsq < cut_coulsq) {
if (!ncoultablebits || rsq <= tabinnersq)
ecoul = prefactor*erfc;
else {
table = etable[itable] + fraction*detable[itable];
ecoul = tmp_coef3 * table;
}
if (factor_coul < 1.0) ecoul -= (1.0-factor_coul)*prefactor;
} else ecoul = 0.0;
if (rsq < cut_ljsq) {
fast_alpha_t& a = tabsixi[jtype];
evdwl = r6inv*(a.lj3*r6inv-a.lj4);
if (rsq > cut_lj_innersq) {
switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) *
(tmp_coef2 + 2.0*rsq) * tmp_coef1;
evdwl *= switch1;
}
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (EVFLAG) ev_tally(i,j,nlocal,NEWTON_PAIR,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
ff[i].x += tmpfx;
ff[i].y += tmpfy;
ff[i].z += tmpfz;
}
free(fast_alpha); fast_alpha = 0;
if (vflag_fdotr) virial_fdotr_compute();
}
diff --git a/src/PERI/atom_vec_peri.cpp b/src/PERI/atom_vec_peri.cpp
index 95a72d10f..b57140062 100644
--- a/src/PERI/atom_vec_peri.cpp
+++ b/src/PERI/atom_vec_peri.cpp
@@ -1,835 +1,835 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Parks (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "float.h"
#include "stdlib.h"
#include "atom_vec_peri.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecPeri::AtomVecPeri(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 0;
comm_x_only = 0;
comm_f_only = 1;
size_forward = 4;
size_reverse = 3;
size_border = 11;
size_velocity = 3;
size_data_atom = 7;
size_data_vel = 4;
xcol_data = 5;
atom->peri_flag = 1;
atom->vfrac_flag = atom->rmass_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecPeri::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
vfrac = memory->grow(atom->vfrac,nmax,"atom:vfrac");
rmass = memory->grow(atom->rmass,nmax,"atom:rmass");
s0 = memory->grow(atom->s0,nmax,"atom:s0");
x0 = memory->grow(atom->x0,nmax,3,"atom:x0");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecPeri::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
vfrac = atom->vfrac; rmass = atom->rmass;
s0 = atom->s0; x0 = atom->x0;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecPeri::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
vfrac[j] = vfrac[i];
rmass[j] = rmass[i];
s0[j] = s0[i];
x0[j][0] = x0[i][0];
x0[j][1] = x0[i][1];
x0[j][2] = x0[i][2];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = s0[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = s0[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = s0[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = s0[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = s0[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::pack_comm_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = s0[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecPeri::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
s0[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecPeri::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
s0[i] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::unpack_comm_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
s0[i] = buf[m++];
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecPeri::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = vfrac[j];
buf[m++] = s0[j];
buf[m++] = x0[j][0];
buf[m++] = x0[j][1];
buf[m++] = x0[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = vfrac[j];
buf[m++] = s0[j];
buf[m++] = x0[j][0];
buf[m++] = x0[j][1];
buf[m++] = x0[j][2];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = vfrac[j];
buf[m++] = s0[j];
buf[m++] = x0[j][0];
buf[m++] = x0[j][1];
buf[m++] = x0[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = vfrac[j];
buf[m++] = s0[j];
buf[m++] = x0[j][0];
buf[m++] = x0[j][1];
buf[m++] = x0[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = vfrac[j];
buf[m++] = s0[j];
buf[m++] = x0[j][0];
buf[m++] = x0[j][1];
buf[m++] = x0[j][2];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = vfrac[j];
buf[m++] = s0[j];
buf[m++] = x0[j][0];
buf[m++] = x0[j][1];
buf[m++] = x0[j][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecPeri::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
vfrac[i] = buf[m++];
s0[i] = buf[m++];
x0[i][0] = buf[m++];
x0[i][1] = buf[m++];
x0[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecPeri::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
vfrac[i] = buf[m++];
s0[i] = buf[m++];
x0[i][0] = buf[m++];
x0[i][1] = buf[m++];
x0[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
vfrac[i] = buf[m++];
s0[i] = buf[m++];
x0[i][0] = buf[m++];
x0[i][1] = buf[m++];
x0[i][2] = buf[m++];
}
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecPeri::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = vfrac[i];
buf[m++] = rmass[i];
buf[m++] = s0[i];
buf[m++] = x0[i][0];
buf[m++] = x0[i][1];
buf[m++] = x0[i][2];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecPeri::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
vfrac[nlocal] = buf[m++];
rmass[nlocal] = buf[m++];
s0[nlocal] = buf[m++];
x0[nlocal][0] = buf[m++];
x0[nlocal][1] = buf[m++];
x0[nlocal][2] = buf[m++];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecPeri::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 17 * nlocal;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecPeri::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = vfrac[i];
buf[m++] = rmass[i];
buf[m++] = s0[i];
buf[m++] = x0[i][0];
buf[m++] = x0[i][1];
buf[m++] = x0[i][2];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecPeri::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
vfrac[nlocal] = buf[m++];
rmass[nlocal] = buf[m++];
s0[nlocal] = buf[m++];
x0[nlocal][0] = buf[m++];
x0[nlocal][1] = buf[m++];
x0[nlocal][2] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecPeri::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
vfrac[nlocal] = 1.0;
rmass[nlocal] = 1.0;
s0[nlocal] = DBL_MAX;
x0[nlocal][0] = coord[0];
x0[nlocal][1] = coord[1];
x0[nlocal][2] = coord[2];
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecPeri::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
vfrac[nlocal] = atof(values[2]);
rmass[nlocal] = atof(values[3]);
- if (rmass[nlocal] <= 0.0) error->one("Invalid mass value");
+ if (rmass[nlocal] <= 0.0) error->one(FLERR,"Invalid mass value");
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
s0[nlocal] = DBL_MAX;
x0[nlocal][0] = coord[0];
x0[nlocal][1] = coord[1];
x0[nlocal][2] = coord[2];
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecPeri::data_atom_hybrid(int nlocal, char **values)
{
vfrac[nlocal] = atof(values[0]);
rmass[nlocal] = atof(values[1]);
- if (rmass[nlocal] <= 0.0) error->one("Invalid mass value");
+ if (rmass[nlocal] <= 0.0) error->one(FLERR,"Invalid mass value");
s0[nlocal] = DBL_MAX;
x0[nlocal][0] = x[nlocal][0];
x0[nlocal][1] = x[nlocal][1];
x0[nlocal][2] = x[nlocal][2];
return 2;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecPeri::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("vfrac")) bytes += memory->usage(vfrac,nmax);
if (atom->memcheck("rmass")) bytes += memory->usage(rmass,nmax);
if (atom->memcheck("s0")) bytes += memory->usage(s0,nmax);
if (atom->memcheck("x0")) bytes += memory->usage(x0,nmax,3);
return bytes;
}
diff --git a/src/PERI/compute_damage_atom.cpp b/src/PERI/compute_damage_atom.cpp
index a66e30598..92407985c 100644
--- a/src/PERI/compute_damage_atom.cpp
+++ b/src/PERI/compute_damage_atom.cpp
@@ -1,131 +1,131 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Parks (SNL)
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_damage_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "comm.h"
#include "force.h"
#include "pair_peri_pmb.h"
#include "fix_peri_neigh.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeDamageAtom::ComputeDamageAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute damage/atom command");
+ if (narg != 3) error->all(FLERR,"Illegal compute damage/atom command");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
damage = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeDamageAtom::~ComputeDamageAtom()
{
memory->destroy(damage);
}
/* ---------------------------------------------------------------------- */
void ComputeDamageAtom::init()
{
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"damage/peri") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute damage/atom");
+ error->warning(FLERR,"More than one compute damage/atom");
// find associated PERI_NEIGH fix that must exist
ifix_peri = -1;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"PERI_NEIGH") == 0) ifix_peri = i;
if (ifix_peri == -1)
- error->all("Compute damage/atom requires peridynamic potential");
+ error->all(FLERR,"Compute damage/atom requires peridynamic potential");
}
/* ---------------------------------------------------------------------- */
void ComputeDamageAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow damage array if necessary
if (atom->nlocal > nmax) {
memory->destroy(damage);
nmax = atom->nmax;
memory->create(damage,nmax,"damage/atom:damage");
vector_atom = damage;
}
// compute damage for each atom in group
int nlocal = atom->nlocal;
int *mask = atom->mask;
double *vfrac = atom->vfrac;
double *vinter = ((FixPeriNeigh *) modify->fix[ifix_peri])->vinter;
int **partner = ((FixPeriNeigh *) modify->fix[ifix_peri])->partner;
int *npartner = ((FixPeriNeigh *) modify->fix[ifix_peri])->npartner;
int i,j,jj,jnum;
double damage_temp;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
jnum = npartner[i];
damage_temp = 0.0;
for (jj = 0; jj < jnum; jj++) {
if (partner[i][jj] == 0) continue;
// look up local index of this partner particle
// skip if particle is "lost"
j = atom->map(partner[i][jj]);
if (j < 0) continue;
damage_temp += vfrac[j];
}
}
else damage_temp = vinter[i];
if (vinter[i] != 0.0) damage[i] = 1.0 - damage_temp/vinter[i];
else damage[i] = 0.0;
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeDamageAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/PERI/fix_peri_neigh.cpp b/src/PERI/fix_peri_neigh.cpp
index 3271e743c..eb7d8c853 100644
--- a/src/PERI/fix_peri_neigh.cpp
+++ b/src/PERI/fix_peri_neigh.cpp
@@ -1,541 +1,538 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Parks (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "fix_peri_neigh.h"
#include "pair_peri_pmb.h"
#include "pair_peri_lps.h"
#include "atom.h"
#include "domain.h"
#include "force.h"
#include "comm.h"
#include "update.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "pair.h"
#include "lattice.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixPeriNeigh::FixPeriNeigh(LAMMPS *lmp,int narg, char **arg) :
Fix(lmp, narg, arg)
{
restart_global = 1;
restart_peratom = 1;
first = 1;
// perform initial allocation of atom-based arrays
// register with atom class
// set maxpartner = 1 as placeholder
maxpartner = 1;
npartner = NULL;
partner = NULL;
r0 = NULL;
vinter = NULL;
wvolume = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
atom->add_callback(1);
// initialize npartner to 0 so atom migration is OK the 1st time
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) npartner[i] = 0;
// set comm sizes needed by this fix
comm_forward = 1;
}
/* ---------------------------------------------------------------------- */
FixPeriNeigh::~FixPeriNeigh()
{
// unregister this fix so atom class doesn't invoke it any more
atom->delete_callback(id,0);
atom->delete_callback(id,1);
// delete locally stored arrays
memory->destroy(npartner);
memory->destroy(partner);
memory->destroy(r0);
memory->destroy(vinter);
memory->destroy(wvolume);
}
/* ---------------------------------------------------------------------- */
int FixPeriNeigh::setmask()
{
int mask = 0;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPeriNeigh::init()
{
if (!first) return;
// need a full neighbor list once
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
}
/* ---------------------------------------------------------------------- */
void FixPeriNeigh::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ----------------------------------------------------------------------
For minimization: setup as with dynamics
------------------------------------------------------------------------- */
void FixPeriNeigh::min_setup(int vflag)
{
setup(vflag);
}
/* ----------------------------------------------------------------------
create initial list of neighbor partners via call to neighbor->build()
must be done in setup (not init) since fix init comes before neigh init
------------------------------------------------------------------------- */
void FixPeriNeigh::setup(int vflag)
{
int i,j,ii,jj,itype,jtype,inum,jnum;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *ilist,*jlist,*numneigh;
int **firstneigh;
double **x = atom->x;
double *vfrac = atom->vfrac;
int *type = atom->type;
int *tag = atom->tag;
int nlocal = atom->nlocal;
// only build list of bonds on very first run
if (!first) return;
first = 0;
// invoke full neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// scan neighbor list to set maxpartner
Pair *anypair = force->pair_match("peri",0);
double **cutsq = anypair->cutsq;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq <= cutsq[itype][jtype]) npartner[i]++;
}
}
maxpartner = 0;
for (i = 0; i < nlocal; i++) maxpartner = MAX(maxpartner,npartner[i]);
int maxall;
MPI_Allreduce(&maxpartner,&maxall,1,MPI_INT,MPI_MAX,world);
maxpartner = maxall;
// realloc arrays with correct value for maxpartner
memory->destroy(partner);
memory->destroy(r0);
memory->destroy(npartner);
npartner = NULL;
partner = NULL;
r0 = NULL;
grow_arrays(atom->nmax);
// create partner list and r0 values from neighbor list
// compute vinter for each atom
for (i = 0; i < nlocal; i++) {
npartner[i] = 0;
vinter[i] = 0.0;
wvolume[i] = 0.0;
}
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq <= cutsq[itype][jtype]) {
partner[i][npartner[i]] = tag[j];
r0[i][npartner[i]] = sqrt(rsq);
npartner[i]++;
vinter[i] += vfrac[j];
}
}
}
// sanity check: does any atom appear twice in any neigborlist?
// should only be possible if using pbc and domain < 2*delta
if (domain->xperiodic || domain->yperiodic || domain->zperiodic) {
for (i = 0; i < nlocal; i++) {
jnum = npartner[i];
for (jj = 0; jj < jnum; jj++) {
for (int kk = jj+1; kk < jnum; kk++) {
if (partner[i][jj] == partner[i][kk])
- error->one("Duplicate particle in PeriDynamic bond - "
+ error->one(FLERR,"Duplicate particle in PeriDynamic bond - "
"simulation box is too small");
}
}
}
}
// compute wvolume for each atom
double **x0 = atom->x0;
double half_lc = 0.5*(domain->lattice->xlattice);
double vfrac_scale;
PairPeriLPS *pairlps = static_cast<PairPeriLPS*>(anypair);
PairPeriPMB *pairpmb = static_cast<PairPeriPMB*>(anypair);
for (i = 0; i < nlocal; i++) {
double xtmp0 = x0[i][0];
double ytmp0 = x0[i][1];
double ztmp0 = x0[i][2];
jnum = npartner[i];
itype = type[i];
// loop over partners of particle i
for (jj = 0; jj < jnum; jj++) {
// if bond already broken, skip this partner
if (partner[i][jj] == 0) continue;
// lookup local index of partner particle
j = atom->map(partner[i][jj]);
// skip if particle is "lost"
if (j < 0) continue;
double delx0 = xtmp0 - x0[j][0];
double dely0 = ytmp0 - x0[j][1];
double delz0 = ztmp0 - x0[j][2];
double rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0;
jtype = type[j];
double delta = sqrt(cutsq[itype][jtype]);
// scale vfrac[j] if particle j near the horizon
if ((fabs(r0[i][jj] - delta)) <= half_lc)
vfrac_scale = (-1.0/(2*half_lc))*(r0[i][jj]) +
(1.0 + ((delta - half_lc)/(2*half_lc) ) );
else vfrac_scale = 1.0;
if (pairpmb != NULL) // define influence function to be 1.0
wvolume[i] += 1.0 * rsq0 * vfrac[j] * vfrac_scale;
else if (pairlps != NULL) // call the PairPeriLPS influence function
wvolume[i] += pairlps->influence_function(delx0,dely0,delz0) *
rsq0 * vfrac[j] * vfrac_scale;
}
}
// communicate wvolume to ghosts
comm->forward_comm_fix(this);
// bond statistics
int n = 0;
for (i = 0; i < nlocal; i++) n += npartner[i];
int nall;
MPI_Allreduce(&n,&nall,1,MPI_INT,MPI_SUM,world);
if (comm->me == 0) {
if (screen) {
fprintf(screen,"Peridynamic bonds:\n");
fprintf(screen," total # of bonds = %d\n",nall);
fprintf(screen," bonds/atom = %g\n",(double)nall/atom->natoms);
}
if (logfile) {
fprintf(logfile,"Peridynamic bonds:\n");
fprintf(logfile," total # of bonds = %d\n",nall);
fprintf(logfile," bonds/atom = %g\n",(double)nall/atom->natoms);
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixPeriNeigh::memory_usage()
{
int nmax = atom->nmax;
int bytes = nmax * sizeof(int);
bytes += nmax*maxpartner * sizeof(int);
bytes += nmax*maxpartner * sizeof(double);
bytes += nmax * sizeof(double);
bytes += nmax * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixPeriNeigh::grow_arrays(int nmax)
{
memory->grow(npartner,nmax,"peri_neigh:npartner");
memory->grow(partner,nmax,maxpartner,"peri_neigh:partner");
memory->grow(r0,nmax,maxpartner,"peri_neigh:r0");
memory->grow(vinter,nmax,"peri_neigh:vinter");
memory->grow(wvolume,nmax,"peri_neigh:wvolume");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixPeriNeigh::copy_arrays(int i, int j)
{
npartner[j] = npartner[i];
for (int m = 0; m < npartner[j]; m++) {
partner[j][m] = partner[i][m];
r0[j][m] = r0[i][m];
}
vinter[j] = vinter[i];
wvolume[j] = wvolume[i];
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixPeriNeigh::pack_exchange(int i, double *buf)
{
// compact list by eliminating partner = 0 entries
// set buf[0] after compaction
int m = 1;
for (int n = 0; n < npartner[i]; n++) {
if (partner[i][n] == 0) continue;
buf[m++] = partner[i][n];
buf[m++] = r0[i][n];
}
buf[0] = m/2;
buf[m++] = vinter[i];
buf[m++] = wvolume[i];
return m;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixPeriNeigh::unpack_exchange(int nlocal, double *buf)
{
int m = 0;
npartner[nlocal] = static_cast<int> (buf[m++]);
for (int n = 0; n < npartner[nlocal]; n++) {
partner[nlocal][n] = static_cast<int> (buf[m++]);
r0[nlocal][n] = buf[m++];
}
vinter[nlocal] = buf[m++];
wvolume[nlocal] = buf[m++];
return m;
}
/* ---------------------------------------------------------------------- */
int FixPeriNeigh::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = wvolume[j];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void FixPeriNeigh::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
wvolume[i] = buf[m++];
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixPeriNeigh::write_restart(FILE *fp)
{
int n = 0;
double list[2];
list[n++] = first;
list[n++] = maxpartner;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),n,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixPeriNeigh::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
first = static_cast<int> (list[n++]);
maxpartner = static_cast<int> (list[n++]);
// grow 2D arrays now, cannot change size of 2nd array index later
grow_arrays(atom->nmax);
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixPeriNeigh::pack_restart(int i, double *buf)
{
int m = 0;
buf[m++] = 2*npartner[i] + 4;
buf[m++] = npartner[i];
for (int n = 0; n < npartner[i]; n++) {
buf[m++] = partner[i][n];
buf[m++] = r0[i][n];
}
buf[m++] = vinter[i];
buf[m++] = wvolume[i];
return m;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixPeriNeigh::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
npartner[nlocal] = static_cast<int> (extra[nlocal][m++]);
for (int n = 0; n < npartner[nlocal]; n++) {
partner[nlocal][n] = static_cast<int> (extra[nlocal][m++]);
r0[nlocal][n] = extra[nlocal][m++];
}
vinter[nlocal] = extra[nlocal][m++];
wvolume[nlocal] = extra[nlocal][m++];
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixPeriNeigh::maxsize_restart()
{
return 2*maxpartner + 4;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixPeriNeigh::size_restart(int nlocal)
{
return 2*npartner[nlocal] + 4;
}
diff --git a/src/PERI/pair_peri_lps.cpp b/src/PERI/pair_peri_lps.cpp
index ec50bdf0e..4efd0b4f3 100644
--- a/src/PERI/pair_peri_lps.cpp
+++ b/src/PERI/pair_peri_lps.cpp
@@ -1,748 +1,745 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Parks (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "pair_peri_lps.h"
#include "atom.h"
#include "domain.h"
#include "lattice.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "fix_peri_neigh.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
#include "update.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairPeriLPS::PairPeriLPS(LAMMPS *lmp) : Pair(lmp)
{
for (int i = 0; i < 6; i++) virial[i] = 0.0;
no_virial_fdotr_compute=1;
ifix_peri = -1;
nmax = 0;
s0_new = NULL;
theta = NULL;
bulkmodulus = NULL;
shearmodulus = NULL;
s00 = alpha = NULL;
cut = NULL;
// set comm size needed by this Pair
// comm_reverse not needed
comm_forward = 1; // for passing dilatation (theta)
}
/* ---------------------------------------------------------------------- */
PairPeriLPS::~PairPeriLPS()
{
if (ifix_peri >= 0) modify->delete_fix("PERI_NEIGH");
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(bulkmodulus);
memory->destroy(shearmodulus);
memory->destroy(s00);
memory->destroy(alpha);
memory->destroy(cut);
memory->destroy(theta);
memory->destroy(s0_new);
}
}
/* ---------------------------------------------------------------------- */
void PairPeriLPS::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz;
double xtmp0,ytmp0,ztmp0,delx0,dely0,delz0,rsq0;
double rsq,r,dr,rk,evdwl,fpair,fbond;
int *ilist,*jlist,*numneigh,**firstneigh;
double d_ij,delta,stretch;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = eflag_atom = 0;
double **f = atom->f;
double **x = atom->x;
int *type = atom->type;
int nlocal = atom->nlocal;
double *vfrac = atom->vfrac;
double *s0 = atom->s0;
double **x0 = atom->x0;
double **r0 = ((FixPeriNeigh *) modify->fix[ifix_peri])->r0;
int **partner = ((FixPeriNeigh *) modify->fix[ifix_peri])->partner;
int *npartner = ((FixPeriNeigh *) modify->fix[ifix_peri])->npartner;
double *wvolume = ((FixPeriNeigh *) modify->fix[ifix_peri])->wvolume;
// lc = lattice constant
// init_style guarantees it's the same in x, y, and z
double lc = domain->lattice->xlattice;
double half_lc = 0.5*lc;
double vfrac_scale = 1.0;
// short-range forces
int newton_pair = force->newton_pair;
int periodic = domain->xperiodic || domain->yperiodic || domain->zperiodic;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
// need minimg() for x0 difference since not ghosted
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
xtmp0 = x0[i][0];
ytmp0 = x0[i][1];
ztmp0 = x0[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
delx0 = xtmp0 - x0[j][0];
dely0 = ytmp0 - x0[j][1];
delz0 = ztmp0 - x0[j][2];
if (periodic) domain->minimum_image(delx0,dely0,delz0);
rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0;
jtype = type[j];
r = sqrt(rsq);
// short-range interaction distance based on initial particle position
// 0.9 and 1.35 are constants
d_ij = MIN(0.9*sqrt(rsq0),1.35*lc);
// short-range contact forces
// 15 is constant taken from the EMU Theory Manual
// Silling, 12 May 2005, p 18
if (r < d_ij) {
dr = r - d_ij;
// kshort based upon short-range force constant
// of the bond-based theory used in PMB model
double kshort = (15.0 * 18.0 * bulkmodulus[itype][itype]) /
(3.141592653589793 * cutsq[itype][jtype] * cutsq[itype][jtype]);
rk = (kshort * vfrac[j]) * (dr / sqrt(cutsq[itype][jtype]));
if (r > 0.0) fpair = -(rk/r);
else fpair = 0.0;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) evdwl = 0.5*rk*dr;
if (evflag) ev_tally(i,j,nlocal,newton_pair,evdwl,0.0,fpair*vfrac[i],delx,dely,delz);
}
}
}
// grow bond forces array if necessary
if (atom->nmax > nmax) {
memory->destroy(s0_new);
memory->destroy(theta);
nmax = atom->nmax;
memory->create(s0_new,nmax,"pair:s0_new");
memory->create(theta,nmax,"pair:theta");
}
// Compute the dilatation on each particle
compute_dilatation();
// communicate dilatation (theta) of each particle
comm->forward_comm_pair(this);
// communicate wighted volume (wvolume) upon every reneighbor
if (neighbor->ago == 0)
comm->forward_comm_fix(modify->fix[ifix_peri]);
// Volume-dependent part of the energy
for (i = 0; i < nlocal; i++) {
itype = type[i];
if (eflag) {
if (eflag_global)
eng_vdwl += 0.5 * bulkmodulus[itype][itype] * (theta[i] * theta[i]);
if (eflag_atom)
eatom[i] += 0.5 * bulkmodulus[itype][itype] * (theta[i] * theta[i]);
}
}
// loop over my particles and their partners
// partner list contains all bond partners, so I-J appears twice
// if bond already broken, skip this partner
// first = true if this is first neighbor of particle i
bool first;
double omega_minus, omega_plus;
for (i = 0; i < nlocal; i++) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
xtmp0 = x0[i][0];
ytmp0 = x0[i][1];
ztmp0 = x0[i][2];
itype = type[i];
jnum = npartner[i];
first = true;
for (jj = 0; jj < jnum; jj++) {
if (partner[i][jj] == 0) continue;
j = atom->map(partner[i][jj]);
// check if lost a partner without first breaking bond
if (j < 0) {
partner[i][jj] = 0;
continue;
}
// compute force density, add to PD equation of motion
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
if (periodic) domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
delx0 = xtmp0 - x0[j][0];
dely0 = ytmp0 - x0[j][1];
delz0 = ztmp0 - x0[j][2];
if (periodic) domain->minimum_image(delx0,dely0,delz0);
jtype = type[j];
delta = sqrt(cutsq[itype][jtype]);
r = sqrt(rsq);
dr = r - r0[i][jj];
// avoid roundoff errors
if (fabs(dr) < 2.2204e-016) dr = 0.0;
// scale vfrac[j] if particle j near the horizon
if ((fabs(r0[i][jj] - delta)) <= half_lc)
vfrac_scale = (-1.0/(2*half_lc))*(r0[i][jj]) +
(1.0 + ((delta - half_lc)/(2*half_lc) ) );
else vfrac_scale = 1.0;
omega_plus = influence_function(-1.0*delx0,-1.0*dely0,-1.0*delz0);
omega_minus = influence_function(delx0,dely0,delz0);
rk = ( (3.0 * bulkmodulus[itype][itype]) -
(5.0 * shearmodulus[itype][itype]) ) * vfrac[j] * vfrac_scale *
( (omega_plus * theta[i] / wvolume[i]) +
( omega_minus * theta[j] / wvolume[j] ) ) * r0[i][jj];
rk += 15.0 * ( shearmodulus[itype][itype] * vfrac[j] * vfrac_scale ) *
( (omega_plus / wvolume[i]) + (omega_minus / wvolume[j]) ) * dr;
if (r > 0.0) fbond = -(rk/r);
else fbond = 0.0;
f[i][0] += delx*fbond;
f[i][1] += dely*fbond;
f[i][2] += delz*fbond;
// since I-J is double counted, set newton off & use 1/2 factor and I,I
double deviatoric_extension = dr - (theta[i]* r0[i][jj] / 3.0);
if (eflag) evdwl = 0.5 * 15 * (shearmodulus[itype][itype]/wvolume[i]) *
omega_plus*(deviatoric_extension * deviatoric_extension) *
vfrac[j] * vfrac_scale;
if (evflag) ev_tally(i,i,nlocal,0,0.5*evdwl,0.0,0.5*fbond*vfrac[i],delx,dely,delz);
// find stretch in bond I-J and break if necessary
// use s0 from previous timestep
stretch = dr / r0[i][jj];
if (stretch > MIN(s0[i],s0[j])) partner[i][jj] = 0;
// update s0 for next timestep
if (first)
s0_new[i] = s00[itype][jtype] - (alpha[itype][jtype] * stretch);
else
s0_new[i] = MAX(s0_new[i],
s00[itype][jtype] - (alpha[itype][jtype] * stretch));
first = false;
}
}
// store new s0
for (i = 0; i < nlocal; i++) s0[i] = s0_new[i];
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairPeriLPS::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(bulkmodulus,n+1,n+1,"pair:bulkmodulus");
memory->create(shearmodulus,n+1,n+1,"pair:shearmodulus");
memory->create(s00,n+1,n+1,"pair:s00");
memory->create(alpha,n+1,n+1,"pair:alpha");
memory->create(cut,n+1,n+1,"pair:cut");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairPeriLPS::settings(int narg, char **arg)
{
- if (narg) error->all("Illegal pair_style command");
+ if (narg) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairPeriLPS::coeff(int narg, char **arg)
{
- if (narg != 7) error->all("Incorrect args for pair coefficients");
+ if (narg != 7) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double bulkmodulus_one = atof(arg[2]);
double shearmodulus_one = atof(arg[3]);
double cut_one = atof(arg[4]);
double s00_one = atof(arg[5]);
double alpha_one = atof(arg[6]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
bulkmodulus[i][j] = bulkmodulus_one;
shearmodulus[i][j] = shearmodulus_one;
cut[i][j] = cut_one;
s00[i][j] = s00_one;
alpha[i][j] = alpha_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairPeriLPS::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
bulkmodulus[j][i] = bulkmodulus[i][j];
shearmodulus[j][i] = shearmodulus[i][j];
s00[j][i] = s00[i][j];
alpha[j][i] = alpha[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairPeriLPS::init_style()
{
// error checks
- if (!atom->peri_flag) error->all("Pair style peri requires atom style peri");
+ if (!atom->peri_flag) error->all(FLERR,"Pair style peri requires atom style peri");
if (atom->map_style == 0)
- error->all("Pair peri requires an atom map, see atom_modify");
+ error->all(FLERR,"Pair peri requires an atom map, see atom_modify");
if (domain->lattice == NULL)
- error->all("Pair peri requires a lattice be defined");
+ error->all(FLERR,"Pair peri requires a lattice be defined");
if (domain->lattice->xlattice != domain->lattice->ylattice ||
domain->lattice->xlattice != domain->lattice->zlattice ||
domain->lattice->ylattice != domain->lattice->zlattice)
- error->all("Pair peri lattice is not identical in x, y, and z");
+ error->all(FLERR,"Pair peri lattice is not identical in x, y, and z");
// if first init, create Fix needed for storing fixed neighbors
if (ifix_peri == -1) {
char **fixarg = new char*[3];
fixarg[0] = (char *) "PERI_NEIGH";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "PERI_NEIGH";
modify->add_fix(3,fixarg);
delete [] fixarg;
}
// find associated PERI_NEIGH fix that must exist
// could have changed locations in fix list since created
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"PERI_NEIGH") == 0) ifix_peri = i;
- if (ifix_peri == -1) error->all("Fix peri neigh does not exist");
+ if (ifix_peri == -1) error->all(FLERR,"Fix peri neigh does not exist");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairPeriLPS::write_restart(FILE *fp)
{
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&bulkmodulus[i][j],sizeof(double),1,fp);
fwrite(&shearmodulus[i][j],sizeof(double),1,fp);
fwrite(&s00[i][j],sizeof(double),1,fp);
fwrite(&alpha[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairPeriLPS::read_restart(FILE *fp)
{
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&bulkmodulus[i][j],sizeof(double),1,fp);
fread(&shearmodulus[i][j],sizeof(double),1,fp);
fread(&s00[i][j],sizeof(double),1,fp);
fread(&alpha[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&bulkmodulus[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&shearmodulus[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&s00[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&alpha[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ---------------------------------------------------------------------- */
double PairPeriLPS::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
double delx0,dely0,delz0,rsq0;
double d_ij,r,dr,rk,vfrac_scale;
double *vfrac = atom->vfrac;
double **x0 = atom->x0;
double **r0 = ((FixPeriNeigh *) modify->fix[ifix_peri])->r0;
int **partner = ((FixPeriNeigh *) modify->fix[ifix_peri])->partner;
int *npartner = ((FixPeriNeigh *) modify->fix[ifix_peri])->npartner;
double *wvolume = ((FixPeriNeigh *) modify->fix[ifix_peri])->wvolume;
double lc = domain->lattice->xlattice;
double half_lc = 0.5*lc;
double kshort;
delx0 = x0[i][0] - x0[j][0];
dely0 = x0[i][1] - x0[j][1];
delz0 = x0[i][2] - x0[j][2];
int periodic = domain->xperiodic || domain->yperiodic || domain->zperiodic;
if (periodic) domain->minimum_image(delx0,dely0,delz0);
rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0;
d_ij = MIN(0.9*sqrt(rsq0),1.35*lc);
r = sqrt(rsq);
double energy = 0.0;
fforce = 0.0;
if (r < d_ij) {
dr = r - d_ij;
// kshort resembles short-range force constant of bond-based theory in 3d
kshort = (15.0 * 18.0 * bulkmodulus[itype][itype]) /
( 3.141592653589793 * cutsq[itype][jtype] * cutsq[itype][jtype]);
rk = ( kshort * vfrac[j]) * (dr / sqrt(cutsq[itype][jtype]));
if (r > 0.0) fforce += -(rk/r);
energy += 0.5*rk*dr;
}
if (atom->nmax > nmax) {
memory->destroy(theta);
nmax = atom->nmax;
memory->create(theta,nmax,"pair:theta");
}
// Compute the dilatation on each particle
compute_dilatation();
// communicate dilatation (theta) of each particle
comm->forward_comm_pair(this);
// communicate wighted volume (wvolume) upon every reneighbor
if (neighbor->ago == 0)
comm->forward_comm_fix(modify->fix[ifix_peri]);
double omega_plus, omega_minus;
int jnum = npartner[i];
for (int jj = 0; jj < jnum; jj++) {
if (partner[i][jj] == 0) continue;
if (j < 0) continue;
if (j == atom->map(partner[i][jj])) {
dr = r - r0[i][jj];
if (fabs(dr) < 2.2204e-016) dr = 0.0;
// scale vfrac[j] if particle j near the horizon
if ( (fabs(r0[i][jj] - sqrt(cutsq[itype][jtype]))) <= half_lc)
vfrac_scale = (-1.0/(2*half_lc))*(r0[i][jj]) +
(1.0 + ((sqrt(cutsq[itype][jtype]) - half_lc)/(2*half_lc)));
else vfrac_scale = 1.0;
omega_plus = influence_function(-1.0*delx0,-1.0*dely0,-1.0*delz0);
omega_minus = influence_function(delx0,dely0,delz0);
rk = (3.0* bulkmodulus[itype][itype] -5.0 * shearmodulus[itype][itype]) *
vfrac[j] * vfrac_scale * ( (omega_plus * theta[i] / wvolume[i]) +
(omega_minus * theta[j] / wvolume[j])) *
r0[i][jj];
rk += 15.0 * ( shearmodulus[itype][itype] * vfrac[j] * vfrac_scale ) *
( (omega_plus / wvolume[i]) + (omega_minus / wvolume[j]) ) * dr;
if (r > 0.0) fforce += -(rk/r);
energy += 0.5 * 15 * (shearmodulus[itype][itype]/wvolume[i]) *
omega_plus * ( dr - theta[i]* r0[i][jj] / 3.0 ) *
( dr - theta[i]* r0[i][jj] / 3.0 ) * vfrac[j] * vfrac_scale;
}
}
return energy;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairPeriLPS::memory_usage()
{
double bytes = 2 * nmax * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
influence function definition
------------------------------------------------------------------------- */
double PairPeriLPS::influence_function(double xi_x, double xi_y, double xi_z)
{
double r = sqrt(xi_x*xi_x + xi_y*xi_y + xi_z*xi_z);
double omega;
if (fabs(r) < 2.2204e-016)
- error->one("Divide by 0 in influence function of pair peri/lps");
+ error->one(FLERR,"Divide by 0 in influence function of pair peri/lps");
omega = 1.0/r;
return omega;
}
/* ---------------------------------------------------------------------- */
void PairPeriLPS::compute_dilatation()
{
int i,j,jj,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz;
double xtmp0,ytmp0,ztmp0,delx0,dely0,delz0;
double rsq,r,dr;
double delta;
double **x = atom->x;
int *type = atom->type;
double **x0 = atom->x0;
int nlocal = atom->nlocal;
double *vfrac = atom->vfrac;
double vfrac_scale = 1.0;
double lc = domain->lattice->xlattice;
double half_lc = 0.5*lc;
double **r0 = ((FixPeriNeigh *) modify->fix[ifix_peri])->r0;
int **partner = ((FixPeriNeigh *) modify->fix[ifix_peri])->partner;
int *npartner = ((FixPeriNeigh *) modify->fix[ifix_peri])->npartner;
double *wvolume = ((FixPeriNeigh *) modify->fix[ifix_peri])->wvolume;
int periodic = domain->xperiodic || domain->yperiodic || domain->zperiodic;
// compute the dilatation theta
for (i = 0; i < nlocal; i++) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
xtmp0 = x0[i][0];
ytmp0 = x0[i][1];
ztmp0 = x0[i][2];
jnum = npartner[i];
theta[i] = 0.0;
itype = type[i];
for (jj = 0; jj < jnum; jj++) {
// if bond already broken, skip this partner
if (partner[i][jj] == 0) continue;
// Look up local index of this partner particle
j = atom->map(partner[i][jj]);
// Skip if particle is "lost"
if (j < 0) continue;
// Compute force density and add to PD equation of motion
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
if (periodic) domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
delx0 = xtmp0 - x0[j][0];
dely0 = ytmp0 - x0[j][1];
delz0 = ztmp0 - x0[j][2];
if (periodic) domain->minimum_image(delx0,dely0,delz0);
r = sqrt(rsq);
dr = r - r0[i][jj];
if (fabs(dr) < 2.2204e-016) dr = 0.0;
jtype = type[j];
delta = sqrt(cutsq[itype][jtype]);
// scale vfrac[j] if particle j near the horizon
if ((fabs(r0[i][jj] - delta)) <= half_lc)
vfrac_scale = (-1.0/(2*half_lc))*(r0[i][jj]) +
(1.0 + ((delta - half_lc)/(2*half_lc) ) );
else vfrac_scale = 1.0;
theta[i] += influence_function(delx0, dely0, delz0) * r0[i][jj] * dr *
vfrac[j] * vfrac_scale;
}
// if wvolume[i] is zero, then particle i has no bonds
// therefore, the dilatation is set to
if (wvolume[i] != 0.0) theta[i] = (3.0/wvolume[i]) * theta[i];
else theta[i] = 0;
}
}
/* ----------------------------------------------------------------------
communication routines
---------------------------------------------------------------------- */
int PairPeriLPS::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = theta[j];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void PairPeriLPS::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
theta[i] = buf[m++];
}
}
diff --git a/src/PERI/pair_peri_pmb.cpp b/src/PERI/pair_peri_pmb.cpp
index 79f0cccd7..a98a398f6 100644
--- a/src/PERI/pair_peri_pmb.cpp
+++ b/src/PERI/pair_peri_pmb.cpp
@@ -1,511 +1,508 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Parks (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "float.h"
#include "stdlib.h"
#include "string.h"
#include "pair_peri_pmb.h"
#include "atom.h"
#include "domain.h"
#include "lattice.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "fix_peri_neigh.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairPeriPMB::PairPeriPMB(LAMMPS *lmp) : Pair(lmp)
{
for (int i = 0; i < 6; i++) virial[i] = 0.0;
no_virial_fdotr_compute=1;
ifix_peri = -1;
nmax = 0;
s0_new = NULL;
kspring = NULL;
s00 = NULL;
alpha = NULL;
cut = NULL;
}
/* ---------------------------------------------------------------------- */
PairPeriPMB::~PairPeriPMB()
{
if (ifix_peri >= 0) modify->delete_fix("PERI_NEIGH");
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(kspring);
memory->destroy(s00);
memory->destroy(alpha);
memory->destroy(cut);
memory->destroy(s0_new);
}
}
/* ---------------------------------------------------------------------- */
void PairPeriPMB::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz;
double xtmp0,ytmp0,ztmp0,delx0,dely0,delz0,rsq0;
double rsq,r,dr,rk,evdwl,fpair,fbond;
int *ilist,*jlist,*numneigh,**firstneigh;
double d_ij,delta,stretch;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **f = atom->f;
double **x = atom->x;
int *type = atom->type;
int nlocal = atom->nlocal;
double *vfrac = atom->vfrac;
double *s0 = atom->s0;
double **x0 = atom->x0;
double **r0 = ((FixPeriNeigh *) modify->fix[ifix_peri])->r0;
int **partner = ((FixPeriNeigh *) modify->fix[ifix_peri])->partner;
int *npartner = ((FixPeriNeigh *) modify->fix[ifix_peri])->npartner;
// lc = lattice constant
// init_style guarantees it's the same in x, y, and z
double lc = domain->lattice->xlattice;
double half_lc = 0.5*lc;
double vfrac_scale = 1.0;
// short-range forces
int newton_pair = force->newton_pair;
int periodic = (domain->xperiodic || domain->yperiodic || domain->zperiodic);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
// need minimg() for x0 difference since not ghosted
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
xtmp0 = x0[i][0];
ytmp0 = x0[i][1];
ztmp0 = x0[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
delx0 = xtmp0 - x0[j][0];
dely0 = ytmp0 - x0[j][1];
delz0 = ztmp0 - x0[j][2];
if (periodic) domain->minimum_image(delx0,dely0,delz0);
rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0;
jtype = type[j];
r = sqrt(rsq);
// short-range interaction distance based on initial particle position
// 0.9 and 1.35 are constants
d_ij = MIN(0.9*sqrt(rsq0),1.35*lc);
// short-range contact forces
// 15 is constant taken from the EMU Theory Manual
// Silling, 12 May 2005, p 18
if (r < d_ij) {
dr = r - d_ij;
rk = (15.0 * kspring[itype][jtype] * vfrac[j]) *
(dr / sqrt(cutsq[itype][jtype]));
if (r > 0.0) fpair = -(rk/r);
else fpair = 0.0;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) evdwl = 0.5*rk*dr;
if (evflag) ev_tally(i,j,nlocal,newton_pair,evdwl,0.0,fpair*vfrac[i],delx,dely,delz);
}
}
}
// grow bond forces array if necessary
if (atom->nmax > nmax) {
memory->destroy(s0_new);
nmax = atom->nmax;
memory->create(s0_new,nmax,"pair:s0_new");
}
// loop over my particles and their partners
// partner list contains all bond partners, so I-J appears twice
// if bond already broken, skip this partner
// first = true if this is first neighbor of particle i
bool first;
for (i = 0; i < nlocal; i++) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jnum = npartner[i];
s0_new[i] = DBL_MAX;
first = true;
for (jj = 0; jj < jnum; jj++) {
if (partner[i][jj] == 0) continue;
j = atom->map(partner[i][jj]);
// check if lost a partner without first breaking bond
if (j < 0) {
partner[i][jj] = 0;
continue;
}
// compute force density, add to PD equation of motion
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
if (periodic) domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
delta = sqrt(cutsq[itype][jtype]);
r = sqrt(rsq);
dr = r - r0[i][jj];
// avoid roundoff errors
if (fabs(dr) < 2.2204e-016) dr = 0.0;
// scale vfrac[j] if particle j near the horizon
if ((fabs(r0[i][jj] - delta)) <= half_lc)
vfrac_scale = (-1.0/(2*half_lc))*(r0[i][jj]) +
(1.0 + ((delta - half_lc)/(2*half_lc) ) );
else vfrac_scale = 1.0;
stretch = dr / r0[i][jj];
rk = (kspring[itype][jtype] * vfrac[j]) * vfrac_scale * stretch;
if (r > 0.0) fbond = -(rk/r);
else fbond = 0.0;
f[i][0] += delx*fbond;
f[i][1] += dely*fbond;
f[i][2] += delz*fbond;
// since I-J is double counted, set newton off & use 1/2 factor and I,I
if (eflag) evdwl = 0.5*rk*dr;
if (evflag) ev_tally(i,i,nlocal,0,0.5*evdwl,0.0,0.5*fbond*vfrac[i],delx,dely,delz);
// find stretch in bond I-J and break if necessary
// use s0 from previous timestep
if (stretch > MIN(s0[i],s0[j])) partner[i][jj] = 0;
// update s0 for next timestep
if (first)
s0_new[i] = s00[itype][jtype] - (alpha[itype][jtype] * stretch);
else
s0_new[i] = MAX(s0_new[i],s00[itype][jtype] - (alpha[itype][jtype] * stretch));
first = false;
}
}
// store new s0
for (i = 0; i < nlocal; i++) s0[i] = s0_new[i];
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairPeriPMB::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(kspring,n+1,n+1,"pair:kspring");
memory->create(s00,n+1,n+1,"pair:s00");
memory->create(alpha,n+1,n+1,"pair:alpha");
memory->create(cut,n+1,n+1,"pair:cut");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairPeriPMB::settings(int narg, char **arg)
{
- if (narg) error->all("Illegal pair_style command");
+ if (narg) error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairPeriPMB::coeff(int narg, char **arg)
{
- if (narg != 6) error->all("Incorrect args for pair coefficients");
+ if (narg != 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double kspring_one = force->numeric(arg[2]);
double cut_one = force->numeric(arg[3]);
double s00_one = force->numeric(arg[4]);
double alpha_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
kspring[i][j] = kspring_one;
s00[i][j] = s00_one;
alpha[i][j] = alpha_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairPeriPMB::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
kspring[j][i] = kspring[i][j];
alpha[j][i] = alpha[i][j];
s00[j][i] = s00[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairPeriPMB::init_style()
{
// error checks
- if (!atom->peri_flag) error->all("Pair style peri requires atom style peri");
+ if (!atom->peri_flag) error->all(FLERR,"Pair style peri requires atom style peri");
if (atom->map_style == 0)
- error->all("Pair peri requires an atom map, see atom_modify");
+ error->all(FLERR,"Pair peri requires an atom map, see atom_modify");
if (domain->lattice == NULL)
- error->all("Pair peri requires a lattice be defined");
+ error->all(FLERR,"Pair peri requires a lattice be defined");
if (domain->lattice->xlattice != domain->lattice->ylattice ||
domain->lattice->xlattice != domain->lattice->zlattice ||
domain->lattice->ylattice != domain->lattice->zlattice)
- error->all("Pair peri lattice is not identical in x, y, and z");
+ error->all(FLERR,"Pair peri lattice is not identical in x, y, and z");
// if first init, create Fix needed for storing fixed neighbors
if (ifix_peri == -1) {
char **fixarg = new char*[3];
fixarg[0] = (char *) "PERI_NEIGH";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "PERI_NEIGH";
modify->add_fix(3,fixarg);
delete [] fixarg;
}
// find associated PERI_NEIGH fix that must exist
// could have changed locations in fix list since created
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"PERI_NEIGH") == 0) ifix_peri = i;
- if (ifix_peri == -1) error->all("Fix peri neigh does not exist");
+ if (ifix_peri == -1) error->all(FLERR,"Fix peri neigh does not exist");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairPeriPMB::write_restart(FILE *fp)
{
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&kspring[i][j],sizeof(double),1,fp);
fwrite(&s00[i][j],sizeof(double),1,fp);
fwrite(&alpha[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairPeriPMB::read_restart(FILE *fp)
{
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&kspring[i][j],sizeof(double),1,fp);
fread(&s00[i][j],sizeof(double),1,fp);
fread(&alpha[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&kspring[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&s00[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&alpha[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ---------------------------------------------------------------------- */
double PairPeriPMB::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double delx0,dely0,delz0,rsq0;
double d_ij,r,dr,rk,vfrac_scale;
double *vfrac = atom->vfrac;
double **x0 = atom->x0;
double **r0 = ((FixPeriNeigh *) modify->fix[ifix_peri])->r0;
int **partner = ((FixPeriNeigh *) modify->fix[ifix_peri])->partner;
int *npartner = ((FixPeriNeigh *) modify->fix[ifix_peri])->npartner;
double lc = domain->lattice->xlattice;
double half_lc = 0.5*lc;
delx0 = x0[i][0] - x0[j][0];
dely0 = x0[i][1] - x0[j][1];
delz0 = x0[i][2] - x0[j][2];
int periodic = domain->xperiodic || domain->yperiodic || domain->zperiodic;
if (periodic) domain->minimum_image(delx0,dely0,delz0);
rsq0 = delx0*delx0 + dely0*dely0 + delz0*delz0;
d_ij = MIN(0.9*sqrt(rsq0),1.35*lc);
r = sqrt(rsq);
double energy = 0.0;
fforce = 0.0;
if (r < d_ij) {
dr = r - d_ij;
rk = (15.0 * kspring[itype][jtype] * vfrac[j]) *
(dr / sqrt(cutsq[itype][jtype]));
if (r > 0.0) fforce += -(rk/r);
energy += 0.5*rk*dr;
}
int jnum = npartner[i];
for (int jj = 0; jj < jnum; jj++) {
if (partner[i][jj] == 0) continue;
if (j < 0) continue;
if (j == atom->map(partner[i][jj])) {
dr = r - r0[i][jj];
if (fabs(dr) < 2.2204e-016) dr = 0.0;
if ( (fabs(r0[i][jj] - sqrt(cutsq[itype][jtype]))) <= half_lc)
vfrac_scale = (-1.0/(2*half_lc))*(r0[i][jj]) +
(1.0 + ((sqrt(cutsq[itype][jtype]) - half_lc)/(2*half_lc)));
else vfrac_scale = 1.0;
rk = (kspring[itype][jtype] * vfrac[j] * vfrac_scale) *
(dr / r0[i][jj]);
if (r > 0.0) fforce += -(rk/r);
energy += 0.5*rk*dr;
}
}
return energy;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairPeriPMB::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/POEMS/fix_poems.cpp b/src/POEMS/fix_poems.cpp
index 47b82dfa2..4e50abb4f 100644
--- a/src/POEMS/fix_poems.cpp
+++ b/src/POEMS/fix_poems.cpp
@@ -1,1594 +1,1591 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
FixPOEMS is a LAMMPS interface to the POEMS coupled multi-body simulator
POEMS authors: Rudranarayan Mukherjee (mukher@rpi.edu)
Kurt Anderson (anderk5@rpi.edu)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "workspace.h"
#include "fix_poems.h"
#include "atom.h"
#include "domain.h"
#include "update.h"
#include "respa.h"
#include "modify.h"
#include "force.h"
#include "output.h"
#include "group.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXBODY 2 // currently 2 since only linear chains allowed
#define DELTA 128
#define TOLERANCE 1.0e-6
#define EPSILON 1.0e-7
#define MAXJACOBI 50
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ----------------------------------------------------------------------
define rigid bodies and joints, initiate POEMS
------------------------------------------------------------------------- */
FixPOEMS::FixPOEMS(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
int i,j,ibody;
time_integrate = 1;
rigid_flag = 1;
virial_flag = 1;
MPI_Comm_rank(world,&me);
// perform initial allocation of atom-based arrays
// register with atom class
natom2body = NULL;
atom2body = NULL;
displace = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
// initialize each atom to belong to no rigid bodies
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) natom2body[i] = 0;
// create an atom map if one doesn't exist already
// readfile() and jointbuild() use global atom IDs
int mapflag = 0;
if (atom->map_style == 0) {
mapflag = 1;
atom->map_style = 1;
atom->map_init();
atom->map_set();
}
// parse command-line args
// set natom2body, atom2body for all atoms and nbody = # of rigid bodies
// atoms must also be in fix group to be in a body
- if (narg < 4) error->all("Illegal fix poems command");
+ if (narg < 4) error->all(FLERR,"Illegal fix poems command");
// group = arg has list of groups
if (strcmp(arg[3],"group") == 0) {
nbody = narg-4;
- if (nbody <= 0) error->all("Illegal fix poems command");
+ if (nbody <= 0) error->all(FLERR,"Illegal fix poems command");
int *igroups = new int[nbody];
for (ibody = 0; ibody < nbody; ibody++) {
igroups[ibody] = group->find(arg[ibody+4]);
if (igroups[ibody] == -1)
- error->all("Could not find fix poems group ID");
+ error->all(FLERR,"Could not find fix poems group ID");
}
int *mask = atom->mask;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
for (ibody = 0; ibody < nbody; ibody++)
if (mask[i] & group->bitmask[igroups[ibody]]) {
if (natom2body[i] < MAXBODY) atom2body[i][natom2body[i]] = ibody;
natom2body[i]++;
}
}
delete [] igroups;
// file = read bodies from file
// file read doesn't pay attention to fix group,
// so after read, reset natom2body = 0 if atom is not in fix group
} else if (strcmp(arg[3],"file") == 0) {
readfile(arg[4]);
int *mask = atom->mask;
for (int i = 0; i < nlocal; i++)
if (!(mask[i] & groupbit)) natom2body[i] = 0;
// each molecule in fix group is a rigid body
// maxmol = largest molecule #
// ncount = # of atoms in each molecule (have to sum across procs)
// nbody = # of non-zero ncount values
// use nall as incremented ptr to set atom2body[] values for each atom
} else if (strcmp(arg[3],"molecule") == 0) {
- if (narg != 4) error->all("Illegal fix poems command");
+ if (narg != 4) error->all(FLERR,"Illegal fix poems command");
if (atom->molecular == 0)
- error->all("Must use a molecular atom style with fix poems molecule");
+ error->all(FLERR,"Must use a molecular atom style with fix poems molecule");
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int maxmol = -1;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) maxmol = MAX(maxmol,molecule[i]);
int itmp;
MPI_Allreduce(&maxmol,&itmp,1,MPI_INT,MPI_MAX,world);
maxmol = itmp + 1;
int *ncount = new int[maxmol];
for (i = 0; i < maxmol; i++) ncount[i] = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) ncount[molecule[i]]++;
int *nall = new int[maxmol];
MPI_Allreduce(ncount,nall,maxmol,MPI_INT,MPI_SUM,world);
nbody = 0;
for (i = 0; i < maxmol; i++)
if (nall[i]) nall[i] = nbody++;
else nall[i] = -1;
for (i = 0; i < nlocal; i++) {
natom2body[i] = 0;
if (mask[i] & groupbit) {
natom2body[i] = 1;
atom2body[i][0] = nall[molecule[i]];
}
}
delete [] ncount;
delete [] nall;
- } else error->all("Illegal fix poems command");
+ } else error->all(FLERR,"Illegal fix poems command");
// error if no bodies
// error if any atom in too many bodies
- if (nbody == 0) error->all("No rigid bodies defined");
+ if (nbody == 0) error->all(FLERR,"No rigid bodies defined");
int flag = 0;
for (int i = 0; i < nlocal; i++)
if (natom2body[i] > MAXBODY) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
- if (flagall) error->all("Atom in too many rigid bodies - boost MAXBODY");
+ if (flagall) error->all(FLERR,"Atom in too many rigid bodies - boost MAXBODY");
// create all nbody-length arrays
nrigid = new int[nbody];
masstotal = new double[nbody];
memory->create(xcm,nbody,3,"poems:xcm");
memory->create(vcm,nbody,3,"poems:vcm");
memory->create(fcm,nbody,3,"poems:fcm");
memory->create(inertia,nbody,3,"poems:inertia");
memory->create(ex_space,nbody,3,"poems:ex_space");
memory->create(ey_space,nbody,3,"poems:ey_space");
memory->create(ez_space,nbody,3,"poems:ez_space");
memory->create(angmom,nbody,3,"poems:angmom");
memory->create(omega,nbody,3,"poems:omega");
memory->create(torque,nbody,3,"poems:torque");
memory->create(sum,nbody,6,"poems:sum");
memory->create(all,nbody,6,"poems:all");
// nrigid[n] = # of atoms in Nth rigid body
// double count joint atoms as being in multiple bodies
// error if one or zero atoms
int *ncount = new int[nbody];
for (ibody = 0; ibody < nbody; ibody++) ncount[ibody] = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < natom2body[i]; j++)
ncount[atom2body[i][j]]++;
MPI_Allreduce(ncount,nrigid,nbody,MPI_INT,MPI_SUM,world);
delete [] ncount;
for (ibody = 0; ibody < nbody; ibody++)
- if (nrigid[ibody] <= 1) error->all("One or zero atoms in rigid body");
+ if (nrigid[ibody] <= 1) error->all(FLERR,"One or zero atoms in rigid body");
// build list of joint connections and check for cycles and trees
jointbuild();
// delete temporary atom map
if (mapflag) {
atom->map_delete();
atom->map_style = 0;
}
// create POEMS instance
poems = new Workspace;
// print statistics
int nsum = 0;
for (ibody = 0; ibody < nbody; ibody++) nsum += nrigid[ibody];
nsum -= njoint;
if (me == 0) {
if (screen)
fprintf(screen,"%d clusters, %d bodies, %d joints, %d atoms\n",
ncluster,nbody,njoint,nsum);
if (logfile)
fprintf(logfile,"%d clusters, %d bodies, %d joints, %d atoms\n",
ncluster,nbody,njoint,nsum);
}
}
/* ----------------------------------------------------------------------
free all memory for rigid bodies, joints, and POEMS
------------------------------------------------------------------------- */
FixPOEMS::~FixPOEMS()
{
// if atom class still exists:
// unregister this fix so atom class doesn't invoke it any more
if (atom) atom->delete_callback(id,0);
// delete locally stored arrays
memory->destroy(natom2body);
memory->destroy(atom2body);
memory->destroy(displace);
// delete nbody-length arrays
delete [] nrigid;
delete [] masstotal;
memory->destroy(xcm);
memory->destroy(vcm);
memory->destroy(fcm);
memory->destroy(inertia);
memory->destroy(ex_space);
memory->destroy(ey_space);
memory->destroy(ez_space);
memory->destroy(angmom);
memory->destroy(omega);
memory->destroy(torque);
memory->destroy(sum);
memory->destroy(all);
// delete joint arrays
memory->destroy(jointbody);
memory->destroy(xjoint);
delete [] freelist;
// delete POEMS object
delete poems;
}
/* ---------------------------------------------------------------------- */
int FixPOEMS::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= PRE_NEIGHBOR;
mask |= POST_FORCE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPOEMS::init()
{
int i,ibody;
// warn if more than one POEMS fix
int count = 0;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"poems") == 0) count++;
- if (count > 1 && comm->me == 0) error->warning("More than one fix poems");
+ if (count > 1 && comm->me == 0) error->warning(FLERR,"More than one fix poems");
// error if npt,nph fix comes before rigid fix
for (i = 0; i < modify->nfix; i++) {
if (strcmp(modify->fix[i]->style,"npt") == 0) break;
if (strcmp(modify->fix[i]->style,"nph") == 0) break;
}
if (i < modify->nfix) {
for (int j = i; j < modify->nfix; j++)
if (strcmp(modify->fix[j]->style,"poems") == 0)
- error->all("POEMS fix must come before NPT/NPH fix");
+ error->all(FLERR,"POEMS fix must come before NPT/NPH fix");
}
// timestep info
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dthalf = 0.5 * update->dt;
// rRESPA info
if (strstr(update->integrate_style,"respa")) {
step_respa = ((Respa *) update->integrate)->step;
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
// compute masstotal & center-of-mass xcm of each rigid body
// only count joint atoms in 1st body
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double **x = atom->x;
double **v = atom->v;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
double massone;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (natom2body[i]) {
ibody = atom2body[i][0];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
massone = mass[type[i]];
sum[ibody][0] += (x[i][0] + xbox*xprd) * massone;
sum[ibody][1] += (x[i][1] + ybox*yprd) * massone;
sum[ibody][2] += (x[i][2] + zbox*zprd) * massone;
sum[ibody][3] += massone;
sum[ibody][4] += massone *
(v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
total_ke = 0.0;
for (ibody = 0; ibody < nbody; ibody++) {
masstotal[ibody] = all[ibody][3];
xcm[ibody][0] = all[ibody][0]/masstotal[ibody];
xcm[ibody][1] = all[ibody][1]/masstotal[ibody];
xcm[ibody][2] = all[ibody][2]/masstotal[ibody];
total_ke += 0.5 * all[ibody][4];
}
// compute 6 moments of inertia of each body
// only count joint atoms in 1st body
// dx,dy,dz = coords relative to center-of-mass
double dx,dy,dz;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (natom2body[i]) {
ibody = atom2body[i][0];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xcm[ibody][0];
dy = x[i][1] + ybox*yprd - xcm[ibody][1];
dz = x[i][2] + zbox*zprd - xcm[ibody][2];
massone = mass[type[i]];
sum[ibody][0] += massone * (dy*dy + dz*dz);
sum[ibody][1] += massone * (dx*dx + dz*dz);
sum[ibody][2] += massone * (dx*dx + dy*dy);
sum[ibody][3] -= massone * dx*dy;
sum[ibody][4] -= massone * dy*dz;
sum[ibody][5] -= massone * dx*dz;
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
// inertia = 3 eigenvalues = principal moments of inertia
// ex_space,ey_space,ez_space = 3 eigenvectors = principal axes of rigid body
double **tensor,**evectors;
memory->create(tensor,3,3,"fix_rigid:tensor");
memory->create(evectors,3,3,"fix_rigid:evectors");
int ierror;
double ez0,ez1,ez2;
for (ibody = 0; ibody < nbody; ibody++) {
tensor[0][0] = all[ibody][0];
tensor[1][1] = all[ibody][1];
tensor[2][2] = all[ibody][2];
tensor[0][1] = tensor[1][0] = all[ibody][3];
tensor[1][2] = tensor[2][1] = all[ibody][4];
tensor[0][2] = tensor[2][0] = all[ibody][5];
ierror = jacobi(tensor,inertia[ibody],evectors);
- if (ierror) error->all("Insufficient Jacobi rotations for POEMS body");
+ if (ierror) error->all(FLERR,"Insufficient Jacobi rotations for POEMS body");
ex_space[ibody][0] = evectors[0][0];
ex_space[ibody][1] = evectors[1][0];
ex_space[ibody][2] = evectors[2][0];
ey_space[ibody][0] = evectors[0][1];
ey_space[ibody][1] = evectors[1][1];
ey_space[ibody][2] = evectors[2][1];
ez_space[ibody][0] = evectors[0][2];
ez_space[ibody][1] = evectors[1][2];
ez_space[ibody][2] = evectors[2][2];
// if any principal moment < scaled EPSILON, error
// this is b/c POEMS cannot yet handle degenerate bodies
double max;
max = MAX(inertia[ibody][0],inertia[ibody][1]);
max = MAX(max,inertia[ibody][2]);
if (inertia[ibody][0] < EPSILON*max ||
inertia[ibody][1] < EPSILON*max ||
inertia[ibody][2] < EPSILON*max)
- error->all("Rigid body has degenerate moment of inertia");
+ error->all(FLERR,"Rigid body has degenerate moment of inertia");
// enforce 3 evectors as a right-handed coordinate system
// flip 3rd evector if needed
ez0 = ex_space[ibody][1]*ey_space[ibody][2] -
ex_space[ibody][2]*ey_space[ibody][1];
ez1 = ex_space[ibody][2]*ey_space[ibody][0] -
ex_space[ibody][0]*ey_space[ibody][2];
ez2 = ex_space[ibody][0]*ey_space[ibody][1] -
ex_space[ibody][1]*ey_space[ibody][0];
if (ez0*ez_space[ibody][0] + ez1*ez_space[ibody][1] +
ez2*ez_space[ibody][2] < 0.0) {
ez_space[ibody][0] = -ez_space[ibody][0];
ez_space[ibody][1] = -ez_space[ibody][1];
ez_space[ibody][2] = -ez_space[ibody][2];
}
}
// free temporary memory
memory->destroy(tensor);
memory->destroy(evectors);
// displace = initial atom coords in basis of principal axes
// only set joint atoms relative to 1st body
// set displace = 0.0 for atoms not in any rigid body
for (i = 0; i < nlocal; i++) {
if (natom2body[i]) {
ibody = atom2body[i][0];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xcm[ibody][0];
dy = x[i][1] + ybox*yprd - xcm[ibody][1];
dz = x[i][2] + zbox*zprd - xcm[ibody][2];
displace[i][0] = dx*ex_space[ibody][0] + dy*ex_space[ibody][1] +
dz*ex_space[ibody][2];
displace[i][1] = dx*ey_space[ibody][0] + dy*ey_space[ibody][1] +
dz*ey_space[ibody][2];
displace[i][2] = dx*ez_space[ibody][0] + dy*ez_space[ibody][1] +
dz*ez_space[ibody][2];
} else displace[i][0] = displace[i][1] = displace[i][2] = 0.0;
}
// test for valid principal moments & axes
// recompute moments of inertia around new axes
// only count joint atoms in 1st body
// 3 diagonal moments should equal principal moments
// 3 off-diagonal moments should be 0.0
// (ddx,ddy,ddz) is projection of atom within rigid body onto principal axes
// 6 moments use (ddx,ddy,ddz) displacements from principal axes
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
double ddx,ddy,ddz;
for (i = 0; i < nlocal; i++) {
if (natom2body[i]) {
ibody = atom2body[i][0];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xcm[ibody][0];
dy = x[i][1] + ybox*yprd - xcm[ibody][1];
dz = x[i][2] + zbox*zprd - xcm[ibody][2];
massone = mass[type[i]];
ddx = dx*ex_space[ibody][0] + dy*ex_space[ibody][1] +
dz*ex_space[ibody][2];
ddy = dx*ey_space[ibody][0] + dy*ey_space[ibody][1] +
dz*ey_space[ibody][2];
ddz = dx*ez_space[ibody][0] + dy*ez_space[ibody][1] +
dz*ez_space[ibody][2];
sum[ibody][0] += massone * (ddy*ddy + ddz*ddz);
sum[ibody][1] += massone * (ddx*ddx + ddz*ddz);
sum[ibody][2] += massone * (ddx*ddx + ddy*ddy);
sum[ibody][3] -= massone * ddx*ddy;
sum[ibody][4] -= massone * ddy*ddz;
sum[ibody][5] -= massone * ddx*ddz;
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
for (ibody = 0; ibody < nbody; ibody++) {
if (fabs(all[ibody][0]-inertia[ibody][0]) > TOLERANCE ||
fabs(all[ibody][1]-inertia[ibody][1]) > TOLERANCE ||
fabs(all[ibody][2]-inertia[ibody][2]) > TOLERANCE)
- error->all("Bad principal moments");
+ error->all(FLERR,"Bad principal moments");
if (fabs(all[ibody][3]) > TOLERANCE ||
fabs(all[ibody][4]) > TOLERANCE ||
fabs(all[ibody][5]) > TOLERANCE)
- error->all("Bad principal moments");
+ error->all(FLERR,"Bad principal moments");
}
}
/* ----------------------------------------------------------------------
compute initial rigid body info
make setup call to POEMS
------------------------------------------------------------------------- */
void FixPOEMS::setup(int vflag)
{
int i,n,ibody;
// vcm = velocity of center-of-mass of each rigid body
// angmom = angular momentum of each rigid body
// only count joint atoms in 1st body
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double **x = atom->x;
double **v = atom->v;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
double massone,dx,dy,dz;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (natom2body[i]) {
ibody = atom2body[i][0];
massone = mass[type[i]];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xcm[ibody][0];
dy = x[i][1] + ybox*yprd - xcm[ibody][1];
dz = x[i][2] + zbox*zprd - xcm[ibody][2];
sum[ibody][0] += v[i][0] * massone;
sum[ibody][1] += v[i][1] * massone;
sum[ibody][2] += v[i][2] * massone;
sum[ibody][3] += dy * massone*v[i][2] - dz * massone*v[i][1];
sum[ibody][4] += dz * massone*v[i][0] - dx * massone*v[i][2];
sum[ibody][5] += dx * massone*v[i][1] - dy * massone*v[i][0];
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
for (ibody = 0; ibody < nbody; ibody++) {
vcm[ibody][0] = all[ibody][0]/masstotal[ibody];
vcm[ibody][1] = all[ibody][1]/masstotal[ibody];
vcm[ibody][2] = all[ibody][2]/masstotal[ibody];
angmom[ibody][0] = all[ibody][3];
angmom[ibody][1] = all[ibody][4];
angmom[ibody][2] = all[ibody][5];
}
// virial setup before call to set_v
if (vflag) v_setup(vflag);
else evflag = 0;
// set velocities from angmom & omega
for (ibody = 0; ibody < nbody; ibody++)
omega_from_mq(angmom[ibody],ex_space[ibody],ey_space[ibody],
ez_space[ibody],inertia[ibody],omega[ibody]);
set_v();
// guestimate virial as 2x the set_v contribution
if (vflag_global)
for (n = 0; n < 6; n++) virial[n] *= 2.0;
if (vflag_atom) {
for (i = 0; i < nlocal; i++)
for (n = 0; n < 6; n++)
vatom[i][n] *= 2.0;
}
// use post_force() to compute initial fcm & torque
post_force(vflag);
// setup for POEMS
poems->MakeSystem(nbody,masstotal,inertia,xcm,vcm,omega,
ex_space,ey_space,ez_space,
njoint,jointbody,xjoint,nfree,freelist,
dthalf,dtv,force->ftm2v,total_ke);
}
/* ----------------------------------------------------------------------
update vcm,omega by 1/2 step and xcm,orientation by full step
set x,v of body atoms accordingly
/* ---------------------------------------------------------------------- */
void FixPOEMS::initial_integrate(int vflag)
{
// perform POEMS integration
poems->LobattoOne(xcm,vcm,omega,torque,fcm,ex_space,ey_space,ez_space);
// virial setup before call to set_xv
if (vflag) v_setup(vflag);
else evflag = 0;
// set coords and velocities of atoms in rigid bodies
set_xv();
}
/* ----------------------------------------------------------------------
compute fcm,torque on each rigid body
only count joint atoms in 1st body
------------------------------------------------------------------------- */
void FixPOEMS::post_force(int vflag)
{
int i,ibody;
int xbox,ybox,zbox;
double dx,dy,dz;
int *image = atom->image;
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (natom2body[i]) {
ibody = atom2body[i][0];
sum[ibody][0] += f[i][0];
sum[ibody][1] += f[i][1];
sum[ibody][2] += f[i][2];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xcm[ibody][0];
dy = x[i][1] + ybox*yprd - xcm[ibody][1];
dz = x[i][2] + zbox*zprd - xcm[ibody][2];
sum[ibody][3] += dy*f[i][2] - dz*f[i][1];
sum[ibody][4] += dz*f[i][0] - dx*f[i][2];
sum[ibody][5] += dx*f[i][1] - dy*f[i][0];
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
for (ibody = 0; ibody < nbody; ibody++) {
fcm[ibody][0] = all[ibody][0];
fcm[ibody][1] = all[ibody][1];
fcm[ibody][2] = all[ibody][2];
torque[ibody][0] = all[ibody][3];
torque[ibody][1] = all[ibody][4];
torque[ibody][2] = all[ibody][5];
}
}
/* ----------------------------------------------------------------------
update vcm,omega by last 1/2 step
set v of body atoms accordingly
------------------------------------------------------------------------- */
void FixPOEMS::final_integrate()
{
// perform POEMS integration
poems->LobattoTwo(vcm,omega,torque,fcm);
// set velocities of atoms in rigid bodies
// virial is already setup from initial_integrate
set_v();
}
/* ---------------------------------------------------------------------- */
void FixPOEMS::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
dthalf = 0.5 * step_respa[ilevel];
if (ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixPOEMS::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixPOEMS::final_integrate_respa(int ilevel, int iloop)
{
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ----------------------------------------------------------------------
remap xcm of each rigid body back into periodic simulation box
done during pre_neighbor so will be after call to pbc()
and after fix_deform::pre_exchange() may have flipped box
if don't do this, then atoms of a body which drifts far away
from a triclinic box will be remapped back into box
with huge displacements when the box tilt changes via set_x()
NOTE: cannot do this by changing xcm of each body in cluster
or even 1st body in cluster
b/c POEMS library does not see xcm but only sets xcm
so remap needs to be coordinated with POEMS library
thus this routine does nothing for now
------------------------------------------------------------------------- */
void FixPOEMS::pre_neighbor() {}
/* ----------------------------------------------------------------------
count # of degrees-of-freedom removed by fix_poems for atoms in igroup
------------------------------------------------------------------------- */
int FixPOEMS::dof(int igroup)
{
int groupbit = group->bitmask[igroup];
// ncount = # of atoms in each rigid body that are also in group
// only count joint atoms as part of first body
int *mask = atom->mask;
int nlocal = atom->nlocal;
int *ncount = new int[nbody];
for (int ibody = 0; ibody < nbody; ibody++) ncount[ibody] = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (natom2body[i]) ncount[atom2body[i][0]]++;
int *nall = new int[nbody];
MPI_Allreduce(ncount,nall,nbody,MPI_INT,MPI_SUM,world);
// remove 3N - 6 dof for each rigid body if at least 2 atoms are in igroup
int n = 0;
for (int ibody = 0; ibody < nbody; ibody++)
if (nall[ibody] > 2) n += 3*nall[ibody] - 6;
// subtract 3 additional dof for each joint if atom is also in igroup
int m = 0;
for (int i = 0; i < nlocal; i++)
if (natom2body[i] > 1 && (mask[i] & groupbit)) m += 3*(natom2body[i]-1);
int mall;
MPI_Allreduce(&m,&mall,1,MPI_INT,MPI_SUM,world);
n += mall;
// delete local memory
delete [] ncount;
delete [] nall;
return n;
}
/* ----------------------------------------------------------------------
adjust xcm of each cluster due to box deformation
called by various fixes that change box size/shape
flag = 0/1 means map from box to lamda coords or vice versa
NOTE: cannot do this by changing xcm of each body in cluster
or even 1st body in cluster
b/c POEMS library does not see xcm but only sets xcm
so deform needs to be coordinated with POEMS library
thus this routine does nothing for now
------------------------------------------------------------------------- */
void FixPOEMS::deform(int flag) {}
/* ---------------------------------------------------------------------- */
void FixPOEMS::readfile(char *file)
{
FILE *fp;
if (me == 0) {
fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix poems file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
nbody = 0;
char *line = NULL;
int maxline = 0;
char *ptr;
int nlocal = atom->nlocal;
int i,id,nlen;
while (1) {
if (me == 0) nlen = readline(fp,&line,&maxline);
MPI_Bcast(&nlen,1,MPI_INT,0,world);
if (nlen == 0) break;
MPI_Bcast(line,nlen,MPI_CHAR,0,world);
ptr = strtok(line," ,\t\n\0");
if (ptr == NULL || ptr[0] == '#') continue;
ptr = strtok(NULL," ,\t\n\0");
while (ptr = strtok(NULL," ,\t\n\0")) {
id = atoi(ptr);
i = atom->map(id);
if (i < 0 || i >= nlocal) continue;
if (natom2body[i] < MAXBODY) atom2body[i][natom2body[i]] = nbody;
natom2body[i]++;
}
nbody++;
}
memory->destroy(line);
fclose(fp);
}
/* ---------------------------------------------------------------------- */
int FixPOEMS::readline(FILE *fp, char **pline, int *pmaxline)
{
int n = 0;
char *line = *pline;
int maxline = *pmaxline;
while (1) {
if (n+1 >= maxline) {
maxline += DELTA;
memory->grow(line,maxline,"fix_poems:line");
}
if (fgets(&line[n],maxline-n,fp) == NULL) {
n = 0;
break;
}
n = strlen(line);
if (n < maxline-1 || line[n-1] == '\n') break;
}
*pmaxline = maxline;
*pline = line;
return n;
}
/* ----------------------------------------------------------------------
build list of joints and error check for cycles and trees
------------------------------------------------------------------------- */
void FixPOEMS::jointbuild()
{
int i,j;
// convert atom2body into list of joint atoms on this proc
// mjoint = # of joint atoms in this proc
// an atom in N rigid bodies, infers N-1 joints between 1st body and others
// mylist = [0],[1] = 2 body indices, [2] = global ID of joint atom
int *tag = atom->tag;
int nlocal = atom->nlocal;
int mjoint = 0;
for (i = 0; i < nlocal; i++) {
if (natom2body[i] <= 1) continue;
mjoint += natom2body[i]-1;
}
int **mylist = NULL;
if (mjoint) memory->create(mylist,mjoint,3,"poems:mylist");
mjoint = 0;
for (i = 0; i < nlocal; i++) {
if (natom2body[i] <= 1) continue;
for (j = 1; j < natom2body[i]; j++) {
mylist[mjoint][0] = atom2body[i][0];
mylist[mjoint][1] = atom2body[i][j];
mylist[mjoint][2] = tag[i];
mjoint++;
}
}
// jlist = mylist concatenated across all procs via MPI_Allgatherv
MPI_Allreduce(&mjoint,&njoint,1,MPI_INT,MPI_SUM,world);
int **jlist = NULL;
if (njoint) memory->create(jlist,njoint,3,"poems:jlist");
int nprocs;
MPI_Comm_size(world,&nprocs);
int *recvcounts = new int[nprocs];
int tmp = 3*mjoint;
MPI_Allgather(&tmp,1,MPI_INT,recvcounts,1,MPI_INT,world);
int *displs = new int[nprocs];
displs[0] = 0;
for (i = 1; i < nprocs; i++) displs[i] = displs[i-1] + recvcounts[i-1];
// allgather the local joint lists
// 2 versions in case mjoint is 0 on this proc
if (njoint) {
if (mjoint)
MPI_Allgatherv(mylist[0],3*mjoint,MPI_INT,jlist[0],
recvcounts,displs,MPI_INT,world);
else
MPI_Allgatherv(NULL,3*mjoint,MPI_INT,jlist[0],
recvcounts,displs,MPI_INT,world);
}
delete [] recvcounts;
delete [] displs;
// warning if no joints
if (njoint == 0 && me == 0)
- error->warning("No joints between rigid bodies, use fix rigid instead");
+ error->warning(FLERR,"No joints between rigid bodies, use fix rigid instead");
// sort joint list in ascending order by body indices
// check for loops in joint connections between rigid bodies
// check for trees = same body in more than 2 joints
sortlist(njoint,jlist);
if (loopcheck(nbody,njoint,jlist))
- error->all("Cyclic loop in joint connections");
+ error->all(FLERR,"Cyclic loop in joint connections");
int *bodyflag = new int[nbody];
for (i = 0; i < nbody; i++) bodyflag[i] = 0;
for (i = 0; i < njoint; i++) {
bodyflag[jlist[i][0]]++;
bodyflag[jlist[i][1]]++;
}
for (i = 0; i < nbody; i++)
- if (bodyflag[i] > 2) error->all("Tree structure in joint connections");
+ if (bodyflag[i] > 2) error->all(FLERR,"Tree structure in joint connections");
delete [] bodyflag;
// allocate and setup joint arrays
// jointbody stores body indices from 1 to Nbody to pass to POEMS
// each proc sets myjoint if it owns joint atom
// MPI_Allreduce gives all procs the xjoint coords
jointbody = NULL;
xjoint = NULL;
double **myjoint = NULL;
if (njoint) {
memory->create(jointbody,njoint,2,"poems:jointbody");
memory->create(xjoint,njoint,3,"poems:xjoint");
memory->create(myjoint,njoint,3,"poems:myjoint");
}
double **x = atom->x;
for (i = 0; i < njoint; i++) {
jointbody[i][0] = jlist[i][0] + 1;
jointbody[i][1] = jlist[i][1] + 1;
j = atom->map(jlist[i][2]);
if (j >= 0 && j < nlocal) {
myjoint[i][0] = x[j][0];
myjoint[i][1] = x[j][1];
myjoint[i][2] = x[j][2];
} else myjoint[i][0] = myjoint[i][1] = myjoint[i][2] = 0.0;
}
if (njoint)
MPI_Allreduce(myjoint[0],xjoint[0],3*njoint,MPI_DOUBLE,MPI_SUM,world);
// compute freelist of nfree single unconnected bodies
// POEMS could do this itself
int *mark = new int[nbody];
for (i = 0; i < nbody; i++) mark[i] = 1;
for (i = 0; i < njoint; i++) {
mark[jointbody[i][0]-1] = 0;
mark[jointbody[i][1]-1] = 0;
}
nfree = 0;
for (i = 0; i < nbody; i++)
if (mark[i]) nfree++;
if (nfree) freelist = new int[nfree];
else freelist = NULL;
nfree = 0;
for (i = 0; i < nbody; i++)
if (mark[i]) freelist[nfree++] = i + 1;
delete [] mark;
// free memory local to this routine
memory->destroy(mylist);
memory->destroy(jlist);
memory->destroy(myjoint);
}
/* ----------------------------------------------------------------------
sort joint list (Numerical Recipes shell sort)
sort criterion: sort on 1st body, if equal sort on 2nd body
------------------------------------------------------------------------- */
void FixPOEMS::sortlist(int n, int **list)
{
int i,j,v0,v1,v2,flag;
int inc = 1;
while (inc <= n) inc = 3*inc + 1;
do {
inc /= 3;
for (i = inc+1; i <= n; i++) {
v0 = list[i-1][0];
v1 = list[i-1][1];
v2 = list[i-1][2];
j = i;
flag = 0;
if (list[j-inc-1][0] > v0 ||
(list[j-inc-1][0] == v0 && list[j-inc-1][1] > v1)) flag = 1;
while (flag) {
list[j-1][0] = list[j-inc-1][0];
list[j-1][1] = list[j-inc-1][1];
list[j-1][2] = list[j-inc-1][2];
j -= inc;
if (j <= inc) break;
flag = 0;
if (list[j-inc-1][0] > v0 ||
(list[j-inc-1][0] == v0 && list[j-inc-1][1] > v1)) flag = 1;
}
list[j-1][0] = v0;
list[j-1][1] = v1;
list[j-1][2] = v2;
}
} while (inc > 1);
}
/* ----------------------------------------------------------------------
check for cycles in list of joint connections between rigid bodies
treat as graph: vertex = body, edge = joint between 2 bodies
------------------------------------------------------------------------- */
int FixPOEMS::loopcheck(int nvert, int nedge, int **elist)
{
int i,j,k;
// ecount[i] = # of vertices connected to vertex i via edge
// elistfull[i][*] = list of vertices connected to vertex i
int *ecount = new int[nvert];
for (i = 0; i < nvert; i++) ecount[i] = 0;
for (i = 0; i < nedge; i++) {
ecount[elist[i][0]]++;
ecount[elist[i][1]]++;
}
int emax = 0;
for (i = 0; i < nvert; i++) emax = MAX(emax,ecount[i]);
int **elistfull;
memory->create(elistfull,nvert,emax,"poems:elistfull");
for (i = 0; i < nvert; i++) ecount[i] = 0;
for (i = 0; i < nedge; i++) {
elistfull[elist[i][0]][ecount[elist[i][0]]++] = elist[i][1];
elistfull[elist[i][1]][ecount[elist[i][1]]++] = elist[i][0];
}
// cycle detection algorithm
// mark = 0/1 marking of each vertex, all initially unmarked
// outer while loop:
// if all vertices are marked, no cycles, exit loop
// push an unmarked vertex on stack and mark it, parent is -1
// while stack is not empty:
// pop vertex I from stack
// loop over vertices J connected to I via edge
// if J is parent (vertex that pushed I on stack), skip it
// else if J is marked, a cycle is found, return 1
// else push J on stack and mark it, parent is I
// increment ncluster each time stack empties since that is new cluster
int *parent = new int[nvert];
int *mark = new int[nvert];
for (i = 0; i < nvert; i++) mark[i] = 0;
int nstack = 0;
int *stack = new int[nvert];
ncluster = 0;
while (1) {
for (i = 0; i < nvert; i++)
if (mark[i] == 0) break;
if (i == nvert) break;
stack[nstack++] = i;
mark[i] = 1;
parent[i] = -1;
while (nstack) {
i = stack[--nstack];
for (k = 0; k < ecount[i]; k++) {
j = elistfull[i][k];
if (j == parent[i]) continue;
if (mark[j]) return 1;
stack[nstack++] = j;
mark[j] = 1;
parent[j] = i;
}
}
ncluster++;
}
// free memory local to this routine
delete [] ecount;
memory->destroy(elistfull);
delete [] parent;
delete [] mark;
delete [] stack;
return 0;
}
/* ----------------------------------------------------------------------
compute evalues and evectors of 3x3 real symmetric matrix
based on Jacobi rotations
adapted from Numerical Recipes jacobi() function
------------------------------------------------------------------------- */
int FixPOEMS::jacobi(double **matrix, double *evalues, double **evectors)
{
int i,j,k;
double tresh,theta,tau,t,sm,s,h,g,c,b[3],z[3];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) evectors[i][j] = 0.0;
evectors[i][i] = 1.0;
}
for (i = 0; i < 3; i++) {
b[i] = evalues[i] = matrix[i][i];
z[i] = 0.0;
}
for (int iter = 1; iter <= MAXJACOBI; iter++) {
sm = 0.0;
for (i = 0; i < 2; i++)
for (j = i+1; j < 3; j++)
sm += fabs(matrix[i][j]);
if (sm == 0.0) return 0;
if (iter < 4) tresh = 0.2*sm/(3*3);
else tresh = 0.0;
for (i = 0; i < 2; i++) {
for (j = i+1; j < 3; j++) {
g = 100.0*fabs(matrix[i][j]);
if (iter > 4 && fabs(evalues[i])+g == fabs(evalues[i])
&& fabs(evalues[j])+g == fabs(evalues[j]))
matrix[i][j] = 0.0;
else if (fabs(matrix[i][j]) > tresh) {
h = evalues[j]-evalues[i];
if (fabs(h)+g == fabs(h)) t = (matrix[i][j])/h;
else {
theta = 0.5*h/(matrix[i][j]);
t = 1.0/(fabs(theta)+sqrt(1.0+theta*theta));
if (theta < 0.0) t = -t;
}
c = 1.0/sqrt(1.0+t*t);
s = t*c;
tau = s/(1.0+c);
h = t*matrix[i][j];
z[i] -= h;
z[j] += h;
evalues[i] -= h;
evalues[j] += h;
matrix[i][j] = 0.0;
for (k = 0; k < i; k++) rotate(matrix,k,i,k,j,s,tau);
for (k = i+1; k < j; k++) rotate(matrix,i,k,k,j,s,tau);
for (k = j+1; k < 3; k++) rotate(matrix,i,k,j,k,s,tau);
for (k = 0; k < 3; k++) rotate(evectors,k,i,k,j,s,tau);
}
}
}
for (i = 0; i < 3; i++) {
evalues[i] = b[i] += z[i];
z[i] = 0.0;
}
}
return 1;
}
/* ----------------------------------------------------------------------
perform a single Jacobi rotation
------------------------------------------------------------------------- */
void FixPOEMS::rotate(double **matrix, int i, int j, int k, int l,
double s, double tau)
{
double g = matrix[i][j];
double h = matrix[k][l];
matrix[i][j] = g-s*(h+g*tau);
matrix[k][l] = h+s*(g-h*tau);
}
/* ----------------------------------------------------------------------
compute omega from angular momentum
w = omega = angular velocity in space frame
wbody = angular velocity in body frame
set wbody component to 0.0 if inertia component is 0.0
otherwise body can spin easily around that axis
project space-frame angular momentum onto body axes
and divide by principal moments
------------------------------------------------------------------------- */
void FixPOEMS::omega_from_mq(double *m, double *ex, double *ey, double *ez,
double *inertia, double *w)
{
double wbody[3];
if (inertia[0] == 0.0) wbody[0] = 0.0;
else wbody[0] = (m[0]*ex[0] + m[1]*ex[1] + m[2]*ex[2]) / inertia[0];
if (inertia[1] == 0.0) wbody[1] = 0.0;
else wbody[1] = (m[0]*ey[0] + m[1]*ey[1] + m[2]*ey[2]) / inertia[1];
if (inertia[2] == 0.0) wbody[2] = 0.0;
else wbody[2] = (m[0]*ez[0] + m[1]*ez[1] + m[2]*ez[2]) / inertia[2];
w[0] = wbody[0]*ex[0] + wbody[1]*ey[0] + wbody[2]*ez[0];
w[1] = wbody[0]*ex[1] + wbody[1]*ey[1] + wbody[2]*ez[1];
w[2] = wbody[0]*ex[2] + wbody[1]*ey[2] + wbody[2]*ez[2];
}
/* ----------------------------------------------------------------------
set space-frame coords and velocity of each atom in each rigid body
x = Q displace + Xcm, mapped back to periodic box
v = Vcm + (W cross (x - Xcm))
------------------------------------------------------------------------- */
void FixPOEMS::set_xv()
{
int ibody;
int xbox,ybox,zbox;
double x0,x1,x2,v0,v1,v2,fc0,fc1,fc2,massone;
double vr[6];
int *image = atom->image;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double *mass = atom->mass;
int *type = atom->type;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
// set x and v of each atom
// only set joint atoms for 1st rigid body they belong to
for (int i = 0; i < nlocal; i++) {
if (natom2body[i] == 0) continue;
ibody = atom2body[i][0];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
// save old positions and velocities for virial
if (evflag) {
x0 = x[i][0] + xbox*xprd;
x1 = x[i][1] + ybox*yprd;
x2 = x[i][2] + zbox*zprd;
v0 = v[i][0];
v1 = v[i][1];
v2 = v[i][2];
}
// x = displacement from center-of-mass, based on body orientation
// v = vcm + omega around center-of-mass
x[i][0] = ex_space[ibody][0]*displace[i][0] +
ey_space[ibody][0]*displace[i][1] +
ez_space[ibody][0]*displace[i][2];
x[i][1] = ex_space[ibody][1]*displace[i][0] +
ey_space[ibody][1]*displace[i][1] +
ez_space[ibody][1]*displace[i][2];
x[i][2] = ex_space[ibody][2]*displace[i][0] +
ey_space[ibody][2]*displace[i][1] +
ez_space[ibody][2]*displace[i][2];
v[i][0] = omega[ibody][1]*x[i][2] - omega[ibody][2]*x[i][1] +
vcm[ibody][0];
v[i][1] = omega[ibody][2]*x[i][0] - omega[ibody][0]*x[i][2] +
vcm[ibody][1];
v[i][2] = omega[ibody][0]*x[i][1] - omega[ibody][1]*x[i][0] +
vcm[ibody][2];
// add center of mass to displacement
// map back into periodic box via xbox,ybox,zbox
x[i][0] += xcm[ibody][0] - xbox*xprd;
x[i][1] += xcm[ibody][1] - ybox*yprd;
x[i][2] += xcm[ibody][2] - zbox*zprd;
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c final_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if (evflag) {
massone = mass[type[i]];
fc0 = massone*(v[i][0] - v0)/dtf - f[i][0];
fc1 = massone*(v[i][1] - v1)/dtf - f[i][1];
fc2 = massone*(v[i][2] - v2)/dtf - f[i][2];
vr[0] = 0.5*fc0*x0;
vr[1] = 0.5*fc1*x1;
vr[2] = 0.5*fc2*x2;
vr[3] = 0.5*fc1*x0;
vr[4] = 0.5*fc2*x0;
vr[5] = 0.5*fc2*x1;
v_tally(1,&i,1.0,vr);
}
}
}
/* ----------------------------------------------------------------------
set space-frame velocity of each atom in a rigid body
v = Vcm + (W cross (x - Xcm))
------------------------------------------------------------------------- */
void FixPOEMS::set_v()
{
int ibody;
int xbox,ybox,zbox;
double dx,dy,dz;
double x0,x1,x2,v0,v1,v2,fc0,fc1,fc2,massone;
double vr[6];
double *mass = atom->mass;
double **f = atom->f;
double **x = atom->x;
double **v = atom->v;
int *type = atom->type;
int *image = atom->image;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
// set v of each atom
// only set joint atoms for 1st rigid body they belong to
for (int i = 0; i < nlocal; i++) {
if (natom2body[i] == 0) continue;
ibody = atom2body[i][0];
dx = ex_space[ibody][0]*displace[i][0] +
ey_space[ibody][0]*displace[i][1] +
ez_space[ibody][0]*displace[i][2];
dy = ex_space[ibody][1]*displace[i][0] +
ey_space[ibody][1]*displace[i][1] +
ez_space[ibody][1]*displace[i][2];
dz = ex_space[ibody][2]*displace[i][0] +
ey_space[ibody][2]*displace[i][1] +
ez_space[ibody][2]*displace[i][2];
// save old velocities for virial
if (evflag) {
v0 = v[i][0];
v1 = v[i][1];
v2 = v[i][2];
}
v[i][0] = omega[ibody][1]*dz - omega[ibody][2]*dy + vcm[ibody][0];
v[i][1] = omega[ibody][2]*dx - omega[ibody][0]*dz + vcm[ibody][1];
v[i][2] = omega[ibody][0]*dy - omega[ibody][1]*dx + vcm[ibody][2];
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c initial_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if (evflag) {
massone = mass[type[i]];
fc0 = massone*(v[i][0] - v0)/dtf - f[i][0];
fc1 = massone*(v[i][1] - v1)/dtf - f[i][1];
fc2 = massone*(v[i][2] - v2)/dtf - f[i][2];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
x0 = x[i][0] + xbox*xprd;
x1 = x[i][1] + ybox*yprd;
x2 = x[i][2] + zbox*zprd;
vr[0] = 0.5*fc0*x0;
vr[1] = 0.5*fc1*x1;
vr[2] = 0.5*fc2*x2;
vr[3] = 0.5*fc1*x0;
vr[4] = 0.5*fc2*x0;
vr[5] = 0.5*fc2*x1;
v_tally(1,&i,1.0,vr);
}
}
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixPOEMS::grow_arrays(int nmax)
{
memory->grow(natom2body,nmax,"fix_poems:natom2body");
memory->grow(atom2body,nmax,MAXBODY,"fix_poems:atom2body");
memory->grow(displace,nmax,3,"fix_poems:displace");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixPOEMS::copy_arrays(int i, int j)
{
natom2body[j] = natom2body[i];
for (int k = 0; k < natom2body[j]; k++) atom2body[j][k] = atom2body[i][k];
displace[j][0] = displace[i][0];
displace[j][1] = displace[i][1];
displace[j][2] = displace[i][2];
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixPOEMS::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int);
bytes += nmax*MAXBODY * sizeof(int);
bytes += nmax*3 * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixPOEMS::pack_exchange(int i, double *buf)
{
int m = 0;
buf[m++] = static_cast<double> (natom2body[i]);
for (int j = 0; j < natom2body[i]; j++)
buf[m++] = static_cast<double> (atom2body[i][j]);
buf[m++] = displace[i][0];
buf[m++] = displace[i][1];
buf[m++] = displace[i][2];
return m;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixPOEMS::unpack_exchange(int nlocal, double *buf)
{
int m = 0;
natom2body[nlocal] = static_cast<int> (buf[m++]);
for (int i = 0; i < natom2body[nlocal]; i++)
atom2body[nlocal][i] = static_cast<int> (buf[m++]);
displace[nlocal][0] = buf[m++];
displace[nlocal][1] = buf[m++];
displace[nlocal][2] = buf[m++];
return m;
}
/* ---------------------------------------------------------------------- */
void FixPOEMS::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dthalf = 0.5 * update->dt;
}
diff --git a/src/REAX/fix_reax_bonds.cpp b/src/REAX/fix_reax_bonds.cpp
index 67317bd6d..ddd5b5eaa 100644
--- a/src/REAX/fix_reax_bonds.cpp
+++ b/src/REAX/fix_reax_bonds.cpp
@@ -1,238 +1,238 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (Sandia)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_reax_bonds.h"
#include "pair_reax_fortran.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "modify.h"
#include "compute.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixReaxBonds::FixReaxBonds(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix reax/bonds command");
+ if (narg < 5) error->all(FLERR,"Illegal fix reax/bonds command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
- if (nevery < 1) error->all("Illegal fix reax/bonds command");
+ if (nevery < 1) error->all(FLERR,"Illegal fix reax/bonds command");
if (me == 0) {
fp = fopen(arg[4],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix reax/bonds file %s",arg[4]);
- error->one(str);
+ error->one(FLERR,str);
}
}
}
/* ---------------------------------------------------------------------- */
FixReaxBonds::~FixReaxBonds()
{
if (me == 0) fclose(fp);
}
/* ---------------------------------------------------------------------- */
int FixReaxBonds::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ----------------------------------------------------------------------
perform initial write
------------------------------------------------------------------------- */
void FixReaxBonds::setup(int vflag)
{
end_of_step();
}
/* ---------------------------------------------------------------------- */
void FixReaxBonds::init()
{
// insure ReaxFF is defined
if (force->pair_match("reax",1) == NULL)
- error->all("Cannot use fix reax/bonds without pair_style reax");
+ error->all(FLERR,"Cannot use fix reax/bonds without pair_style reax");
}
/* ---------------------------------------------------------------------- */
void FixReaxBonds::end_of_step()
{
OutputReaxBonds(update->ntimestep,fp);
if (me == 0) fflush(fp);
}
/* ---------------------------------------------------------------------- */
void FixReaxBonds::OutputReaxBonds(bigint ntimestep, FILE *fp)
{
int nparticles,nparticles_tot,nbuf,nbuf_local,most,j;
int ii,jn,mbond,numbonds,nsbmax,nsbmax_most;
int nprocs,nlocal_tmp,itmp;
double cutof3;
double *buf;
MPI_Request irequest;
MPI_Status istatus;
MPI_Comm_size(world,&nprocs);
nparticles = atom->nlocal;
nparticles_tot = static_cast<int> (atom->natoms);
mbond = ReaxParams::mbond;
FORTRAN(getnsbmax,GETNSBMAX)(&nsbmax);
FORTRAN(getcutof3,GETCUTOF3)(&cutof3);
MPI_Allreduce(&nparticles,&most,1,MPI_INT,MPI_MAX,world);
MPI_Allreduce(&nsbmax,&nsbmax_most,1,MPI_INT,MPI_MAX,world);
if (me == 0) {
fprintf(fp,"# Timestep " BIGINT_FORMAT " \n",ntimestep);
fprintf(fp,"# \n");
fprintf(fp,"# Number of particles %d \n",nparticles_tot);
fprintf(fp,"# \n");
fprintf(fp,"# Max number of bonds per atom %d with "
"coarse bond order cutoff %5.3f \n",
nsbmax_most,cutof3);
fprintf(fp,"# Particle connection table and bond orders \n");
fprintf(fp,"# id type nb id_1...id_nb mol bo_1...bo_nb abo nlp q \n");
}
// allocate a temporary buffer for the snapshot info
// big enough for largest number of atoms on any one proc
// nbuf_local = size of local buffer for table of atom bonds
nbuf = 1+(2*nsbmax_most+7)*most;
memory->create(buf,nbuf,"reax/bonds:buf");
j = 2;
jn = ReaxParams::nat;
buf[0] = nparticles;
for (int iparticle=0;iparticle<nparticles;iparticle++) {
buf[j-1] = atom->tag[iparticle]; //atom tag
buf[j+0] = FORTRAN(cbkia,CBKIA).iag[iparticle]; //atom type
buf[j+1] = FORTRAN(cbkia,CBKIA).iag[iparticle+jn]; //no.bonds
int k;
numbonds = nint(buf[j+1]);
// connection table based on coarse bond order cutoff (> cutof3)
for (k=2;k<2+numbonds;k++) {
ii = FORTRAN(cbkia,CBKIA).iag[iparticle+jn*k];
buf[j+k] = FORTRAN(cbkc,CBKC).itag[ii-1];
}
buf[j+k]=FORTRAN(cbkia,CBKIA).iag[iparticle+jn*(mbond+2)]; //molec.id
j+=(3+numbonds);
// bond orders (> cutof3)
for (k=0;k<numbonds;k++) {
ii = FORTRAN(cbknubon2,CBKNUBON2).nubon1[iparticle+jn*k];
buf[j+k] = FORTRAN(cbkbo,CBKBO).bo[ii-1];
}
// sum of bond orders (abo), no. of lone pairs (vlp), charge (ch)
buf[j+k] = FORTRAN(cbkabo,CBKABO).abo[iparticle];
buf[j+k+1] = FORTRAN(cbklonpar,CBKLONPAR).vlp[iparticle];
// buf[j+k+2] = FORTRAN(cbkch,CBKCH).ch[iparticle];
buf[j+k+2] = atom->q[iparticle];
j+=(4+numbonds);
}
nbuf_local = j-1;
// node 0 pings each node, receives their buffer, writes to file
// all other nodes wait for ping, send buffer to node 0
if (me == 0) {
for (int inode = 0; inode<nprocs; inode++) {
if (inode == 0) {
nlocal_tmp = nparticles;
} else {
MPI_Irecv(&buf[0],nbuf,MPI_DOUBLE,inode,0,world,&irequest);
MPI_Send(&itmp,0,MPI_INT,inode,0,world);
MPI_Wait(&irequest,&istatus);
nlocal_tmp = nint(buf[0]);
}
j = 2;
for (int iparticle=0;iparticle<nlocal_tmp;iparticle++) {
// print atom tag, atom type, no.bonds
fprintf(fp," %d %d %d",nint(buf[j-1]),nint(buf[j+0]),nint(buf[j+1]));
int k;
numbonds = nint(buf[j+1]);
if (numbonds > nsbmax_most) {
char str[128];
sprintf(str,"Fix reax/bonds numbonds > nsbmax_most");
- error->one(str);
+ error->one(FLERR,str);
}
// print connection table
for (k=2;k<2+numbonds;k++)
fprintf(fp," %d",nint(buf[j+k]));
fprintf(fp," %d",nint(buf[j+k]));
j+=(3+numbonds);
// print bond orders
for (k=0;k<numbonds;k++)
fprintf(fp,"%14.3f",buf[j+k]);
// print sum of bond orders, no. of lone pairs, charge
fprintf(fp,"%14.3f%14.3f%14.3f\n",buf[j+k],buf[j+k+1],buf[j+k+2]);
j+=(4+numbonds);
}
}
} else {
MPI_Recv(&itmp,0,MPI_INT,0,0,world,&istatus);
MPI_Rsend(&buf[0],nbuf_local,MPI_DOUBLE,0,0,world);
}
if (me == 0) fprintf(fp,"# \n");
memory->destroy(buf);
}
/* ---------------------------------------------------------------------- */
int FixReaxBonds::nint(const double &r)
{
int i = 0;
if (r>0.0) i = static_cast<int>(r+0.5);
else if (r<0.0) i = static_cast<int>(r-0.5);
return i;
}
diff --git a/src/REAX/pair_reax.cpp b/src/REAX/pair_reax.cpp
index 6e9e3020f..f32281f5f 100644
--- a/src/REAX/pair_reax.cpp
+++ b/src/REAX/pair_reax.cpp
@@ -1,1066 +1,1064 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Aidan Thompson (Sandia, athomps@sandia.gov)
Hansohl Cho (MIT, hansohl@mit.edu)
LAMMPS implementation of the Reactive Force Field (ReaxFF) is based on
Aidan Thompson's GRASP code
(General Reactive Atomistic Simulation Program)
and Ardi Van Duin's original ReaxFF code
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_reax.h"
#include "pair_reax_fortran.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define SMALL 0.0001
/* ---------------------------------------------------------------------- */
PairREAX::PairREAX(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
no_virial_fdotr_compute = 1;
nextra = 14;
pvector = new double[nextra];
cutmax = 0.0;
hbcut = 6.0;
ihbnew = 1;
itripstaball = 1;
iprune = 4;
ihb = 1;
chpot = 0;
nmax = 0;
arow_ptr = NULL;
ch = NULL;
elcvec = NULL;
rcg = NULL;
wcg = NULL;
pcg = NULL;
poldcg = NULL;
qcg = NULL;
matmax = 0;
aval = NULL;
acol_ind = NULL;
comm_forward = 1;
comm_reverse = 1;
precision = 1.0e-6;
}
/* ----------------------------------------------------------------------
free all arrays
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairREAX::~PairREAX()
{
delete [] pvector;
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
for (int i = 1; i <= atom->ntypes; i++)
delete [] param_list[i].params;
delete [] param_list;
delete [] map;
}
memory->destroy(arow_ptr);
memory->destroy(ch);
memory->destroy(elcvec);
memory->destroy(rcg);
memory->destroy(wcg);
memory->destroy(pcg);
memory->destroy(poldcg);
memory->destroy(qcg);
memory->destroy(aval);
memory->destroy(acol_ind);
}
/* ---------------------------------------------------------------------- */
void PairREAX::compute(int eflag, int vflag)
{
int i,j;
double evdwl,ecoul;
double energy_charge_equilibration;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = vflag_global =
eflag_atom = vflag_atom = 0;
if (vflag_global) FORTRAN(cbkvirial, CBKVIRIAL).Lvirial = 1;
else FORTRAN(cbkvirial, CBKVIRIAL).Lvirial = 0;
if (vflag_atom) FORTRAN(cbkvirial, CBKVIRIAL).Latomvirial = 1;
else FORTRAN(cbkvirial, CBKVIRIAL).Latomvirial = 0;
// reallocate charge equilibration and CG arrays if necessary
if (atom->nmax > nmax) {
memory->destroy(rcg);
memory->destroy(wcg);
memory->destroy(pcg);
memory->destroy(poldcg);
memory->destroy(qcg);
nmax = atom->nmax;
int n = nmax+1;
memory->create(arow_ptr,n,"reax:arow_ptr");
memory->create(ch,n,"reax:ch");
memory->create(elcvec,n,"reax:elcvec");
memory->create(rcg,n,"reax:rcg");
memory->create(wcg,n,"reax:wcg");
memory->create(pcg,n,"reax:pcg");
memory->create(poldcg,n,"reax:poldcg");
memory->create(qcg,n,"reax:qcg");
}
// calculate the atomic charge distribution
compute_charge(energy_charge_equilibration);
// transfer LAMMPS positions and neighbor lists to REAX
write_reax_positions();
write_reax_vlist();
// determine whether this bond is owned by the processor or not
FORTRAN(srtbon1, SRTBON1)(&iprune, &ihb, &hbcut, &ihbnew, &itripstaball);
// communicate with other processors for the atomic bond order calculations
FORTRAN(cbkabo, CBKABO).abo;
// communicate local atomic bond order to ghost atomic bond order
packflag = 0;
comm->forward_comm_pair(this);
FORTRAN(molec, MOLEC)();
FORTRAN(encalc, ENCALC)();
FORTRAN(mdsav, MDSAV)(&comm->me);
// read forces from ReaxFF Fortran
read_reax_forces();
// extract global and per-atom energy from ReaxFF Fortran
// compute_charge already contributed to eatom
if (eflag_global) {
evdwl += FORTRAN(cbkenergies, CBKENERGIES).eb;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).ea;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).elp;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).emol;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).ev;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).epen;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).ecoa;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).ehb;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).et;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).eco;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).ew;
evdwl += FORTRAN(cbkenergies, CBKENERGIES).efi;
ecoul += FORTRAN(cbkenergies, CBKENERGIES).ep;
ecoul += energy_charge_equilibration;
eng_vdwl += evdwl;
eng_coul += ecoul;
// Store the different parts of the energy
// in a list for output by compute pair command
pvector[0] = FORTRAN(cbkenergies, CBKENERGIES).eb;
pvector[1] = FORTRAN(cbkenergies, CBKENERGIES).ea;
pvector[2] = FORTRAN(cbkenergies, CBKENERGIES).elp;
pvector[3] = FORTRAN(cbkenergies, CBKENERGIES).emol;
pvector[4] = FORTRAN(cbkenergies, CBKENERGIES).ev;
pvector[5] = FORTRAN(cbkenergies, CBKENERGIES).epen;
pvector[6] = FORTRAN(cbkenergies, CBKENERGIES).ecoa;
pvector[7] = FORTRAN(cbkenergies, CBKENERGIES).ehb;
pvector[8] = FORTRAN(cbkenergies, CBKENERGIES).et;
pvector[9] = FORTRAN(cbkenergies, CBKENERGIES).eco;
pvector[10] = FORTRAN(cbkenergies, CBKENERGIES).ew;
pvector[11] = FORTRAN(cbkenergies, CBKENERGIES).ep;
pvector[12] = FORTRAN(cbkenergies, CBKENERGIES).efi;
pvector[13] = energy_charge_equilibration;
}
if (eflag_atom) {
int ntotal = atom->nlocal + atom->nghost;
for (i = 0; i < ntotal; i++)
eatom[i] += FORTRAN(cbkd,CBKD).estrain[i];
}
// extract global and per-atom virial from ReaxFF Fortran
if (vflag_global) {
virial[0] = -FORTRAN(cbkvirial, CBKVIRIAL).virial[0];
virial[1] = -FORTRAN(cbkvirial, CBKVIRIAL).virial[1];
virial[2] = -FORTRAN(cbkvirial, CBKVIRIAL).virial[2];
virial[3] = -FORTRAN(cbkvirial, CBKVIRIAL).virial[3];
virial[4] = -FORTRAN(cbkvirial, CBKVIRIAL).virial[4];
virial[5] = -FORTRAN(cbkvirial, CBKVIRIAL).virial[5];
}
if (vflag_atom) {
int ntotal = atom->nlocal + atom->nghost;
j = 0;
for (i = 0; i < ntotal; i++) {
vatom[i][0] = -FORTRAN(cbkvirial, CBKVIRIAL).atomvirial[j+0];
vatom[i][1] = -FORTRAN(cbkvirial, CBKVIRIAL).atomvirial[j+1];
vatom[i][2] = -FORTRAN(cbkvirial, CBKVIRIAL).atomvirial[j+2];
vatom[i][3] = -FORTRAN(cbkvirial, CBKVIRIAL).atomvirial[j+3];
vatom[i][4] = -FORTRAN(cbkvirial, CBKVIRIAL).atomvirial[j+4];
vatom[i][5] = -FORTRAN(cbkvirial, CBKVIRIAL).atomvirial[j+5];
j += 6;
}
}
}
/* ---------------------------------------------------------------------- */
void PairREAX::write_reax_positions()
{
int j, jx, jy, jz, jia;
double **x = atom->x;
double *q = atom->q;
int *type = atom->type;
int *tag = atom->tag;
int nlocal = atom->nlocal;
int nghost = atom->nghost;
FORTRAN(rsmall, RSMALL).na = nlocal+nghost;
FORTRAN(rsmall, RSMALL).na_local = nlocal;
if (nlocal+nghost > ReaxParams::nat)
- error->one("Reax_defs.h setting for NATDEF is too small");
+ error->one(FLERR,"Reax_defs.h setting for NATDEF is too small");
jx = 0;
jy = ReaxParams::nat;
jz = 2*ReaxParams::nat;
jia = 0;
j = 0;
for (int i = 0; i < nlocal+nghost; i++, j++) {
FORTRAN(cbkc, CBKC).c[j+jx] = x[i][0];
FORTRAN(cbkc, CBKC).c[j+jy] = x[i][1];
FORTRAN(cbkc, CBKC).c[j+jz] = x[i][2];
FORTRAN(cbkch, CBKCH).ch[j] = q[i];
FORTRAN(cbkia, CBKIA).ia[j+jia] = map[type[i]];
FORTRAN(cbkia, CBKIA).iag[j+jia] = map[type[i]];
FORTRAN(cbkc, CBKC).itag[j] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void PairREAX::write_reax_vlist()
{
int ii, jj, i, j, iii, jjj;
double xitmp, yitmp, zitmp;
double xjtmp, yjtmp, zjtmp;
int itag,jtag;
int nvpair, nvlself, nvpairmax;
int nbond;
int inum,jnum;
int *ilist,*jlist,*numneigh,**firstneigh;
double delr2;
double delx, dely, delz;
double **x = atom->x;
int *tag = atom->tag;
int nlocal = atom->nlocal;
int nghost = atom->nghost;
nvpairmax = ReaxParams::nneighmax * ReaxParams::nat;
nvpair = 0;
nvlself =0;
nbond = 0;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xitmp = x[i][0];
yitmp = x[i][1];
zitmp = x[i][2];
itag = tag[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
xjtmp = x[j][0];
yjtmp = x[j][1];
zjtmp = x[j][2];
jtag = tag[j];
delx = xitmp - xjtmp;
dely = yitmp - yjtmp;
delz = zitmp - zjtmp;
delr2 = delx*delx+dely*dely+delz*delz;
if (delr2 <= rcutvsq) {
if (i < j) {
iii = i+1;
jjj = j+1;
} else {
iii = j+1;
jjj = i+1;
}
if (nvpair >= nvpairmax)
- error->one("Reax_defs.h setting for NNEIGHMAXDEF is too small");
+ error->one(FLERR,"Reax_defs.h setting for NNEIGHMAXDEF is too small");
FORTRAN(cbkpairs, CBKPAIRS).nvl1[nvpair] = iii;
FORTRAN(cbkpairs, CBKPAIRS).nvl2[nvpair] = jjj;
FORTRAN(cbknvlbo, CBKNVLBO).nvlbo[nvpair] = 0;
if (delr2 <= rcutbsq) {
FORTRAN(cbknvlbo, CBKNVLBO).nvlbo[nvpair] = 1;
nbond++;
}
FORTRAN(cbknvlown, CBKNVLOWN).nvlown[nvpair] = 0;
if (j < nlocal)
FORTRAN(cbknvlown, CBKNVLOWN).nvlown[nvpair] = 1;
else if (itag < jtag)
FORTRAN(cbknvlown, CBKNVLOWN).nvlown[nvpair] = 1;
else if (itag == jtag) {
if (delz > SMALL)
FORTRAN(cbknvlown, CBKNVLOWN).nvlown[nvpair] = 1;
else if (fabs(delz) < SMALL) {
if (dely > SMALL)
FORTRAN(cbknvlown, CBKNVLOWN).nvlown[nvpair] = 1;
else if (fabs(dely) < SMALL && delx > SMALL)
FORTRAN(cbknvlown, CBKNVLOWN).nvlown[nvpair] = 1;
}
}
nvpair++;
}
}
}
int ntotal = nlocal + nghost;
for (int i = nlocal; i < ntotal; i++) {
xitmp = x[i][0];
yitmp = x[i][1];
zitmp = x[i][2];
itag = tag[i];
for (int j = i+1; j < ntotal; j++) {
xjtmp = x[j][0];
yjtmp = x[j][1];
zjtmp = x[j][2];
jtag = tag[j];
delx = xitmp - xjtmp;
dely = yitmp - yjtmp;
delz = zitmp - zjtmp;
delr2 = delx*delx+dely*dely+delz*delz;
// don't need to check the double count since i < j in the ghost region
if (delr2 <= rcutvsq) {
iii = i+1;
jjj = j+1;
if (nvpair >= nvpairmax)
- error->one("Reax_defs.h setting for NNEIGHMAXDEF is too small");
+ error->one(FLERR,"Reax_defs.h setting for NNEIGHMAXDEF is too small");
FORTRAN(cbkpairs, CBKPAIRS).nvl1[nvpair] = iii;
FORTRAN(cbkpairs, CBKPAIRS).nvl2[nvpair] = jjj;
FORTRAN(cbknvlbo, CBKNVLBO).nvlbo[nvpair] = 0;
if (delr2 <= rcutbsq) {
FORTRAN(cbknvlbo, CBKNVLBO).nvlbo[nvpair] = 1;
nbond++;
}
FORTRAN(cbknvlown, CBKNVLOWN).nvlown[nvpair] = 0;
nvpair++;
}
}
}
FORTRAN(cbkpairs, CBKPAIRS).nvpair = nvpair;
FORTRAN(cbkpairs, CBKPAIRS).nvlself = nvlself;
}
/* ---------------------------------------------------------------------- */
void PairREAX::read_reax_forces()
{
double ftmp[3];
double **f = atom->f;
int ntotal = atom->nlocal + atom->nghost;
int j = 0;
for (int i = 0; i < ntotal; i++) {
ftmp[0] = -FORTRAN(cbkd, CBKD).d[j];
ftmp[1] = -FORTRAN(cbkd, CBKD).d[j+1];
ftmp[2] = -FORTRAN(cbkd, CBKD).d[j+2];
f[i][0] = ftmp[0];
f[i][1] = ftmp[1];
f[i][2] = ftmp[2];
j += 3;
}
}
/* ---------------------------------------------------------------------- */
void PairREAX::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
memory->create(cutsq,n+1,n+1,"pair:cutsq");
param_list = new ff_params[n+1];
for (int i = 1; i <= n; i++)
param_list[i].params = new double[5];
map = new int[n+1];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairREAX::settings(int narg, char **arg)
{
- if (narg != 0 && narg !=4) error->all("Illegal pair_style command");
+ if (narg != 0 && narg !=4) error->all(FLERR,"Illegal pair_style command");
if (narg == 4) {
hbcut = force->numeric(arg[0]);
ihbnew = static_cast<int> (force->numeric(arg[1]));
itripstaball = static_cast<int> (force->numeric(arg[2]));
precision = force->numeric(arg[3]);
if (hbcut <= 0.0 ||
(ihbnew != 0 && ihbnew != 1) ||
(itripstaball != 0 && itripstaball != 1) ||
precision <= 0.0)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairREAX::coeff(int narg, char **arg)
{
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure filename is ffield.reax
if (strcmp(arg[2],"ffield.reax") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read args that map atom types to elements in potential file
// map[i] = which element the Ith atom type is, -1 if NULL
// NOTE: for now throw an error if NULL is used to disallow use with hybrid
// qEq atrix solver needs to be modified to exclude atoms
for (int i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
- error->all("Cannot currently use pair reax with pair hybrid");
+ error->all(FLERR,"Cannot currently use pair reax with pair hybrid");
continue;
}
map[i-2] = force->inumeric(arg[i]);
}
int n = atom->ntypes;
int count = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++) {
setflag[i][j] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairREAX::init_style()
{
if (atom->tag_enable == 0)
- error->all("Pair style reax requires atom IDs");
+ error->all(FLERR,"Pair style reax requires atom IDs");
if (force->newton_pair == 0)
- error->all("Pair style reax requires newton pair on");
+ error->all(FLERR,"Pair style reax requires newton pair on");
if (strcmp(update->unit_style,"real") != 0 && comm->me == 0)
- error->warning("Not using real units with pair reax");
+ error->warning(FLERR,"Not using real units with pair reax");
int irequest = neighbor->request(this);
neighbor->requests[irequest]->newton = 2;
FORTRAN(readc, READC)();
FORTRAN(reaxinit, REAXINIT)();
FORTRAN(ffinpt, FFINPT)();
FORTRAN(tap7th, TAP7TH)();
// turn off read_in by fort.3 in REAX Fortran
int ngeofor_tmp = -1;
FORTRAN(setngeofor, SETNGEOFOR)(&ngeofor_tmp);
if (comm->me == 0) FORTRAN(readgeo, READGEO)();
// initial setup for cutoff radius of VLIST and BLIST in ReaxFF
double vlbora;
FORTRAN(getswb, GETSWB)(&swb);
cutmax=MAX(swb, hbcut);
rcutvsq=cutmax*cutmax;
FORTRAN(getvlbora, GETVLBORA)(&vlbora);
rcutbsq=vlbora*vlbora;
// parameters for charge equilibration from ReaxFF input, fort.4
// verify that no LAMMPS type to REAX type mapping was invalid
int nelements;
FORTRAN(getnso, GETNSO)(&nelements);
FORTRAN(getswa, GETSWA)(&swa);
double chi, eta, gamma;
for (int itype = 1; itype <= atom->ntypes; itype++) {
if (map[itype] < 1 || map[itype] > nelements)
- error->all("Invalid REAX atom type");
+ error->all(FLERR,"Invalid REAX atom type");
chi = FORTRAN(cbkchb, CBKCHB).chi[map[itype]-1];
eta = FORTRAN(cbkchb, CBKCHB).eta[map[itype]-1];
gamma = FORTRAN(cbkchb, CBKCHB).gam[map[itype]-1];
param_list[itype].np = 5;
param_list[itype].rcutsq = cutmax;
param_list[itype].params[0] = chi;
param_list[itype].params[1] = eta;
param_list[itype].params[2] = gamma;
param_list[itype].params[3] = swa;
param_list[itype].params[4] = swb;
}
taper_setup();
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairREAX::init_one(int i, int j)
{
return cutmax;
}
/* ---------------------------------------------------------------------- */
int PairREAX::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
if (packflag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = FORTRAN(cbkabo, CBKABO).abo[j];
}
} else {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = wcg[j];
}
}
return 1;
}
/* ---------------------------------------------------------------------- */
void PairREAX::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (packflag == 0) {
for (i = first; i < last; i++)
FORTRAN(cbkabo, CBKABO).abo[i] = buf[m++];
} else {
for (i = first; i < last; i++)
wcg[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int PairREAX::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
buf[m++] = wcg[i];
return 1;
}
/* ---------------------------------------------------------------------- */
void PairREAX::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
wcg[j] += buf[m++];
}
}
/* ----------------------------------------------------------------------
charge equilibration routines
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void PairREAX::taper_setup()
{
double swb2,swa2,swb3,swa3,d1,d7;
d1=swb-swa;
d7=pow(d1,7);
swa2=swa*swa;
swa3=swa2*swa;
swb2=swb*swb;
swb3=swb2*swb;
swc7= 20.0e0/d7;
swc6= -70.0e0*(swa+swb)/d7;
swc5= 84.0e0*(swa2+3.0e0*swa*swb+swb2)/d7;
swc4= -35.0e0*(swa3+9.0e0*swa2*swb+9.0e0*swa*swb2+swb3)/d7;
swc3= 140.0e0*(swa3*swb+3.0e0*swa2*swb2+swa*swb3)/d7;
swc2=-210.0e0*(swa3*swb2+swa2*swb3)/d7;
swc1= 140.0e0*swa3*swb3/d7;
swc0=(-35.0e0*swa3*swb2*swb2+21.0e0*swa2*swb3*swb2+
7.0e0*swa*swb3*swb3+swb3*swb3*swb)/d7;
}
/* ---------------------------------------------------------------------- */
double PairREAX::taper_E(const double &r, const double &r2)
{
double r3=r2*r;
return swc7*r3*r3*r+swc6*r3*r3+swc5*r3*r2+swc4*r2*r2+swc3*r3+swc2*r2+
swc1*r+swc0;
}
/* ---------------------------------------------------------------------- */
double PairREAX::taper_F(const double &r, const double &r2)
{
double r3=r2*r;
return 7.0e0*swc7*r3*r3+6.0e0*swc6*r3*r2+5.0e0*swc5*r2*r2+
4.0e0*swc4*r3+3.0e0*swc3*r2+2.0e0*swc2*r+swc1;
}
/* ----------------------------------------------------------------------
compute current charge distributions based on the charge equilibration
------------------------------------------------------------------------- */
void PairREAX::compute_charge(double &energy_charge_equilibration)
{
double xitmp, yitmp, zitmp;
double xjtmp, yjtmp, zjtmp;
int itype, jtype, itag, jtag;
int ii, jj, i, j;
double delr2, delr_norm, gamt, hulp1, hulp2;
double delx, dely, delz;
double qsum,qi;
int nmatentries;
double sw;
int inum,jnum;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double *q = atom->q;
int *type = atom->type;
int *tag = atom->tag;
int nlocal = atom->nlocal;
int nghost = atom->nghost;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// realloc neighbor based arrays if necessary
int numneigh_total = 0;
for (ii = 0; ii < inum; ii++)
numneigh_total += numneigh[ilist[ii]];
if (numneigh_total + 2*nlocal > matmax) {
memory->destroy(aval);
memory->destroy(acol_ind);
matmax = numneigh_total + 2*nlocal;
memory->create(aval,matmax,"reax:aval");
memory->create(acol_ind,matmax,"reax:acol_ind");
}
// build linear system
nmatentries = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xitmp = x[i][0];
yitmp = x[i][1];
zitmp = x[i][2];
itype = type[i];
itag = tag[i];
jlist = firstneigh[i];
jnum = numneigh[i];
arow_ptr[i] = nmatentries;
aval[nmatentries] = 2.0*param_list[itype].params[1];
acol_ind[nmatentries] = i;
nmatentries++;
aval[nmatentries] = 1.0;
acol_ind[nmatentries] = nlocal + nghost;
nmatentries++;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
xjtmp = x[j][0];
yjtmp = x[j][1];
zjtmp = x[j][2];
jtype = type[j];
jtag = tag[j];
delx = xitmp - xjtmp;
dely = yitmp - yjtmp;
delz = zitmp - zjtmp;
delr2 = delx*delx+dely*dely+delz*delz;
// avoid counting local-ghost pair twice since
// ReaxFF uses half neigh list with newton off
if (j >= nlocal) {
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (zjtmp < zitmp) continue;
if (zjtmp == zitmp && yjtmp < yitmp) continue;
if (zjtmp == zitmp && yjtmp == yitmp && xjtmp < xitmp) continue;
}
}
// rcutvsq = cutmax*cutmax, in ReaxFF
if (delr2 <= rcutvsq) {
gamt = sqrt(param_list[itype].params[2]*param_list[jtype].params[2]);
delr_norm = sqrt(delr2);
sw = taper_E(delr_norm, delr2);
hulp1=(delr_norm*delr2+(1.0/(gamt*gamt*gamt)));
hulp2=sw*14.40/cbrt(hulp1);
aval[nmatentries] = hulp2;
acol_ind[nmatentries] = j;
nmatentries++;
}
}
}
// in this case, we don't use Midpoint method
// so, we don't need to consider ghost-ghost interactions
// but, need to fill the arow_ptr[] arrays for the ghost atoms
for (i = nlocal; i < nlocal+nghost; i++)
arow_ptr[i] = nmatentries;
arow_ptr[nlocal+nghost] = nmatentries;
// add rhs matentries to linear system
for (ii =0; ii<inum; ii++) {
i = ilist[ii];
itype = type[i];
elcvec[i] = -param_list[itype].params[0];
}
for (i = nlocal; i < nlocal+nghost; i++) elcvec[i] = 0.0;
// assign current charges to charge vector
qsum = 0.0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qi = q[i];
ch[i] = qi;
if (i < nlocal) qsum += qi;
}
for (i = nlocal; i < nlocal+nghost; i++) {
qi = q[i];
ch[i] = qi;
}
double qtot;
MPI_Allreduce(&qsum,&qtot,1,MPI_DOUBLE,MPI_SUM,world);
elcvec[nlocal+nghost] = 0.0;
ch[nlocal+nghost] = chpot;
// solve the linear system using CG sover
charge_reax(nlocal,nghost,ch,aval,acol_ind,arow_ptr,elcvec);
// calculate the charge equilibration energy
energy_charge_equilibration = 0;
// have already updated charge distributions for the current structure
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
// 23.02 is the ReaxFF conversion from eV to kcal/mol
// should really use constants.evfactor ~23.06
// but that would break consistency with serial ReaxFF code
// NOTE: this hard-wired real units
// if want other units would have to change params[] in file
qi = 23.02 * (param_list[itype].params[0]*ch[i]+
param_list[itype].params[1]*ch[i]*ch[i]);
energy_charge_equilibration += qi;
if (eflag_atom) eatom[i] += qi;
}
// copy charge vector back to particles from the calculated values
for (i = 0; i < nlocal+nghost; i++) q[i] = ch[i];
chpot = ch[nlocal+nghost];
}
/* ---------------------------------------------------------------------- */
void PairREAX::charge_reax(const int & nlocal, const int & nghost,
double ch[], double aval[], int acol_ind[],
int arow_ptr[], double elcvec[])
{
cg_solve(nlocal,nghost,aval,acol_ind,arow_ptr,ch,elcvec);
}
/* ----------------------------------------------------------------------
CG solver for linear systems
------------------------------------------------------------------------- */
void PairREAX::cg_solve(const int & nlocal, const int & nghost,
double aval[], int acol_ind[], int arow_ptr[],
double x[], double b[])
{
double one, zero, rho, rho_old, alpha, beta, gamma;
int iter, maxiter;
int n;
double sumtmp;
// parallel CG method by A. P. Thompson
// distributed (partial) vectors: b, r, q, A
// accumulated (full) vectors: x, w, p
// r = b-A.x
// w = r (ReverseComm + Comm)
double *r = rcg;
double *w = wcg;
double *p = pcg;
double *p_old = poldcg;
double *q = qcg;
n = nlocal+nghost+1;
one = 1.0;
zero = 0.0;
maxiter = 100;
for (int i = 0; i < n; i++) w[i] = 0;
// construct r = b-Ax
sparse_product(n, nlocal, nghost, aval, acol_ind, arow_ptr, x, r);
// not using BLAS library
for (int i=0; i<n; i++) {
r[i] = b[i] - r[i];
w[i] = r[i];
}
packflag = 1;
comm->reverse_comm_pair(this);
comm->forward_comm_pair(this);
MPI_Allreduce(&w[n-1], &sumtmp, 1, MPI_DOUBLE, MPI_SUM, world);
w[n-1] = sumtmp;
rho_old = one;
for (iter = 1; iter < maxiter; iter++) {
rho = 0.0;
for (int i=0; i<nlocal; i++) rho += w[i]*w[i];
MPI_Allreduce(&rho, &sumtmp, 1, MPI_DOUBLE, MPI_SUM, world);
rho = sumtmp + w[n-1]*w[n-1];
if (rho < precision) break;
for (int i = 0; i<n; i++) p[i] = w[i];
if (iter > 1) {
beta = rho/rho_old;
for (int i = 0; i<n; i++) p[i] += beta*p_old[i];
}
sparse_product(n, nlocal, nghost, aval, acol_ind, arow_ptr, p, q);
gamma = 0.0;
for (int i=0; i<n; i++) gamma += p[i]*q[i];
MPI_Allreduce(&gamma, &sumtmp, 1, MPI_DOUBLE, MPI_SUM, world);
gamma = sumtmp;
alpha = rho/gamma;
for (int i=0; i<n; i++) {
x[i] += alpha*p[i];
r[i] -= alpha*q[i];
w[i] = r[i];
}
comm->reverse_comm_pair(this);
comm->forward_comm_pair(this);
MPI_Allreduce(&w[n-1], &sumtmp, 1, MPI_DOUBLE, MPI_SUM, world);
w[n-1] = sumtmp;
for (int i=0; i<n; i++) p_old[i] = p[i];
rho_old = rho;
}
}
/* ----------------------------------------------------------------------
sparse maxtrix operations
------------------------------------------------------------------------- */
void PairREAX::sparse_product(const int &n, const int &nlocal,
const int &nghost,
double aval[], int acol_ind[], int arow_ptr[],
double *x, double *r)
{
int i,j,jj;
for (i=0; i<n; i++) r[i] = 0.0;
for (i=0; i<nlocal; i++) {
r[i] += aval[arow_ptr[i]]*x[i];
for (j=arow_ptr[i]+1; j<arow_ptr[i+1]; j++) {
jj = acol_ind[j];
r[i] += aval[j]*x[jj];
r[jj] += aval[j]*x[i];
}
}
for (i=nlocal; i<nlocal+nghost; i++)
for (j=arow_ptr[i]; j<arow_ptr[i+1]; j++) {
jj = acol_ind[j];
r[i] += aval[j]*x[jj];
r[jj] += aval[j]*x[i];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairREAX::memory_usage()
{
double bytes = nmax * sizeof(int);
bytes += 7 * nmax * sizeof(double);
bytes += matmax * sizeof(int);
bytes += matmax * sizeof(double);
return bytes;
}
diff --git a/src/REPLICA/compute_event_displace.cpp b/src/REPLICA/compute_event_displace.cpp
index 53e9d9f8f..3f5f401c4 100644
--- a/src/REPLICA/compute_event_displace.cpp
+++ b/src/REPLICA/compute_event_displace.cpp
@@ -1,157 +1,157 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "compute_event_displace.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "fix_event.h"
#include "memory.h"
#include "error.h"
#include "update.h"
using namespace LAMMPS_NS;
#define INVOKED_SCALAR 1
/* ---------------------------------------------------------------------- */
ComputeEventDisplace::ComputeEventDisplace(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal compute event/displace command");
+ if (narg != 4) error->all(FLERR,"Illegal compute event/displace command");
scalar_flag = 1;
extscalar = 0;
double displace_dist = atof(arg[3]);
if (displace_dist <= 0.0)
- error->all("Distance must be > 0 for compute event/displace");
+ error->all(FLERR,"Distance must be > 0 for compute event/displace");
displace_distsq = displace_dist * displace_dist;
// fix event ID will be set later by PRD
id_event = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeEventDisplace::~ComputeEventDisplace()
{
delete [] id_event;
}
/* ---------------------------------------------------------------------- */
void ComputeEventDisplace::init()
{
// if id_event is not set, this compute is not active
// if set by PRD, then find fix which stores original atom coords
// check if it is correct style
if (id_event != NULL) {
int ifix = modify->find_fix(id_event);
- if (ifix < 0) error->all("Could not find compute event/displace fix ID");
+ if (ifix < 0) error->all(FLERR,"Could not find compute event/displace fix ID");
fix_event = (FixEvent*) modify->fix[ifix];
if (strcmp(fix_event->style,"EVENT/PRD") != 0 &&
strcmp(fix_event->style,"EVENT/TAD") != 0)
- error->all("Compute event/displace has invalid fix event assigned");
+ error->all(FLERR,"Compute event/displace has invalid fix event assigned");
}
triclinic = domain->triclinic;
}
/* ----------------------------------------------------------------------
return non-zero if an atom has moved > displace_dist since last event
------------------------------------------------------------------------- */
double ComputeEventDisplace::compute_scalar()
{
invoked_scalar = update->ntimestep;
if (id_event == NULL) return 0.0;
double event = 0.0;
double **xevent = fix_event->array_atom;
double **x = atom->x;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
double *h = domain->h;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
double dx,dy,dz,rsq;
if (triclinic == 0) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xevent[i][0];
dy = x[i][1] + ybox*yprd - xevent[i][1];
dz = x[i][2] + zbox*zprd - xevent[i][2];
rsq = dx*dx + dy*dy + dz*dz;
if (rsq >= displace_distsq) {
event = 1.0;
break;
}
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox - xevent[i][0];
dy = x[i][1] + h[1]*ybox + h[3]*zbox - xevent[i][1];
dz = x[i][2] + h[2]*zbox - xevent[i][2];
rsq = dx*dx + dy*dy + dz*dz;
if (rsq >= displace_distsq) {
event = 1.0;
break;
}
}
}
MPI_Allreduce(&event,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeEventDisplace::reset_extra_compute_fix(char *id_new)
{
delete [] id_event;
id_event = NULL;
if (id_new == NULL) return;
int n = strlen(id_new) + 1;
id_event = new char[n];
strcpy(id_event,id_new);
}
diff --git a/src/REPLICA/fix_event.cpp b/src/REPLICA/fix_event.cpp
index 1b4f795e3..127713550 100644
--- a/src/REPLICA/fix_event.cpp
+++ b/src/REPLICA/fix_event.cpp
@@ -1,263 +1,263 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL), Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_event.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "neighbor.h"
#include "comm.h"
#include "universe.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixEvent::FixEvent(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal fix event command");
+ if (narg != 3) error->all(FLERR,"Illegal fix event command");
restart_global = 1;
// perform initial allocation of atom-based array
// register with Atom class
xevent = NULL;
xold = NULL;
vold = NULL;
imageold = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
}
/* ---------------------------------------------------------------------- */
FixEvent::~FixEvent()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
// delete locally stored array
memory->destroy(xevent);
memory->destroy(xold);
memory->destroy(vold);
memory->destroy(imageold);
}
/* ---------------------------------------------------------------------- */
int FixEvent::setmask()
{
return 0;
}
/* ----------------------------------------------------------------------
save current atom coords as an event
called when an event occurs
------------------------------------------------------------------------- */
void FixEvent::store_event()
{
double **x = atom->x;
int *image = atom->image;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
domain->unmap(x[i],image[i],xevent[i]);
}
/* ----------------------------------------------------------------------
restore atom coords to quenched initial state
called prior to NEB calculation
------------------------------------------------------------------------- */
void FixEvent::restore_event()
{
double **x = atom->x;
int *image = atom->image;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
x[i][0] = xevent[i][0];
x[i][1] = xevent[i][1];
x[i][2] = xevent[i][2];
// Since xevent is unwrapped coordinate, need to
// adjust image flags when remapping
image[i] = (512 << 20) | (512 << 10) | 512;
domain->remap(x[i],image[i]);
// domain->remap(x[i]);
}
}
/* ----------------------------------------------------------------------
store state of all atoms
called before quench and subsequent check for event
so can later restore pre-quench state if no event occurs
------------------------------------------------------------------------- */
void FixEvent::store_state()
{
double **x = atom->x;
double **v = atom->v;
int *image = atom->image;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
xold[i][0] = x[i][0];
xold[i][1] = x[i][1];
xold[i][2] = x[i][2];
vold[i][0] = v[i][0];
vold[i][1] = v[i][1];
vold[i][2] = v[i][2];
imageold[i] = image[i];
}
}
/* ----------------------------------------------------------------------
restore state of all atoms to pre-quench state
called after no event detected so can continue
------------------------------------------------------------------------- */
void FixEvent::restore_state()
{
double **x = atom->x;
double **v = atom->v;
int *image = atom->image;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
x[i][0] = xold[i][0];
x[i][1] = xold[i][1];
x[i][2] = xold[i][2];
v[i][0] = vold[i][0];
v[i][1] = vold[i][1];
v[i][2] = vold[i][2];
image[i] = imageold[i];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixEvent::memory_usage()
{
double bytes = 6*atom->nmax * sizeof(double);
bytes += atom->nmax*sizeof(int);
return bytes;
}
/* ----------------------------------------------------------------------
allocate atom-based array
------------------------------------------------------------------------- */
void FixEvent::grow_arrays(int nmax)
{
memory->grow(xevent,nmax,3,"event:xevent");
memory->grow(xold,nmax,3,"event:xold");
memory->grow(vold,nmax,3,"event:vold");
memory->grow(imageold,nmax,"event:imageold");
// allow compute event to access stored event coords
array_atom = xevent;
}
/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */
void FixEvent::copy_arrays(int i, int j)
{
xevent[j][0] = xevent[i][0];
xevent[j][1] = xevent[i][1];
xevent[j][2] = xevent[i][2];
xold[j][0] = xold[i][0];
xold[j][1] = xold[i][1];
xold[j][2] = xold[i][2];
vold[j][0] = vold[i][0];
vold[j][1] = vold[i][1];
vold[j][2] = vold[i][2];
imageold[j] = imageold[i];
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixEvent::pack_exchange(int i, double *buf)
{
buf[0] = xevent[i][0];
buf[1] = xevent[i][1];
buf[2] = xevent[i][2];
buf[3] = xold[i][0];
buf[4] = xold[i][1];
buf[5] = xold[i][2];
buf[6] = vold[i][0];
buf[7] = vold[i][1];
buf[8] = vold[i][2];
buf[9] = imageold[i];
return 10;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixEvent::unpack_exchange(int nlocal, double *buf)
{
xevent[nlocal][0] = buf[0];
xevent[nlocal][1] = buf[1];
xevent[nlocal][2] = buf[2];
xold[nlocal][0] = buf[3];
xold[nlocal][1] = buf[4];
xold[nlocal][2] = buf[5];
vold[nlocal][0] = buf[6];
vold[nlocal][1] = buf[7];
vold[nlocal][2] = buf[8];
imageold[nlocal] = static_cast<int>(buf[9]);
return 10;
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixEvent::write_restart(FILE *fp)
{
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixEvent::restart(char *buf)
{
}
diff --git a/src/REPLICA/fix_event_prd.cpp b/src/REPLICA/fix_event_prd.cpp
index ac428f371..84dedd18f 100644
--- a/src/REPLICA/fix_event_prd.cpp
+++ b/src/REPLICA/fix_event_prd.cpp
@@ -1,101 +1,101 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_event_prd.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "neighbor.h"
#include "comm.h"
#include "universe.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixEventPRD::FixEventPRD(LAMMPS *lmp, int narg, char **arg) :
FixEvent(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal fix event command");
+ if (narg != 3) error->all(FLERR,"Illegal fix event command");
restart_global = 1;
event_number = 0;
event_timestep = update->ntimestep;
clock = 0;
}
/* ----------------------------------------------------------------------
save current atom coords as an event (via call to base class)
called when an event occurs in some replica
set event_timestep = when event occurred in a particular replica
update clock = elapsed time since last event, across all replicas
------------------------------------------------------------------------- */
void FixEventPRD::store_event_prd(bigint ntimestep, int delta_clock)
{
store_event();
event_timestep = ntimestep;
clock += delta_clock;
event_number++;
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixEventPRD::write_restart(FILE *fp)
{
int n = 0;
double list[6];
list[n++] = event_number;
list[n++] = event_timestep;
list[n++] = clock;
list[n++] = replica_number;
list[n++] = correlated_event;
list[n++] = ncoincident;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),n,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixEventPRD::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
event_number = static_cast<int> (list[n++]);
event_timestep = static_cast<int> (list[n++]);
clock = static_cast<int> (list[n++]);
replica_number = static_cast<int> (list[n++]);
correlated_event = static_cast<int> (list[n++]);
ncoincident = static_cast<int> (list[n++]);
}
diff --git a/src/REPLICA/fix_event_tad.cpp b/src/REPLICA/fix_event_tad.cpp
index 950fcd6b8..7574b4873 100644
--- a/src/REPLICA/fix_event_tad.cpp
+++ b/src/REPLICA/fix_event_tad.cpp
@@ -1,95 +1,95 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_event_tad.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "neighbor.h"
#include "comm.h"
#include "universe.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixEventTAD::FixEventTAD(LAMMPS *lmp, int narg, char **arg) :
FixEvent(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal fix event command");
+ if (narg != 3) error->all(FLERR,"Illegal fix event command");
restart_global = 1;
event_number = 0;
event_timestep = update->ntimestep;
tlo = 0.0;
ebarrier = 0.0;
}
/* ----------------------------------------------------------------------
save current atom coords as an event (via call to base class)
called when an event occurs in some replica
set event_timestep = when event occurred
------------------------------------------------------------------------- */
void FixEventTAD::store_event_tad(bigint ntimestep)
{
store_event();
event_timestep = ntimestep;
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixEventTAD::write_restart(FILE *fp)
{
int n = 0;
double list[4];
list[n++] = event_number;
list[n++] = event_timestep;
list[n++] = tlo;
list[n++] = ebarrier;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),n,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixEventTAD::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
event_number = static_cast<int> (list[n++]);
event_timestep = static_cast<int> (list[n++]);
tlo = list[n++];
ebarrier = list[n++];
}
diff --git a/src/REPLICA/fix_neb.cpp b/src/REPLICA/fix_neb.cpp
index 958aaa6cf..d244ea7a8 100644
--- a/src/REPLICA/fix_neb.cpp
+++ b/src/REPLICA/fix_neb.cpp
@@ -1,311 +1,308 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_neb.h"
#include "universe.h"
#include "update.h"
#include "domain.h"
#include "modify.h"
#include "compute.h"
#include "atom.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixNEB::FixNEB(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal fix neb command");
+ if (narg != 4) error->all(FLERR,"Illegal fix neb command");
kspring = atof(arg[3]);
- if (kspring <= 0.0) error->all("Illegal fix neb command");
+ if (kspring <= 0.0) error->all(FLERR,"Illegal fix neb command");
// nreplica = number of partitions
// ireplica = which world I am in universe
// procprev,procnext = root proc in adjacent replicas
nreplica = universe->nworlds;
ireplica = universe->iworld;
if (ireplica > 0) procprev = universe->root_proc[ireplica-1];
else procprev = -1;
if (ireplica < nreplica-1) procnext = universe->root_proc[ireplica+1];
else procnext = -1;
uworld = universe->uworld;
// create a new compute pe style
// id = fix-ID + pe, compute group = all
int n = strlen(id) + 4;
id_pe = new char[n];
strcpy(id_pe,id);
strcat(id_pe,"_pe");
char **newarg = new char*[3];
newarg[0] = id_pe;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pe";
modify->add_compute(3,newarg);
delete [] newarg;
xprev = xnext = tangent = NULL;
}
/* ---------------------------------------------------------------------- */
FixNEB::~FixNEB()
{
modify->delete_compute(id_pe);
delete [] id_pe;
memory->destroy(xprev);
memory->destroy(xnext);
memory->destroy(tangent);
}
/* ---------------------------------------------------------------------- */
int FixNEB::setmask()
{
int mask = 0;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNEB::init()
{
int icompute = modify->find_compute(id_pe);
if (icompute < 0)
- error->all("Potential energy ID for fix neb does not exist");
+ error->all(FLERR,"Potential energy ID for fix neb does not exist");
pe = modify->compute[icompute];
// turn off climbing mode, NEB command turns it on after init()
rclimber = -1;
// setup xprev and xnext arrays
memory->destroy(xprev);
memory->destroy(xnext);
memory->destroy(tangent);
nebatoms = atom->nlocal;
memory->create(xprev,nebatoms,3,"neb:xprev");
memory->create(xnext,nebatoms,3,"neb:xnext");
memory->create(tangent,nebatoms,3,"neb:tangent");
}
/* ---------------------------------------------------------------------- */
void FixNEB::min_setup(int vflag)
{
min_post_force(vflag);
// trigger potential energy computation on next timestep
pe->addstep(update->ntimestep+1);
}
/* ---------------------------------------------------------------------- */
void FixNEB::min_post_force(int vflag)
{
double vprev,vnext,vmax,vmin;
double delx,dely,delz;
double delta1[3],delta2[3];
MPI_Status status;
MPI_Request request;
// veng = PE of this replica
// vprev,vnext = PEs of adjacent replicas
veng = pe->compute_scalar();
if (ireplica < nreplica-1) MPI_Send(&veng,1,MPI_DOUBLE,procnext,0,uworld);
if (ireplica > 0) MPI_Recv(&vprev,1,MPI_DOUBLE,procprev,0,uworld,&status);
if (ireplica > 0) MPI_Send(&veng,1,MPI_DOUBLE,procprev,0,uworld);
if (ireplica < nreplica-1)
MPI_Recv(&vnext,1,MPI_DOUBLE,procnext,0,uworld,&status);
// xprev,xnext = atom coords of adjacent replicas
// assume order of atoms in all replicas is the same
// check that number of atoms hasn't changed
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
- if (nlocal != nebatoms) error->one("Atom count changed in fix neb");
+ if (nlocal != nebatoms) error->one(FLERR,"Atom count changed in fix neb");
if (ireplica > 0)
MPI_Irecv(xprev[0],3*nlocal,MPI_DOUBLE,procprev,0,uworld,&request);
if (ireplica < nreplica-1)
MPI_Send(x[0],3*nlocal,MPI_DOUBLE,procnext,0,uworld);
if (ireplica > 0) MPI_Wait(&request,&status);
if (ireplica < nreplica-1)
MPI_Irecv(xnext[0],3*nlocal,MPI_DOUBLE,procnext,0,uworld,&request);
if (ireplica > 0)
MPI_Send(x[0],3*nlocal,MPI_DOUBLE,procprev,0,uworld);
if (ireplica < nreplica-1) MPI_Wait(&request,&status);
// trigger potential energy computation on next timestep
pe->addstep(update->ntimestep+1);
// Compute norm of GradV for log output
double **f = atom->f;
double fsq = 0.0;
for (int i = 0; i < nlocal; i++) {
fsq += f[i][0]*f[i][0]+f[i][1]*f[i][1]+f[i][2]*f[i][2];
}
MPI_Allreduce(&fsq,&gradvnorm,1,MPI_DOUBLE,MPI_MAX,world);
gradvnorm = sqrt(gradvnorm);
// if this is first or last replica, no change to forces, just return
if (ireplica == 0 || ireplica == nreplica-1) {
plen = nlen = 0.0;
return;
}
// tangent = unit tangent vector in 3N space
// based on delta vectors between atoms and their images in adjacent replicas
// use one or two delta vecs to compute tangent,
// depending on relative PEs of 3 replicas
// see Henkelman & Jonsson 2000 paper, eqs 8-11
if (vnext > veng && veng > vprev) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
tangent[i][0] = xnext[i][0] - x[i][0];
tangent[i][1] = xnext[i][1] - x[i][1];
tangent[i][2] = xnext[i][2] - x[i][2];
domain->minimum_image(tangent[i]);
}
} else if (vnext < veng && veng < vprev) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
tangent[i][0] = x[i][0] - xprev[i][0];
tangent[i][1] = x[i][1] - xprev[i][1];
tangent[i][2] = x[i][2] - xprev[i][2];
domain->minimum_image(tangent[i]);
}
} else {
vmax = MAX(fabs(vnext-veng),fabs(vprev-veng));
vmin = MIN(fabs(vnext-veng),fabs(vprev-veng));
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
delta1[0] = xnext[i][0] - x[i][0];
delta1[1] = xnext[i][1] - x[i][1];
delta1[2] = xnext[i][2] - x[i][2];
domain->minimum_image(delta1);
delta2[0] = x[i][0] - xprev[i][0];
delta2[1] = x[i][1] - xprev[i][1];
delta2[2] = x[i][2] - xprev[i][2];
domain->minimum_image(delta2);
if (vnext > vprev) {
tangent[i][0] = vmax*delta1[0] + vmin*delta2[0];
tangent[i][1] = vmax*delta1[1] + vmin*delta2[1];
tangent[i][2] = vmax*delta1[2] + vmin*delta2[2];
} else {
tangent[i][0] = vmin*delta1[0] + vmax*delta2[0];
tangent[i][1] = vmin*delta1[1] + vmax*delta2[1];
tangent[i][2] = vmin*delta1[2] + vmax*delta2[2];
}
}
}
// tlen,plen,nlen = lengths of tangent, prev, next vectors
double tlen = 0.0;
plen = 0.0;
nlen = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
tlen += tangent[i][0]*tangent[i][0] + tangent[i][1]*tangent[i][1] +
tangent[i][2]*tangent[i][2];
delx = x[i][0] - xprev[i][0];
dely = x[i][1] - xprev[i][1];
delz = x[i][2] - xprev[i][2];
domain->minimum_image(delx,dely,delz);
plen += delx*delx + dely*dely + delz*delz;
delx = xnext[i][0] - x[i][0];
dely = xnext[i][1] - x[i][1];
delz = xnext[i][2] - x[i][2];
domain->minimum_image(delx,dely,delz);
nlen += delx*delx + dely*dely + delz*delz;
}
tlen = sqrt(tlen);
plen = sqrt(plen);
nlen = sqrt(nlen);
// normalize tangent vector
if (tlen > 0.0) {
double tleninv = 1.0/tlen;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
tangent[i][0] *= tleninv;
tangent[i][1] *= tleninv;
tangent[i][2] *= tleninv;
}
}
// reset force on each atom in this replica
// regular NEB for all replicas except rclimber does hill-climbing NEB
// currently have F = -Grad(V) = -Grad(V)_perp - Grad(V)_parallel
// want F = -Grad(V)_perp + Fspring for regular NEB
// thus Fdelta = Grad(V)_parallel + Fspring for regular NEB
// want F = -Grad(V) + 2 Grad(V)_parallel for hill-climbing NEB
// thus Fdelta = 2 Grad(V)_parallel for hill-climbing NEB
// Grad(V)_parallel = (Grad(V) . utan) * utangent = -(F . utan) * utangent
// Fspring = k (nlen - plen) * utangent
// see Henkelman & Jonsson 2000 paper, eqs 3,4,12
// see Henkelman & Jonsson 2000a paper, eq 5
double dot = 0.0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
dot += f[i][0]*tangent[i][0] + f[i][1]*tangent[i][1] +
f[i][2]*tangent[i][2];
}
double prefactor;
if (ireplica == rclimber) prefactor = -2.0*dot;
else prefactor = -dot + kspring*(nlen-plen);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
f[i][0] += prefactor*tangent[i][0];
f[i][1] += prefactor*tangent[i][1];
f[i][2] += prefactor*tangent[i][2];
}
}
diff --git a/src/REPLICA/neb.cpp b/src/REPLICA/neb.cpp
index 6768b89ac..c8747aa81 100644
--- a/src/REPLICA/neb.cpp
+++ b/src/REPLICA/neb.cpp
@@ -1,508 +1,508 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "neb.h"
#include "universe.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "min.h"
#include "modify.h"
#include "fix.h"
#include "fix_neb.h"
#include "output.h"
#include "thermo.h"
#include "finish.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define CHUNK 1000
#define MAXLINE 256
/* ---------------------------------------------------------------------- */
NEB::NEB(LAMMPS *lmp) : Pointers(lmp) {}
/* ----------------------------------------------------------------------
internal NEB constructor, called from TAD
------------------------------------------------------------------------- */
NEB::NEB(LAMMPS *lmp, double etol_in, double ftol_in, int n1steps_in,
int n2steps_in, int nevery_in, double *buf_init, double *buf_final)
: Pointers(lmp)
{
double delx,dely,delz;
etol = etol_in;
ftol = ftol_in;
n1steps = n1steps_in;
n2steps = n2steps_in;
nevery = nevery_in;
// replica info
nreplica = universe->nworlds;
ireplica = universe->iworld;
me_universe = universe->me;
uworld = universe->uworld;
MPI_Comm_rank(world,&me);
// generate linear interpolate replica
double fraction = ireplica/(nreplica-1.0);
double **x = atom->x;
int nlocal = atom->nlocal;
int ii = 0;
for (int i = 0; i < nlocal; i++) {
delx = buf_final[ii] - buf_init[ii];
dely = buf_final[ii+1] - buf_init[ii+1];
delz = buf_final[ii+2] - buf_init[ii+2];
domain->minimum_image(delx,dely,delz);
x[i][0] = buf_init[ii] + fraction*delx;
x[i][1] = buf_init[ii+1] + fraction*dely;
x[i][2] = buf_init[ii+2] + fraction*delz;
ii += 3;
}
}
/* ---------------------------------------------------------------------- */
NEB::~NEB()
{
MPI_Comm_free(&roots);
memory->destroy(all);
delete [] rdist;
}
/* ----------------------------------------------------------------------
perform NEB on multiple replicas
------------------------------------------------------------------------- */
void NEB::command(int narg, char **arg)
{
if (domain->box_exist == 0)
- error->all("NEB command before simulation box is defined");
+ error->all(FLERR,"NEB command before simulation box is defined");
- if (narg != 6) error->universe_all("Illegal NEB command");
+ if (narg != 6) error->universe_all(FLERR,"Illegal NEB command");
etol = atof(arg[0]);
ftol = atof(arg[1]);
n1steps = atoi(arg[2]);
n2steps = atoi(arg[3]);
nevery = atoi(arg[4]);
infile = arg[5];
// error checks
- if (etol < 0.0) error->all("Illegal NEB command");
- if (ftol < 0.0) error->all("Illegal NEB command");
- if (nevery == 0) error->universe_all("Illegal NEB command");
+ if (etol < 0.0) error->all(FLERR,"Illegal NEB command");
+ if (ftol < 0.0) error->all(FLERR,"Illegal NEB command");
+ if (nevery == 0) error->universe_all(FLERR,"Illegal NEB command");
if (n1steps % nevery || n2steps % nevery)
- error->universe_all("Illegal NEB command");
+ error->universe_all(FLERR,"Illegal NEB command");
// replica info
nreplica = universe->nworlds;
ireplica = universe->iworld;
me_universe = universe->me;
uworld = universe->uworld;
MPI_Comm_rank(world,&me);
// error checks
- if (nreplica == 1) error->all("Cannot use NEB with a single replica");
+ if (nreplica == 1) error->all(FLERR,"Cannot use NEB with a single replica");
if (nreplica != universe->nprocs)
- error->all("Can only use NEB with 1-processor replicas");
+ error->all(FLERR,"Can only use NEB with 1-processor replicas");
if (atom->sortfreq > 0)
- error->all("Cannot use NEB with atom_modify sort enabled");
+ error->all(FLERR,"Cannot use NEB with atom_modify sort enabled");
if (atom->map_style == 0)
- error->all("Cannot use NEB unless atom map exists");
+ error->all(FLERR,"Cannot use NEB unless atom map exists");
// read in file of final state atom coords and reset my coords
readfile(infile);
// run the NEB calculation
run();
}
/* ----------------------------------------------------------------------
run NEB on multiple replicas
------------------------------------------------------------------------- */
void NEB::run()
{
// create MPI communicator for root proc from each world
int color;
if (me == 0) color = 0;
else color = 1;
MPI_Comm_split(uworld,color,0,&roots);
int ineb;
for (ineb = 0; ineb < modify->nfix; ineb++)
if (strcmp(modify->fix[ineb]->style,"neb") == 0) break;
- if (ineb == modify->nfix) error->all("NEB requires use of fix neb");
+ if (ineb == modify->nfix) error->all(FLERR,"NEB requires use of fix neb");
fneb = (FixNEB *) modify->fix[ineb];
nall = 4;
memory->create(all,nreplica,nall,"neb:all");
rdist = new double[nreplica];
// initialize LAMMPS
update->whichflag = 2;
update->etol = etol;
update->ftol = ftol;
update->multireplica = 1;
lmp->init();
if (update->minimize->searchflag)
- error->all("NEB requires damped dynamics minimizer");
+ error->all(FLERR,"NEB requires damped dynamics minimizer");
// setup regular NEB minimization
if (me_universe == 0 && universe->uscreen)
fprintf(universe->uscreen,"Setting up regular NEB ...\n");
update->beginstep = update->firststep = update->ntimestep;
update->endstep = update->laststep = update->firststep + n1steps;
update->nsteps = n1steps;
update->max_eval = n1steps;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many timesteps for NEB");
+ error->all(FLERR,"Too many timesteps for NEB");
update->minimize->setup();
if (me_universe == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,"Step MaxReplicaForce MaxAtomForce "
"GradV0 GradV1 GradVc "
"EBF EBR RDT "
"RD1 PE1 RD2 PE2 ... RDN PEN\n");
if (universe->ulogfile)
fprintf(universe->ulogfile,"Step MaxReplicaForce MaxAtomForce "
"GradV0 GradV1 GradVc "
"EBF EBR RDT "
"RD1 PE1 RD2 PE2 ... RDN PEN\n");
}
print_status();
// perform regular NEB for n1steps or until replicas converge
// retrieve PE values from fix NEB and print every nevery iterations
// break induced if converged
// damped dynamic min styles insure all replicas converge together
timer->barrier_start(TIME_LOOP);
while (update->minimize->niter < n1steps) {
update->minimize->run(nevery);
print_status();
if (update->minimize->stop_condition) break;
}
timer->barrier_stop(TIME_LOOP);
update->minimize->cleanup();
Finish finish(lmp);
finish.end(1);
// switch fix NEB to climbing mode
// top = replica that becomes hill climber
double vmax = all[0][0];
int top = 0;
for (int m = 1; m < nreplica; m++)
if (vmax < all[m][0]) {
vmax = all[m][0];
top = m;
}
// setup climbing NEB minimization
// must reinitialize minimizer so it re-creates its fix MINIMIZE
if (me_universe == 0 && universe->uscreen)
fprintf(universe->uscreen,"Setting up climbing ...\n");
if (me_universe == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,"Climbing replica = %d\n",top+1);
if (universe->ulogfile)
fprintf(universe->ulogfile,"Climbing replica = %d\n",top+1);
}
update->beginstep = update->firststep = update->ntimestep;
update->endstep = update->laststep = update->firststep + n2steps;
update->nsteps = n2steps;
update->max_eval = n2steps;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many timesteps");
+ error->all(FLERR,"Too many timesteps");
update->minimize->init();
fneb->rclimber = top;
update->minimize->setup();
if (me_universe == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,"Step MaxReplicaForce MaxAtomForce "
"GradV0 GradV1 GradVc "
"EBF EBR RDT "
"RD1 PE1 RD2 PE2 ... RDN PEN\n");
if (universe->ulogfile)
fprintf(universe->ulogfile,"Step MaxReplicaForce MaxAtomForce "
"GradV0 GradV1 GradVc "
"EBF EBR RDT "
"RD1 PE1 RD2 PE2 ... RDN PEN\n");
}
print_status();
// perform climbing NEB for n2steps or until replicas converge
// retrieve PE values from fix NEB and print every nevery iterations
// break induced if converged
// damped dynamic min styles insure all replicas converge together
timer->barrier_start(TIME_LOOP);
while (update->minimize->niter < n2steps) {
update->minimize->run(nevery);
print_status();
if (update->minimize->stop_condition) break;
}
timer->barrier_stop(TIME_LOOP);
update->minimize->cleanup();
finish.end(1);
update->whichflag = 0;
update->multireplica = 0;
update->firststep = update->laststep = 0;
update->beginstep = update->endstep = 0;
}
/* ----------------------------------------------------------------------
read target coordinates from file, store with appropriate atom
adjust coords of each atom based on ireplica
new coord = replica fraction between current and final state
------------------------------------------------------------------------- */
void NEB::readfile(char *file)
{
if (me_universe == 0) {
if (screen) fprintf(screen,"Reading NEB coordinate file %s ...\n",file);
open(file);
}
double fraction = ireplica/(nreplica-1.0);
double **x = atom->x;
int nlocal = atom->nlocal;
char *buffer = new char[CHUNK*MAXLINE];
char *ptr,*next,*bufptr;
int i,m,nlines,tag;
double xx,yy,zz,delx,dely,delz;
int firstline = 1;
int ncount = 0;
int eof = 0;
while (!eof) {
if (me_universe == 0) {
m = 0;
for (nlines = 0; nlines < CHUNK; nlines++) {
ptr = fgets(&buffer[m],MAXLINE,fp);
if (ptr == NULL) break;
m += strlen(&buffer[m]);
}
if (ptr == NULL) eof = 1;
buffer[m++] = '\n';
}
MPI_Bcast(&eof,1,MPI_INT,0,uworld);
MPI_Bcast(&nlines,1,MPI_INT,0,uworld);
MPI_Bcast(&m,1,MPI_INT,0,uworld);
MPI_Bcast(buffer,m,MPI_CHAR,0,uworld);
bufptr = buffer;
for (i = 0; i < nlines; i++) {
next = strchr(bufptr,'\n');
*next = '\0';
if (firstline) {
if (atom->count_words(bufptr) == 4) firstline = 0;
- else error->all("Incorrect format in NEB coordinate file");
+ else error->all(FLERR,"Incorrect format in NEB coordinate file");
}
sscanf(bufptr,"%d %lg %lg %lg",&tag,&xx,&yy,&zz);
// adjust atom coord based on replica fraction
// ignore image flags of final x
// new x is displacement from old x
// if final x is across periodic boundary:
// new x may be outside box
// will be remapped back into box when simulation starts
// its image flags will be adjusted appropriately
m = atom->map(tag);
if (m >= 0 && m < nlocal) {
delx = xx - x[m][0];
dely = yy - x[m][1];
delz = zz - x[m][2];
domain->minimum_image(delx,dely,delz);
x[m][0] += fraction*delx;
x[m][1] += fraction*dely;
x[m][2] += fraction*delz;
ncount++;
}
bufptr = next + 1;
}
}
// clean up
delete [] buffer;
if (me_universe == 0) {
if (compressed) pclose(fp);
else fclose(fp);
}
}
/* ----------------------------------------------------------------------
universe proc 0 opens NEB data file
test if gzipped
------------------------------------------------------------------------- */
void NEB::open(char *file)
{
compressed = 0;
char *suffix = file + strlen(file) - 3;
if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1;
if (!compressed) fp = fopen(file,"r");
else {
#ifdef LAMMPS_GZIP
char gunzip[128];
sprintf(gunzip,"gunzip -c %s",file);
fp = popen(gunzip,"r");
#else
- error->one("Cannot open gzipped file");
+ error->one(FLERR,"Cannot open gzipped file");
#endif
}
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
/* ----------------------------------------------------------------------
query fix NEB for PE of each replica
proc 0 prints current NEB status
------------------------------------------------------------------------- */
void NEB::print_status()
{
double fnorm2 = sqrt(update->minimize->fnorm_sqr());
double fmaxreplica;
MPI_Allreduce(&fnorm2,&fmaxreplica,1,MPI_DOUBLE,MPI_MAX,roots);
double fnorminf = update->minimize->fnorm_inf();
double fmaxatom;
MPI_Allreduce(&fnorminf,&fmaxatom,1,MPI_DOUBLE,MPI_MAX,roots);
double one[4];
one[0] = fneb->veng;
one[1] = fneb->plen;
one[2] = fneb->nlen;
one[nall-1] = fneb->gradvnorm;
if (output->thermo->normflag) one[0] /= atom->natoms;
if (me == 0)
MPI_Allgather(one,nall,MPI_DOUBLE,&all[0][0],nall,MPI_DOUBLE,roots);
rdist[0] = 0.0;
for (int i = 1; i < nreplica; i++)
rdist[i] = rdist[i-1] + all[i][1];
double endpt = rdist[nreplica-1] = rdist[nreplica-2] + all[nreplica-2][2];
for (int i = 1; i < nreplica; i++)
rdist[i] /= endpt;
// look up GradV for the initial, final, and climbing replicas
// these are identical to fnorm2, but to be safe we
// take them straight from fix_neb
double gradvnorm0, gradvnorm1, gradvnormc;
int irep;
irep = 0;
gradvnorm0 = all[irep][3];
irep = nreplica-1;
gradvnorm1 = all[irep][3];
irep = fneb->rclimber;
if (irep > -1) {
gradvnormc = all[irep][3];
ebf = all[irep][0]-all[0][0];
ebr = all[irep][0]-all[nreplica-1][0];
} else {
double vmax = all[0][0];
int top = 0;
for (int m = 1; m < nreplica; m++)
if (vmax < all[m][0]) {
vmax = all[m][0];
top = m;
}
irep = top;
gradvnormc = all[irep][3];
ebf = all[irep][0]-all[0][0];
ebr = all[irep][0]-all[nreplica-1][0];
}
if (me_universe == 0) {
if (universe->uscreen) {
fprintf(universe->uscreen,BIGINT_FORMAT " %g %g ",update->ntimestep,
fmaxreplica,fmaxatom);
fprintf(universe->uscreen,"%g %g %g ",
gradvnorm0,gradvnorm1,gradvnormc);
fprintf(universe->uscreen,"%g %g %g ",ebf,ebr,endpt);
for (int i = 0; i < nreplica; i++)
fprintf(universe->uscreen,"%g %g ",rdist[i],all[i][0]);
fprintf(universe->uscreen,"\n");
}
if (universe->ulogfile) {
fprintf(universe->ulogfile,BIGINT_FORMAT " %g %g ",update->ntimestep,
fmaxreplica,fmaxatom);
fprintf(universe->ulogfile,"%g %g %g ",
gradvnorm0,gradvnorm1,gradvnormc);
fprintf(universe->ulogfile,"%g %g %g ",ebf,ebr,endpt);
for (int i = 0; i < nreplica; i++)
fprintf(universe->ulogfile,"%g %g ",rdist[i],all[i][0]);
fprintf(universe->ulogfile,"\n");
fflush(universe->ulogfile);
}
}
}
diff --git a/src/REPLICA/prd.cpp b/src/REPLICA/prd.cpp
index 85d1b4906..909d7e35e 100644
--- a/src/REPLICA/prd.cpp
+++ b/src/REPLICA/prd.cpp
@@ -1,817 +1,817 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "prd.h"
#include "universe.h"
#include "update.h"
#include "atom.h"
#include "domain.h"
#include "region.h"
#include "comm.h"
#include "velocity.h"
#include "integrate.h"
#include "min.h"
#include "neighbor.h"
#include "modify.h"
#include "compute.h"
#include "fix.h"
#include "fix_event_prd.h"
#include "force.h"
#include "pair.h"
#include "random_park.h"
#include "random_mars.h"
#include "output.h"
#include "dump.h"
#include "finish.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PRD::PRD(LAMMPS *lmp) : Pointers(lmp) {}
/* ----------------------------------------------------------------------
perform PRD simulation on one or more replicas
------------------------------------------------------------------------- */
void PRD::command(int narg, char **arg)
{
int flag,ireplica;
// error checks
if (domain->box_exist == 0)
- error->all("PRD command before simulation box is defined");
+ error->all(FLERR,"PRD command before simulation box is defined");
if (universe->nworlds != universe->nprocs &&
atom->map_style == 0)
- error->all("Cannot use PRD with multi-processor replicas "
+ error->all(FLERR,"Cannot use PRD with multi-processor replicas "
"unless atom map exists");
if (universe->nworlds == 1 && comm->me == 0)
- error->warning("Running PRD with only one replica");
+ error->warning(FLERR,"Running PRD with only one replica");
- if (narg < 7) error->universe_all("Illegal prd command");
+ if (narg < 7) error->universe_all(FLERR,"Illegal prd command");
nsteps = atoi(arg[0]);
t_event = atoi(arg[1]);
n_dephase = atoi(arg[2]);
t_dephase = atoi(arg[3]);
t_corr = atoi(arg[4]);
char id_compute[strlen(arg[5])+1];
strcpy(id_compute,arg[5]);
int seed = atoi(arg[6]);
options(narg-7,&arg[7]);
// total # of timesteps must be multiple of t_event
- if (t_event <= 0) error->universe_all("Invalid t_event in prd command");
+ if (t_event <= 0) error->universe_all(FLERR,"Invalid t_event in prd command");
if (nsteps % t_event)
- error->universe_all("PRD nsteps must be multiple of t_event");
+ error->universe_all(FLERR,"PRD nsteps must be multiple of t_event");
if (t_corr % t_event)
- error->universe_all("PRD t_corr must be multiple of t_event");
+ error->universe_all(FLERR,"PRD t_corr must be multiple of t_event");
// local storage
int me_universe = universe->me;
int nprocs_universe = universe->nprocs;
int nreplica = universe->nworlds;
int iworld = universe->iworld;
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
// comm_replica = communicator between same proc across replicas
// not used if replicas have unequal number of procs
// equal_size_replicas = 1 if all replicas have same # of procs
int color = me;
MPI_Comm_split(universe->uworld,color,0,&comm_replica);
flag = 0;
if (nreplica*nprocs == nprocs_universe) flag = 1;
MPI_Allreduce(&flag,&equal_size_replicas,1,MPI_INT,MPI_MIN,universe->uworld);
// workspace for inter-replica communication via gathers
natoms = atom->natoms;
displacements = NULL;
tagall = NULL;
xall = NULL;
imageall = NULL;
if (nreplica != nprocs_universe) {
displacements = new int[nprocs];
memory->create(tagall,natoms,"prd:tagall");
memory->create(xall,natoms,3,"prd:xall");
memory->create(imageall,natoms,"prd:imageall");
}
// random_select = same RNG for each replica for multiple event selection
// random_dephase = unique RNG for each replica for dephasing
random_select = new RanPark(lmp,seed);
random_dephase = new RanMars(lmp,seed+iworld);
// create ComputeTemp class to monitor temperature
char **args = new char*[3];
args[0] = (char *) "prd_temp";
args[1] = (char *) "all";
args[2] = (char *) "temp";
modify->add_compute(3,args);
temperature = modify->compute[modify->ncompute-1];
// create Velocity class for velocity creation in dephasing
// pass it temperature compute, loop_setting, dist_setting settings
atom->check_mass();
velocity = new Velocity(lmp);
velocity->init_external("all");
args[0] = (char *) "temp";
args[1] = (char *) "prd_temp";
velocity->options(2,args);
args[0] = (char *) "loop";
args[1] = (char *) loop_setting;
if (loop_setting) velocity->options(2,args);
args[0] = (char *) "dist";
args[1] = (char *) dist_setting;
if (dist_setting) velocity->options(2,args);
// create FixEventPRD class to store event and pre-quench states
args[0] = (char *) "prd_event";
args[1] = (char *) "all";
args[2] = (char *) "EVENT/PRD";
modify->add_fix(3,args);
fix_event = (FixEventPRD *) modify->fix[modify->nfix-1];
// create Finish for timing output
finish = new Finish(lmp);
// string clean-up
delete [] args;
delete [] loop_setting;
delete [] dist_setting;
// assign FixEventPRD to event-detection compute
// necessary so it will know atom coords at last event
int icompute = modify->find_compute(id_compute);
- if (icompute < 0) error->all("Could not find compute ID for PRD");
+ if (icompute < 0) error->all(FLERR,"Could not find compute ID for PRD");
compute_event = modify->compute[icompute];
compute_event->reset_extra_compute_fix("prd_event");
// reset reneighboring criteria since will perform minimizations
neigh_every = neighbor->every;
neigh_delay = neighbor->delay;
neigh_dist_check = neighbor->dist_check;
if (neigh_every != 1 || neigh_delay != 0 || neigh_dist_check != 1) {
if (me == 0)
- error->warning("Resetting reneighboring criteria during PRD");
+ error->warning(FLERR,"Resetting reneighboring criteria during PRD");
}
neighbor->every = 1;
neighbor->delay = 0;
neighbor->dist_check = 1;
// initialize PRD as if one long dynamics run
update->whichflag = 1;
update->nsteps = nsteps;
update->beginstep = update->firststep = update->ntimestep;
update->endstep = update->laststep = update->firststep + nsteps;
update->restrict_output = 1;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many timesteps");
+ error->all(FLERR,"Too many timesteps");
lmp->init();
// init minimizer settings and minimizer itself
update->etol = etol;
update->ftol = ftol;
update->max_eval = maxeval;
update->minimize->init();
// cannot use PRD with time-dependent fixes or regions or atom sorting
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->time_depend)
- error->all("Cannot use PRD with a time-dependent fix defined");
+ error->all(FLERR,"Cannot use PRD with a time-dependent fix defined");
for (int i = 0; i < domain->nregion; i++)
if (domain->regions[i]->dynamic_check())
- error->all("Cannot use PRD with a time-dependent region defined");
+ error->all(FLERR,"Cannot use PRD with a time-dependent region defined");
if (atom->sortfreq > 0)
- error->all("Cannot use PRD with atom_modify sort enabled");
+ error->all(FLERR,"Cannot use PRD with atom_modify sort enabled");
// perform PRD simulation
if (me_universe == 0 && universe->uscreen)
fprintf(universe->uscreen,"Setting up PRD ...\n");
if (me_universe == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,"Step CPU Clock Event "
"Correlated Coincident Replica\n");
if (universe->ulogfile)
fprintf(universe->ulogfile,"Step CPU Clock Event "
"Correlated Coincident Replica\n");
}
// store hot state and quenched event for replica 0
// use share_event() to copy that info to all replicas
// this insures all start from same place
// need this line if quench() does only setup_minimal()
// update->minimize->setup();
fix_event->store_state();
quench();
ncoincident = 0;
share_event(0,0);
timer->barrier_start(TIME_LOOP);
time_start = timer->array[TIME_LOOP];
log_event();
// do full init/setup since are starting all replicas after event
// replica 0 bcasts temp to all replicas if temp_dephase is not set
update->whichflag = 1;
lmp->init();
update->integrate->setup();
if (temp_flag == 0) {
if (universe->iworld == 0) temp_dephase = temperature->compute_scalar();
MPI_Bcast(&temp_dephase,1,MPI_DOUBLE,universe->root_proc[0],
universe->uworld);
}
// main loop: look for events until out of time
// (1) dephase independently on each proc after event
// (2) loop: dynamics, store state, quench, check event, restore state
// (3) share and record event
nbuild = ndanger = 0;
time_dephase = time_dynamics = time_quench = time_comm = time_output = 0.0;
timer->barrier_start(TIME_LOOP);
time_start = timer->array[TIME_LOOP];
while (update->ntimestep < update->endstep) {
dephase();
ireplica = -1;
while (update->ntimestep < update->endstep) {
dynamics();
fix_event->store_state();
quench();
ireplica = check_event();
if (ireplica >= 0) break;
fix_event->restore_state();
}
if (ireplica < 0) break;
// potentially more efficient for correlated events if don't
// share until correlated check has completed
// this will complicate the dump (always on replica 0)
share_event(ireplica,1);
log_event();
int restart_flag = 0;
if (output->restart_every && universe->iworld == 0)
if (fix_event->event_number % output->restart_every == 0)
restart_flag = 1;
// correlated event loop
// other procs could be dephasing during this time
int corr_endstep = update->ntimestep + t_corr;
while (update->ntimestep < corr_endstep) {
if (update->ntimestep == update->endstep) {
restart_flag = 0;
break;
}
dynamics();
fix_event->store_state();
quench();
int corr_event_check = check_event(ireplica);
if (corr_event_check >= 0) {
share_event(ireplica,2);
log_event();
corr_endstep = update->ntimestep + t_corr;
} else fix_event->restore_state();
}
// full init/setup since are starting all replicas after event
// event replica bcasts temp to all replicas if temp_dephase is not set
update->whichflag = 1;
lmp->init();
update->integrate->setup();
timer->barrier_start(TIME_LOOP);
if (t_corr > 0) replicate(ireplica);
if (temp_flag == 0) {
if (ireplica == universe->iworld)
temp_dephase = temperature->compute_scalar();
MPI_Bcast(&temp_dephase,1,MPI_DOUBLE,universe->root_proc[ireplica],
universe->uworld);
}
timer->barrier_stop(TIME_LOOP);
time_comm += timer->array[TIME_LOOP];
// write restart file of hot coords
if (restart_flag) {
timer->barrier_start(TIME_LOOP);
output->write_restart(update->ntimestep);
timer->barrier_stop(TIME_LOOP);
time_output += timer->array[TIME_LOOP];
}
}
// set total timers and counters so Finish() will process them
timer->array[TIME_LOOP] = time_start;
timer->barrier_stop(TIME_LOOP);
timer->array[TIME_PAIR] = time_dephase;
timer->array[TIME_BOND] = time_dynamics;
timer->array[TIME_KSPACE] = time_quench;
timer->array[TIME_COMM] = time_comm;
timer->array[TIME_OUTPUT] = time_output;
neighbor->ncalls = nbuild;
neighbor->ndanger = ndanger;
if (me_universe == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,
"Loop time of %g on %d procs for %d steps with " BIGINT_FORMAT
" atoms\n",
timer->array[TIME_LOOP],nprocs_universe,nsteps,atom->natoms);
if (universe->ulogfile)
fprintf(universe->ulogfile,
"Loop time of %g on %d procs for %d steps with " BIGINT_FORMAT
" atoms\n",
timer->array[TIME_LOOP],nprocs_universe,nsteps,atom->natoms);
}
finish->end(2);
update->whichflag = 0;
update->firststep = update->laststep = 0;
update->beginstep = update->endstep = 0;
update->restrict_output = 0;
// reset reneighboring criteria
neighbor->every = neigh_every;
neighbor->delay = neigh_delay;
neighbor->dist_check = neigh_dist_check;
// clean up
delete [] displacements;
memory->destroy(tagall);
memory->destroy(xall);
memory->destroy(imageall);
MPI_Comm_free(&comm_replica);
delete random_select;
delete random_dephase;
delete velocity;
delete finish;
modify->delete_compute("prd_temp");
modify->delete_fix("prd_event");
compute_event->reset_extra_compute_fix(NULL);
}
/* ----------------------------------------------------------------------
dephasing = one or more short runs with new random velocities
------------------------------------------------------------------------- */
void PRD::dephase()
{
bigint ntimestep_hold = update->ntimestep;
update->whichflag = 1;
update->nsteps = n_dephase*t_dephase;
timer->barrier_start(TIME_LOOP);
for (int i = 0; i < n_dephase; i++) {
int seed = static_cast<int> (random_dephase->uniform() * MAXSMALLINT);
if (seed == 0) seed = 1;
velocity->create(temp_dephase,seed);
update->integrate->run(t_dephase);
if (temp_flag == 0) temp_dephase = temperature->compute_scalar();
}
timer->barrier_stop(TIME_LOOP);
time_dephase += timer->array[TIME_LOOP];
update->integrate->cleanup();
finish->end(0);
// reset timestep as if dephase did not occur
// clear timestep storage from computes, since now invalid
update->ntimestep = ntimestep_hold;
for (int i = 0; i < modify->ncompute; i++)
if (modify->compute[i]->timeflag) modify->compute[i]->clearstep();
}
/* ----------------------------------------------------------------------
single short dynamics run
------------------------------------------------------------------------- */
void PRD::dynamics()
{
update->whichflag = 1;
update->nsteps = t_event;
lmp->init();
update->integrate->setup();
// this may be needed if don't do full init
//modify->addstep_compute_all(update->ntimestep);
int ncalls = neighbor->ncalls;
timer->barrier_start(TIME_LOOP);
update->integrate->run(t_event);
timer->barrier_stop(TIME_LOOP);
time_dynamics += timer->array[TIME_LOOP];
nbuild += neighbor->ncalls - ncalls;
ndanger += neighbor->ndanger;
update->integrate->cleanup();
finish->end(0);
}
/* ----------------------------------------------------------------------
quench minimization
------------------------------------------------------------------------- */
void PRD::quench()
{
bigint ntimestep_hold = update->ntimestep;
bigint endstep_hold = update->endstep;
// need to change whichflag so that minimize->setup() calling
// modify->setup() will call fix->min_setup()
update->whichflag = 2;
update->nsteps = maxiter;
update->endstep = update->laststep = update->firststep + maxiter;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many iterations");
+ error->all(FLERR,"Too many iterations");
// full init works
lmp->init();
update->minimize->setup();
// partial init does not work
//modify->addstep_compute_all(update->ntimestep);
//update->minimize->setup_minimal(1);
int ncalls = neighbor->ncalls;
timer->barrier_start(TIME_LOOP);
update->minimize->run(maxiter);
timer->barrier_stop(TIME_LOOP);
time_quench += timer->array[TIME_LOOP];
if (neighbor->ncalls == ncalls) quench_reneighbor = 0;
else quench_reneighbor = 1;
update->minimize->cleanup();
finish->end(0);
// reset timestep as if dephase did not occur
// clear timestep storage from computes, since now invalid
update->ntimestep = ntimestep_hold;
update->endstep = update->laststep = endstep_hold;
for (int i = 0; i < modify->ncompute; i++)
if (modify->compute[i]->timeflag) modify->compute[i]->clearstep();
}
/* ----------------------------------------------------------------------
check for an event in any replica
if replica_num is non-negative only check for event on replica_num
if multiple events, choose one at random
return -1 if no event
else return ireplica = world in which event occured
------------------------------------------------------------------------- */
int PRD::check_event(int replica_num)
{
int worldflag,universeflag,scanflag,replicaflag,ireplica;
worldflag = 0;
if (compute_event->compute_scalar() > 0.0) worldflag = 1;
if (replica_num >= 0 && replica_num != universe->iworld) worldflag = 0;
timer->barrier_start(TIME_LOOP);
if (me == 0) MPI_Allreduce(&worldflag,&universeflag,1,
MPI_INT,MPI_SUM,comm_replica);
MPI_Bcast(&universeflag,1,MPI_INT,0,world);
ncoincident = universeflag;
if (!universeflag) ireplica = -1;
else {
if (universeflag > 1) {
int iwhich = static_cast<int>
(universeflag*random_select->uniform()) + 1;
if (me == 0) MPI_Scan(&worldflag,&scanflag,1,
MPI_INT,MPI_SUM,comm_replica);
MPI_Bcast(&scanflag,1,MPI_INT,0,world);
if (scanflag != iwhich) worldflag = 0;
}
if (worldflag) replicaflag = universe->iworld;
else replicaflag = 0;
if (me == 0) MPI_Allreduce(&replicaflag,&ireplica,1,
MPI_INT,MPI_SUM,comm_replica);
MPI_Bcast(&ireplica,1,MPI_INT,0,world);
}
timer->barrier_stop(TIME_LOOP);
time_comm += timer->array[TIME_LOOP];
return ireplica;
}
/* ----------------------------------------------------------------------
share quenched and hot coords owned by ireplica with all replicas
all replicas store event in fix_event
replica 0 dumps event snapshot
flag = 0 = called before PRD run
flag = 1 = called during PRD run = not correlated event
flag = 2 = called during PRD run = correlated event
------------------------------------------------------------------------- */
void PRD::share_event(int ireplica, int flag)
{
timer->barrier_start(TIME_LOOP);
// communicate quenched coords to all replicas and store as event
// decrement event counter if flag = 0 since not really an event
replicate(ireplica);
timer->barrier_stop(TIME_LOOP);
time_comm += timer->array[TIME_LOOP];
// adjust time for last correlated event check (not on first event)
int corr_adjust = t_corr;
if (fix_event->event_number < 1 || flag == 2) corr_adjust = 0;
// delta = time since last correlated event check
int delta = update->ntimestep - fix_event->event_timestep - corr_adjust;
// if this is a correlated event, time elapsed only on one partition
if (flag != 2) delta *= universe->nworlds;
delta += corr_adjust;
// don't change the clock or timestep if this is a restart
if (flag == 0 && fix_event->event_number != 0)
fix_event->store_event_prd(fix_event->event_timestep,0);
else {
fix_event->store_event_prd(update->ntimestep,delta);
fix_event->replica_number = ireplica;
fix_event->correlated_event = 0;
if (flag == 2) fix_event->correlated_event = 1;
fix_event->ncoincident = ncoincident;
}
if (flag == 0) fix_event->event_number--;
// dump snapshot of quenched coords
// must reneighbor and compute forces before dumping
// since replica 0 possibly has new state from another replica
// addstep_compute_all insures eng/virial are calculated if needed
if (output->ndump && universe->iworld == 0) {
timer->barrier_start(TIME_LOOP);
modify->addstep_compute_all(update->ntimestep);
update->integrate->setup_minimal(1);
output->write_dump(update->ntimestep);
timer->barrier_stop(TIME_LOOP);
time_output += timer->array[TIME_LOOP];
}
// restore and communicate hot coords to all replicas
fix_event->restore_state();
timer->barrier_start(TIME_LOOP);
replicate(ireplica);
timer->barrier_stop(TIME_LOOP);
time_comm += timer->array[TIME_LOOP];
}
/* ----------------------------------------------------------------------
universe proc 0 prints event info
------------------------------------------------------------------------- */
void PRD::log_event()
{
timer->array[TIME_LOOP] = time_start;
if (universe->me == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,
BIGINT_FORMAT " %.3f %d %d %d %d %d\n",
fix_event->event_timestep,
timer->elapsed(TIME_LOOP),
fix_event->clock,
fix_event->event_number,fix_event->correlated_event,
fix_event->ncoincident,
fix_event->replica_number);
if (universe->ulogfile)
fprintf(universe->ulogfile,
BIGINT_FORMAT " %.3f %d %d %d %d %d\n",
fix_event->event_timestep,
timer->elapsed(TIME_LOOP),
fix_event->clock,
fix_event->event_number,fix_event->correlated_event,
fix_event->ncoincident,
fix_event->replica_number);
}
}
/* ----------------------------------------------------------------------
communicate atom coords and image flags in ireplica to all other replicas
one proc per replica:
direct overwrite via bcast
equal procs per replica and no replica reneighbored:
direct overwrite via bcast
unequal procs per replica or reneighboring occurred:
collect to root proc of event replica
bcast to roots of other replicas
bcast within each replica
each proc extracts info for atoms it owns using atom IDs
------------------------------------------------------------------------- */
void PRD::replicate(int ireplica)
{
int nreplica = universe->nworlds;
int nprocs_universe = universe->nprocs;
int i,m,flag,commflag;
int counts[nprocs];
if (nreplica == nprocs_universe) commflag = 0;
else if (equal_size_replicas) {
flag = 0;
if (quench_reneighbor) flag = 1;
MPI_Allreduce(&flag,&commflag,1,MPI_INT,MPI_MAX,universe->uworld);
} else commflag = 1;
if (commflag == 0) {
MPI_Bcast(atom->image,atom->nlocal,MPI_INT,ireplica,comm_replica);
MPI_Bcast(atom->x[0],3*atom->nlocal,MPI_DOUBLE,ireplica,comm_replica);
} else {
if (universe->iworld == ireplica) {
MPI_Gather(&atom->nlocal,1,MPI_INT,counts,1,MPI_INT,0,world);
displacements[0] = 0;
for (i = 0; i < nprocs-1; i++)
displacements[i+1] = displacements[i] + counts[i];
MPI_Gatherv(atom->tag,atom->nlocal,MPI_INT,
tagall,counts,displacements,MPI_INT,0,world);
MPI_Gatherv(atom->image,atom->nlocal,MPI_INT,
imageall,counts,displacements,MPI_INT,0,world);
for (i = 0; i < nprocs; i++) counts[i] *= 3;
for (i = 0; i < nprocs-1; i++)
displacements[i+1] = displacements[i] + counts[i];
MPI_Gatherv(atom->x[0],3*atom->nlocal,MPI_DOUBLE,
xall[0],counts,displacements,MPI_DOUBLE,0,world);
}
if (me == 0) {
MPI_Bcast(tagall,natoms,MPI_INT,ireplica,comm_replica);
MPI_Bcast(imageall,natoms,MPI_INT,ireplica,comm_replica);
MPI_Bcast(xall[0],3*natoms,MPI_DOUBLE,ireplica,comm_replica);
}
MPI_Bcast(tagall,natoms,MPI_INT,0,world);
MPI_Bcast(imageall,natoms,MPI_INT,0,world);
MPI_Bcast(xall[0],3*natoms,MPI_DOUBLE,0,world);
double **x = atom->x;
int nlocal = atom->nlocal;
for (i = 0; i < natoms; i++) {
m = atom->map(tagall[i]);
if (m >= 0 && m < nlocal) {
x[m][0] = xall[i][0];
x[m][1] = xall[i][1];
x[m][2] = xall[i][2];
atom->image[m] = imageall[i];
}
}
}
}
/* ----------------------------------------------------------------------
parse optional parameters at end of PRD input line
------------------------------------------------------------------------- */
void PRD::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal prd command");
+ if (narg < 0) error->all(FLERR,"Illegal prd command");
// set defaults
etol = 0.1;
ftol = 0.1;
maxiter = 40;
maxeval = 50;
temp_flag = 0;
char *str = "geom";
int n = strlen(str) + 1;
loop_setting = new char[n];
strcpy(loop_setting,str);
str = "gaussian";
n = strlen(str) + 1;
dist_setting = new char[n];
strcpy(dist_setting,str);
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"min") == 0) {
- if (iarg+5 > narg) error->all("Illegal prd command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal prd command");
etol = atof(arg[iarg+1]);
ftol = atof(arg[iarg+2]);
maxiter = atoi(arg[iarg+3]);
maxeval = atoi(arg[iarg+4]);
- if (maxiter < 0) error->all("Illegal prd command");
+ if (maxiter < 0) error->all(FLERR,"Illegal prd command");
iarg += 5;
} else if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+2 > narg) error->all("Illegal prd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal prd command");
temp_flag = 1;
temp_dephase = atof(arg[iarg+1]);
- if (temp_dephase <= 0.0) error->all("Illegal prd command");
+ if (temp_dephase <= 0.0) error->all(FLERR,"Illegal prd command");
iarg += 2;
} else if (strcmp(arg[iarg],"vel") == 0) {
- if (iarg+3 > narg) error->all("Illegal prd command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal prd command");
delete [] loop_setting;
delete [] dist_setting;
if (strcmp(arg[iarg+1],"all") == 0) loop_setting = NULL;
else if (strcmp(arg[iarg+1],"local") == 0) loop_setting = NULL;
else if (strcmp(arg[iarg+1],"geom") == 0) loop_setting = NULL;
- else error->all("Illegal prd command");
+ else error->all(FLERR,"Illegal prd command");
int n = strlen(arg[iarg+1]) + 1;
loop_setting = new char[n];
strcpy(loop_setting,arg[iarg+1]);
if (strcmp(arg[iarg+2],"uniform") == 0) dist_setting = NULL;
else if (strcmp(arg[iarg+2],"gaussian") == 0) dist_setting = NULL;
- else error->all("Illegal prd command");
+ else error->all(FLERR,"Illegal prd command");
n = strlen(arg[iarg+2]) + 1;
dist_setting = new char[n];
strcpy(dist_setting,arg[iarg+2]);
iarg += 3;
- } else error->all("Illegal prd command");
+ } else error->all(FLERR,"Illegal prd command");
}
}
diff --git a/src/REPLICA/tad.cpp b/src/REPLICA/tad.cpp
index 8241d407a..3f4ba9c16 100644
--- a/src/REPLICA/tad.cpp
+++ b/src/REPLICA/tad.cpp
@@ -1,1011 +1,1011 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "tad.h"
#include "universe.h"
#include "update.h"
#include "atom.h"
#include "domain.h"
#include "region.h"
#include "comm.h"
#include "velocity.h"
#include "integrate.h"
#include "min.h"
#include "neighbor.h"
#include "modify.h"
#include "neb.h"
#include "compute.h"
#include "fix.h"
#include "fix_event_tad.h"
#include "fix_store_state.h"
#include "force.h"
#include "pair.h"
#include "random_park.h"
#include "random_mars.h"
#include "output.h"
#include "dump.h"
#include "finish.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
TAD::TAD(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
TAD::~TAD()
{
memory->sfree(fix_event_list);
if (neb_logfilename != NULL) delete [] neb_logfilename;
delete [] min_style;
delete [] min_style_neb;
}
/* ----------------------------------------------------------------------
perform TAD simulation on root proc
other procs only used for NEB calcs
------------------------------------------------------------------------- */
void TAD::command(int narg, char **arg)
{
fix_event_list = NULL;
n_event_list = 0;
nmax_event_list = 0;
nmin_event_list = 10;
// error checks
if (domain->box_exist == 0)
- error->all("Tad command before simulation box is defined");
+ error->all(FLERR,"Tad command before simulation box is defined");
if (universe->nworlds == 1)
- error->all("Cannot use TAD with a single replica for NEB");
+ error->all(FLERR,"Cannot use TAD with a single replica for NEB");
if (universe->nworlds != universe->nprocs)
- error->all("Can only use TAD with 1-processor replicas for NEB");
+ error->all(FLERR,"Can only use TAD with 1-processor replicas for NEB");
if (atom->sortfreq > 0)
- error->all("Cannot use TAD with atom_modify sort enabled for NEB");
+ error->all(FLERR,"Cannot use TAD with atom_modify sort enabled for NEB");
if (atom->map_style == 0)
- error->all("Cannot use TAD unless atom map exists for NEB");
+ error->all(FLERR,"Cannot use TAD unless atom map exists for NEB");
- if (narg < 7) error->universe_all("Illegal tad command");
+ if (narg < 7) error->universe_all(FLERR,"Illegal tad command");
nsteps = atoi(arg[0]);
t_event = atoi(arg[1]);
templo = atof(arg[2]);
temphi = atof(arg[3]);
delta_conf = atof(arg[4]);
tmax = atof(arg[5]);
char id_compute[strlen(arg[6])+1];
strcpy(id_compute,arg[6]);
options(narg-7,&arg[7]);
// total # of timesteps must be multiple of t_event
- if (t_event <= 0) error->universe_all("Invalid t_event in tad command");
+ if (t_event <= 0) error->universe_all(FLERR,"Invalid t_event in tad command");
if (nsteps % t_event)
- error->universe_all("TAD nsteps must be multiple of t_event");
+ error->universe_all(FLERR,"TAD nsteps must be multiple of t_event");
if (delta_conf <= 0.0 || delta_conf >= 1.0)
- error->universe_all("Invalid delta_conf in tad command");
+ error->universe_all(FLERR,"Invalid delta_conf in tad command");
if (tmax <= 0.0)
- error->universe_all("Invalid tmax in tad command");
+ error->universe_all(FLERR,"Invalid tmax in tad command");
// deltconf = (ln(1/delta))/freq_min (timestep units)
deltconf = -log(delta_conf)*tmax/update->dt;
// local storage
int me_universe = universe->me;
int nprocs_universe = universe->nprocs;
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
delta_beta = (1.0/templo - 1.0/temphi) / force->boltz;
ratio_beta = templo/temphi;
// create FixEventTAD object to store last event
int narg2 = 3;
char **args = new char*[narg2];
args[0] = (char *) "tad_event";
args[1] = (char *) "all";
args[2] = (char *) "EVENT/TAD";
modify->add_fix(narg2,args);
fix_event = (FixEventTAD *) modify->fix[modify->nfix-1];
delete [] args;
// create FixStoreState object to store revert state
narg2 = 13;
args = new char*[narg2];
args[0] = (char *) "tad_revert";
args[1] = (char *) "all";
args[2] = (char *) "store/state";
args[3] = (char *) "0";
args[4] = (char *) "x";
args[5] = (char *) "y";
args[6] = (char *) "z";
args[7] = (char *) "ix";
args[8] = (char *) "iy";
args[9] = (char *) "iz";
args[10] = (char *) "vx";
args[11] = (char *) "vy";
args[12] = (char *) "vz";
modify->add_fix(narg2,args);
fix_revert = (FixStoreState *) modify->fix[modify->nfix-1];
delete [] args;
// create Finish for timing output
finish = new Finish(lmp);
// assign FixEventTAD to event-detection compute
// necessary so it will know atom coords at last event
int icompute = modify->find_compute(id_compute);
- if (icompute < 0) error->all("Could not find compute ID for TAD");
+ if (icompute < 0) error->all(FLERR,"Could not find compute ID for TAD");
compute_event = modify->compute[icompute];
compute_event->reset_extra_compute_fix("tad_event");
// reset reneighboring criteria since will perform minimizations
neigh_every = neighbor->every;
neigh_delay = neighbor->delay;
neigh_dist_check = neighbor->dist_check;
if (neigh_every != 1 || neigh_delay != 0 || neigh_dist_check != 1) {
if (me_universe == 0)
- error->warning("Resetting reneighboring criteria during TAD");
+ error->warning(FLERR,"Resetting reneighboring criteria during TAD");
}
neighbor->every = 1;
neighbor->delay = 0;
neighbor->dist_check = 1;
// initialize TAD as if one long dynamics run
update->whichflag = 1;
update->nsteps = nsteps;
update->beginstep = update->firststep = update->ntimestep;
update->endstep = update->laststep = update->firststep + nsteps;
update->restrict_output = 1;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many timesteps");
+ error->all(FLERR,"Too many timesteps");
lmp->init();
// set minimize style for quench
narg2 = 1;
args = new char*[narg2];
args[0] = min_style;
update->create_minimize(narg2,args);
delete [] args;
// init minimizer settings and minimizer itself
update->etol = etol;
update->ftol = ftol;
update->max_eval = maxeval;
update->minimize->init();
// perform TAD simulation
if (me_universe == 0 && universe->uscreen)
fprintf(universe->uscreen,"Setting up TAD ...\n");
if (me_universe == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,
"Step CPU N M Status Barrier Margin t_lo delt_lo\n"
);
if (universe->ulogfile)
fprintf(universe->ulogfile,
"Step CPU N M Status Barrier Margin t_lo delt_lo\n"
);
}
ulogfile_lammps = universe->ulogfile;
uscreen_lammps = universe->uscreen;
ulogfile_neb = NULL;
uscreen_neb = NULL;
if (me_universe == 0 && neb_logfilename)
ulogfile_neb = fopen(neb_logfilename,"w");
// store hot state and quenched event, only on replica 0
// need this line if quench() does only setup_minimal()
// update->minimize->setup();
// This should work with if uncommented, but does not
// if (universe->iworld == 0) {
fix_event->store_state();
quench();
timer->barrier_start(TIME_LOOP);
time_start = timer->array[TIME_LOOP];
fix_event->store_event_tad(update->ntimestep);
log_event(0);
fix_event->restore_state();
// do full init/setup
update->whichflag = 1;
lmp->init();
update->integrate->setup();
// }
// main loop: look for events until out of time
// (1) dynamics, store state, quench, check event, restore state
// (2) if event, perform NEB, record in fix_event_list
// (3) if confident, pick earliest event
nbuild = ndanger = 0;
time_neb = time_dynamics = time_quench = time_comm = time_output = 0.0;
timer->barrier_start(TIME_LOOP);
time_start = timer->array[TIME_LOOP];
int confident_flag, event_flag;
if (universe->iworld == 0) {
while (update->ntimestep < update->endstep) {
// initialize list of possible events
initialize_event_list();
confident_flag = 0;
while (update->ntimestep < update->endstep) {
event_flag = 0;
while (update->ntimestep < update->endstep) {
dynamics();
fix_event->store_state();
quench();
event_flag = check_event();
MPI_Bcast(&event_flag,1,MPI_INT,0,universe->uworld);
if (event_flag) break;
// restore hot state
fix_event->restore_state();
// store hot state in revert
fix_revert->end_of_step();
}
if (!event_flag) break;
add_event();
perform_neb(n_event_list-1);
compute_tlo(n_event_list-1);
confident_flag = check_confidence();
MPI_Bcast(&confident_flag,1,MPI_INT,0,universe->uworld);
if (confident_flag) break;
if (universe->iworld == 0) revert();
}
if (!confident_flag) break;
perform_event(event_first);
// need to sync timestep with TAD
MPI_Bcast(&(update->ntimestep),1,MPI_INT,0,universe->uworld);
int restart_flag = 0;
if (output->restart_every && universe->iworld == 0)
if (fix_event->event_number % output->restart_every == 0)
restart_flag = 1;
// full init/setup since are starting after event
update->whichflag = 1;
lmp->init();
update->integrate->setup();
// write restart file of hot coords
if (restart_flag) {
timer->barrier_start(TIME_LOOP);
output->write_restart(update->ntimestep);
timer->barrier_stop(TIME_LOOP);
time_output += timer->array[TIME_LOOP];
}
}
} else {
while (update->ntimestep < update->endstep) {
confident_flag = 0;
while (update->ntimestep < update->endstep) {
event_flag = 0;
while (update->ntimestep < update->endstep) {
update->ntimestep += t_event;
MPI_Bcast(&event_flag,1,MPI_INT,0,universe->uworld);
if (event_flag) break;
}
if (!event_flag) break;
perform_neb(-1);
MPI_Bcast(&confident_flag,1,MPI_INT,0,universe->uworld);
if (confident_flag) break;
}
if (!confident_flag) break;
// need to sync timestep with TAD
MPI_Bcast(&(update->ntimestep),1,MPI_INT,0,universe->uworld);
}
}
// set total timers and counters so Finish() will process them
timer->array[TIME_LOOP] = time_start;
timer->barrier_stop(TIME_LOOP);
timer->array[TIME_PAIR] = time_neb;
timer->array[TIME_BOND] = time_dynamics;
timer->array[TIME_KSPACE] = time_quench;
timer->array[TIME_COMM] = time_comm;
timer->array[TIME_OUTPUT] = time_output;
neighbor->ncalls = nbuild;
neighbor->ndanger = ndanger;
if (me_universe == 0) {
if (universe->uscreen)
fprintf(universe->uscreen,
"Loop time of %g on %d procs for %d steps with " BIGINT_FORMAT
" atoms\n",
timer->array[TIME_LOOP],nprocs_universe,nsteps,atom->natoms);
if (universe->ulogfile)
fprintf(universe->ulogfile,
"Loop time of %g on %d procs for %d steps with " BIGINT_FORMAT
" atoms\n",
timer->array[TIME_LOOP],nprocs_universe,nsteps,atom->natoms);
}
if (me_universe == 0) fclose(ulogfile_neb);
finish->end(3);
update->whichflag = 0;
update->firststep = update->laststep = 0;
update->beginstep = update->endstep = 0;
update->restrict_output = 0;
// reset reneighboring criteria
neighbor->every = neigh_every;
neighbor->delay = neigh_delay;
neighbor->dist_check = neigh_dist_check;
delete finish;
modify->delete_fix("tad_event");
modify->delete_fix("tad_revert");
delete_event_list();
compute_event->reset_extra_compute_fix(NULL);
}
/* ----------------------------------------------------------------------
single short dynamics run
------------------------------------------------------------------------- */
void TAD::dynamics()
{
update->whichflag = 1;
update->nsteps = t_event;
lmp->init();
update->integrate->setup();
// this may be needed if don't do full init
//modify->addstep_compute_all(update->ntimestep);
int ncalls = neighbor->ncalls;
timer->barrier_start(TIME_LOOP);
update->integrate->run(t_event);
timer->barrier_stop(TIME_LOOP);
time_dynamics += timer->array[TIME_LOOP];
nbuild += neighbor->ncalls - ncalls;
ndanger += neighbor->ndanger;
update->integrate->cleanup();
finish->end(0);
}
/* ----------------------------------------------------------------------
quench minimization
------------------------------------------------------------------------- */
void TAD::quench()
{
bigint ntimestep_hold = update->ntimestep;
bigint endstep_hold = update->endstep;
// need to change whichflag so that minimize->setup() calling
// modify->setup() will call fix->min_setup()
update->whichflag = 2;
update->nsteps = maxiter;
update->endstep = update->laststep = update->firststep + maxiter;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many iterations");
+ error->all(FLERR,"Too many iterations");
// full init works
lmp->init();
update->minimize->setup();
// partial init does not work
//modify->addstep_compute_all(update->ntimestep);
//update->minimize->setup_minimal(1);
int ncalls = neighbor->ncalls;
timer->barrier_start(TIME_LOOP);
update->minimize->run(maxiter);
timer->barrier_stop(TIME_LOOP);
time_quench += timer->array[TIME_LOOP];
if (neighbor->ncalls == ncalls) quench_reneighbor = 0;
else quench_reneighbor = 1;
update->minimize->cleanup();
finish->end(1);
// reset timestep as if quench did not occur
// clear timestep storage from computes, since now invalid
update->ntimestep = ntimestep_hold;
update->endstep = update->laststep = endstep_hold;
for (int i = 0; i < modify->ncompute; i++)
if (modify->compute[i]->timeflag) modify->compute[i]->clearstep();
}
/* ----------------------------------------------------------------------
check for an event
return 0 if no event
return 1 if event
------------------------------------------------------------------------- */
int TAD::check_event()
{
int flag;
flag = 0;
if (compute_event->compute_scalar() > 0.0) flag = 1;
return flag;
}
/* ----------------------------------------------------------------------
universe proc 0 prints event info
------------------------------------------------------------------------- */
void TAD::log_event(int ievent)
{
timer->array[TIME_LOOP] = time_start;
if (universe->me == 0) {
double tfrac = 0.0;
if (universe->uscreen)
fprintf(universe->uscreen,
BIGINT_FORMAT " %.3f %d %d %s %.3f %.3f %.3f %.3f\n",
fix_event->event_timestep,
timer->elapsed(TIME_LOOP),
fix_event->event_number,ievent,
"E ",
fix_event->ebarrier,tfrac,
fix_event->tlo,deltfirst);
if (universe->ulogfile)
fprintf(universe->ulogfile,
BIGINT_FORMAT " %.3f %d %d %s %.3f %.3f %.3f %.3f\n",
fix_event->event_timestep,
timer->elapsed(TIME_LOOP),
fix_event->event_number,ievent,
"E ",
fix_event->ebarrier,tfrac,
fix_event->tlo,deltfirst);
}
// dump snapshot of quenched coords
// must reneighbor and compute forces before dumping
// addstep_compute_all insures eng/virial are calculated if needed
if (output->ndump && universe->iworld == 0) {
timer->barrier_start(TIME_LOOP);
modify->addstep_compute_all(update->ntimestep);
update->integrate->setup_minimal(1);
output->write_dump(update->ntimestep);
timer->barrier_stop(TIME_LOOP);
time_output += timer->array[TIME_LOOP];
}
}
/* ----------------------------------------------------------------------
parse optional parameters at end of TAD input line
------------------------------------------------------------------------- */
void TAD::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal tad command");
+ if (narg < 0) error->all(FLERR,"Illegal tad command");
// set defaults
etol = 0.1;
ftol = 0.1;
maxiter = 40;
maxeval = 50;
etol_neb = 0.01;
ftol_neb = 0.01;
n1steps_neb = 100;
n2steps_neb = 100;
nevery_neb = 10;
min_style = new char[3];
strcpy(min_style,"cg");
min_style_neb = new char[9];
strcpy(min_style_neb,"quickmin");
neb_logfilename = NULL;
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"min") == 0) {
- if (iarg+5 > narg) error->all("Illegal tad command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal tad command");
etol = atof(arg[iarg+1]);
ftol = atof(arg[iarg+2]);
maxiter = atoi(arg[iarg+3]);
maxeval = atoi(arg[iarg+4]);
if (maxiter < 0 || maxeval < 0 ||
etol < 0.0 || ftol < 0.0 )
- error->all("Illegal tad command");
+ error->all(FLERR,"Illegal tad command");
iarg += 5;
} else if (strcmp(arg[iarg],"neb") == 0) {
- if (iarg+6 > narg) error->all("Illegal tad command");
+ if (iarg+6 > narg) error->all(FLERR,"Illegal tad command");
etol_neb = atof(arg[iarg+1]);
ftol_neb = atof(arg[iarg+2]);
n1steps_neb = atoi(arg[iarg+3]);
n2steps_neb = atoi(arg[iarg+4]);
nevery_neb = atoi(arg[iarg+5]);
if (etol_neb < 0.0 || ftol_neb < 0.0 ||
n1steps_neb < 0 || n2steps_neb < 0 ||
- nevery_neb < 0) error->all("Illegal tad command");
+ nevery_neb < 0) error->all(FLERR,"Illegal tad command");
iarg += 6;
} else if (strcmp(arg[iarg],"min_style") == 0) {
- if (iarg+2 > narg) error->all("Illegal tad command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal tad command");
int n = strlen(arg[iarg+1]) + 1;
delete [] min_style;
min_style = new char[n];
strcpy(min_style,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"neb_style") == 0) {
- if (iarg+2 > narg) error->all("Illegal tad command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal tad command");
int n = strlen(arg[iarg+1]) + 1;
delete [] min_style_neb;
min_style_neb = new char[n];
strcpy(min_style_neb,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"neb_log") == 0) {
delete [] neb_logfilename;
- if (iarg+2 > narg) error->all("Illegal tad command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal tad command");
if (strcmp(arg[iarg+1],"none") == 0) neb_logfilename = NULL;
else {
int n = strlen(arg[iarg+1]) + 1;
neb_logfilename = new char[n];
strcpy(neb_logfilename,arg[iarg+1]);
}
iarg += 2;
- } else error->all("Illegal tad command");
+ } else error->all(FLERR,"Illegal tad command");
}
}
/* ----------------------------------------------------------------------
perform NEB calculation
------------------------------------------------------------------------- */
void TAD::perform_neb(int ievent)
{
double **x = atom->x;
int nlocal = atom->nlocal;
double *buf_final;
memory->create(buf_final,3*nlocal,"tad:buffinal");
// set system to quenched state of event ievent
if (universe->iworld == 0) {
fix_event_list[ievent]->restore_event();
int ii = 0;
for (int i = 0; i < nlocal; i++) {
buf_final[ii++] = x[i][0];
buf_final[ii++] = x[i][1];
buf_final[ii++] = x[i][2];
}
}
MPI_Bcast(buf_final,3*nlocal,MPI_DOUBLE,universe->root_proc[0],
universe->uworld);
double *buf_init;
memory->create(buf_init,3*nlocal,"tad:bufinit");
// set system to quenched state of fix_event
if (universe->iworld == 0) {
fix_event->restore_event();
int ii = 0;
for (int i = 0; i < nlocal; i++) {
buf_init[ii++] = x[i][0];
buf_init[ii++] = x[i][1];
buf_init[ii++] = x[i][2];
}
}
MPI_Bcast(buf_init,3*nlocal,MPI_DOUBLE,universe->root_proc[0],
universe->uworld);
// create FixNEB object to support NEB
int narg2 = 4;
char **args = new char*[narg2];
args[0] = (char *) "neb";
args[1] = (char *) "all";
args[2] = (char *) "neb";
char str[128];
args[3] = str;
double kspring = 1.0;
sprintf(args[3],"%f",kspring);
modify->add_fix(narg2,args);
fix_neb = (Fix *) modify->fix[modify->nfix-1];
delete [] args;
// switch minimize style to quickmin for NEB
narg2 = 1;
args = new char*[narg2];
args[0] = min_style_neb;
update->create_minimize(narg2,args);
delete [] args;
// create NEB object
neb = new NEB(lmp,etol_neb,ftol_neb,n1steps_neb,
n2steps_neb,nevery_neb,buf_init,buf_final);
// free up temporary arrays
memory->destroy(buf_init);
memory->destroy(buf_final);
// Run NEB
int beginstep_hold = update->beginstep;
int endstep_hold = update->endstep;
int ntimestep_hold = update->ntimestep;
int nsteps_hold = update->nsteps;
if (universe->me == 0) {
universe->ulogfile = ulogfile_neb;
universe->uscreen = uscreen_neb;
}
// Had to bypass timer interface
// because timer->array is reset
// inside neb->run()
// timer->barrier_start(TIME_LOOP);
// neb->run();
// timer->barrier_stop(TIME_LOOP);
// time_neb += timer->array[TIME_LOOP];
MPI_Barrier(world);
double time_tmp = MPI_Wtime();
neb->run();
MPI_Barrier(world);
time_neb += MPI_Wtime() - time_tmp;
if (universe->me == 0) {
universe->ulogfile = ulogfile_lammps;
universe->uscreen = uscreen_lammps;
}
// Extract barrier energy from NEB
if (universe->iworld == 0)
fix_event_list[ievent]->ebarrier = neb->ebf;
update->beginstep = update->firststep = beginstep_hold;
update->endstep = update->laststep = endstep_hold;
update->ntimestep = ntimestep_hold;
update->nsteps = nsteps_hold;
// switch minimize style back for quench
narg2 = 1;
args = new char*[narg2];
args[0] = min_style;
update->create_minimize(narg2,args);
update->etol = etol;
update->ftol = ftol;
delete [] args;
// Clean up
modify->delete_fix("neb");
delete neb;
}
/* ----------------------------------------------------------------------
check if confidence criterion for tstop is satisfied
return 0 if not satisfied
return 1 if satisfied
------------------------------------------------------------------------- */
int TAD::check_confidence()
{
int flag;
// update stopping time
deltstop = deltconf*pow(deltfirst/deltconf, ratio_beta);
flag = 0;
if (deltstop < update->ntimestep - fix_event->event_timestep) flag = 1;
return flag;
}
/* ----------------------------------------------------------------------
reflect back in to starting state
------------------------------------------------------------------------- */
void TAD::revert()
{
double **x = atom->x;
double **v = atom->v;
int *image = atom->image;
int nlocal = atom->nlocal;
double **array_atom = fix_revert->array_atom;
for (int i = 0; i < nlocal; i++) {
x[i][0] = array_atom[i][0];
x[i][1] = array_atom[i][1];
x[i][2] = array_atom[i][2];
image[i] = ((int(array_atom[i][5]) + 512 & 1023) << 20) |
((int(array_atom[i][4]) + 512 & 1023) << 10) |
(int(array_atom[i][3]) + 512 & 1023);
v[i][0] = -array_atom[i][6];
v[i][1] = -array_atom[i][7];
v[i][2] = -array_atom[i][8];
}
}
/* ----------------------------------------------------------------------
Initialize list of possible events
------------------------------------------------------------------------- */
void TAD::initialize_event_list() {
// First delete old events, if any
delete_event_list();
// Create new list
n_event_list = 0;
grow_event_list(nmin_event_list);
}
/* ----------------------------------------------------------------------
Delete list of possible events
------------------------------------------------------------------------- */
void TAD::delete_event_list() {
for (int i = 0; i < n_event_list; i++) {
char str[128];
sprintf(str,"tad_event_%d",i);
modify->delete_fix(str);
}
memory->sfree(fix_event_list);
fix_event_list = NULL;
n_event_list = 0;
nmax_event_list = 0;
}
/* ----------------------------------------------------------------------
add event
------------------------------------------------------------------------- */
void TAD::add_event()
{
// create FixEventTAD object to store possible event
int narg = 3;
char **args = new char*[narg];
char str[128];
sprintf(str,"tad_event_%d",n_event_list);
args[0] = str;
args[1] = (char *) "all";
args[2] = (char *) "EVENT/TAD";
modify->add_fix(narg,args);
if (n_event_list == nmax_event_list)
grow_event_list(nmax_event_list+nmin_event_list);
n_event_list += 1;
int ievent = n_event_list-1;
fix_event_list[ievent] = (FixEventTAD *) modify->fix[modify->nfix-1];
// store quenched state for new event
fix_event_list[ievent]->store_event_tad(update->ntimestep);
// store hot state for new event
fix_event->restore_state();
fix_event_list[ievent]->store_state();
// string clean-up
delete [] args;
}
/* ----------------------------------------------------------------------
compute cold time for event ievent
------------------------------------------------------------------------- */
void TAD::compute_tlo(int ievent)
{
double deltlo,delthi,ebarrier;
ebarrier = fix_event_list[ievent]->ebarrier;
delthi = fix_event_list[ievent]->event_timestep
- fix_event->event_timestep;
deltlo = delthi*exp(ebarrier*delta_beta);
fix_event_list[ievent]->tlo = fix_event->tlo + deltlo;
// update first event
char* statstr = "D ";
if (ievent == 0) {
deltfirst = deltlo;
event_first = ievent;
statstr = "DF";
} else if (deltlo < deltfirst) {
deltfirst = deltlo;
event_first = ievent;
statstr = "DF";
}
// first-replica output about each event
timer->array[TIME_LOOP] = time_start;
if (universe->me == 0) {
double tfrac = 0.0;
if (ievent > 0) tfrac = delthi/deltstop;
if (universe->uscreen)
fprintf(universe->uscreen,
BIGINT_FORMAT " %.3f %d %d %s %.3f %.3f %.3f %.3f\n",
fix_event_list[ievent]->event_timestep,
timer->elapsed(TIME_LOOP),
fix_event->event_number,
ievent,statstr,ebarrier,tfrac,
fix_event->tlo,deltlo);
if (universe->ulogfile)
fprintf(universe->ulogfile,
BIGINT_FORMAT " %.3f %d %d %s %.3f %.3f %.3f %.3f\n",
fix_event_list[ievent]->event_timestep,
timer->elapsed(TIME_LOOP),
fix_event->event_number,
ievent,statstr,ebarrier,tfrac,
fix_event->tlo,deltlo);
}
}
/* ----------------------------------------------------------------------
perform event
------------------------------------------------------------------------- */
void TAD::perform_event(int ievent)
{
// reset timestep to that of event
update->ntimestep = fix_event_list[ievent]->event_timestep;
// Copy event to current event
// Should really use copy constructor for this
fix_event->tlo = fix_event_list[ievent]->tlo;
fix_event->ebarrier = fix_event_list[ievent]->ebarrier;
fix_event->event_number++;
fix_event->event_timestep = update->ntimestep;
fix_event_list[ievent]->restore_event();
fix_event->store_event_tad(fix_event_list[ievent]->event_timestep);
// output stats and dump for quenched state
log_event(ievent);
// load and store hot state
fix_event_list[ievent]->restore_state();
fix_event->store_state();
}
/* ----------------------------------------------------------------------
Allocate list of pointers to events
------------------------------------------------------------------------- */
void TAD::grow_event_list(int nmax) {
if (nmax_event_list > nmax) return;
fix_event_list = (FixEventTAD **)
memory->srealloc(fix_event_list,nmax*sizeof(FixEventTAD *),"tad:eventlist");
nmax_event_list = nmax;
}
diff --git a/src/REPLICA/temper.cpp b/src/REPLICA/temper.cpp
index ea8fcfaab..d95fb3d89 100644
--- a/src/REPLICA/temper.cpp
+++ b/src/REPLICA/temper.cpp
@@ -1,360 +1,360 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mark Sears (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "temper.h"
#include "universe.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "integrate.h"
#include "modify.h"
#include "compute.h"
#include "force.h"
#include "output.h"
#include "thermo.h"
#include "fix.h"
#include "random_park.h"
#include "finish.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
// #define TEMPER_DEBUG 1
/* ---------------------------------------------------------------------- */
Temper::Temper(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
Temper::~Temper()
{
MPI_Comm_free(&roots);
if (ranswap) delete ranswap;
delete ranboltz;
delete [] set_temp;
delete [] temp2world;
delete [] world2temp;
delete [] world2root;
}
/* ----------------------------------------------------------------------
perform tempering with inter-world swaps
------------------------------------------------------------------------- */
void Temper::command(int narg, char **arg)
{
if (universe->nworlds == 1)
- error->all("Must have more than one processor partition to temper");
+ error->all(FLERR,"Must have more than one processor partition to temper");
if (domain->box_exist == 0)
- error->all("Temper command before simulation box is defined");
- if (narg != 6 && narg != 7) error->universe_all("Illegal temper command");
+ error->all(FLERR,"Temper command before simulation box is defined");
+ if (narg != 6 && narg != 7) error->universe_all(FLERR,"Illegal temper command");
int nsteps = atoi(arg[0]);
nevery = atoi(arg[1]);
double temp = atof(arg[2]);
for (whichfix = 0; whichfix < modify->nfix; whichfix++)
if (strcmp(arg[3],modify->fix[whichfix]->id) == 0) break;
if (whichfix == modify->nfix)
- error->universe_all("Tempering fix ID is not defined");
+ error->universe_all(FLERR,"Tempering fix ID is not defined");
seed_swap = atoi(arg[4]);
seed_boltz = atoi(arg[5]);
my_set_temp = universe->iworld;
if (narg == 7) my_set_temp = atoi(arg[6]);
// swap frequency must evenly divide total # of timesteps
- if (nevery == 0) error->universe_all("Invalid frequency in temper command");
+ if (nevery == 0) error->universe_all(FLERR,"Invalid frequency in temper command");
nswaps = nsteps/nevery;
if (nswaps*nevery != nsteps)
- error->universe_all("Non integer # of swaps in temper command");
+ error->universe_all(FLERR,"Non integer # of swaps in temper command");
// fix style must be appropriate for temperature control
if ((strcmp(modify->fix[whichfix]->style,"nvt") != 0) &&
(strcmp(modify->fix[whichfix]->style,"langevin") != 0) &&
(strcmp(modify->fix[whichfix]->style,"temp/berendsen") != 0) &&
(strcmp(modify->fix[whichfix]->style,"temp/rescale") != 0))
- error->universe_all("Tempering temperature fix is not valid");
+ error->universe_all(FLERR,"Tempering temperature fix is not valid");
// setup for long tempering run
update->whichflag = 1;
update->nsteps = nsteps;
update->beginstep = update->firststep = update->ntimestep;
update->endstep = update->laststep = update->firststep + nsteps;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many timesteps");
+ error->all(FLERR,"Too many timesteps");
lmp->init();
// local storage
me_universe = universe->me;
MPI_Comm_rank(world,&me);
nworlds = universe->nworlds;
iworld = universe->iworld;
boltz = force->boltz;
// pe_compute = ptr to thermo_pe compute
// notify compute it will be called at first swap
int id = modify->find_compute("thermo_pe");
- if (id < 0) error->all("Tempering could not find thermo_pe compute");
+ if (id < 0) error->all(FLERR,"Tempering could not find thermo_pe compute");
Compute *pe_compute = modify->compute[id];
pe_compute->addstep(update->ntimestep + nevery);
// create MPI communicator for root proc from each world
int color;
if (me == 0) color = 0;
else color = 1;
MPI_Comm_split(universe->uworld,color,0,&roots);
// RNGs for swaps and Boltzmann test
// warm up Boltzmann RNG
if (seed_swap) ranswap = new RanPark(lmp,seed_swap);
else ranswap = NULL;
ranboltz = new RanPark(lmp,seed_boltz + me_universe);
for (int i = 0; i < 100; i++) ranboltz->uniform();
// world2root[i] = global proc that is root proc of world i
world2root = new int[nworlds];
if (me == 0)
MPI_Allgather(&me_universe,1,MPI_INT,world2root,1,MPI_INT,roots);
MPI_Bcast(world2root,nworlds,MPI_INT,0,world);
// create static list of set temperatures
// allgather tempering arg "temp" across root procs
// bcast from each root to other procs in world
set_temp = new double[nworlds];
if (me == 0) MPI_Allgather(&temp,1,MPI_DOUBLE,set_temp,1,MPI_DOUBLE,roots);
MPI_Bcast(set_temp,nworlds,MPI_DOUBLE,0,world);
// create world2temp only on root procs from my_set_temp
// create temp2world on root procs from world2temp,
// then bcast to all procs within world
world2temp = new int[nworlds];
temp2world = new int[nworlds];
if (me == 0) {
MPI_Allgather(&my_set_temp,1,MPI_INT,world2temp,1,MPI_INT,roots);
for (int i = 0; i < nworlds; i++) temp2world[world2temp[i]] = i;
}
MPI_Bcast(temp2world,nworlds,MPI_INT,0,world);
// if restarting tempering, reset temp target of Fix to current my_set_temp
if (narg == 7) {
double new_temp = set_temp[my_set_temp];
modify->fix[whichfix]->reset_target(new_temp);
}
// setup tempering runs
int i,which,partner,swap,partner_set_temp,partner_world;
double pe,pe_partner,boltz_factor,new_temp;
MPI_Status status;
if (me_universe == 0 && universe->uscreen)
fprintf(universe->uscreen,"Setting up tempering ...\n");
update->integrate->setup();
if (me_universe == 0) {
if (universe->uscreen) {
fprintf(universe->uscreen,"Step");
for (int i = 0; i < nworlds; i++)
fprintf(universe->uscreen," T%d",i);
fprintf(universe->uscreen,"\n");
}
if (universe->ulogfile) {
fprintf(universe->ulogfile,"Step");
for (int i = 0; i < nworlds; i++)
fprintf(universe->ulogfile," T%d",i);
fprintf(universe->ulogfile,"\n");
}
print_status();
}
timer->barrier_start(TIME_LOOP);
for (int iswap = 0; iswap < nswaps; iswap++) {
// run for nevery timesteps
update->integrate->run(nevery);
// compute PE
// notify compute it will be called at next swap
pe = pe_compute->compute_scalar();
pe_compute->addstep(update->ntimestep + nevery);
// which = which of 2 kinds of swaps to do (0,1)
if (!ranswap) which = iswap % 2;
else if (ranswap->uniform() < 0.5) which = 0;
else which = 1;
// partner_set_temp = which set temp I am partnering with for this swap
if (which == 0) {
if (my_set_temp % 2 == 0) partner_set_temp = my_set_temp + 1;
else partner_set_temp = my_set_temp - 1;
} else {
if (my_set_temp % 2 == 1) partner_set_temp = my_set_temp + 1;
else partner_set_temp = my_set_temp - 1;
}
// partner = proc ID to swap with
// if partner = -1, then I am not a proc that swaps
partner = -1;
if (me == 0 && partner_set_temp >= 0 && partner_set_temp < nworlds) {
partner_world = temp2world[partner_set_temp];
partner = world2root[partner_world];
}
// swap with a partner, only root procs in each world participate
// hi proc sends PE to low proc
// lo proc make Boltzmann decision on whether to swap
// lo proc communicates decision back to hi proc
swap = 0;
if (partner != -1) {
if (me_universe > partner)
MPI_Send(&pe,1,MPI_DOUBLE,partner,0,universe->uworld);
else
MPI_Recv(&pe_partner,1,MPI_DOUBLE,partner,0,universe->uworld,&status);
if (me_universe < partner) {
boltz_factor = (pe - pe_partner) *
(1.0/(boltz*set_temp[my_set_temp]) -
1.0/(boltz*set_temp[partner_set_temp]));
if (boltz_factor >= 0.0) swap = 1;
else if (ranboltz->uniform() < exp(boltz_factor)) swap = 1;
}
if (me_universe < partner)
MPI_Send(&swap,1,MPI_INT,partner,0,universe->uworld);
else
MPI_Recv(&swap,1,MPI_INT,partner,0,universe->uworld,&status);
#ifdef TEMPER_DEBUG
if (me_universe < partner)
printf("SWAP %d & %d: yes = %d,Ts = %d %d, PEs = %g %g, Bz = %g %g\n",
me_universe,partner,swap,my_set_temp,partner_set_temp,
pe,pe_partner,boltz_factor,exp(boltz_factor));
#endif
}
// bcast swap result to other procs in my world
MPI_Bcast(&swap,1,MPI_INT,0,world);
// rescale kinetic energy via velocities if move is accepted
if (swap) scale_velocities(partner_set_temp,my_set_temp);
// if my world swapped, all procs in world reset temp target of Fix
if (swap) {
new_temp = set_temp[partner_set_temp];
modify->fix[whichfix]->reset_target(new_temp);
}
// update my_set_temp and temp2world on every proc
// root procs update their value if swap took place
// allgather across root procs
// bcast within my world
if (swap) my_set_temp = partner_set_temp;
if (me == 0) {
MPI_Allgather(&my_set_temp,1,MPI_INT,world2temp,1,MPI_INT,roots);
for (i = 0; i < nworlds; i++) temp2world[world2temp[i]] = i;
}
MPI_Bcast(temp2world,nworlds,MPI_INT,0,world);
// print out current swap status
if (me_universe == 0) print_status();
}
timer->barrier_stop(TIME_LOOP);
update->integrate->cleanup();
Finish finish(lmp);
finish.end(1);
update->whichflag = 0;
update->firststep = update->laststep = 0;
update->beginstep = update->endstep = 0;
}
/* ----------------------------------------------------------------------
scale kinetic energy via velocities a la Sugita
------------------------------------------------------------------------- */
void Temper::scale_velocities(int t_partner, int t_me)
{
double sfactor = sqrt(set_temp[t_partner]/set_temp[t_me]);
double **v = atom->v;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
v[i][0] = v[i][0]*sfactor;
v[i][1] = v[i][1]*sfactor;
v[i][2] = v[i][2]*sfactor;
}
}
/* ----------------------------------------------------------------------
proc 0 prints current tempering status
------------------------------------------------------------------------- */
void Temper::print_status()
{
if (universe->uscreen) {
fprintf(universe->uscreen,BIGINT_FORMAT,update->ntimestep);
for (int i = 0; i < nworlds; i++)
fprintf(universe->uscreen," %d",world2temp[i]);
fprintf(universe->uscreen,"\n");
}
if (universe->ulogfile) {
fprintf(universe->ulogfile,BIGINT_FORMAT,update->ntimestep);
for (int i = 0; i < nworlds; i++)
fprintf(universe->ulogfile," %d",world2temp[i]);
fprintf(universe->ulogfile,"\n");
fflush(universe->ulogfile);
}
}
diff --git a/src/SHOCK/fix_append_atoms.cpp b/src/SHOCK/fix_append_atoms.cpp
index 8036c2724..42fd494f9 100644
--- a/src/SHOCK/fix_append_atoms.cpp
+++ b/src/SHOCK/fix_append_atoms.cpp
@@ -1,483 +1,483 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_append_atoms.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "modify.h"
#include "domain.h"
#include "lattice.h"
#include "update.h"
#include "random_mars.h"
#include "error.h"
#include "force.h"
using namespace LAMMPS_NS;
#define BIG 1.0e30
#define EPSILON 1.0e-6
/* ---------------------------------------------------------------------- */
FixAppendAtoms::FixAppendAtoms(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
force_reneighbor = 1;
next_reneighbor = -1;
box_change = 1;
time_depend = 1;
- if (narg < 4) error->all("Illegal fix append_atoms command");
+ if (narg < 4) error->all(FLERR,"Illegal fix append_atoms command");
scaleflag = 1;
spatflag=0;
xloflag = xhiflag = yloflag = yhiflag = zloflag = zhiflag = 0;
tempflag = 0;
ranflag = 0;
ranx = 0.0;
rany = 0.0;
ranz = 0.0;
randomx = NULL;
randomt = NULL;
int iarg = 0;
iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"xlo") == 0) {
- error->all("Only zhi currently implemented for append_atoms");
+ error->all(FLERR,"Only zhi currently implemented for append_atoms");
xloflag = 1;
iarg++;
- if (domain->boundary[0][0] != 3) error->all("Must shrink-wrap with minimum the append boundary");
+ if (domain->boundary[0][0] != 3) error->all(FLERR,"Must shrink-wrap with minimum the append boundary");
} else if (strcmp(arg[iarg],"xhi") == 0) {
- error->all("Only zhi currently implemented for append_atom");
+ error->all(FLERR,"Only zhi currently implemented for append_atom");
xhiflag = 1;
iarg++;
- if (domain->boundary[0][1] != 3) error->all("Must shrink-wrap with minimum th append boundary");
+ if (domain->boundary[0][1] != 3) error->all(FLERR,"Must shrink-wrap with minimum th append boundary");
} else if (strcmp(arg[iarg],"ylo") == 0) {
- error->all("Only zhi currently implemented for append_atom");
+ error->all(FLERR,"Only zhi currently implemented for append_atom");
yloflag = 1;
iarg++;
- if (domain->boundary[1][0] != 3) error->all("Must shrink-wrap with minimum th append boundary");
+ if (domain->boundary[1][0] != 3) error->all(FLERR,"Must shrink-wrap with minimum th append boundary");
} else if (strcmp(arg[iarg],"yhi") == 0) {
- error->all("Only zhi currently implemented for append_atom");
+ error->all(FLERR,"Only zhi currently implemented for append_atom");
yhiflag = 1;
iarg++;
- if (domain->boundary[1][1] != 3) error->all("Must shrink-wrap with minimum th append boundary");
+ if (domain->boundary[1][1] != 3) error->all(FLERR,"Must shrink-wrap with minimum th append boundary");
} else if (strcmp(arg[iarg],"zlo") == 0) {
- error->all("Only zhi currently implemented for append_atom");
+ error->all(FLERR,"Only zhi currently implemented for append_atom");
zloflag = 1;
iarg++;
- if (domain->boundary[2][0] != 3) error->all("Must shrink-wrap with minimum th append boundary");
+ if (domain->boundary[2][0] != 3) error->all(FLERR,"Must shrink-wrap with minimum th append boundary");
} else if (strcmp(arg[iarg],"zhi") == 0) {
zhiflag = 1;
iarg++;
- if (domain->boundary[2][1] != 3) error->all("Must shrink-wrap with minimum th append boundary");
+ if (domain->boundary[2][1] != 3) error->all(FLERR,"Must shrink-wrap with minimum th append boundary");
} else if (strcmp(arg[iarg],"freq") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix append_atoms command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix append_atoms command");
freq = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"spatial") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix append_atoms command");
- if (strcmp(arg[iarg+1],"f_") == 0) error->all("Bad fix ID in fix append_atoms command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix append_atoms command");
+ if (strcmp(arg[iarg+1],"f_") == 0) error->all(FLERR,"Bad fix ID in fix append_atoms command");
spatflag = 1;
int n = strlen(arg[iarg+1]);
spatlead = atof(arg[iarg+2]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg+1][2]);
n = strlen(suffix) + 1;
spatialid = new char[n];
strcpy(spatialid,suffix);
delete [] suffix;
iarg += 3;
// NEED TO CHECK TO MAKE SURE FIX IS AN AVE/SPATIAL
} else if (strcmp(arg[iarg],"size") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix append_atoms command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix append_atoms command");
size = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix append_atoms command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix append_atoms command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix append_atoms command");
+ else error->all(FLERR,"Illegal fix append_atoms command");
iarg += 2;
} else if (strcmp(arg[iarg],"random") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix append_atoms command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix append_atoms command");
ranflag = 1;
ranx = atof(arg[iarg+1]);
rany = atof(arg[iarg+2]);
ranz = atof(arg[iarg+3]);
xseed = atoi(arg[iarg+4]);
- if (xseed <= 0) error->all("Illegal fix append_atoms command");
+ if (xseed <= 0) error->all(FLERR,"Illegal fix append_atoms command");
randomx = new RanMars(lmp,xseed + comm->me);
iarg += 5;
} else if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix append_atoms command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix append_atoms command");
tempflag = 1;
t_target = atof(arg[iarg+1]);
t_period = atof(arg[iarg+2]);
tseed = atoi(arg[iarg+3]);
t_extent = atof(arg[iarg+4]);
- if (t_target <= 0) error->all("Illegal fix append_atoms command");
- if (t_period <= 0) error->all("Illegal fix append_atoms command");
- if (t_extent <= 0) error->all("Illegal fix append_atoms command");
- if (tseed <= 0) error->all("Illegal fix append_atoms command");
+ if (t_target <= 0) error->all(FLERR,"Illegal fix append_atoms command");
+ if (t_period <= 0) error->all(FLERR,"Illegal fix append_atoms command");
+ if (t_extent <= 0) error->all(FLERR,"Illegal fix append_atoms command");
+ if (tseed <= 0) error->all(FLERR,"Illegal fix append_atoms command");
randomt = new RanMars(lmp,tseed + comm->me);
gfactor1 = new double[atom->ntypes+1];
gfactor2 = new double[atom->ntypes+1];
iarg += 5;
- } else error->all("Illegal fix append_atoms command");
+ } else error->all(FLERR,"Illegal fix append_atoms command");
}
if ((xloflag || xhiflag) && domain->xperiodic)
- error->all("Cannot use append_atoms in periodic dimension");
+ error->all(FLERR,"Cannot use append_atoms in periodic dimension");
if ((yloflag || yhiflag) && domain->yperiodic)
- error->all("Cannot use append_atoms in periodic dimension");
+ error->all(FLERR,"Cannot use append_atoms in periodic dimension");
if ((zloflag || zhiflag) && domain->zperiodic)
- error->all("Cannot use append_atoms in periodic dimension");
+ error->all(FLERR,"Cannot use append_atoms in periodic dimension");
- if (domain->triclinic == 1) error->all("Cannot append atoms to a triclinic box");
+ if (domain->triclinic == 1) error->all(FLERR,"Cannot append atoms to a triclinic box");
// setup scaling
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix append_atoms with undefined lattice");
+ error->all(FLERR,"Use of fix append_atoms with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
if (xloflag || xhiflag) size *= xscale;
if (yloflag || yhiflag) size *= yscale;
if (zloflag || zhiflag) size *= zscale;
if (ranflag) {
ranx *= xscale;
rany *= yscale;
ranz *= zscale;
}
}
/* ---------------------------------------------------------------------- */
FixAppendAtoms::~FixAppendAtoms()
{
if (ranflag) delete randomx;
if (tempflag) {
delete randomt;
delete [] gfactor1;
delete [] gfactor2;
}
}
/* ---------------------------------------------------------------------- */
int FixAppendAtoms::setmask()
{
int mask = 0;
mask |= PRE_EXCHANGE;
mask |= INITIAL_INTEGRATE;
mask |= POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAppendAtoms::initial_integrate(int vflag)
{
if (update->ntimestep % freq == 0) {
next_reneighbor = update->ntimestep;
}
}
/* ---------------------------------------------------------------------- */
void FixAppendAtoms::setup(int vflag)
{
/*** CALL TO CREATE GROUP? SEE POST_FORCE ***/
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
int FixAppendAtoms::get_spatial()
{
if (update->ntimestep % freq == 0) {
int ifix = modify->find_fix(spatialid);
if (ifix < 0)
- error->all("Fix ID for fix ave/spatial does not exist");
+ error->all(FLERR,"Fix ID for fix ave/spatial does not exist");
Fix *fix = modify->fix[ifix];
int failed = 0;
int count = 0;
while (failed < 2) {
double tmp = fix->compute_vector(2*count);
if (tmp == 0.0) failed++;
else failed = 0;
count++;
}
double pos[count-2];
double val[count-2];
for (int loop=0; loop < count-2; loop++) {
pos[loop] = fix->compute_vector(2*loop);
val[loop] = fix->compute_vector(2*loop+1);
}
// Always ignor the first and last
// SHOULD HAVE A MEMORY OF MIN AND MAX ENERGY
// CAPTURE BINSIZE FROM SPATIAL
double binsize = 2.0;
double min_energy=0.0;
double max_energy=0.0;
int header = static_cast<int> (size / binsize);
advance = 0;
for (int loop=1; loop <= header; loop++) {
max_energy += val[loop];
}
for (int loop=count-2-2*header; loop <=count-3-header; loop++) {
min_energy += val[loop];
}
max_energy /= header;
min_energy /= header;
double shockfront_min = 0.0;
double shockfront_max = 0.0;
double shockfront_loc = 0.0;
int front_found1 = 0;
for (int loop=count-3-header; loop > header; loop--) {
if (front_found1 == 1) continue;
if (val[loop] > min_energy + 0.1*(max_energy - min_energy)) {
shockfront_max = pos[loop];
front_found1=1;
}
}
int front_found2 = 0;
for (int loop=header+1; loop <=count-3-header; loop++) {
if (val[loop] > min_energy + 0.6*(max_energy - min_energy)) {
shockfront_min = pos[loop];
front_found2=1;
}
}
if (front_found1 + front_found2 == 0) shockfront_loc = 0.0;
else if (front_found1 + front_found2 == 1) shockfront_loc = shockfront_max + shockfront_min;
else if (front_found1 == 1 && front_found2 == 1 && shockfront_max-shockfront_min > spatlead/2.0) shockfront_loc = shockfront_max;
else shockfront_loc = (shockfront_max + shockfront_min) / 2.0;
if (comm->me == 0) printf("SHOCK: %g %g %g %g %g\n", shockfront_loc, shockfront_min, shockfront_max, domain->boxlo[2], domain->boxhi[2]);
if (domain->boxhi[2] - shockfront_loc < spatlead) advance = 1;
}
advance_sum = 0;
MPI_Allreduce(&advance,&advance_sum,1,MPI_INT,MPI_SUM,world);
if (advance_sum > 0) return 1;
else return 0;
}
/* ---------------------------------------------------------------------- */
void FixAppendAtoms::post_force(int vflag)
{
double **f = atom->f;
double **v = atom->v;
double **x = atom->x;
int *type = atom->type;
int nlocal = atom->nlocal;
double gamma1,gamma2;
double tsqrt = sqrt(t_target);
if (atom->mass) {
if (tempflag) {
for (int i = 1; i <= atom->ntypes; i++) {
gfactor1[i] = -atom->mass[i] / t_period / force->ftm2v;
gfactor2[i] = sqrt(atom->mass[i]) *
sqrt(24.0*force->boltz/t_period/update->dt/force->mvv2e) /
force->ftm2v;
}
}
for (int i = 0; i < nlocal; i++) {
// SET TEMP AHEAD OF SHOCK
if (tempflag && x[i][2] >= domain->boxhi[2] - t_extent ) {
gamma1 = gfactor1[type[i]];
gamma2 = gfactor2[type[i]] * tsqrt;
f[i][0] += gamma1*v[i][0] + gamma2*(randomt->uniform()-0.5);
f[i][1] += gamma1*v[i][1] + gamma2*(randomt->uniform()-0.5);
f[i][2] += gamma1*v[i][2] + gamma2*(randomt->uniform()-0.5);
}
// FREEZE ATOMS AT BOUNDARY
if (x[i][2] >= domain->boxhi[2] - size) {
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
v[i][0] = 0.0;
v[i][1] = 0.0;
v[i][2] = 0.0;
}
}
} else {
double *rmass = atom->rmass;
double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;
for (int i = 0; i < nlocal; i++) {
// SET TEMP AHEAD OF SHOCK
if (tempflag && x[i][2] >= domain->boxhi[2] - t_extent ) {
gamma1 = -rmass[i] / t_period / ftm2v;
gamma2 = sqrt(rmass[i]) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma2 *= tsqrt;
f[i][0] += gamma1*v[i][0] + gamma2*(randomt->uniform()-0.5);
f[i][1] += gamma1*v[i][1] + gamma2*(randomt->uniform()-0.5);
f[i][2] += gamma1*v[i][2] + gamma2*(randomt->uniform()-0.5);
}
// FREEZE ATOMS AT BOUNDARY
if (x[i][2] >= domain->boxhi[2] - size) {
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
v[i][0] = 0.0;
v[i][1] = 0.0;
v[i][2] = 0.0;
}
}
}
}
/* ---------------------------------------------------------------------- */
void FixAppendAtoms::pre_exchange()
{
int ntimestep = update->ntimestep;
int addnode = 0;
if (ntimestep % freq == 0) {
if (spatflag==1) if (get_spatial()==0) return;
if (comm->myloc[2] == comm->procgrid[2]-1) {
if (domain->lattice) {
nbasis = domain->lattice->nbasis;
basistype = new int[nbasis];
for (int i = 0; i < nbasis; i++) basistype[i] = 1;
- } else error->all("must define lattice to append_atoms");
+ } else error->all(FLERR,"must define lattice to append_atoms");
double bboxlo[3],bboxhi[3];
bboxlo[0] = domain->sublo[0]; bboxhi[0] = domain->subhi[0];
bboxlo[1] = domain->sublo[1]; bboxhi[1] = domain->subhi[1];
bboxlo[2] = domain->subhi[2]; bboxhi[2] = domain->subhi[2]+size;
double xmin,ymin,zmin,xmax,ymax,zmax;
xmin = ymin = zmin = BIG;
xmax = ymax = zmax = -BIG;
domain->lattice->bbox(1,bboxlo[0],bboxlo[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxlo[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxhi[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxhi[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxlo[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxlo[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxhi[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxhi[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
int ilo,ihi,jlo,jhi,klo,khi;
ilo = static_cast<int> (xmin);
jlo = static_cast<int> (ymin);
klo = static_cast<int> (zmin);
ihi = static_cast<int> (xmax);
jhi = static_cast<int> (ymax);
khi = static_cast<int> (zmax);
if (xmin < 0.0) ilo--;
if (ymin < 0.0) jlo--;
if (zmin < 0.0) klo--;
double **basis = domain->lattice->basis;
double x[3];
double *sublo = domain->sublo;
double *subhi = domain->subhi;
double *mass = atom->mass;
int i,j,k,m;
for (k = klo; k <= khi; k++) {
for (j = jlo; j <= jhi; j++) {
for (i = ilo; i <= ihi; i++) {
for (m = 0; m < nbasis; m++) {
x[0] = i + basis[m][0];
x[1] = j + basis[m][1];
x[2] = k + basis[m][2];
int flag = 0;
// convert from lattice coords to box coords
domain->lattice->lattice2box(x[0],x[1],x[2]);
if (x[0] >= sublo[0] && x[0] < subhi[0] &&
x[1] >= sublo[1] && x[1] < subhi[1] &&
x[2] >= subhi[2] && x[2] < subhi[2]+size) flag = 1;
else if (domain->dimension == 2 && x[1] >= domain->boxhi[1] &&
comm->myloc[1] == comm->procgrid[1]-1 &&
x[0] >= sublo[0] && x[0] < subhi[0]) flag = 1;
if (flag) {
if (ranflag) {
x[0] += ranx * 2.0*(randomx->uniform()-0.5);
x[1] += rany * 2.0*(randomx->uniform()-0.5);
x[2] += ranz * 2.0*(randomx->uniform()-0.5);
}
addnode++;
atom->avec->create_atom(basistype[m],x);
}
}
}
}
}
}
int addtotal = 0;
MPI_Barrier(world);
MPI_Allreduce(&addnode,&addtotal,1,MPI_INT,MPI_SUM,world);
if (addtotal) {
domain->reset_box();
if (atom->tag_enable) {
atom->tag_extend();
atom->natoms += addtotal;
if (atom->map_style) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
}
}
}
}
diff --git a/src/SHOCK/fix_msst.cpp b/src/SHOCK/fix_msst.cpp
index 90cb7b324..1ba47ee14 100644
--- a/src/SHOCK/fix_msst.cpp
+++ b/src/SHOCK/fix_msst.cpp
@@ -1,960 +1,960 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Laurence Fried (LLNL), Evan Reed (LLNL, Stanford)
implementation of the Multi-Scale Shock Method
See Reed, Fried, Joannopoulos, Phys Rev Lett, 90, 235503 (2003)
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_msst.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "output.h"
#include "modify.h"
#include "compute.h"
#include "kspace.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "error.h"
#include "thermo.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixMSST::FixMSST(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix msst command");
+ if (narg < 4) error->all(FLERR,"Illegal fix msst command");
restart_global = 1;
box_change = 1;
time_integrate = 1;
scalar_flag = 1;
vector_flag = 1;
size_vector = 4;
global_freq = 1;
extscalar = 1;
extvector = 0;
// set defaults
velocity = 0.0;
dilation[0] = dilation[1] = dilation[2] = 1.0;
p0 = 0.0;
v0 = 1.0;
e0 = 0.0;
qmass = 1.0e1;
mu = 0.0;
direction = 2;
p0_set = 0;
v0_set = 0;
e0_set = 0;
tscale = 0.01;
if ( strcmp(arg[3],"x") == 0 )
direction = 0;
else if ( strcmp(arg[3],"y") == 0 )
direction = 1;
else if ( strcmp(arg[3],"z") == 0 )
direction = 2;
else {
- error->all("Illegal fix msst command");
+ error->all(FLERR,"Illegal fix msst command");
}
velocity = atof(arg[4]);
if ( velocity < 0 )
- error->all("Illegal fix msst command");
+ error->all(FLERR,"Illegal fix msst command");
for ( int iarg = 5; iarg < narg; iarg++ ) {
if ( strcmp(arg[iarg],"q") == 0 ) {
qmass = atof(arg[iarg+1]);
iarg++;
} else if ( strcmp(arg[iarg],"mu") == 0 ) {
mu = atof(arg[iarg+1]);
iarg++;
} else if ( strcmp(arg[iarg],"p0") == 0 ) {
p0 = atof(arg[iarg+1]);
iarg++;
p0_set = 1;
} else if ( strcmp(arg[iarg],"v0") == 0 ) {
v0 = atof(arg[iarg+1]);
v0_set = 1;
iarg++;
} else if ( strcmp(arg[iarg],"e0") == 0 ) {
e0 = atof(arg[iarg+1]);
e0_set = 1;
iarg++;
} else if ( strcmp(arg[iarg],"tscale") == 0 ) {
tscale = atof(arg[iarg+1]);
if (tscale < 0.0 || tscale > 1.0)
- error->all("Fix msst tscale must satisfy 0 <= tscale < 1");
+ error->all(FLERR,"Fix msst tscale must satisfy 0 <= tscale < 1");
iarg++;
- } else error->all("Illegal fix msst command");
+ } else error->all(FLERR,"Illegal fix msst command");
}
if (comm->me == 0) {
if (screen) {
fprintf(screen,"MSST parameters:\n");
if (direction == 0) fprintf(screen," Shock in x direction\n");
else if (direction == 1) fprintf(screen," Shock in y direction\n");
else if (direction == 2) fprintf(screen," Shock in z direction\n");
fprintf(screen," Cell mass-like parameter qmass "
"(units of mass^2/length^4) = %12.5e\n", qmass);
fprintf(screen," Shock velocity = %12.5e\n", velocity);
fprintf(screen," Artificial viscosity "
"(units of mass/length/time) = %12.5e\n", mu);
if (p0_set)
fprintf(screen," Initial pressure specified to be %12.5e\n", p0);
else fprintf(screen," Initial pressure calculated on first step\n");
if (v0_set)
fprintf(screen," Initial volume specified to be %12.5e\n", v0);
else fprintf(screen," Initial volume calculated on first step\n");
if (e0_set)
fprintf(screen," Initial energy specified to be %12.5e\n", e0);
else fprintf(screen," Initial energy calculated on first step\n");
}
if (logfile) {
fprintf(logfile,"MSST parameters:\n");
if (direction == 0) fprintf(logfile," Shock in x direction\n");
else if (direction == 1) fprintf(logfile," Shock in y direction\n");
else if (direction == 2) fprintf(logfile," Shock in z direction\n");
fprintf(logfile," Cell mass-like parameter qmass "
"(units of mass^2/length^4) = %12.5e\n", qmass);
fprintf(logfile," Shock velocity = %12.5e\n", velocity);
fprintf(logfile," Artificial viscosity "
"(units of mass/length/time) = %12.5e\n", mu);
if (p0_set)
fprintf(logfile," Initial pressure specified to be %12.5e\n", p0);
else fprintf(logfile," Initial pressure calculated on first step\n");
if (v0_set)
fprintf(logfile," Initial volume specified to be %12.5e\n", v0);
else fprintf(logfile," Initial volume calculated on first step\n");
if (e0_set)
fprintf(logfile," Initial energy specified to be %12.5e\n", e0);
else fprintf(logfile," Initial energy calculated on first step\n");
}
}
// check for periodicity in controlled dimensions
- if (domain->nonperiodic) error->all("Fix msst requires a periodic box");
+ if (domain->nonperiodic) error->all(FLERR,"Fix msst requires a periodic box");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = "all";
newarg[2] = "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = "all";
newarg[2] = "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
// create a new compute potential energy compute
n = strlen(id) + 3;
id_pe = new char[n];
strcpy(id_pe,id);
strcat(id_pe,"_pe");
newarg = new char*[3];
newarg[0] = id_pe;
newarg[1] = (char*)"all";
newarg[2] = (char*)"pe";
modify->add_compute(3,newarg);
delete [] newarg;
peflag = 1;
// initialize the time derivative of the volume.
omega[0] = omega[1] = omega[2] = 0.0;
nrigid = 0;
rfix = NULL;
old_velocity = new double* [atom->nlocal];
for ( int j = 0; j < atom->nlocal; j++ ) {
old_velocity[j] = new double [3];
}
atoms_allocated = atom->nlocal;
}
/* ---------------------------------------------------------------------- */
FixMSST::~FixMSST()
{
delete [] rfix;
// delete temperature and pressure if fix created them
if (tflag) modify->delete_compute(id_temp);
if (pflag) modify->delete_compute(id_press);
if (peflag) modify->delete_compute(id_pe);
delete [] id_temp;
delete [] id_press;
delete [] id_pe;
for ( int j = 0; j < atoms_allocated; j++ ) {
delete [] old_velocity[j];
}
delete [] old_velocity;
}
/* ---------------------------------------------------------------------- */
int FixMSST::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= THERMO_ENERGY;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixMSST::init()
{
if (atom->mass == NULL)
- error->all("Cannot use fix msst without per-type mass defined");
+ error->all(FLERR,"Cannot use fix msst without per-type mass defined");
// set compute ptrs
int itemp = modify->find_compute(id_temp);
int ipress = modify->find_compute(id_press);
int ipe = modify->find_compute(id_pe);
if (itemp < 0 || ipress < 0|| ipe < 0)
- error->all("Could not find fix msst compute ID");
+ error->all(FLERR,"Could not find fix msst compute ID");
if (modify->compute[itemp]->tempflag == 0)
- error->all("Fix msst compute ID does not compute temperature");
+ error->all(FLERR,"Fix msst compute ID does not compute temperature");
if (modify->compute[ipress]->pressflag == 0)
- error->all("Fix msst compute ID does not compute pressure");
+ error->all(FLERR,"Fix msst compute ID does not compute pressure");
if (modify->compute[ipe]->peflag == 0)
- error->all("Fix msst compute ID does not compute potential energy");
+ error->all(FLERR,"Fix msst compute ID does not compute potential energy");
temperature = modify->compute[itemp];
pressure = modify->compute[ipress];
pe = modify->compute[ipe];
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dthalf = 0.5 * update->dt;
boltz = force->boltz;
nktv2p = force->nktv2p;
mvv2e = force->mvv2e;
double mass = 0.0;
for (int i = 0; i < atom->nlocal; i++) mass += atom->mass[atom->type[i]];
MPI_Allreduce(&mass,&total_mass,1,MPI_DOUBLE,MPI_SUM,world);
total_mass = total_mass;
if (force->kspace) kspace_flag = 1;
else kspace_flag = 0;
// detect if any fix rigid exist so rigid bodies move when box is dilated
// rfix[] = indices to each fix rigid
delete [] rfix;
nrigid = 0;
rfix = NULL;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"rigid") == 0 ||
strcmp(modify->fix[i]->style,"poems") == 0) nrigid++;
if (nrigid) {
rfix = new int[nrigid];
nrigid = 0;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"rigid") == 0 ||
strcmp(modify->fix[i]->style,"poems") == 0) rfix[nrigid++] = i;
}
}
/* ----------------------------------------------------------------------
compute T,P before integrator starts
------------------------------------------------------------------------- */
void FixMSST::setup(int vflag)
{
lagrangian_position = 0.0;
temperature->compute_vector();
pressure->compute_vector();
couple();
velocity_sum = compute_vsum();
if ( v0_set == 0 ) {
v0 = compute_vol();
v0_set = 1;
if (comm->me == 0) {
if ( screen ) fprintf(screen,"Fix MSST v0 = %12.5e\n", v0);
if ( logfile ) fprintf(logfile,"Fix MSST v0 = %12.5e\n", v0);
}
}
if ( p0_set == 0 ) {
p0 = p_current[direction];
p0_set = 1;
if ( comm->me == 0 ) {
if ( screen ) fprintf(screen,"Fix MSST p0 = %12.5e\n", p0);
if ( logfile ) fprintf(logfile,"Fix MSST p0 = %12.5e\n", p0);
}
}
if ( e0_set == 0 ) {
e0 = compute_etotal();
e0_set = 1;
if ( comm->me == 0 ) {
if ( screen ) fprintf(screen,"Fix MSST e0 = to be %12.5e\n",e0);
if ( logfile ) fprintf(logfile,"Fix MSST e0 = to be %12.5e\n",e0);
}
}
temperature->compute_vector();
double *ke_tensor = temperature->vector;
double ke_temp = ke_tensor[0]+ke_tensor[1]+ke_tensor[2];
if (ke_temp > 0.0 && tscale > 0.0 ) {
// transfer energy from atom velocities to cell volume motion
// to bias initial compression
double **v = atom->v;
int *mask = atom->mask;
double sqrt_initial_temperature_scaling = sqrt(1.0-tscale);
double fac1 = tscale*total_mass/qmass*ke_temp/force->mvv2e;
omega[direction]=-1*sqrt(fac1);
double fac2 = omega[direction]/v0;
if ( comm->me == 0 && tscale != 1.0) {
if ( screen )
fprintf(screen,"Fix MSST initial strain rate of %12.5e established "
"by reducing temperature by factor of %12.5e\n",
fac2,tscale);
if ( logfile )
fprintf(logfile,"Fix MSST initial strain rate of %12.5e established "
"by reducing temperature by factor of %12.5e\n",
fac2,tscale);
}
for (int i = 0; i < atom->nlocal; i++) {
if (mask[i] & groupbit) {
for (int k = 0; k < 3; k++ ) {
v[i][k]*=sqrt_initial_temperature_scaling;
}
}
}
}
// trigger virial computation on next timestep
pressure->addstep(update->ntimestep+1);
}
/* ----------------------------------------------------------------------
1st half of Verlet update
------------------------------------------------------------------------- */
void FixMSST::initial_integrate(int vflag)
{
int sd;
double p_msst; // MSST driving pressure.
int i, k;
double vol;
int nlocal = atom->nlocal;
int *mask = atom->mask;
double **v = atom->v;
double **f = atom->f;
double *mass = atom->mass;
int *type = atom->type;
double **x = atom->x;
// check to see if old_velocity is correctly allocated
check_alloc(nlocal);
sd = direction;
// compute new pressure and volume.
temperature->compute_vector();
pressure->compute_vector();
couple();
vol = compute_vol();
// propagate the time derivative of
// the volume 1/2 step at fixed vol, r, rdot.
p_msst = nktv2p * mvv2e * velocity * velocity * total_mass *
( v0 - vol)/( v0 * v0);
double A = total_mass * ( p_current[sd] - p0 - p_msst ) /
(qmass * nktv2p * mvv2e);
double B = total_mass * mu / ( qmass * vol );
// prevent blow-up of the volume.
if ( vol > v0 && A > 0.0 ) {
A = -A;
}
// use taylor expansion to avoid singularity at B == 0.
if ( B * dthalf > 1.0e-06 ) {
omega[sd] = ( omega[sd] + A * ( exp(B * dthalf) - 1.0 ) / B )
* exp(-B * dthalf);
} else {
omega[sd] = omega[sd] + (A - B * omega[sd]) * dthalf +
0.5 * (B * B * omega[sd] - A * B ) * dthalf * dthalf;
}
// propagate velocity sum 1/2 step by
// temporarily propagating the velocities.
velocity_sum = compute_vsum();
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
for ( k = 0; k < 3; k++ ) {
double C = f[i][k] * force->ftm2v / mass[type[i]];
double D = mu * omega[sd] * omega[sd] /
(velocity_sum * mass[type[i]] * vol );
old_velocity[i][k] = v[i][k];
if ( k == direction ) {
D = D - 2.0 * omega[sd] / vol;
}
if ( fabs(dthalf * D) > 1.0e-06 ) {
double expd = exp(D * dthalf);
v[i][k] = expd * ( C + D * v[i][k] - C / expd ) / D;
} else {
v[i][k] = v[i][k] + ( C + D * v[i][k] ) * dthalf +
0.5 * (D * D * v[i][k] + C * D ) * dthalf * dthalf;
}
}
}
}
velocity_sum = compute_vsum();
// reset the velocities.
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
for ( k = 0; k < 3; k++ ) {
v[i][k] = old_velocity[i][k];
}
}
}
// propagate velocities 1/2 step using the new velocity sum.
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
for ( k = 0; k < 3; k++ ) {
double C = f[i][k] * force->ftm2v / mass[type[i]];
double D = mu * omega[sd] * omega[sd] /
(velocity_sum * mass[type[i]] * vol );
if ( k == direction ) {
D = D - 2.0 * omega[sd] / vol;
}
if ( fabs(dthalf * D) > 1.0e-06 ) {
double expd = exp(D * dthalf);
v[i][k] = expd * ( C + D * v[i][k] - C / expd ) / D;
} else {
v[i][k] = v[i][k] + ( C + D * v[i][k] ) * dthalf +
0.5 * (D * D * v[i][k] + C * D ) * dthalf * dthalf;
}
}
}
}
// propagate the volume 1/2 step.
double vol1 = vol + omega[sd] * dthalf;
// rescale positions and change box size.
dilation[sd] = vol1/vol;
remap(0);
// propagate particle positions 1 time step.
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
// propagate the volume 1/2 step.
double vol2 = vol1 + omega[sd] * dthalf;
// rescale positions and change box size.
dilation[sd] = vol2/vol1;
remap(0);
if (kspace_flag) force->kspace->setup();
}
/* ----------------------------------------------------------------------
2nd half of Verlet update
------------------------------------------------------------------------- */
void FixMSST::final_integrate()
{
int i;
// v update only for atoms in MSST group
double **v = atom->v;
double **f = atom->f;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double vol = compute_vol();
double p_msst;
int sd = direction;
// propagate particle velocities 1/2 step.
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
for ( int k = 0; k < 3; k++ ) {
double C = f[i][k] * force->ftm2v / mass[type[i]];
double D = mu * omega[sd] * omega[sd] /
(velocity_sum * mass[type[i]] * vol );
if ( k == direction ) {
D = D - 2.0 * omega[sd] / vol;
}
if ( fabs(dthalf * D) > 1.0e-06 ) {
double expd = exp(D * dthalf);
v[i][k] = expd * ( C + D * v[i][k] - C / expd ) / D;
} else {
v[i][k] = v[i][k] + ( C + D * v[i][k] ) * dthalf +
0.5 * (D * D * v[i][k] + C * D ) * dthalf * dthalf;
}
}
}
}
// compute new pressure and volume.
temperature->compute_vector();
pressure->compute_vector();
couple();
velocity_sum = compute_vsum();
vol = compute_vol();
// propagate the time derivative of the volume 1/2 step at fixed V, r, rdot.
p_msst = nktv2p * mvv2e * velocity * velocity * total_mass *
( v0 - vol )/( v0 * v0 );
double A = total_mass * ( p_current[sd] - p0 - p_msst ) /
( qmass * nktv2p * mvv2e );
double B = total_mass * mu / ( qmass * vol );
// prevent blow-up of the volume.
if ( vol > v0 && A > 0.0 ) {
A = -A;
}
// use taylor expansion to avoid singularity at B == 0.
if ( B * dthalf > 1.0e-06 ) {
omega[sd] = ( omega[sd] + A *
( exp(B * dthalf) - 1.0 ) / B ) * exp(-B * dthalf);
} else {
omega[sd] = omega[sd] + (A - B * omega[sd]) * dthalf +
0.5 * (B * B * omega[sd] - A * B ) * dthalf * dthalf;
}
// calculate Lagrangian position of computational cell
lagrangian_position -= velocity*vol/v0*update->dt;
// trigger virial computation on next timestep
pressure->addstep(update->ntimestep+1);
}
/* ---------------------------------------------------------------------- */
void FixMSST::couple()
{
double *tensor = pressure->vector;
p_current[0] = tensor[0];
p_current[1] = tensor[1];
p_current[2] = tensor[2];
}
/* ----------------------------------------------------------------------
change box size
remap owned or owned+ghost atoms depending on flag
if rigid bodies exist, scale rigid body centers-of-mass
------------------------------------------------------------------------- */
void FixMSST::remap(int flag)
{
int i,n;
double oldlo,oldhi,ctr;
double **v = atom->v;
if (flag) n = atom->nlocal + atom->nghost;
else n = atom->nlocal;
// convert pertinent atoms and rigid bodies to lamda coords
domain->x2lamda(n);
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(0);
// reset global and local box to new size/shape
for (i = 0; i < 3; i++) {
if ( direction == i ) {
oldlo = domain->boxlo[i];
oldhi = domain->boxhi[i];
ctr = 0.5 * (oldlo + oldhi);
domain->boxlo[i] = (oldlo-ctr)*dilation[i] + ctr;
domain->boxhi[i] = (oldhi-ctr)*dilation[i] + ctr;
}
}
domain->set_global_box();
domain->set_local_box();
// convert pertinent atoms and rigid bodies back to box coords
domain->lamda2x(n);
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(1);
for (i = 0; i < n; i++) {
v[i][direction] = v[i][direction] *
dilation[direction];
}
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixMSST::write_restart(FILE *fp)
{
int n = 0;
double list[4];
list[n++] = omega[direction];
list[n++] = e0;
list[n++] = v0;
list[n++] = p0;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(&list,sizeof(double),n,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixMSST::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
omega[direction] = list[n++];
e0 = list[n++];
v0 = list[n++];
p0 = list[n++];
p0_set = 1;
v0_set = 1;
e0_set = 1;
}
/* ---------------------------------------------------------------------- */
int FixMSST::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != 0 && comm->me == 0)
- error->warning("Temperature for MSST is not for group all");
+ error->warning(FLERR,"Temperature for MSST is not for group all");
return 2;
} else if (strcmp(arg[0],"press") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (pflag) {
modify->delete_compute(id_press);
pflag = 0;
}
delete [] id_press;
int n = strlen(arg[1]) + 1;
id_press = new char[n];
strcpy(id_press,arg[1]);
int icompute = modify->find_compute(id_press);
- if (icompute < 0) error->all("Could not find fix_modify pressure ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify pressure ID");
pressure = modify->compute[icompute];
if (pressure->pressflag == 0)
- error->all("Fix_modify pressure ID does not compute pressure");
+ error->all(FLERR,"Fix_modify pressure ID does not compute pressure");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
double FixMSST::compute_scalar()
{
// compute new pressure and volume.
temperature->compute_vector();
pressure->compute_vector();
couple();
double volume = compute_vol();
double energy = 0.0;
int i;
i = direction;
energy = qmass * omega[i] * omega[i] / (2.0 * total_mass) * mvv2e;
energy -= 0.5 * total_mass * velocity * velocity *
(1.0 - volume/ v0) *
(1.0 - volume/ v0) * mvv2e;
energy -= p0 * ( v0 - volume ) / nktv2p;
return energy;
}
/* ----------------------------------------------------------------------
return a single element from the following vector,
[dhug,dray,lgr_vel,lgr_pos]
------------------------------------------------------------------------- */
double FixMSST::compute_vector(int n)
{
if (n == 0) {
return compute_hugoniot();
} else if (n == 1) {
return compute_rayleigh();
} else if (n == 2) {
return compute_lagrangian_speed();
} else if (n == 3) {
return compute_lagrangian_position();
}
return 0.0;
}
/* ----------------------------------------------------------------------
Computes the deviation of the current point
from the Hugoniot in Kelvin for the MSST.
------------------------------------------------------------------------- */
double FixMSST::compute_hugoniot()
{
double v, e, p;
double dhugo;
e = compute_etotal();
temperature->compute_vector();
pressure->compute_vector();
p = pressure->vector[direction];
v = compute_vol();
dhugo = (0.5 * (p + p0 ) * ( v0 - v)) /
force->nktv2p + e0 - e;
dhugo /= temperature->dof * force->boltz;
return dhugo;
}
/* ----------------------------------------------------------------------
Computes the deviation of the current point from the Rayleigh
in pressure units for the MSST.
------------------------------------------------------------------------- */
double FixMSST::compute_rayleigh()
{
double v, p;
double drayleigh;
temperature->compute_vector();
pressure->compute_vector();
p = pressure->vector[direction];
v = compute_vol();
drayleigh = p - p0 -
total_mass * velocity * velocity * force->mvv2e *
(1.0 - v / v0 ) * force->nktv2p / v0;
return drayleigh;
}
/* ----------------------------------------------------------------------
Computes the speed of the MSST computational cell in the
unshocked material rest-frame
------------------------------------------------------------------------- */
double FixMSST::compute_lagrangian_speed()
{
double v = compute_vol();
return velocity*(1.0-v/v0);
}
/* ----------------------------------------------------------------------
Computes the distance behind the
shock front of the MSST computational cell.
------------------------------------------------------------------------- */
double FixMSST::compute_lagrangian_position()
{
return lagrangian_position;
}
/* ---------------------------------------------------------------------- */
double FixMSST::compute_etotal()
{
double epot,ekin,etot;
epot = pe->compute_scalar();
if (thermo_energy) epot -= compute_scalar();
ekin = temperature->compute_scalar();
ekin *= 0.5 * temperature->dof * force->boltz;
etot = epot+ekin;
return etot;
}
/* ---------------------------------------------------------------------- */
double FixMSST::compute_vol()
{
if (domain->dimension == 3)
return domain->xprd * domain->yprd * domain->zprd;
else
return domain->xprd * domain->yprd;
}
/* ----------------------------------------------------------------------
Checks to see if the allocated size of old_velocity is >= n
The number of local atoms can change during a parallel run.
------------------------------------------------------------------------- */
void FixMSST::check_alloc(int n)
{
if ( atoms_allocated < n ) {
for ( int j = 0; j < atoms_allocated; j++ ) {
delete [] old_velocity[j];
}
delete [] old_velocity;
old_velocity = new double* [n];
for ( int j = 0; j < n; j++ )
old_velocity[j] = new double [3];
atoms_allocated = n;
}
}
double FixMSST::compute_vsum()
{
double vsum;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) ;
}
}
MPI_Allreduce(&t,&vsum,1,MPI_DOUBLE,MPI_SUM,world);
return vsum;
}
diff --git a/src/SHOCK/fix_nphug.cpp b/src/SHOCK/fix_nphug.cpp
index 85463535c..32230940d 100644
--- a/src/SHOCK/fix_nphug.cpp
+++ b/src/SHOCK/fix_nphug.cpp
@@ -1,460 +1,460 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "fix_nphug.h"
#include "modify.h"
#include "error.h"
#include "update.h"
#include "compute.h"
#include "force.h"
#include "domain.h"
#include "group.h"
#include "math.h"
#include "memory.h"
#include "comm.h"
#include "math.h"
using namespace LAMMPS_NS;
enum{ISO,ANISO,TRICLINIC}; // same as fix_nh.cpp
/* ---------------------------------------------------------------------- */
FixNPHug::FixNPHug(LAMMPS *lmp, int narg, char **arg) :
FixNH(lmp, narg, arg)
{
// Prevent masses from being updated every timestep
eta_mass_flag = 0;
omega_mass_flag = 0;
etap_mass_flag = 0;
// extend vector of base-class computes
size_vector += 3;
// turn off deviatoric flag and remove strain energy from vector
deviatoric_flag = 0;
size_vector -= 1;
// use initial state as reference state
v0_set = p0_set = e0_set = 0;
// check pressure settings
if (p_start[0] != p_stop[0] ||
p_start[1] != p_stop[1] ||
p_start[2] != p_stop[2])
- error->all("Invalid argument for fix nphug");
+ error->all(FLERR,"Invalid argument for fix nphug");
// uniaxial = 0 means hydrostatic compression
// uniaxial = 1 means uniaxial compression
// in x, y, or z (idir = 0, 1, or 2)
// isotropic hydrostatic compression
if (pstyle == ISO) {
uniaxial = 0;
// anisotropic compression
} else if (pstyle == ANISO) {
// anisotropic hydrostatic compression
if (p_start[0] == p_start[1] &&
p_start[0] == p_start[2] )
uniaxial = 0;
// uniaxial compression
else if (p_flag[0] == 1 && p_flag[1] == 0
&& p_flag[2] == 0) {
uniaxial = 1;
idir = 0;
} else if (p_flag[0] == 0 && p_flag[1] == 1
&& p_flag[2] == 0) {
uniaxial = 1;
idir = 1;
} else if (p_flag[0] == 0 && p_flag[1] == 0
&& p_flag[2] == 1) {
uniaxial = 1;
idir = 2;
- } else error->all("Invalid argument for fix nphug");
+ } else error->all(FLERR,"Invalid argument for fix nphug");
// triclinic hydrostatic compression
} else if (pstyle == TRICLINIC) {
if (p_start[0] == p_start[1] &&
p_start[0] == p_start[2] &&
p_start[3] == 0.0 &&
p_start[4] == 0.0 &&
p_start[5] == 0.0 )
uniaxial = 0;
- else error->all("Invalid argument for fix nphug");
+ else error->all(FLERR,"Invalid argument for fix nphug");
}
if (!tstat_flag)
- error->all("Temperature control must be used with fix nphug");
+ error->all(FLERR,"Temperature control must be used with fix nphug");
if (!pstat_flag)
- error->all("Pressure control must be used with fix nphug");
+ error->all(FLERR,"Pressure control must be used with fix nphug");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
// create a new compute potential energy compute
n = strlen(id) + 3;
id_pe = new char[n];
strcpy(id_pe,id);
strcat(id_pe,"_pe");
newarg = new char*[3];
newarg[0] = id_pe;
newarg[1] = (char*)"all";
newarg[2] = (char*)"pe";
modify->add_compute(3,newarg);
delete [] newarg;
peflag = 1;
}
/* ---------------------------------------------------------------------- */
FixNPHug::~FixNPHug()
{
// temp and press computes handled by base class
// delete pe compute
if (peflag) modify->delete_compute(id_pe);
delete [] id_pe;
}
/* ---------------------------------------------------------------------- */
void FixNPHug::init()
{
// Call base class init()
FixNH::init();
// set pe ptr
int icompute = modify->find_compute(id_pe);
if (icompute < 0)
- error->all("Potential energy ID for fix nvt/nph/npt does not exist");
+ error->all(FLERR,"Potential energy ID for fix nvt/nph/npt does not exist");
pe = modify->compute[icompute];
}
/* ----------------------------------------------------------------------
compute initial state before integrator starts
------------------------------------------------------------------------- */
void FixNPHug::setup(int vflag)
{
FixNH::setup(vflag);
if ( v0_set == 0 ) {
v0 = compute_vol();
v0_set = 1;
}
if ( p0_set == 0 ) {
p0_set = 1;
if (uniaxial == 1)
p0 = p_current[idir];
else
p0 = (p_current[0]+p_current[1]+p_current[2])/3.0;
}
if ( e0_set == 0 ) {
e0 = compute_etotal();
e0_set = 1;
}
double masstot = group->mass(igroup);
rho0 = nktv2p*force->mvv2e*masstot/v0;
t_target = 0.01;
pe->addstep(update->ntimestep+1);
}
/* ----------------------------------------------------------------------
compute target temperature and kinetic energy
-----------------------------------------------------------------------*/
void FixNPHug::compute_temp_target()
{
t_target = t_current + compute_hugoniot();
ke_target = tdof * boltz * t_target;
pe->addstep(update->ntimestep+1);
}
/* ---------------------------------------------------------------------- */
double FixNPHug::compute_etotal()
{
double epot,ekin,etot;
epot = pe->compute_scalar();
if (thermo_energy) epot -= compute_scalar();
ekin = temperature->compute_scalar();
ekin *= 0.5 * tdof * force->boltz;
etot = epot+ekin;
return etot;
}
/* ---------------------------------------------------------------------- */
double FixNPHug::compute_vol()
{
if (domain->dimension == 3)
return domain->xprd * domain->yprd * domain->zprd;
else
return domain->xprd * domain->yprd;
}
/* ----------------------------------------------------------------------
Computes the deviation of the current point
from the Hugoniot in temperature units.
------------------------------------------------------------------------- */
double FixNPHug::compute_hugoniot()
{
double v,e,p;
double dhugo;
e = compute_etotal();
temperature->compute_vector();
if (uniaxial == 1) {
pressure->compute_vector();
p = pressure->vector[idir];
} else
p = pressure->compute_scalar();
v = compute_vol();
dhugo = (0.5 * (p + p0 ) * ( v0 - v)) /
force->nktv2p + e0 - e;
dhugo /= tdof * boltz;
return dhugo;
}
/* ----------------------------------------------------------------------
Compute shock velocity is distance/time units
------------------------------------------------------------------------- */
double FixNPHug::compute_us()
{
double v,p;
double eps,us;
temperature->compute_vector();
if (uniaxial == 1) {
pressure->compute_vector();
p = pressure->vector[idir];
} else
p = pressure->compute_scalar();
v = compute_vol();
// Us^2 = (p-p0)/(rho0*eps)
eps = 1.0 - v/v0;
if (eps < 1.0e-10) us = 0.0;
else if (p < p0) us = 0.0;
else us = sqrt((p-p0)/(rho0*eps));
return us;
}
/* ----------------------------------------------------------------------
Compute particle velocity is distance/time units
------------------------------------------------------------------------- */
double FixNPHug::compute_up()
{
double v;
double eps,us,up;
v = compute_vol();
us = compute_us();
// u = eps*Us
eps = 1.0 - v/v0;
up = us*eps;
return up;
}
// look for index in local class
// if index not found, look in base class
double FixNPHug::compute_vector(int n)
{
int ilen;
// n = 0: Hugoniot energy difference (temperature units)
ilen = 1;
if (n < ilen) return compute_hugoniot();
n -= ilen;
// n = 1: Shock velocity
ilen = 1;
if (n < ilen) return compute_us();
n -= ilen;
// n = 2: Particle velocity
ilen = 1;
if (n < ilen) return compute_up();
n -= ilen;
// index not found, look in base class
return FixNH::compute_vector(n);
}
/* ----------------------------------------------------------------------
pack restart data
------------------------------------------------------------------------- */
int FixNPHug::pack_restart_data(double *list)
{
int n = 0;
list[n++] = e0;
list[n++] = v0;
list[n++] = p0;
// call the base class function
n += FixNH::pack_restart_data(list+n);
return n;
}
/* ----------------------------------------------------------------------
calculate the number of data to be packed
------------------------------------------------------------------------- */
int FixNPHug::size_restart_global()
{
int nsize = 3;
// call the base class function
nsize += FixNH::size_restart_global();
return nsize;
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixNPHug::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
e0 = list[n++];
v0 = list[n++];
p0 = list[n++];
e0_set = 1;
v0_set = 1;
p0_set = 1;
// call the base class function
buf += n*sizeof(double);
FixNH::restart(buf);
}
/* ---------------------------------------------------------------------- */
int FixNPHug::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"e0") == 0) {
- if (narg < 2) error->all("Illegal fix nphug command");
+ if (narg < 2) error->all(FLERR,"Illegal fix nphug command");
e0 = atof(arg[1]);
e0_set = 1;
return 2;
} else if (strcmp(arg[0],"v0") == 0) {
- if (narg < 2) error->all("Illegal fix nphug command");
+ if (narg < 2) error->all(FLERR,"Illegal fix nphug command");
v0 = atof(arg[1]);
v0_set = 1;
return 2;
} else if (strcmp(arg[0],"p0") == 0) {
- if (narg < 2) error->all("Illegal fix nphug command");
+ if (narg < 2) error->all(FLERR,"Illegal fix nphug command");
p0 = atof(arg[1]);
p0_set = 1;
return 2;
}
return 0;
}
diff --git a/src/SHOCK/fix_wall_piston.cpp b/src/SHOCK/fix_wall_piston.cpp
index e639b6285..2d610ea2e 100644
--- a/src/SHOCK/fix_wall_piston.cpp
+++ b/src/SHOCK/fix_wall_piston.cpp
@@ -1,327 +1,327 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_wall_piston.h"
#include "atom.h"
#include "modify.h"
#include "domain.h"
#include "lattice.h"
#include "update.h"
#include "error.h"
#include "random_mars.h"
#include "force.h"
#include "comm.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixWallPiston::FixWallPiston(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
force_reneighbor = 1;
next_reneighbor = -1;
box_change = 1;
time_depend = 1;
- if (narg < 4) error->all("Illegal fix wall/piston command");
+ if (narg < 4) error->all(FLERR,"Illegal fix wall/piston command");
randomt = NULL;
tempflag = 0;
scaleflag = 1;
roughflag = 0;
rampflag = 0;
rampNL1flag = 0;
rampNL2flag = 0;
rampNL3flag = 0;
rampNL4flag = 0;
rampNL5flag = 0;
x0 = y0 = z0 = vx = vy = vz = 0.0;
xloflag = xhiflag = yloflag = yhiflag = zloflag = zhiflag = 0;
int iarg = 0;
iarg = 3;
while (iarg < narg) {
- if (strcmp(arg[iarg],"xlo") == 0) { error->all("Fix wall/piston command only available at zlo");
- } else if (strcmp(arg[iarg],"ylo") == 0) { error->all("Fix wall/piston command only available at zlo");
+ if (strcmp(arg[iarg],"xlo") == 0) { error->all(FLERR,"Fix wall/piston command only available at zlo");
+ } else if (strcmp(arg[iarg],"ylo") == 0) { error->all(FLERR,"Fix wall/piston command only available at zlo");
} else if (strcmp(arg[iarg],"zlo") == 0) {
zloflag = 1;
iarg++;
- if (domain->boundary[2][0] != 2) error->all("Must shrink-wrap piston boundary");
- } else if (strcmp(arg[iarg],"xhi") == 0) { error->all("Fix wall/piston command only available at zlo");
- } else if (strcmp(arg[iarg],"yhi") == 0) { error->all("Fix wall/piston command only available at zlo");
- } else if (strcmp(arg[iarg],"zhi") == 0) { error->all("Fix wall/piston command only available at zlo");
+ if (domain->boundary[2][0] != 2) error->all(FLERR,"Must shrink-wrap piston boundary");
+ } else if (strcmp(arg[iarg],"xhi") == 0) { error->all(FLERR,"Fix wall/piston command only available at zlo");
+ } else if (strcmp(arg[iarg],"yhi") == 0) { error->all(FLERR,"Fix wall/piston command only available at zlo");
+ } else if (strcmp(arg[iarg],"zhi") == 0) { error->all(FLERR,"Fix wall/piston command only available at zlo");
} else if (strcmp(arg[iarg],"vel") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix wall/piston command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix wall/piston command");
vx = atof(arg[iarg+1]);
vy = atof(arg[iarg+2]);
vz = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"pos") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix wall/piston command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix wall/piston command");
x0 = atof(arg[iarg+1]);
y0 = atof(arg[iarg+2]);
z0 = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix wall/pistons command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix wall/pistons command");
tempflag = 1;
t_target = atof(arg[iarg+1]);
t_period = atof(arg[iarg+2]);
tseed = atoi(arg[iarg+3]);
t_extent = atof(arg[iarg+4]);
- if (t_target <= 0) error->all("Illegal fix wall/piston command");
- if (t_period <= 0) error->all("Illegal fix wall/piston command");
- if (t_extent <= 0) error->all("Illegal fix wall/piston command");
- if (tseed <= 0) error->all("Illegal fix wall/pistons command");
+ if (t_target <= 0) error->all(FLERR,"Illegal fix wall/piston command");
+ if (t_period <= 0) error->all(FLERR,"Illegal fix wall/piston command");
+ if (t_extent <= 0) error->all(FLERR,"Illegal fix wall/piston command");
+ if (tseed <= 0) error->all(FLERR,"Illegal fix wall/pistons command");
randomt = new RanMars(lmp,tseed + comm->me);
gfactor1 = new double[atom->ntypes+1];
gfactor2 = new double[atom->ntypes+1];
iarg += 5;
} else if (strcmp(arg[iarg],"rough") == 0) {
roughflag = 1;
roughdist = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"ramp") == 0) {
rampflag = 1;
iarg++;
} else if (strcmp(arg[iarg],"rampNL1") == 0) {
rampNL1flag = 1;
iarg++;
} else if (strcmp(arg[iarg],"rampNL2") == 0) {
rampNL2flag = 1;
iarg++;
} else if (strcmp(arg[iarg],"rampNL3") == 0) {
rampNL3flag = 1;
iarg++;
} else if (strcmp(arg[iarg],"rampNL4") == 0) {
rampNL4flag = 1;
iarg++;
} else if (strcmp(arg[iarg],"rampNL5") == 0) {
rampNL5flag = 1;
iarg++;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix wall/piston command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix wall/piston command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix wall/piston command");
+ else error->all(FLERR,"Illegal fix wall/piston command");
iarg += 2;
- } else error->all("Illegal fix wall/piston command");
+ } else error->all(FLERR,"Illegal fix wall/piston command");
}
- if (vx < 0.0 || vy < 0.0 || vz < 0.0) error->all("Illegal fix wall/piston velocity");
+ if (vx < 0.0 || vy < 0.0 || vz < 0.0) error->all(FLERR,"Illegal fix wall/piston velocity");
if ((xloflag || xhiflag) && domain->xperiodic)
- error->all("Cannot use wall in periodic dimension");
+ error->all(FLERR,"Cannot use wall in periodic dimension");
if ((yloflag || yhiflag) && domain->yperiodic)
- error->all("Cannot use wall in periodic dimension");
+ error->all(FLERR,"Cannot use wall in periodic dimension");
if ((zloflag || zhiflag) && domain->zperiodic)
- error->all("Cannot use wall in periodic dimension");
+ error->all(FLERR,"Cannot use wall in periodic dimension");
// setup scaling
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix wall/piston with undefined lattice");
+ error->all(FLERR,"Use of fix wall/piston with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
vx *= xscale;
vy *= yscale;
vz *= zscale;
x0 *= xscale;
y0 *= yscale;
z0 *= zscale;
roughdist *= zscale;
if (rampflag || rampNL1flag || rampNL2flag || rampNL3flag || rampNL4flag || rampNL5flag) {
maxvx = vx;
maxvy = vy;
maxvz = vz;
}
}
/* ---------------------------------------------------------------------- */
int FixWallPiston::setmask()
{
int mask = 0;
mask |= POST_INTEGRATE;
mask |= POST_INTEGRATE_RESPA;
mask |= INITIAL_INTEGRATE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixWallPiston::initial_integrate(int vflag)
{
next_reneighbor = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void FixWallPiston::post_integrate()
{
double xlo, xhi, ylo, yhi, zlo, zhi;
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = (update->ntimestep - update->beginstep) * update->dt;
double tott = (update->endstep - update->beginstep) * update->dt;
double tt = t * t;
double ttt = tt * t;
double tttt = tt * tt;
double t0p5 = sqrt(t/tott);
double t1p5 = t0p5*t0p5*t0p5;
double t2p5 = t1p5*t0p5*t0p5;
if (rampflag) {
paccelx = maxvx / tott;
paccely = maxvy / tott;
paccelz = maxvz / tott;
if (zloflag) { zlo = z0 + 0.5 * paccelz * tt; vz = paccelz * t; }
}
else if (rampNL1flag) {
paccelz = maxvz / tott;
angfreq = 6.283185 / (0.5 * tott);
if (zloflag) {
zlo = z0 + paccelz * (0.5*tt + 1.0/(angfreq*angfreq) - 1.0/(angfreq*angfreq)*cos(angfreq*t));
vz = paccelz * (t + 1.0/angfreq*sin(angfreq*t));
}
- else { error->all("NL ramp in wall/piston only implemented in zlo for now"); }
+ else { error->all(FLERR,"NL ramp in wall/piston only implemented in zlo for now"); }
}
else if (rampNL2flag) {
paccelz = maxvz / tott;
angfreq = 18.84956 / tott;
if (zloflag) {
zlo = z0 + paccelz * (0.5*tt + 4.0/(3.0*angfreq*angfreq)*(1.0-cos(angfreq*t)) + 1.0/(6.0*angfreq*angfreq)*(1.0-cos(2.0*angfreq*t)));
vz = paccelz * (t + 4.0/(3.0*angfreq)*sin(angfreq*t) + 1.0/(3.0*angfreq)*sin(2.0*angfreq*t));
}
- else { error->all("NL ramp in wall/piston only implemented in zlo for now"); }
+ else { error->all(FLERR,"NL ramp in wall/piston only implemented in zlo for now"); }
}
else if (rampNL3flag) {
paccelz = maxvz / tott;
if (zloflag) {
zlo = z0 + paccelz*tott*tott/2.5 * (t2p5 );
vz = paccelz * tott * (t1p5 );
}
- else { error->all("NL ramp in wall/piston only implemented in zlo for now"); }
+ else { error->all(FLERR,"NL ramp in wall/piston only implemented in zlo for now"); }
}
else if (rampNL4flag) {
paccelz = maxvz / tott;
if (zloflag) {
zlo = z0 + paccelz/tott/3.0 * (ttt);
vz = paccelz / tott * (tt);
}
- else { error->all("NL ramp in wall/piston only implemented in zlo for now"); }
+ else { error->all(FLERR,"NL ramp in wall/piston only implemented in zlo for now"); }
}
else if (rampNL5flag) {
paccelz = maxvz / tott;
if (zloflag) {
zlo = z0 + paccelz/tott/tott/4.0 * (tttt);
vz = paccelz / tott / tott * (ttt);
}
- else { error->all("NL ramp in wall/piston only implemented in zlo for now"); }
+ else { error->all(FLERR,"NL ramp in wall/piston only implemented in zlo for now"); }
}
else {
if (zloflag) { zlo = z0 + vz * t; }
}
if (update->ntimestep % 1000 == 0)
if (comm->me == 0) {
if (screen)
fprintf(screen,"SHOCK: step " BIGINT_FORMAT
" t %g zpos %g vz %g az %g zlo %g\n",
update->ntimestep, t, zlo, vz, paccelz, domain->boxlo[2]);
if (logfile)
fprintf(logfile,"SHOCK: step " BIGINT_FORMAT
" t %g zpos %g vz %g az %g zlo %g\n",
update->ntimestep, t, zlo, vz, paccelz, domain->boxlo[2]);
}
// VIRIAL PRESSURE CONTRIBUTION?
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
roughoff = 0.0;
if (roughflag) {
roughoff += roughdist*fabs((x[i][0] - domain->boxlo[0])/(domain->boxhi[0]-domain->boxlo[0])-0.5);
roughoff += roughdist*fabs((x[i][1] - domain->boxlo[1])/(domain->boxhi[1]-domain->boxlo[1])-0.5);
}
if (zloflag && x[i][2] < zlo - roughoff) {
x[i][2] = 2.0 * (zlo - roughoff) - x[i][2];
v[i][2] = 2.0 * vz - v[i][2];
}
}
}
double **f = atom->f;
int *type = atom->type;
double gamma1,gamma2;
double tsqrt = sqrt(t_target);
if (atom->mass) {
if (tempflag) {
for (int i = 1; i <= atom->ntypes; i++) {
gfactor1[i] = -atom->mass[i] / t_period / force->ftm2v;
gfactor2[i] = sqrt(atom->mass[i]) *
sqrt(24.0*force->boltz/t_period/update->dt/force->mvv2e) /
force->ftm2v;
}
}
for (int i = 0; i < nlocal; i++) {
// SET TEMP AHEAD OF PISTON
if (tempflag && x[i][2] <= domain->boxlo[2] + t_extent ) {
gamma1 = gfactor1[type[i]];
gamma2 = gfactor2[type[i]] * tsqrt;
f[i][0] += gamma1*v[i][0] + gamma2*(randomt->uniform()-0.5);
f[i][1] += gamma1*v[i][1] + gamma2*(randomt->uniform()-0.5);
f[i][2] += gamma1*(v[i][2]-vz) + gamma2*(randomt->uniform()-0.5);
}
}
} else {
double *rmass = atom->rmass;
double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;
for (int i = 0; i < nlocal; i++) {
// SET TEMP AHEAD OF PISTON
if (tempflag && x[i][2] <= domain->boxlo[2] + t_extent ) {
gamma1 = -rmass[i] / t_period / ftm2v;
gamma2 = sqrt(rmass[i]) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma2 *= tsqrt;
f[i][0] += gamma1*v[i][0] + gamma2*(randomt->uniform()-0.5);
f[i][1] += gamma1*v[i][1] + gamma2*(randomt->uniform()-0.5);
f[i][2] += gamma1*v[i][2] + gamma2*(randomt->uniform()-0.5);
}
}
}
}
diff --git a/src/SRD/fix_srd.cpp b/src/SRD/fix_srd.cpp
index 1516e23d5..ec0d07d20 100644
--- a/src/SRD/fix_srd.cpp
+++ b/src/SRD/fix_srd.cpp
@@ -1,3486 +1,3483 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Jeremy Lechman (SNL), Pieter in 't Veld (BASF)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_srd.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "group.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "neighbor.h"
#include "comm.h"
#include "modify.h"
#include "fix_deform.h"
#include "fix_wall_srd.h"
#include "random_mars.h"
#include "random_park.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{SLIP,NOSLIP};
enum{SPHERE,ELLIPSOID,WALL};
enum{INSIDE_ERROR,INSIDE_WARN,INSIDE_IGNORE};
enum{BIG_MOVE,SRD_MOVE,SRD_ROTATE};
enum{CUBIC_ERROR,CUBIC_WARN};
enum{SHIFT_NO,SHIFT_YES,SHIFT_POSSIBLE};
enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp
#define INERTIA 0.4
#define ATOMPERBIN 10
#define BIG 1.0e20
#define VBINSIZE 5
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
//#define SRD_DEBUG 1
//#define SRD_DEBUG_ATOMID 58
//#define SRD_DEBUG_TIMESTEP 449
/* ---------------------------------------------------------------------- */
FixSRD::FixSRD(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
- if (narg < 8) error->all("Illegal fix srd command");
+ if (narg < 8) error->all(FLERR,"Illegal fix srd command");
restart_pbc = 1;
vector_flag = 1;
size_vector = 12;
global_freq = 1;
extvector = 0;
nevery = atoi(arg[3]);
bigexist = 1;
if (strcmp(arg[4],"NULL") == 0) bigexist = 0;
else biggroup = group->find(arg[4]);
temperature_srd = atof(arg[5]);
gridsrd = atof(arg[6]);
int seed = atoi(arg[7]);
// parse options
lamdaflag = 0;
collidestyle = NOSLIP;
overlap = 0;
insideflag = INSIDE_ERROR;
exactflag = 1;
radfactor = 1.0;
maxbounceallow = 0;
gridsearch = gridsrd;
cubicflag = CUBIC_ERROR;
cubictol = 0.01;
shiftuser = SHIFT_NO;
shiftseed = 0;
streamflag = 1;
int iarg = 8;
while (iarg < narg) {
if (strcmp(arg[iarg],"lamda") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
lamda = atof(arg[iarg+1]);
lamdaflag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"collision") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"slip") == 0) collidestyle = SLIP;
else if (strcmp(arg[iarg+1],"noslip") == 0) collidestyle = NOSLIP;
- else error->all("Illegal fix srd command");
+ else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"overlap") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"yes") == 0) overlap = 1;
else if (strcmp(arg[iarg+1],"no") == 0) overlap = 0;
- else error->all("Illegal fix srd command");
+ else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"inside") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"error") == 0) insideflag = INSIDE_ERROR;
else if (strcmp(arg[iarg+1],"warn") == 0) insideflag = INSIDE_WARN;
else if (strcmp(arg[iarg+1],"ignore") == 0) insideflag = INSIDE_IGNORE;
- else error->all("Illegal fix srd command");
+ else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"exact") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"yes") == 0) exactflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) exactflag = 0;
- else error->all("Illegal fix srd command");
+ else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
} else if (strcmp(arg[iarg],"radius") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
radfactor = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"bounce") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
maxbounceallow = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"search") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
gridsearch = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"cubic") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix srd command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"error") == 0) cubicflag = CUBIC_ERROR;
else if (strcmp(arg[iarg+1],"warn") == 0) cubicflag = CUBIC_WARN;
- else error->all("Illegal fix srd command");
+ else error->all(FLERR,"Illegal fix srd command");
cubictol = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"shift") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix srd command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix srd command");
else if (strcmp(arg[iarg+1],"no") == 0) shiftuser = SHIFT_NO;
else if (strcmp(arg[iarg+1],"yes") == 0) shiftuser = SHIFT_YES;
else if (strcmp(arg[iarg+1],"possible") == 0) shiftuser = SHIFT_POSSIBLE;
- else error->all("Illegal fix srd command");
+ else error->all(FLERR,"Illegal fix srd command");
shiftseed = atoi(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"stream") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix srd command");
if (strcmp(arg[iarg+1],"yes") == 0) streamflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) streamflag = 0;
- else error->all("Illegal fix srd command");
+ else error->all(FLERR,"Illegal fix srd command");
iarg += 2;
- } else error->all("Illegal fix srd command");
+ } else error->all(FLERR,"Illegal fix srd command");
}
// error check
- if (nevery <= 0) error->all("Illegal fix srd command");
- if (bigexist && biggroup < 0) error->all("Could not find fix srd group ID");
- if (gridsrd <= 0.0) error->all("Illegal fix srd command");
- if (temperature_srd <= 0.0) error->all("Illegal fix srd command");
- if (seed <= 0) error->all("Illegal fix srd command");
- if (radfactor <= 0.0) error->all("Illegal fix srd command");
- if (maxbounceallow < 0) error->all("Illegal fix srd command");
- if (lamdaflag && lamda <= 0.0) error->all("Illegal fix srd command");
- if (gridsearch <= 0.0) error->all("Illegal fix srd command");
- if (cubictol < 0.0 || cubictol > 1.0) error->all("Illegal fix srd command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix srd command");
+ if (bigexist && biggroup < 0) error->all(FLERR,"Could not find fix srd group ID");
+ if (gridsrd <= 0.0) error->all(FLERR,"Illegal fix srd command");
+ if (temperature_srd <= 0.0) error->all(FLERR,"Illegal fix srd command");
+ if (seed <= 0) error->all(FLERR,"Illegal fix srd command");
+ if (radfactor <= 0.0) error->all(FLERR,"Illegal fix srd command");
+ if (maxbounceallow < 0) error->all(FLERR,"Illegal fix srd command");
+ if (lamdaflag && lamda <= 0.0) error->all(FLERR,"Illegal fix srd command");
+ if (gridsearch <= 0.0) error->all(FLERR,"Illegal fix srd command");
+ if (cubictol < 0.0 || cubictol > 1.0) error->all(FLERR,"Illegal fix srd command");
if ((shiftuser == SHIFT_YES || shiftuser == SHIFT_POSSIBLE) &&
- shiftseed <= 0) error->all("Illegal fix srd command");
+ shiftseed <= 0) error->all(FLERR,"Illegal fix srd command");
// initialize Marsaglia RNG with processor-unique seed
me = comm->me;
nprocs = comm->nprocs;
random = new RanMars(lmp,seed + me);
// if requested, initialize shift RNG, same on every proc
if (shiftuser == SHIFT_YES || shiftuser == SHIFT_POSSIBLE)
randomshift = new RanPark(lmp,shiftseed);
else randomshift = NULL;
// initialize data structs and flags
if (bigexist) biggroupbit = group->bitmask[biggroup];
else biggroupbit = 0;
nmax = 0;
binhead = NULL;
maxbin1 = 0;
binnext = NULL;
maxbuf = 0;
sbuf1 = sbuf2 = rbuf1 = rbuf2 = NULL;
shifts[0].maxvbin = shifts[1].maxvbin = 0;
shifts[0].vbin = shifts[1].vbin = NULL;
shifts[0].maxbinsq = shifts[1].maxbinsq = 0;
for (int ishift = 0; ishift < 2; ishift++)
for (int iswap = 0; iswap < 6; iswap++)
shifts[ishift].bcomm[iswap].sendlist =
shifts[ishift].bcomm[iswap].recvlist = NULL;
maxbin2 = 0;
nbinbig = NULL;
binbig = NULL;
binsrd = NULL;
nstencil = maxstencil = 0;
stencil = NULL;
maxbig = 0;
biglist = NULL;
stats_flag = 1;
for (int i = 0; i < size_vector; i++) stats_all[i] = 0.0;
initflag = 0;
srd_bin_temp = 0.0;
srd_bin_count = 0;
// atom style pointers to particles that store bonus info
avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
// fix parameters
if (collidestyle == SLIP) comm_reverse = 3;
else comm_reverse = 6;
force_reneighbor = 1;
}
/* ---------------------------------------------------------------------- */
FixSRD::~FixSRD()
{
delete random;
delete randomshift;
memory->destroy(binhead);
memory->destroy(binnext);
memory->destroy(sbuf1);
memory->destroy(sbuf2);
memory->destroy(rbuf1);
memory->destroy(rbuf2);
memory->sfree(shifts[0].vbin);
memory->sfree(shifts[1].vbin);
for (int ishift = 0; ishift < 2; ishift++)
for (int iswap = 0; iswap < 6; iswap++) {
memory->destroy(shifts[ishift].bcomm[iswap].sendlist);
memory->destroy(shifts[ishift].bcomm[iswap].recvlist);
}
memory->destroy(nbinbig);
memory->destroy(binbig);
memory->destroy(binsrd);
memory->destroy(stencil);
memory->sfree(biglist);
}
/* ---------------------------------------------------------------------- */
int FixSRD::setmask()
{
int mask = 0;
mask |= PRE_NEIGHBOR;
mask |= POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixSRD::init()
{
// error checks
- if (force->newton_pair == 0) error->all("Fix srd requires newton pair on");
+ if (force->newton_pair == 0) error->all(FLERR,"Fix srd requires newton pair on");
if (bigexist && comm->ghost_velocity == 0)
- error->all("Fix srd requires ghost atoms store velocity");
+ error->all(FLERR,"Fix srd requires ghost atoms store velocity");
if (bigexist && collidestyle == NOSLIP && !atom->torque_flag)
- error->all("Fix SRD no-slip requires atom attribute torque");
+ error->all(FLERR,"Fix SRD no-slip requires atom attribute torque");
if (initflag && update->dt != dt_big)
- error->all("Cannot change timestep once fix srd is setup");
+ error->all(FLERR,"Cannot change timestep once fix srd is setup");
// orthogonal vs triclinic simulation box
// could be static or shearing box
triclinic = domain->triclinic;
// wallexist = 1 if SRD wall(s) are defined
wallexist = 0;
for (int m = 0; m < modify->nfix; m++) {
if (strcmp(modify->fix[m]->style,"wall/srd") == 0) {
- if (wallexist) error->all("Cannot use fix wall/srd more than once");
+ if (wallexist) error->all(FLERR,"Cannot use fix wall/srd more than once");
wallexist = 1;
wallfix = (FixWallSRD *) modify->fix[m];
nwall = wallfix->nwall;
wallvarflag = wallfix->varflag;
wallwhich = wallfix->wallwhich;
xwall = wallfix->xwall;
xwallhold = wallfix->xwallhold;
vwall = wallfix->vwall;
fwall = wallfix->fwall;
walltrigger = 0.5 * neighbor->skin;
if (wallfix->overlap && overlap == 0 && me == 0)
- error->warning("Fix SRD walls overlap but fix srd overlap not set");
+ error->warning(FLERR,"Fix SRD walls overlap but fix srd overlap not set");
}
}
// set change_flags if box size or shape changes
change_size = change_shape = 0;
if (domain->nonperiodic == 2) change_size = 1;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->box_change) {
if (modify->fix[i]->box_change_size) change_size = 1;
if (modify->fix[i]->box_change_shape) change_shape = 1;
if (strcmp(modify->fix[i]->style,"deform") == 0) {
FixDeform *deform = (FixDeform *) modify->fix[i];
if (deform->box_change_shape && deform->remapflag != V_REMAP)
- error->all("Using fix srd with inconsistent "
+ error->all(FLERR,"Using fix srd with inconsistent "
"fix deform remap option");
}
}
// parameterize based on current box volume
dimension = domain->dimension;
parameterize();
// limit initial SRD velocities if necessary
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double vsq;
nrescale = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),v[i]);
}
}
int all;
MPI_Allreduce(&nrescale,&all,1,MPI_INT,MPI_SUM,world);
if (me == 0) {
if (screen)
fprintf(screen," # of rescaled SRD velocities = %d\n",all);
if (logfile)
fprintf(logfile," # of rescaled SRD velocities = %d\n",all);
}
velocity_stats(igroup);
if (bigexist) velocity_stats(biggroup);
// zero per-run stats
bouncemaxnum = 0;
bouncemax = 0;
reneighcount = 0;
initflag = 1;
next_reneighbor = -1;
}
/* ---------------------------------------------------------------------- */
void FixSRD::setup(int vflag)
{
setup_bounds();
if (dist_srd_reneigh < nevery*dt_big*vmax && me == 0)
- error->warning("Fix srd SRD moves may trigger frequent reneighboring");
+ error->warning(FLERR,"Fix srd SRD moves may trigger frequent reneighboring");
// setup search bins and search stencil based on these distances
if (bigexist || wallexist) {
setup_search_bins();
setup_search_stencil();
} else nbins2 = 0;
// perform first bining of SRD and big particles and walls
// set reneighflag to turn off SRD rotation
// don't do SRD rotation in setup, only during timestepping
reneighflag = BIG_MOVE;
pre_neighbor();
}
/* ----------------------------------------------------------------------
assign SRD particles to bins
assign big particles to all bins they overlap
------------------------------------------------------------------------- */
void FixSRD::pre_neighbor()
{
int i,j,m,ix,iy,iz,jx,jy,jz,ibin,jbin,lo,hi;
double rsq,cutbinsq;
// grow SRD per-atom bin arrays if necessary
if (atom->nlocal > nmax) {
nmax = atom->nmax;
memory->destroy(binsrd);
memory->destroy(binnext);
memory->create(binsrd,nmax,"fix/srd:binsrd");
memory->create(binnext,nmax,"fix/srd:binnext");
}
// setup and grow BIG info list if necessary
// set index ptrs to BIG particles and to WALLS
// big_static() adds static properties to info list
if (bigexist || wallexist) {
if (bigexist) {
if (biggroup == atom->firstgroup) nbig = atom->nfirst + atom->nghost;
else {
int *mask = atom->mask;
int nlocal = atom->nlocal;
nbig = atom->nghost;
for (i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) nbig++;
}
} else nbig = 0;
int ninfo = nbig;
if (wallexist) ninfo += nwall;
if (ninfo > maxbig) {
maxbig = ninfo;
memory->destroy(biglist);
biglist = (Big *) memory->smalloc(maxbig*sizeof(Big),"fix/srd:biglist");
}
if (bigexist) {
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (biggroup == atom->firstgroup) nlocal = atom->nfirst;
nbig = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) biglist[nbig++].index = i;
int nall = atom->nlocal + atom->nghost;
for (i = atom->nlocal; i < nall; i++)
if (mask[i] & biggroupbit) biglist[nbig++].index = i;
big_static();
}
if (wallexist) {
for (m = 0; m < nwall; m++) {
biglist[nbig+m].index = m;
biglist[nbig+m].type = WALL;
}
wallfix->wall_params(1);
}
}
// if simulation box size changes, reset velocity bins
// if big particles exist, reset search bins if box size or shape changes,
// b/c finite-size particles will overlap different bins as the box tilts
if (change_size) setup_bounds();
if (change_size) setup_velocity_bins();
if ((change_size || change_shape) && (bigexist || wallexist)) {
setup_search_bins();
setup_search_stencil();
}
// map each owned & ghost big particle to search bins it overlaps
// zero out bin counters for big particles
// if firstgroup is defined, only loop over first and ghost particles
// for each big particle: loop over stencil to find overlap bins
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int nfirst = nlocal;
if (bigexist && biggroup == atom->firstgroup) nfirst = atom->nfirst;
if (bigexist || wallexist)
for (i = 0; i < nbins2; i++)
nbinbig[i] = 0;
if (bigexist) {
i = nbig = 0;
while (i < nall) {
if (mask[i] & biggroupbit) {
ix = static_cast<int> ((x[i][0]-xblo2)*bininv2x);
iy = static_cast<int> ((x[i][1]-yblo2)*bininv2y);
iz = static_cast<int> ((x[i][2]-zblo2)*bininv2z);
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (ix < 0 || ix >= nbin2x || iy < 0 || iy >= nbin2y ||
iz < 0 || iz >= nbin2z)
- error->one("Fix SRD: bad search bin assignment");
+ error->one(FLERR,"Fix SRD: bad search bin assignment");
cutbinsq = biglist[nbig].cutbinsq;
for (j = 0; j < nstencil; j++) {
jx = ix + stencil[j][0];
jy = iy + stencil[j][1];
jz = iz + stencil[j][2];
if (jx < 0 || jx >= nbin2x || jy < 0 || jy >= nbin2y ||
jz < 0 || jz >= nbin2z) {
printf("Big particle %d %d %g %g %g\n",
atom->tag[i],i,x[i][0],x[i][1],x[i][2]);
printf("Bin indices: %d %d %d, %d %d %d, %d %d %d\n",
ix,iy,iz,jx,jy,jz,nbin2x,nbin2y,nbin2z);
- error->one("Fix SRD: bad stencil bin for big particle");
+ error->one(FLERR,"Fix SRD: bad stencil bin for big particle");
}
rsq = point_bin_distance(x[i],jx,jy,jz);
if (rsq < cutbinsq) {
jbin = ibin + stencil[j][3];
if (nbinbig[jbin] == ATOMPERBIN)
- error->one("Fix SRD: too many big particles in bin");
+ error->one(FLERR,"Fix SRD: too many big particles in bin");
binbig[jbin][nbinbig[jbin]++] = nbig;
}
}
nbig++;
}
i++;
if (i == nfirst) i = nlocal;
}
}
// map each wall to search bins it covers, up to non-periodic boundary
// if wall moves, add walltrigger to its position
// this insures it is added to all search bins it may move into
// may not overlap any of my search bins
if (wallexist) {
double delta = 0.0;
if (wallvarflag) delta = walltrigger;
for (m = 0; m < nwall; m++) {
int dim = wallwhich[m] / 2;
int side = wallwhich[m] % 2;
if (dim == 0) {
if (side == 0) {
hi = static_cast<int> ((xwall[m]+delta-xblo2)*bininv2x);
if (hi < 0) continue;
- if (hi >= nbin2x) error->all("Fix SRD: bad search bin assignment");
+ if (hi >= nbin2x) error->all(FLERR,"Fix SRD: bad search bin assignment");
lo = 0;
} else {
lo = static_cast<int> ((xwall[m]-delta-xblo2)*bininv2x);
if (lo >= nbin2x) continue;
- if (lo < 0) error->all("Fix SRD: bad search bin assignment");
+ if (lo < 0) error->all(FLERR,"Fix SRD: bad search bin assignment");
hi = nbin2x-1;
}
for (ix = lo; ix <= hi; ix++)
for (iy = 0; iy < nbin2y; iy++)
for (iz = 0; iz < nbin2z; iz++) {
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (nbinbig[ibin] == ATOMPERBIN)
- error->all("Fix SRD: too many walls in bin");
+ error->all(FLERR,"Fix SRD: too many walls in bin");
binbig[ibin][nbinbig[ibin]++] = nbig+m;
}
} else if (dim == 1) {
if (side == 0) {
hi = static_cast<int> ((xwall[m]+delta-yblo2)*bininv2y);
if (hi < 0) continue;
- if (hi >= nbin2y) error->all("Fix SRD: bad search bin assignment");
+ if (hi >= nbin2y) error->all(FLERR,"Fix SRD: bad search bin assignment");
lo = 0;
} else {
lo = static_cast<int> ((xwall[m]-delta-yblo2)*bininv2y);
if (lo >= nbin2y) continue;
- if (lo < 0) error->all("Fix SRD: bad search bin assignment");
+ if (lo < 0) error->all(FLERR,"Fix SRD: bad search bin assignment");
hi = nbin2y-1;
}
for (iy = lo; iy <= hi; iy++)
for (ix = 0; ix < nbin2x; ix++)
for (iz = 0; iz < nbin2z; iz++) {
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (nbinbig[ibin] == ATOMPERBIN)
- error->all("Fix SRD: too many walls in bin");
+ error->all(FLERR,"Fix SRD: too many walls in bin");
binbig[ibin][nbinbig[ibin]++] = nbig+m;
}
} else if (dim == 2) {
if (side == 0) {
hi = static_cast<int> ((xwall[m]+delta-zblo2)*bininv2z);
if (hi < 0) continue;
- if (hi >= nbin2z) error->all("Fix SRD: bad search bin assignment");
+ if (hi >= nbin2z) error->all(FLERR,"Fix SRD: bad search bin assignment");
lo = 0;
} else {
lo = static_cast<int> ((xwall[m]-delta-zblo2)*bininv2z);
if (lo >= nbin2z) continue;
- if (lo < 0) error->all("Fix SRD: bad search bin assignment");
+ if (lo < 0) error->all(FLERR,"Fix SRD: bad search bin assignment");
hi = nbin2z-1;
}
for (iz = lo; iz < hi; iz++)
for (ix = 0; ix < nbin2x; ix++)
for (iy = 0; iy < nbin2y; iy++) {
ibin = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (nbinbig[ibin] == ATOMPERBIN)
- error->all("Fix SRD: too many walls in bin");
+ error->all(FLERR,"Fix SRD: too many walls in bin");
binbig[ibin][nbinbig[ibin]++] = nbig+m;
}
}
}
}
// rotate SRD velocities on SRD timestep
// done now since all SRDs are currently inside my sub-domain
if (reneighflag == SRD_ROTATE) reset_velocities();
// log stats if reneighboring occurred b/c SRDs moved too far
if (reneighflag == SRD_MOVE) reneighcount++;
reneighflag = BIG_MOVE;
}
/* ----------------------------------------------------------------------
advect SRD particles and detect collisions between SRD and BIG particles
when collision occurs, change x,v of SRD, force,torque of BIG particle
------------------------------------------------------------------------- */
void FixSRD::post_force(int vflag)
{
int i,m,ix,iy,iz;
// zero per-timestep stats
stats_flag = 0;
ncheck = ncollide = nbounce = ninside = nrescale = 0;
// zero ghost forces & torques on BIG particles
double **f = atom->f;
double **torque = atom->torque;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (bigexist == 0) nall = 0;
for (i = nlocal; i < nall; i++)
f[i][0] = f[i][1] = f[i][2] = 0.0;
if (collidestyle == NOSLIP)
for (i = nlocal; i < nall; i++)
torque[i][0] = torque[i][1] = torque[i][2] = 0.0;
// advect SRD particles
// assign to search bins if big particles or walls exist
int *mask = atom->mask;
double **x = atom->x;
double **v = atom->v;
if (bigexist || wallexist) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
x[i][0] += dt_big*v[i][0];
x[i][1] += dt_big*v[i][1];
x[i][2] += dt_big*v[i][2];
ix = static_cast<int> ((x[i][0]-xblo2)*bininv2x);
iy = static_cast<int> ((x[i][1]-yblo2)*bininv2y);
iz = static_cast<int> ((x[i][2]-zblo2)*bininv2z);
binsrd[i] = iz*nbin2y*nbin2x + iy*nbin2x + ix;
if (ix < 0 || ix >= nbin2x || iy < 0 || iy >= nbin2y ||
iz < 0 || iz >= nbin2z) {
if (screen) {
fprintf(screen,"SRD particle %d on step " BIGINT_FORMAT "\n",
atom->tag[i],update->ntimestep);
fprintf(screen,"v = %g %g %g\n",v[i][0],v[i][1],v[i][2]);
fprintf(screen,"x = %g %g %g\n",x[i][0],x[i][1],x[i][2]);
fprintf(screen,"ix,iy,iz nx,ny,nz = %d %d %d %d %d %d\n",
ix,iy,iz,nbin2x,nbin2y,nbin2z);
}
- error->one("Fix SRD: bad bin assignment for SRD advection");
+ error->one(FLERR,"Fix SRD: bad bin assignment for SRD advection");
}
}
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
x[i][0] += dt_big*v[i][0];
x[i][1] += dt_big*v[i][1];
x[i][2] += dt_big*v[i][2];
}
}
// detect collision of SRDs with BIG particles or walls
if (bigexist || wallexist) {
if (bigexist) big_dynamic();
if (wallexist) wallfix->wall_params(0);
if (overlap) collisions_multi();
else collisions_single();
}
// reverse communicate forces & torques on BIG particles
if (bigexist) {
flocal = f;
tlocal = torque;
comm->reverse_comm_fix(this);
}
// if any SRD particle has moved too far, trigger reneigh on next step
// for triclinic, perform check in lamda units
int flag = 0;
if (triclinic) domain->x2lamda(nlocal);
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (x[i][0] < srdlo_reneigh[0] || x[i][0] > srdhi_reneigh[0] ||
x[i][1] < srdlo_reneigh[1] || x[i][1] > srdhi_reneigh[1] ||
x[i][2] < srdlo_reneigh[2] || x[i][2] > srdhi_reneigh[2]) flag = 1;
}
if (triclinic) domain->lamda2x(nlocal);
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall) {
next_reneighbor = update->ntimestep + 1;
reneighflag = SRD_MOVE;
}
// if wall has moved too far, trigger reneigh on next step
// analagous to neighbor check for big particle moving 1/2 of skin distance
if (wallexist) {
for (m = 0; m < nwall; m++)
if (fabs(xwall[m]-xwallhold[m]) > walltrigger)
next_reneighbor = update->ntimestep + 1;
}
// if next timestep is SRD timestep, trigger reneigh
if ((update->ntimestep+1) % nevery == 0) {
next_reneighbor = update->ntimestep + 1;
reneighflag = SRD_ROTATE;
}
}
/* ----------------------------------------------------------------------
reset SRD velocities
may perform random shifting by 1/2 bin in each dimension
called at pre-neighbor stage when all SRDs are now inside my sub-domain
for triclinic, will set mean velocity to box deformation velocity
------------------------------------------------------------------------- */
void FixSRD::reset_velocities()
{
int i,j,n,ix,iy,iz,ibin,axis,sign,irandom;
double u[3],vave[3];
double vx,vy,vz,vsq;
double *vold,*vnew,*xlamda;
// if requested, perform a dynamic shift
if (shiftflag) {
double *boxlo;
if (triclinic == 0) boxlo = domain->boxlo;
else boxlo = domain->boxlo_lamda;
shifts[1].corner[0] = boxlo[0] - binsize1x*randomshift->uniform();
shifts[1].corner[1] = boxlo[1] - binsize1y*randomshift->uniform();
if (dimension == 3)
shifts[1].corner[2] = boxlo[2] - binsize1z*randomshift->uniform();
else shifts[1].corner[2] = boxlo[2];
setup_velocity_shift(1,1);
}
double *corner = shifts[shiftflag].corner;
int *binlo = shifts[shiftflag].binlo;
int *binhi = shifts[shiftflag].binhi;
int nbins = shifts[shiftflag].nbins;
int nbinx = shifts[shiftflag].nbinx;
int nbiny = shifts[shiftflag].nbiny;
BinAve *vbin = shifts[shiftflag].vbin;
// binhead = 1st SRD particle in each bin
// binnext = index of next particle in bin
// bin assignment is done in lamda units for triclinic
int *mask = atom->mask;
double **x = atom->x;
double **v = atom->v;
int nlocal = atom->nlocal;
if (triclinic) domain->x2lamda(nlocal);
for (i = 0; i < nbins; i++) binhead[i] = -1;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
ix = static_cast<int> ((x[i][0]-corner[0])*bininv1x);
ix = MAX(ix,binlo[0]);
ix = MIN(ix,binhi[0]);
iy = static_cast<int> ((x[i][1]-corner[1])*bininv1y);
iy = MAX(iy,binlo[1]);
iy = MIN(iy,binhi[1]);
iz = static_cast<int> ((x[i][2]-corner[2])*bininv1z);
iz = MAX(iz,binlo[2]);
iz = MIN(iz,binhi[2]);
ibin = (iz-binlo[2])*nbiny*nbinx + (iy-binlo[1])*nbinx + (ix-binlo[0]);
binnext[i] = binhead[ibin];
binhead[ibin] = i;
}
if (triclinic) domain->lamda2x(nlocal);
if (triclinic && streamflag) {
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xlamda = x[i];
v[i][0] -= h_rate[0]*xlamda[0] + h_rate[5]*xlamda[1] +
h_rate[4]*xlamda[2] + h_ratelo[0];
v[i][1] -= h_rate[1]*xlamda[1] + h_rate[3]*xlamda[2] + h_ratelo[1];
v[i][2] -= h_rate[2]*xlamda[2] + h_ratelo[2];
}
}
// for each bin I have particles contributing to:
// compute ave v and v^2 of particles in that bin
// if I own the bin, set its random value, else set to 0.0
for (i = 0; i < nbins; i++) {
n = 0;
vave[0] = vave[1] = vave[2] = 0.0;
for (j = binhead[i]; j >= 0; j = binnext[j]) {
vx = v[j][0];
vy = v[j][1];
vz = v[j][2];
vave[0] += vx;
vave[1] += vy;
vave[2] += vz;
n++;
}
vbin[i].vave[0] = vave[0];
vbin[i].vave[1] = vave[1];
vbin[i].vave[2] = vave[2];
vbin[i].n = n;
if (vbin[i].owner) vbin[i].random = random->uniform();
else vbin[i].random = 0.0;
}
// communicate bin info for bins which more than 1 proc contribute to
if (shifts[shiftflag].commflag) vbin_comm(shiftflag);
// for each bin I have particles contributing to:
// reassign particle velocity by rotation around a random axis
// accumulate T_srd for each bin I own
// for triclinic, replace mean velocity with stream velocity
srd_bin_temp = 0.0;
srd_bin_count = 0;
if (dimension == 2) axis = 2;
for (i = 0; i < nbins; i++) {
n = vbin[i].n;
if (n == 0) continue;
vold = vbin[i].vave;
vold[0] /= n;
vold[1] /= n;
vold[2] /= n;
vnew = vold;
irandom = static_cast<int> (6.0*vbin[i].random);
sign = irandom % 2;
if (dimension == 3) axis = irandom / 2;
vsq = 0.0;
for (j = binhead[i]; j >= 0; j = binnext[j]) {
if (axis == 0) {
u[0] = v[j][0]-vold[0];
u[1] = sign ? v[j][2]-vold[2] : vold[2]-v[j][2];
u[2] = sign ? vold[1]-v[j][1] : v[j][1]-vold[1];
} else if (axis == 1) {
u[1] = v[j][1]-vold[1];
u[0] = sign ? v[j][2]-vold[2] : vold[2]-v[j][2];
u[2] = sign ? vold[0]-v[j][0] : v[j][0]-vold[0];
} else {
u[2] = v[j][2]-vold[2];
u[1] = sign ? v[j][0]-vold[0] : vold[0]-v[j][0];
u[0] = sign ? vold[1]-v[j][1] : v[j][1]-vold[1];
}
vsq += u[0]*u[0] + u[1]*u[1] + u[2]*u[2];
v[j][0] = u[0] + vnew[0];
v[j][1] = u[1] + vnew[1];
v[j][2] = u[2] + vnew[2];
}
// sum partial contribution of my particles to T even if I don't own bin
// but only count bin if I own it, so that bin is counted exactly once
if (n > 1) {
srd_bin_temp += vsq / (n-1);
if (vbin[i].owner) srd_bin_count++;
}
}
srd_bin_temp *= force->mvv2e * mass_srd / (dimension * force->boltz);
if (triclinic && streamflag) {
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xlamda = x[i];
v[i][0] += h_rate[0]*xlamda[0] + h_rate[5]*xlamda[1] +
h_rate[4]*xlamda[2] + h_ratelo[0];
v[i][1] += h_rate[1]*xlamda[1] + h_rate[3]*xlamda[2] + h_ratelo[1];
v[i][2] += h_rate[2]*xlamda[2] + h_ratelo[2];
}
}
// rescale any too-large velocities
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),v[i]);
}
}
}
/* ----------------------------------------------------------------------
communicate summed particle info for bins that overlap 1 or more procs
------------------------------------------------------------------------- */
void FixSRD::vbin_comm(int ishift)
{
BinComm *bcomm1,*bcomm2;
MPI_Request request1,request2;
MPI_Status status;
// send/recv bins in both directions in each dimension
// don't send if nsend = 0
// due to static bins aliging with proc boundary
// due to dynamic bins across non-periodic global boundary
// copy to self if sendproc = me
// MPI send to another proc if sendproc != me
// don't recv if nrecv = 0
// copy from self if recvproc = me
// MPI recv from another proc if recvproc != me
BinAve *vbin = shifts[ishift].vbin;
int *procgrid = comm->procgrid;
int iswap = 0;
for (int idim = 0; idim < dimension; idim++) {
bcomm1 = &shifts[ishift].bcomm[iswap++];
bcomm2 = &shifts[ishift].bcomm[iswap++];
if (procgrid[idim] == 1) {
if (bcomm1->nsend)
vbin_pack(vbin,bcomm1->nsend,bcomm1->sendlist,sbuf1);
if (bcomm2->nsend)
vbin_pack(vbin,bcomm2->nsend,bcomm2->sendlist,sbuf2);
if (bcomm1->nrecv)
vbin_unpack(sbuf1,vbin,bcomm1->nrecv,bcomm1->recvlist);
if (bcomm2->nrecv)
vbin_unpack(sbuf2,vbin,bcomm2->nrecv,bcomm2->recvlist);
} else {
if (bcomm1->nrecv)
MPI_Irecv(rbuf1,bcomm1->nrecv*VBINSIZE,MPI_DOUBLE,bcomm1->recvproc,0,
world,&request1);
if (bcomm2->nrecv)
MPI_Irecv(rbuf2,bcomm2->nrecv*VBINSIZE,MPI_DOUBLE,bcomm2->recvproc,0,
world,&request2);
if (bcomm1->nsend) {
vbin_pack(vbin,bcomm1->nsend,bcomm1->sendlist,sbuf1);
MPI_Send(sbuf1,bcomm1->nsend*VBINSIZE,MPI_DOUBLE,
bcomm1->sendproc,0,world);
}
if (bcomm2->nsend) {
vbin_pack(vbin,bcomm2->nsend,bcomm2->sendlist,sbuf2);
MPI_Send(sbuf2,bcomm2->nsend*VBINSIZE,MPI_DOUBLE,
bcomm2->sendproc,0,world);
}
if (bcomm1->nrecv) {
MPI_Wait(&request1,&status);
vbin_unpack(rbuf1,vbin,bcomm1->nrecv,bcomm1->recvlist);
}
if (bcomm2->nrecv) {
MPI_Wait(&request2,&status);
vbin_unpack(rbuf2,vbin,bcomm2->nrecv,bcomm2->recvlist);
}
}
}
}
/* ----------------------------------------------------------------------
pack velocity bin data into a message buffer for sending
------------------------------------------------------------------------- */
void FixSRD::vbin_pack(BinAve *vbin, int n, int *list, double *buf)
{
int j;
int m = 0;
for (int i = 0; i < n; i++) {
j = list[i];
buf[m++] = vbin[j].n;
buf[m++] = vbin[j].vave[0];
buf[m++] = vbin[j].vave[1];
buf[m++] = vbin[j].vave[2];
buf[m++] = vbin[j].random;
}
}
/* ----------------------------------------------------------------------
unpack velocity bin data from a message buffer and sum values to my bins
------------------------------------------------------------------------- */
void FixSRD::vbin_unpack(double *buf, BinAve *vbin, int n, int *list)
{
int j;
int m = 0;
for (int i = 0; i < n; i++) {
j = list[i];
vbin[j].n += static_cast<int> (buf[m++]);
vbin[j].vave[0] += buf[m++];
vbin[j].vave[1] += buf[m++];
vbin[j].vave[2] += buf[m++];
vbin[j].random += buf[m++];
}
}
/* ----------------------------------------------------------------------
detect all collisions between SRD and BIG particles or WALLS
assume SRD can be inside at most one BIG particle or WALL at a time
unoverlap SRDs for each collision
------------------------------------------------------------------------- */
void FixSRD::collisions_single()
{
int i,j,k,m,type,mbig,ibin,ibounce,inside,collide_flag;
double dt,t_remain;
double norm[3],xscoll[3],xbcoll[3],vsnew[3];
Big *big;
// outer loop over SRD particles
// inner loop over BIG particles or WALLS that overlap SRD particle bin
// if overlap between SRD and BIG particle or wall:
// for exact, compute collision pt in time
// for inexact, push SRD to surf of BIG particle or WALL
// update x,v of SRD and f,torque on BIG particle
// re-bin SRD particle after collision
// iterate until the SRD particle has no overlaps with BIG particles or WALLS
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (!(mask[i] & groupbit)) continue;
ibin = binsrd[i];
if (nbinbig[ibin] == 0) continue;
ibounce = 0;
collide_flag = 1;
dt = dt_big;
while (collide_flag) {
mbig = nbinbig[ibin];
if (ibounce == 0) ncheck += mbig;
collide_flag = 0;
for (m = 0; m < mbig; m++) {
k = binbig[ibin][m];
big = &biglist[k];
j = big->index;
type = big->type;
if (type == SPHERE) inside = inside_sphere(x[i],x[j],big);
else if (type == ELLIPSOID) inside = inside_ellipsoid(x[i],x[j],big);
else inside = inside_wall(x[i],j);
if (inside) {
if (exactflag) {
if (type == SPHERE)
t_remain = collision_sphere_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else if (type == ELLIPSOID)
t_remain = collision_ellipsoid_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else
t_remain = collision_wall_exact(x[i],j,v[i],xscoll,xbcoll,norm);
} else {
t_remain = 0.5*dt;
if (type == SPHERE)
collision_sphere_inexact(x[i],x[j],big,xscoll,xbcoll,norm);
else if (type == ELLIPSOID)
collision_ellipsoid_inexact(x[i],x[j],big,xscoll,xbcoll,norm);
else
collision_wall_inexact(x[i],j,xscoll,xbcoll,norm);
}
#ifdef SRD_DEBUG
if (update->ntimestep == SRD_DEBUG_TIMESTEP &&
atom->tag[i] == SRD_DEBUG_ATOMID)
print_collision(i,j,ibounce,t_remain,dt,xscoll,xbcoll,norm,type);
#endif
if (t_remain > dt) {
ninside++;
if (insideflag == INSIDE_ERROR || insideflag == INSIDE_WARN) {
char str[128];
if (type != WALL)
sprintf(str,
"SRD particle %d started "
"inside big particle %d on step " BIGINT_FORMAT
" bounce %d\n",
atom->tag[i],atom->tag[j],update->ntimestep,ibounce+1);
else
sprintf(str,
"SRD particle %d started "
"inside big particle %d on step " BIGINT_FORMAT
" bounce %d\n",
atom->tag[i],atom->tag[j],update->ntimestep,ibounce+1);
- if (insideflag == INSIDE_ERROR) error->one(str);
- error->warning(str);
+ if (insideflag == INSIDE_ERROR) error->one(FLERR,str);
+ error->warning(FLERR,str);
}
break;
}
if (collidestyle == SLIP) {
if (type == SPHERE)
slip_sphere(v[i],v[j],norm,vsnew);
else if (type == ELLIPSOID)
slip_ellipsoid(v[i],v[j],x[j],big,xscoll,norm,vsnew);
else
slip_wall(v[i],j,norm,vsnew);
} else {
if (type != WALL)
noslip(v[i],v[j],x[j],big,xscoll,norm,vsnew);
else
noslip_wall(v[i],j,xscoll,norm,vsnew);
}
if (dimension == 2) vsnew[2] = 0.0;
// check on rescaling of vsnew
double vsq = vsnew[0]*vsnew[0] + vsnew[1]*vsnew[1] +
vsnew[2]*vsnew[2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),vsnew);
}
// update BIG particle and WALL and SRD
// BIG particle is not torqued if sphere and SLIP collision
if (collidestyle == SLIP && type == SPHERE)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],NULL);
else if (type != WALL)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],torque[j]);
else if (type == WALL)
force_wall(v[i],vsnew,j);
ibin = binsrd[i] = update_srd(i,t_remain,xscoll,vsnew,x[i],v[i]);
if (ibounce == 0) ncollide++;
ibounce++;
if (ibounce < maxbounceallow || maxbounceallow == 0)
collide_flag = 1;
dt = t_remain;
break;
}
}
}
nbounce += ibounce;
if (maxbounceallow && ibounce >= maxbounceallow) bouncemaxnum++;
if (ibounce > bouncemax) bouncemax = ibounce;
}
}
/* ----------------------------------------------------------------------
detect all collisions between SRD and big particles
an SRD can be inside more than one big particle at a time
requires finding which big particle SRD collided with first
unoverlap SRDs for each collision
------------------------------------------------------------------------- */
void FixSRD::collisions_multi()
{
int i,j,k,m,type,mbig,ibin,ibounce,inside,jfirst,typefirst;
double dt,t_remain,t_first;
double norm[3],xscoll[3],xbcoll[3],vsnew[3];
double normfirst[3],xscollfirst[3],xbcollfirst[3];
Big *big;
// outer loop over SRD particles
// inner loop over BIG particles or WALLS that overlap SRD particle bin
// loop over all BIG and WALLS to find which one SRD collided with first
// if overlap between SRD and BIG particle or wall:
// compute collision pt in time
// update x,v of SRD and f,torque on BIG particle
// re-bin SRD particle after collision
// iterate until the SRD particle has no overlaps with BIG particles or WALLS
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (!(mask[i] & groupbit)) continue;
ibin = binsrd[i];
if (nbinbig[ibin] == 0) continue;
ibounce = 0;
dt = dt_big;
while (1) {
mbig = nbinbig[ibin];
if (ibounce == 0) ncheck += mbig;
t_first = 0.0;
for (m = 0; m < mbig; m++) {
k = binbig[ibin][m];
big = &biglist[k];
j = big->index;
type = big->type;
if (type == SPHERE) inside = inside_sphere(x[i],x[j],big);
else if (type == ELLIPSOID) inside = inside_ellipsoid(x[i],x[j],big);
else inside = inside_wall(x[i],j);
if (inside) {
if (type == SPHERE)
t_remain = collision_sphere_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else if (type == ELLIPSOID)
t_remain = collision_ellipsoid_exact(x[i],x[j],v[i],v[j],big,
xscoll,xbcoll,norm);
else
t_remain = collision_wall_exact(x[i],j,v[i],xscoll,xbcoll,norm);
#ifdef SRD_DEBUG
if (update->ntimestep == SRD_DEBUG_TIMESTEP &&
atom->tag[i] == SRD_DEBUG_ATOMID)
print_collision(i,j,ibounce,t_remain,dt,xscoll,xbcoll,norm,type);
#endif
if (t_remain > dt || t_remain < 0.0) {
ninside++;
if (insideflag == INSIDE_ERROR || insideflag == INSIDE_WARN) {
char str[128];
sprintf(str,
"SRD particle %d started "
"inside big particle %d on step " BIGINT_FORMAT
" bounce %d\n",
atom->tag[i],atom->tag[j],update->ntimestep,ibounce+1);
- if (insideflag == INSIDE_ERROR) error->one(str);
- error->warning(str);
+ if (insideflag == INSIDE_ERROR) error->one(FLERR,str);
+ error->warning(FLERR,str);
}
t_first = 0.0;
break;
}
if (t_remain > t_first) {
t_first = t_remain;
jfirst = j;
typefirst = type;
xscollfirst[0] = xscoll[0];
xscollfirst[1] = xscoll[1];
xscollfirst[2] = xscoll[2];
xbcollfirst[0] = xbcoll[0];
xbcollfirst[1] = xbcoll[1];
xbcollfirst[2] = xbcoll[2];
normfirst[0] = norm[0];
normfirst[1] = norm[1];
normfirst[2] = norm[2];
}
}
}
if (t_first == 0.0) break;
j = jfirst;
type = typefirst;
xscoll[0] = xscollfirst[0];
xscoll[1] = xscollfirst[1];
xscoll[2] = xscollfirst[2];
xbcoll[0] = xbcollfirst[0];
xbcoll[1] = xbcollfirst[1];
xbcoll[2] = xbcollfirst[2];
norm[0] = normfirst[0];
norm[1] = normfirst[1];
norm[2] = normfirst[2];
if (collidestyle == SLIP) {
if (type == SPHERE)
slip_sphere(v[i],v[j],norm,vsnew);
else if (type == ELLIPSOID)
slip_ellipsoid(v[i],v[j],x[j],big,xscoll,norm,vsnew);
else
slip_wall(v[i],j,norm,vsnew);
} else {
if (type != WALL)
noslip(v[i],v[j],x[j],big,xscoll,norm,vsnew);
else
noslip_wall(v[i],j,xscoll,norm,vsnew);
}
if (dimension == 2) vsnew[2] = 0.0;
// check on rescaling of vsnew
double vsq = vsnew[0]*vsnew[0] + vsnew[1]*vsnew[1] + vsnew[2]*vsnew[2];
if (vsq > vmaxsq) {
nrescale++;
MathExtra::scale3(vmax/sqrt(vsq),vsnew);
}
// update BIG particle and WALL and SRD
// BIG particle is not torqued if sphere and SLIP collision
if (collidestyle == SLIP && type == SPHERE)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],NULL);
else if (type != WALL)
force_torque(v[i],vsnew,xscoll,xbcoll,f[j],torque[j]);
else if (type == WALL)
force_wall(v[i],vsnew,j);
ibin = binsrd[i] = update_srd(i,t_first,xscoll,vsnew,x[i],v[i]);
if (ibounce == 0) ncollide++;
ibounce++;
if (ibounce == maxbounceallow) break;
dt = t_first;
}
nbounce += ibounce;
if (maxbounceallow && ibounce >= maxbounceallow) bouncemaxnum++;
if (ibounce > bouncemax) bouncemax = ibounce;
}
}
/* ----------------------------------------------------------------------
check if SRD particle S is inside spherical big particle B
------------------------------------------------------------------------- */
int FixSRD::inside_sphere(double *xs, double *xb, Big *big)
{
double dx,dy,dz;
dx = xs[0] - xb[0];
dy = xs[1] - xb[1];
dz = xs[2] - xb[2];
if (dx*dx + dy*dy + dz*dz <= big->radsq) return 1;
return 0;
}
/* ----------------------------------------------------------------------
check if SRD particle S is inside ellipsoidal big particle B
------------------------------------------------------------------------- */
int FixSRD::inside_ellipsoid(double *xs, double *xb, Big *big)
{
double x,y,z;
double *ex = big->ex;
double *ey = big->ey;
double *ez = big->ez;
double xs_xb[3];
xs_xb[0] = xs[0] - xb[0];
xs_xb[1] = xs[1] - xb[1];
xs_xb[2] = xs[2] - xb[2];
x = xs_xb[0]*ex[0] + xs_xb[1]*ex[1] + xs_xb[2]*ex[2];
y = xs_xb[0]*ey[0] + xs_xb[1]*ey[1] + xs_xb[2]*ey[2];
z = xs_xb[0]*ez[0] + xs_xb[1]*ez[1] + xs_xb[2]*ez[2];
if (x*x*big->aradsqinv + y*y*big->bradsqinv + z*z*big->cradsqinv <= 1.0)
return 1;
return 0;
}
/* ----------------------------------------------------------------------
check if SRD particle S is inside wall IWALL
------------------------------------------------------------------------- */
int FixSRD::inside_wall(double *xs, int iwall)
{
int dim = wallwhich[iwall] / 2;
int side = wallwhich[iwall] % 2;
if (side == 0 && xs[dim] < xwall[iwall]) return 1;
if (side && xs[dim] > xwall[iwall]) return 1;
return 0;
}
/* ----------------------------------------------------------------------
collision of SRD particle S with surface of spherical big particle B
exact because compute time of collision
dt = time previous to now at which collision occurs
xscoll = collision pt = position of SRD at time of collision
xbcoll = position of big particle at time of collision
norm = surface normal of collision pt at time of collision
------------------------------------------------------------------------- */
double FixSRD::collision_sphere_exact(double *xs, double *xb,
double *vs, double *vb, Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double vs_dot_vs,vb_dot_vb,vs_dot_vb;
double vs_dot_xb,vb_dot_xs,vs_dot_xs,vb_dot_xb;
double xs_dot_xs,xb_dot_xb,xs_dot_xb;
double a,b,c,scale,dt;
vs_dot_vs = vs[0]*vs[0] + vs[1]*vs[1] + vs[2]*vs[2];
vb_dot_vb = vb[0]*vb[0] + vb[1]*vb[1] + vb[2]*vb[2];
vs_dot_vb = vs[0]*vb[0] + vs[1]*vb[1] + vs[2]*vb[2];
vs_dot_xb = vs[0]*xb[0] + vs[1]*xb[1] + vs[2]*xb[2];
vb_dot_xs = vb[0]*xs[0] + vb[1]*xs[1] + vb[2]*xs[2];
vs_dot_xs = vs[0]*xs[0] + vs[1]*xs[1] + vs[2]*xs[2];
vb_dot_xb = vb[0]*xb[0] + vb[1]*xb[1] + vb[2]*xb[2];
xs_dot_xs = xs[0]*xs[0] + xs[1]*xs[1] + xs[2]*xs[2];
xb_dot_xb = xb[0]*xb[0] + xb[1]*xb[1] + xb[2]*xb[2];
xs_dot_xb = xs[0]*xb[0] + xs[1]*xb[1] + xs[2]*xb[2];
a = vs_dot_vs + vb_dot_vb - 2.0*vs_dot_vb;
b = 2.0 * (vs_dot_xb + vb_dot_xs - vs_dot_xs - vb_dot_xb);
c = xs_dot_xs + xb_dot_xb - 2.0*xs_dot_xb - big->radsq;
dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);
xscoll[0] = xs[0] - dt*vs[0];
xscoll[1] = xs[1] - dt*vs[1];
xscoll[2] = xs[2] - dt*vs[2];
xbcoll[0] = xb[0] - dt*vb[0];
xbcoll[1] = xb[1] - dt*vb[1];
xbcoll[2] = xb[2] - dt*vb[2];
norm[0] = xscoll[0] - xbcoll[0];
norm[1] = xscoll[1] - xbcoll[1];
norm[2] = xscoll[2] - xbcoll[2];
scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
norm[0] *= scale;
norm[1] *= scale;
norm[2] *= scale;
return dt;
}
/* ----------------------------------------------------------------------
collision of SRD particle S with surface of spherical big particle B
inexact because just push SRD to surface of big particle at end of step
time of collision = end of step
xscoll = collision pt = position of SRD at time of collision
xbcoll = xb = position of big particle at time of collision
norm = surface normal of collision pt at time of collision
------------------------------------------------------------------------- */
void FixSRD::collision_sphere_inexact(double *xs, double *xb,
Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double scale;
norm[0] = xs[0] - xb[0];
norm[1] = xs[1] - xb[1];
norm[2] = xs[2] - xb[2];
scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
norm[0] *= scale;
norm[1] *= scale;
norm[2] *= scale;
xscoll[0] = xb[0] + big->radius*norm[0];
xscoll[1] = xb[1] + big->radius*norm[1];
xscoll[2] = xb[2] + big->radius*norm[2];
xbcoll[0] = xb[0];
xbcoll[1] = xb[1];
xbcoll[2] = xb[2];
}
/* ----------------------------------------------------------------------
collision of SRD particle S with surface of ellipsoidal big particle B
exact because compute time of collision
dt = time previous to now at which collision occurs
xscoll = collision pt = position of SRD at time of collision
xbcoll = position of big particle at time of collision
norm = surface normal of collision pt at time of collision
------------------------------------------------------------------------- */
double FixSRD::collision_ellipsoid_exact(double *xs, double *xb,
double *vs, double *vb, Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double vs_vb[3],xs_xb[3],omega_ex[3],omega_ey[3],omega_ez[3];
double excoll[3],eycoll[3],ezcoll[3],delta[3],xbody[3],nbody[3];
double ax,bx,cx,ay,by,cy,az,bz,cz;
double a,b,c,dt,scale;
double *omega = big->omega;
double *ex = big->ex;
double *ey = big->ey;
double *ez = big->ez;
vs_vb[0] = vs[0]-vb[0]; vs_vb[1] = vs[1]-vb[1]; vs_vb[2] = vs[2]-vb[2];
xs_xb[0] = xs[0]-xb[0]; xs_xb[1] = xs[1]-xb[1]; xs_xb[2] = xs[2]-xb[2];
omega_ex[0] = omega[1]*ex[2] - omega[2]*ex[1];
omega_ex[1] = omega[2]*ex[0] - omega[0]*ex[2];
omega_ex[2] = omega[0]*ex[1] - omega[1]*ex[0];
omega_ey[0] = omega[1]*ey[2] - omega[2]*ey[1];
omega_ey[1] = omega[2]*ey[0] - omega[0]*ey[2];
omega_ey[2] = omega[0]*ey[1] - omega[1]*ey[0];
omega_ez[0] = omega[1]*ez[2] - omega[2]*ez[1];
omega_ez[1] = omega[2]*ez[0] - omega[0]*ez[2];
omega_ez[2] = omega[0]*ez[1] - omega[1]*ez[0];
ax = vs_vb[0]*omega_ex[0] + vs_vb[1]*omega_ex[1] + vs_vb[2]*omega_ex[2];
bx = -(vs_vb[0]*ex[0] + vs_vb[1]*ex[1] + vs_vb[2]*ex[2]);
bx -= xs_xb[0]*omega_ex[0] + xs_xb[1]*omega_ex[1] + xs_xb[2]*omega_ex[2];
cx = xs_xb[0]*ex[0] + xs_xb[1]*ex[1] + xs_xb[2]*ex[2];
ay = vs_vb[0]*omega_ey[0] + vs_vb[1]*omega_ey[1] + vs_vb[2]*omega_ey[2];
by = -(vs_vb[0]*ey[0] + vs_vb[1]*ey[1] + vs_vb[2]*ey[2]);
by -= xs_xb[0]*omega_ey[0] + xs_xb[1]*omega_ey[1] + xs_xb[2]*omega_ey[2];
cy = xs_xb[0]*ey[0] + xs_xb[1]*ey[1] + xs_xb[2]*ey[2];
az = vs_vb[0]*omega_ez[0] + vs_vb[1]*omega_ez[1] + vs_vb[2]*omega_ez[2];
bz = -(vs_vb[0]*ez[0] + vs_vb[1]*ez[1] + vs_vb[2]*ez[2]);
bz -= xs_xb[0]*omega_ez[0] + xs_xb[1]*omega_ez[1] + xs_xb[2]*omega_ez[2];
cz = xs_xb[0]*ez[0] + xs_xb[1]*ez[1] + xs_xb[2]*ez[2];
a = (bx*bx + 2.0*ax*cx)*big->aradsqinv +
(by*by + 2.0*ay*cy)*big->bradsqinv +
(bz*bz + 2.0*az*cz)*big->cradsqinv;
b = 2.0 * (bx*cx*big->aradsqinv + by*cy*big->bradsqinv +
bz*cz*big->cradsqinv);
c = cx*cx*big->aradsqinv + cy*cy*big->bradsqinv +
cz*cz*big->cradsqinv - 1.0;
dt = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);
xscoll[0] = xs[0] - dt*vs[0];
xscoll[1] = xs[1] - dt*vs[1];
xscoll[2] = xs[2] - dt*vs[2];
xbcoll[0] = xb[0] - dt*vb[0];
xbcoll[1] = xb[1] - dt*vb[1];
xbcoll[2] = xb[2] - dt*vb[2];
// calculate normal to ellipsoid at collision pt
// Excoll,Eycoll,Ezcoll = orientation of ellipsoid at collision time
// nbody = normal in body frame of ellipsoid (Excoll,Eycoll,Ezcoll)
// norm = normal in space frame
// only worry about normalizing final norm vector
excoll[0] = ex[0] - dt * (omega[1]*ex[2] - omega[2]*ex[1]);
excoll[1] = ex[1] - dt * (omega[2]*ex[0] - omega[0]*ex[2]);
excoll[2] = ex[2] - dt * (omega[0]*ex[1] - omega[1]*ex[0]);
eycoll[0] = ey[0] - dt * (omega[1]*ey[2] - omega[2]*ey[1]);
eycoll[1] = ey[1] - dt * (omega[2]*ey[0] - omega[0]*ey[2]);
eycoll[2] = ey[2] - dt * (omega[0]*ey[1] - omega[1]*ey[0]);
ezcoll[0] = ez[0] - dt * (omega[1]*ez[2] - omega[2]*ez[1]);
ezcoll[1] = ez[1] - dt * (omega[2]*ez[0] - omega[0]*ez[2]);
ezcoll[2] = ez[2] - dt * (omega[0]*ez[1] - omega[1]*ez[0]);
delta[0] = xscoll[0] - xbcoll[0];
delta[1] = xscoll[1] - xbcoll[1];
delta[2] = xscoll[2] - xbcoll[2];
xbody[0] = delta[0]*excoll[0] + delta[1]*excoll[1] + delta[2]*excoll[2];
xbody[1] = delta[0]*eycoll[0] + delta[1]*eycoll[1] + delta[2]*eycoll[2];
xbody[2] = delta[0]*ezcoll[0] + delta[1]*ezcoll[1] + delta[2]*ezcoll[2];
nbody[0] = xbody[0]*big->aradsqinv;
nbody[1] = xbody[1]*big->bradsqinv;
nbody[2] = xbody[2]*big->cradsqinv;
norm[0] = excoll[0]*nbody[0] + eycoll[0]*nbody[1] + ezcoll[0]*nbody[2];
norm[1] = excoll[1]*nbody[0] + eycoll[1]*nbody[1] + ezcoll[1]*nbody[2];
norm[2] = excoll[2]*nbody[0] + eycoll[2]*nbody[1] + ezcoll[2]*nbody[2];
scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
norm[0] *= scale;
norm[1] *= scale;
norm[2] *= scale;
return dt;
}
/* ----------------------------------------------------------------------
collision of SRD particle S with surface of ellipsoidal big particle B
inexact because just push SRD to surface of big particle at end of step
------------------------------------------------------------------------- */
void FixSRD::collision_ellipsoid_inexact(double *xs, double *xb,
Big *big,
double *xscoll, double *xbcoll,
double *norm)
{
double xs_xb[3],delta[3],xbody[3],nbody[3];
double x,y,z,scale;
double *ex = big->ex;
double *ey = big->ey;
double *ez = big->ez;
xs_xb[0] = xs[0] - xb[0];
xs_xb[1] = xs[1] - xb[1];
xs_xb[2] = xs[2] - xb[2];
x = xs_xb[0]*ex[0] + xs_xb[1]*ex[1] + xs_xb[2]*ex[2];
y = xs_xb[0]*ey[0] + xs_xb[1]*ey[1] + xs_xb[2]*ey[2];
z = xs_xb[0]*ez[0] + xs_xb[1]*ez[1] + xs_xb[2]*ez[2];
scale = 1.0/sqrt(x*x*big->aradsqinv + y*y*big->bradsqinv +
z*z*big->cradsqinv);
x *= scale;
y *= scale;
z *= scale;
xscoll[0] = x*ex[0] + y*ey[0] + z*ez[0] + xb[0];
xscoll[1] = x*ex[1] + y*ey[1] + z*ez[1] + xb[1];
xscoll[2] = x*ex[2] + y*ey[2] + z*ez[2] + xb[2];
xbcoll[0] = xb[0];
xbcoll[1] = xb[1];
xbcoll[2] = xb[2];
// calculate normal to ellipsoid at collision pt
// nbody = normal in body frame of ellipsoid
// norm = normal in space frame
// only worry about normalizing final norm vector
delta[0] = xscoll[0] - xbcoll[0];
delta[1] = xscoll[1] - xbcoll[1];
delta[2] = xscoll[2] - xbcoll[2];
xbody[0] = delta[0]*ex[0] + delta[1]*ex[1] + delta[2]*ex[2];
xbody[1] = delta[0]*ey[0] + delta[1]*ey[1] + delta[2]*ey[2];
xbody[2] = delta[0]*ez[0] + delta[1]*ez[1] + delta[2]*ez[2];
nbody[0] = xbody[0]*big->aradsqinv;
nbody[1] = xbody[1]*big->bradsqinv;
nbody[2] = xbody[2]*big->cradsqinv;
norm[0] = ex[0]*nbody[0] + ey[0]*nbody[1] + ez[0]*nbody[2];
norm[1] = ex[1]*nbody[0] + ey[1]*nbody[1] + ez[1]*nbody[2];
norm[2] = ex[2]*nbody[0] + ey[2]*nbody[1] + ez[2]*nbody[2];
scale = 1.0/sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
norm[0] *= scale;
norm[1] *= scale;
norm[2] *= scale;
}
/* ----------------------------------------------------------------------
collision of SRD particle S with wall IWALL
exact because compute time of collision
dt = time previous to now at which collision occurs
xscoll = collision pt = position of SRD at time of collision
norm = surface normal of collision pt at time of collision
------------------------------------------------------------------------- */
double FixSRD::collision_wall_exact(double *xs, int iwall, double *vs,
double *xscoll, double *xbcoll,
double *norm)
{
int dim = wallwhich[iwall] / 2;
double dt = (xs[dim] - xwall[iwall]) / (vs[dim] - vwall[iwall]);
xscoll[0] = xs[0] - dt*vs[0];
xscoll[1] = xs[1] - dt*vs[1];
xscoll[2] = xs[2] - dt*vs[2];
xbcoll[0] = xbcoll[1] = xbcoll[2] = 0.0;
xbcoll[dim] = xwall[iwall] - dt*vwall[iwall];
int side = wallwhich[iwall] % 2;
norm[0] = norm[1] = norm[2] = 0.0;
if (side == 0) norm[dim] = 1.0;
else norm[dim] = -1.0;
return dt;
}
/* ----------------------------------------------------------------------
collision of SRD particle S with wall IWALL
inexact because just push SRD to surface of wall at end of step
time of collision = end of step
xscoll = collision pt = position of SRD at time of collision
norm = surface normal of collision pt at time of collision
------------------------------------------------------------------------- */
void FixSRD::collision_wall_inexact(double *xs, int iwall, double *xscoll,
double *xbcoll, double *norm)
{
int dim = wallwhich[iwall] / 2;
xscoll[0] = xs[0];
xscoll[1] = xs[1];
xscoll[2] = xs[2];
xscoll[dim] = xwall[iwall];
xbcoll[0] = xbcoll[1] = xbcoll[2] = 0.0;
xbcoll[dim] = xwall[iwall];
int side = wallwhich[iwall] % 2;
norm[0] = norm[1] = norm[2] = 0.0;
if (side == 0) norm[dim] = 1.0;
else norm[dim] = -1.0;
}
/* ----------------------------------------------------------------------
SLIP collision with sphere
vs = velocity of SRD, vb = velocity of BIG
norm = unit normal from surface of BIG at collision pt
v of BIG particle in direction of surf normal is added to v of SRD
return vsnew of SRD
------------------------------------------------------------------------- */
void FixSRD::slip_sphere(double *vs, double *vb, double *norm, double *vsnew)
{
double r1,r2,vnmag,vs_dot_n,vsurf_dot_n;
double tangent[3];
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
if (vnmag*vnmag <= vmaxsq) break;
}
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent[0] = vs[0] - vs_dot_n*norm[0];
tangent[1] = vs[1] - vs_dot_n*norm[1];
tangent[2] = vs[2] - vs_dot_n*norm[2];
// vsurf = velocity of collision pt = translation/rotation of BIG particle
// for sphere, only vb (translation) can contribute in normal direction
vsurf_dot_n = vb[0]*norm[0] + vb[1]*norm[1] + vb[2]*norm[2];
vsnew[0] = (vnmag+vsurf_dot_n)*norm[0] + tangent[0];
vsnew[1] = (vnmag+vsurf_dot_n)*norm[1] + tangent[1];
vsnew[2] = (vnmag+vsurf_dot_n)*norm[2] + tangent[2];
}
/* ----------------------------------------------------------------------
SLIP collision with ellipsoid
vs = velocity of SRD, vb = velocity of BIG
xb = position of BIG, omega = rotation of BIG
xsurf = collision pt on surf of BIG
norm = unit normal from surface of BIG at collision pt
v of BIG particle in direction of surf normal is added to v of SRD
includes component due to rotation of ellipsoid
return vsnew of SRD
------------------------------------------------------------------------- */
void FixSRD::slip_ellipsoid(double *vs, double *vb, double *xb, Big *big,
double *xsurf, double *norm, double *vsnew)
{
double r1,r2,vnmag,vs_dot_n,vsurf_dot_n;
double tangent[3],vsurf[3];
double *omega = big->omega;
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
if (vnmag*vnmag <= vmaxsq) break;
}
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent[0] = vs[0] - vs_dot_n*norm[0];
tangent[1] = vs[1] - vs_dot_n*norm[1];
tangent[2] = vs[2] - vs_dot_n*norm[2];
// vsurf = velocity of collision pt = translation/rotation of BIG particle
vsurf[0] = vb[0] + omega[1]*(xsurf[2]-xb[2]) - omega[2]*(xsurf[1]-xb[1]);
vsurf[1] = vb[1] + omega[2]*(xsurf[0]-xb[0]) - omega[0]*(xsurf[2]-xb[2]);
vsurf[2] = vb[2] + omega[0]*(xsurf[1]-xb[1]) - omega[1]*(xsurf[0]-xb[0]);
vsurf_dot_n = vsurf[0]*norm[0] + vsurf[1]*norm[1] + vsurf[2]*norm[2];
vsnew[0] = (vnmag+vsurf_dot_n)*norm[0] + tangent[0];
vsnew[1] = (vnmag+vsurf_dot_n)*norm[1] + tangent[1];
vsnew[2] = (vnmag+vsurf_dot_n)*norm[2] + tangent[2];
}
/* ----------------------------------------------------------------------
SLIP collision with wall IWALL
vs = velocity of SRD
norm = unit normal from WALL at collision pt
v of WALL in direction of surf normal is added to v of SRD
return vsnew of SRD
------------------------------------------------------------------------- */
void FixSRD::slip_wall(double *vs, int iwall, double *norm, double *vsnew)
{
double vs_dot_n,scale,r1,r2,vnmag,vtmag1,vtmag2;
double tangent1[3],tangent2[3];
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent1[0] = vs[0] - vs_dot_n*norm[0];
tangent1[1] = vs[1] - vs_dot_n*norm[1];
tangent1[2] = vs[2] - vs_dot_n*norm[2];
scale = 1.0/sqrt(tangent1[0]*tangent1[0] + tangent1[1]*tangent1[1] +
tangent1[2]*tangent1[2]);
tangent1[0] *= scale;
tangent1[1] *= scale;
tangent1[2] *= scale;
tangent2[0] = norm[1]*tangent1[2] - norm[2]*tangent1[1];
tangent2[1] = norm[2]*tangent1[0] - norm[0]*tangent1[2];
tangent2[2] = norm[0]*tangent1[1] - norm[1]*tangent1[0];
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
vtmag1 = sigma * random->gaussian();
vtmag2 = sigma * random->gaussian();
if (vnmag*vnmag + vtmag1*vtmag1 + vtmag2*vtmag2 <= vmaxsq) break;
}
vsnew[0] = vnmag*norm[0] + vtmag1*tangent1[0] + vtmag2*tangent2[0];
vsnew[1] = vnmag*norm[1] + vtmag1*tangent1[1] + vtmag2*tangent2[1];
vsnew[2] = vnmag*norm[2] + vtmag1*tangent1[2] + vtmag2*tangent2[2];
// add in velocity of collision pt = velocity of wall
int dim = wallwhich[iwall] / 2;
vsnew[dim] += vwall[iwall];
}
/* ----------------------------------------------------------------------
NO-SLIP collision with sphere or ellipsoid
vs = velocity of SRD, vb = velocity of BIG
xb = position of BIG, omega = rotation of BIG
xsurf = collision pt on surf of BIG
norm = unit normal from surface of BIG at collision pt
v of collision pt is added to v of SRD
includes component due to rotation of BIG
return vsnew of SRD
------------------------------------------------------------------------- */
void FixSRD::noslip(double *vs, double *vb, double *xb, Big *big,
double *xsurf, double *norm, double *vsnew)
{
double vs_dot_n,scale,r1,r2,vnmag,vtmag1,vtmag2;
double tangent1[3],tangent2[3];
double *omega = big->omega;
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent1[0] = vs[0] - vs_dot_n*norm[0];
tangent1[1] = vs[1] - vs_dot_n*norm[1];
tangent1[2] = vs[2] - vs_dot_n*norm[2];
scale = 1.0/sqrt(tangent1[0]*tangent1[0] + tangent1[1]*tangent1[1] +
tangent1[2]*tangent1[2]);
tangent1[0] *= scale;
tangent1[1] *= scale;
tangent1[2] *= scale;
tangent2[0] = norm[1]*tangent1[2] - norm[2]*tangent1[1];
tangent2[1] = norm[2]*tangent1[0] - norm[0]*tangent1[2];
tangent2[2] = norm[0]*tangent1[1] - norm[1]*tangent1[0];
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
vtmag1 = sigma * random->gaussian();
vtmag2 = sigma * random->gaussian();
if (vnmag*vnmag + vtmag1*vtmag1 + vtmag2*vtmag2 <= vmaxsq) break;
}
vsnew[0] = vnmag*norm[0] + vtmag1*tangent1[0] + vtmag2*tangent2[0];
vsnew[1] = vnmag*norm[1] + vtmag1*tangent1[1] + vtmag2*tangent2[1];
vsnew[2] = vnmag*norm[2] + vtmag1*tangent1[2] + vtmag2*tangent2[2];
// add in velocity of collision pt = translation/rotation of BIG particle
vsnew[0] += vb[0] + omega[1]*(xsurf[2]-xb[2]) - omega[2]*(xsurf[1]-xb[1]);
vsnew[1] += vb[1] + omega[2]*(xsurf[0]-xb[0]) - omega[0]*(xsurf[2]-xb[2]);
vsnew[2] += vb[2] + omega[0]*(xsurf[1]-xb[1]) - omega[1]*(xsurf[0]-xb[0]);
}
/* ----------------------------------------------------------------------
NO-SLIP collision with wall IWALL
vs = velocity of SRD
xsurf = collision pt on surf of WALL
norm = unit normal from WALL at collision pt
v of collision pt is added to v of SRD
return vsnew of SRD
------------------------------------------------------------------------- */
void FixSRD::noslip_wall(double *vs, int iwall,
double *xsurf, double *norm, double *vsnew)
{
double vs_dot_n,scale,r1,r2,vnmag,vtmag1,vtmag2;
double tangent1[3],tangent2[3];
vs_dot_n = vs[0]*norm[0] + vs[1]*norm[1] + vs[2]*norm[2];
tangent1[0] = vs[0] - vs_dot_n*norm[0];
tangent1[1] = vs[1] - vs_dot_n*norm[1];
tangent1[2] = vs[2] - vs_dot_n*norm[2];
scale = 1.0/sqrt(tangent1[0]*tangent1[0] + tangent1[1]*tangent1[1] +
tangent1[2]*tangent1[2]);
tangent1[0] *= scale;
tangent1[1] *= scale;
tangent1[2] *= scale;
tangent2[0] = norm[1]*tangent1[2] - norm[2]*tangent1[1];
tangent2[1] = norm[2]*tangent1[0] - norm[0]*tangent1[2];
tangent2[2] = norm[0]*tangent1[1] - norm[1]*tangent1[0];
while (1) {
r1 = sigma * random->gaussian();
r2 = sigma * random->gaussian();
vnmag = sqrt(r1*r1 + r2*r2);
vtmag1 = sigma * random->gaussian();
vtmag2 = sigma * random->gaussian();
if (vnmag*vnmag + vtmag1*vtmag1 + vtmag2*vtmag2 <= vmaxsq) break;
}
vsnew[0] = vnmag*norm[0] + vtmag1*tangent1[0] + vtmag2*tangent2[0];
vsnew[1] = vnmag*norm[1] + vtmag1*tangent1[1] + vtmag2*tangent2[1];
vsnew[2] = vnmag*norm[2] + vtmag1*tangent1[2] + vtmag2*tangent2[2];
// add in velocity of collision pt = velocity of wall
int dim = wallwhich[iwall] / 2;
vsnew[dim] += vwall[iwall];
}
/* ----------------------------------------------------------------------
impart force and torque to BIG particle
force on BIG particle = -dp/dt of SRD particle
torque on BIG particle = r cross (-dp/dt)
------------------------------------------------------------------------- */
void FixSRD::force_torque(double *vsold, double *vsnew,
double *xs, double *xb,
double *fb, double *tb)
{
double dpdt[3],xs_xb[3];
double factor = mass_srd / dt_big / force->ftm2v;
dpdt[0] = factor * (vsnew[0] - vsold[0]);
dpdt[1] = factor * (vsnew[1] - vsold[1]);
dpdt[2] = factor * (vsnew[2] - vsold[2]);
fb[0] -= dpdt[0];
fb[1] -= dpdt[1];
fb[2] -= dpdt[2];
// no torque if SLIP collision and BIG is a sphere
if (tb) {
xs_xb[0] = xs[0]-xb[0];
xs_xb[1] = xs[1]-xb[1];
xs_xb[2] = xs[2]-xb[2];
tb[0] -= xs_xb[1]*dpdt[2] - xs_xb[2]*dpdt[1];
tb[1] -= xs_xb[2]*dpdt[0] - xs_xb[0]*dpdt[2];
tb[2] -= xs_xb[0]*dpdt[1] - xs_xb[1]*dpdt[0];
}
}
/* ----------------------------------------------------------------------
impart force to WALL
force on WALL = -dp/dt of SRD particle
------------------------------------------------------------------------- */
void FixSRD::force_wall(double *vsold, double *vsnew, int iwall)
{
double dpdt[3];
double factor = mass_srd / dt_big / force->ftm2v;
dpdt[0] = factor * (vsnew[0] - vsold[0]);
dpdt[1] = factor * (vsnew[1] - vsold[1]);
dpdt[2] = factor * (vsnew[2] - vsold[2]);
fwall[iwall][0] -= dpdt[0];
fwall[iwall][1] -= dpdt[1];
fwall[iwall][2] -= dpdt[2];
}
/* ----------------------------------------------------------------------
update SRD particle position & velocity & search bin assignment
check if SRD moved outside of valid region
if so, may overlap off-processor BIG particle
------------------------------------------------------------------------- */
int FixSRD::update_srd(int i, double dt, double *xscoll, double *vsnew,
double *xs, double *vs)
{
int ix,iy,iz;
vs[0] = vsnew[0];
vs[1] = vsnew[1];
vs[2] = vsnew[2];
xs[0] = xscoll[0] + dt*vsnew[0];
xs[1] = xscoll[1] + dt*vsnew[1];
xs[2] = xscoll[2] + dt*vsnew[2];
if (triclinic) domain->x2lamda(xs,xs);
if (xs[0] < srdlo[0] || xs[0] > srdhi[0] ||
xs[1] < srdlo[1] || xs[1] > srdhi[1] ||
xs[2] < srdlo[2] || xs[2] > srdhi[2]) {
if (screen) {
- error->warning("Fix srd particle moved outside valid domain");
+ error->warning(FLERR,"Fix srd particle moved outside valid domain");
fprintf(screen," particle %d on proc %d at timestep " BIGINT_FORMAT,
atom->tag[i],me,update->ntimestep);
fprintf(screen," xnew %g %g %g\n",xs[0],xs[1],xs[2]);
fprintf(screen," srdlo/hi x %g %g\n",srdlo[0],srdhi[0]);
fprintf(screen," srdlo/hi y %g %g\n",srdlo[1],srdhi[1]);
fprintf(screen," srdlo/hi z %g %g\n",srdlo[2],srdhi[2]);
}
}
if (triclinic) domain->lamda2x(xs,xs);
ix = static_cast<int> ((xs[0]-xblo2)*bininv2x);
iy = static_cast<int> ((xs[1]-yblo2)*bininv2y);
iz = static_cast<int> ((xs[2]-zblo2)*bininv2z);
return iz*nbin2y*nbin2x + iy*nbin2x + ix;
}
/* ----------------------------------------------------------------------
setup all SRD parameters with big particles
------------------------------------------------------------------------- */
void FixSRD::parameterize()
{
double PI = 4.0*atan(1.0);
// timesteps
dt_big = update->dt;
dt_srd = nevery * update->dt;
// maxbigdiam,minbigdiam = max/min diameter of any big particle
// big particle must either have radius > 0 or shape > 0 defined
// apply radfactor at end
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
double *radius = atom->radius;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
any_ellipsoids = 0;
maxbigdiam = 0.0;
minbigdiam = BIG;
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) {
if (radius && radius[i] > 0.0) {
maxbigdiam = MAX(maxbigdiam,2.0*radius[i]);
minbigdiam = MIN(minbigdiam,2.0*radius[i]);
} else if (ellipsoid && ellipsoid[i] >= 0) {
any_ellipsoids = 1;
double *shape = ebonus[ellipsoid[i]].shape;
maxbigdiam = MAX(maxbigdiam,2.0*shape[0]);
maxbigdiam = MAX(maxbigdiam,2.0*shape[1]);
maxbigdiam = MAX(maxbigdiam,2.0*shape[2]);
minbigdiam = MIN(minbigdiam,2.0*shape[0]);
minbigdiam = MIN(minbigdiam,2.0*shape[1]);
minbigdiam = MIN(minbigdiam,2.0*shape[2]);
} else
- error->one("Big particle in fix srd cannot be point particle");
+ error->one(FLERR,"Big particle in fix srd cannot be point particle");
}
double tmp = maxbigdiam;
MPI_Allreduce(&tmp,&maxbigdiam,1,MPI_DOUBLE,MPI_MAX,world);
tmp = minbigdiam;
MPI_Allreduce(&tmp,&minbigdiam,1,MPI_DOUBLE,MPI_MIN,world);
maxbigdiam *= radfactor;
minbigdiam *= radfactor;
int itmp = any_ellipsoids;
MPI_Allreduce(&itmp,&any_ellipsoids,1,MPI_INT,MPI_MAX,world);
// big particles are only torqued if are ellipsoids or NOSLIP collisions
if (any_ellipsoids == 0 && collidestyle == SLIP) torqueflag = 0;
else torqueflag = 1;
// mass of SRD particles, require monodispersity
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int flag = 0;
mass_srd = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) {
if (mass_srd == 0.0) mass_srd = rmass[i];
else if (rmass[i] != mass_srd) flag = 1;
} else {
if (mass_srd == 0.0) mass_srd = mass[type[i]];
else if (mass[type[i]] != mass_srd) flag = 1;
}
}
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_MAX,world);
if (flagall)
- error->all("Fix srd requires SRD particles all have same mass");
+ error->all(FLERR,"Fix srd requires SRD particles all have same mass");
// set temperature and lamda of SRD particles from each other
// lamda = dt_srd * sqrt(boltz * temperature_srd / mass_srd);
if (lamdaflag == 0)
lamda = dt_srd * sqrt(force->boltz*temperature_srd/mass_srd/force->mvv2e);
else
temperature_srd = force->mvv2e *
(lamda/dt_srd)*(lamda/dt_srd) * mass_srd/force->boltz;
// vmax = maximum velocity of an SRD particle
// dmax = maximum distance an SRD can move = 4*lamda = vmax * dt_srd
sigma = lamda/dt_srd;
dmax = 4.0*lamda;
vmax = dmax/dt_srd;
vmaxsq = vmax*vmax;
// volbig = total volume of all big particles
// apply radfactor to reduce final volume
double volbig = 0.0;
if (dimension == 3) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) {
if (radius && radius[i] > 0.0)
volbig += 4.0/3.0*PI*radius[i]*radius[i]*radius[i];
else if (ellipsoid && ellipsoid[i] >= 0) {
double *shape = ebonus[ellipsoid[i]].shape;
volbig += 4.0/3.0*PI * shape[0]*shape[1]*shape[2];
}
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) {
if (radius && radius[i] > 0.0)
volbig += PI*radius[i]*radius[i];
else if (ellipsoid && ellipsoid[i] >= 0) {
double *shape = ebonus[ellipsoid[i]].shape;
volbig += PI*shape[0]*shape[1];
}
}
}
tmp = volbig;
MPI_Allreduce(&tmp,&volbig,1,MPI_DOUBLE,MPI_SUM,world);
if (dimension == 3) volbig *= radfactor*radfactor*radfactor;
else volbig *= radfactor*radfactor;
// particle counts
bigint mbig = 0;
if (bigexist) mbig = group->count(biggroup);
bigint nsrd = group->count(igroup);
// mass_big = total mass of all big particles
mass_big = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & biggroupbit) mass_big += rmass[i];
tmp = mass_big;
MPI_Allreduce(&tmp,&mass_big,1,MPI_DOUBLE,MPI_SUM,world);
// mass density ratio = big / SRD
double density_big = 0.0;
if (bigexist) density_big = mass_big / volbig;
double volsrd,density_srd;
if (dimension == 3) {
volsrd = (domain->xprd * domain->yprd * domain->zprd) - volbig;
density_srd = nsrd * mass_srd /
(domain->xprd*domain->yprd*domain->zprd - volbig);
} else {
volsrd = (domain->xprd * domain->yprd) - volbig;
density_srd = nsrd * mass_srd /
(domain->xprd*domain->yprd - volbig);
}
double mdratio = density_big/density_srd;
// create grid for binning/rotating SRD particles from gridsrd
setup_velocity_bins();
// binsize3 = binsize1 in box units (not lamda units for triclinic)
double binsize3x = binsize1x;
double binsize3y = binsize1y;
double binsize3z = binsize1z;
if (triclinic) {
binsize3x = binsize1x * domain->xprd;
binsize3y = binsize1y * domain->yprd;
binsize3z = binsize1z * domain->zprd;
}
// srd_per_grid = # of SRD particles per SRD grid cell
double ncell;
if (dimension == 3)
ncell = volsrd / (binsize3x*binsize3y*binsize3z);
else
ncell = volsrd / (binsize3x*binsize3y);
srd_per_cell = (double) nsrd / ncell;
// kinematic viscosity of SRD fluid
// output in cm^2/sec units, converted by xxt2kmu
double viscosity;
if (dimension == 3)
viscosity = gridsrd*gridsrd/(18.0*dt_srd) *
(1.0-(1.0-exp(-srd_per_cell))/srd_per_cell) +
(force->boltz*temperature_srd*dt_srd/(4.0*mass_srd*force->mvv2e)) *
((srd_per_cell+2.0)/(srd_per_cell-1.0));
else
viscosity =
(force->boltz*temperature_srd*dt_srd/(2.0*mass_srd*force->mvv2e)) *
(srd_per_cell/(srd_per_cell-1.0 + exp(-srd_per_cell)) - 1.0) +
(gridsrd*gridsrd)/(12.0*dt_srd) *
((srd_per_cell-1.0 + exp(-srd_per_cell))/srd_per_cell);
viscosity *= force->xxt2kmu;
// print SRD parameters
if (me == 0) {
if (screen) {
fprintf(screen,"SRD info:\n");
fprintf(screen,
" SRD/big particles = " BIGINT_FORMAT " " BIGINT_FORMAT "\n",
nsrd,mbig);
fprintf(screen," big particle diameter max/min = %g %g\n",
maxbigdiam,minbigdiam);
fprintf(screen," SRD temperature & lamda = %g %g\n",
temperature_srd,lamda);
fprintf(screen," SRD max distance & max velocity = %g %g\n",dmax,vmax);
fprintf(screen," SRD grid counts: %d %d %d\n",nbin1x,nbin1y,nbin1z);
fprintf(screen," SRD grid size: request, actual (xyz) = %g, %g %g %g\n",
gridsrd,binsize3x,binsize3y,binsize3z);
fprintf(screen," SRD per actual grid cell = %g\n",srd_per_cell);
fprintf(screen," SRD viscosity = %g\n",viscosity);
fprintf(screen," big/SRD mass density ratio = %g\n",mdratio);
}
if (logfile) {
fprintf(logfile,"SRD info:\n");
fprintf(logfile,
" SRD/big particles = " BIGINT_FORMAT " " BIGINT_FORMAT "\n",
nsrd,mbig);
fprintf(logfile," big particle diameter max/min = %g %g\n",
maxbigdiam,minbigdiam);
fprintf(logfile," SRD temperature & lamda = %g %g\n",
temperature_srd,lamda);
fprintf(logfile," SRD max distance & max velocity = %g %g\n",dmax,vmax);
fprintf(logfile," SRD grid counts: %d %d %d\n",nbin1x,nbin1y,nbin1z);
fprintf(logfile," SRD grid size: request, actual (xyz) = %g, %g %g %g\n",
gridsrd,binsize3x,binsize3y,binsize3z);
fprintf(logfile," SRD per actual grid cell = %g\n",srd_per_cell);
fprintf(logfile," SRD viscosity = %g\n",viscosity);
fprintf(logfile," big/SRD mass density ratio = %g\n",mdratio);
}
}
// error if less than 1 SRD bin per processor in some dim
if (nbin1x < comm->procgrid[0] || nbin1y < comm->procgrid[1] ||
nbin1z < comm->procgrid[2])
- error->all("Fewer SRD bins than processors in some dimension");
+ error->all(FLERR,"Fewer SRD bins than processors in some dimension");
// check if SRD bins are within tolerance for shape and size
int tolflag = 0;
if (binsize3y/binsize3x > 1.0+cubictol ||
binsize3x/binsize3y > 1.0+cubictol) tolflag = 1;
if (dimension == 3) {
if (binsize3z/binsize3x > 1.0+cubictol ||
binsize3x/binsize3z > 1.0+cubictol) tolflag = 1;
}
if (tolflag) {
if (cubicflag == CUBIC_ERROR)
- error->all("SRD bins for fix srd are not cubic enough");
+ error->all(FLERR,"SRD bins for fix srd are not cubic enough");
if (me == 0)
- error->warning("SRD bins for fix srd are not cubic enough");
+ error->warning(FLERR,"SRD bins for fix srd are not cubic enough");
}
tolflag = 0;
if (binsize3x/gridsrd > 1.0+cubictol || gridsrd/binsize3x > 1.0+cubictol)
tolflag = 1;
if (binsize3y/gridsrd > 1.0+cubictol || gridsrd/binsize3y > 1.0+cubictol)
tolflag = 1;
if (dimension == 3) {
if (binsize3z/gridsrd > 1.0+cubictol || gridsrd/binsize3z > 1.0+cubictol)
tolflag = 1;
}
if (tolflag) {
if (cubicflag == CUBIC_ERROR)
- error->all("SRD bin size for fix srd differs from user request");
+ error->all(FLERR,"SRD bin size for fix srd differs from user request");
if (me == 0)
- error->warning("SRD bin size for fix srd differs from user request");
+ error->warning(FLERR,"SRD bin size for fix srd differs from user request");
}
// error if lamda < 0.6 of SRD grid size and no shifting allowed
// turn on shifting in this case if allowed
double maxgridsrd = MAX(binsize3x,binsize3y);
if (dimension == 3) maxgridsrd = MAX(maxgridsrd,binsize3z);
shiftflag = 0;
if (lamda < 0.6*maxgridsrd && shiftuser == SHIFT_NO)
- error->all("Fix srd lamda must be >= 0.6 of SRD grid size");
+ error->all(FLERR,"Fix srd lamda must be >= 0.6 of SRD grid size");
else if (lamda < 0.6*maxgridsrd && shiftuser == SHIFT_POSSIBLE) {
shiftflag = 1;
if (me == 0)
- error->warning("SRD bin shifting turned on due to small lamda");
+ error->warning(FLERR,"SRD bin shifting turned on due to small lamda");
} else if (shiftuser == SHIFT_YES) shiftflag = 1;
// warnings
if (bigexist && maxgridsrd > 0.25 * minbigdiam && me == 0)
- error->warning("Fix srd grid size > 1/4 of big particle diameter");
+ error->warning(FLERR,"Fix srd grid size > 1/4 of big particle diameter");
if (viscosity < 0.0 && me == 0)
- error->warning("Fix srd viscosity < 0.0 due to low SRD density");
+ error->warning(FLERR,"Fix srd viscosity < 0.0 due to low SRD density");
if (bigexist && dt_big*vmax > minbigdiam && me == 0)
- error->warning("Fix srd particles may move > big particle diameter");
+ error->warning(FLERR,"Fix srd particles may move > big particle diameter");
}
/* ----------------------------------------------------------------------
set static parameters of each big particle, owned and ghost
called each reneighboring
use radfactor in distance parameters
------------------------------------------------------------------------- */
void FixSRD::big_static()
{
int i;
double rad,arad,brad,crad;
double *shape;
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
double *radius = atom->radius;
int *ellipsoid = atom->ellipsoid;
double skinhalf = 0.5 * neighbor->skin;
for (int k = 0; k < nbig; k++) {
i = biglist[k].index;
if (radius && radius[i] > 0.0) {
biglist[k].type = SPHERE;
rad = radfactor*radius[i];
biglist[k].radius = rad;
biglist[k].radsq = rad*rad;
biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf);
} else if (ellipsoid && ellipsoid[i] >= 0) {
shape = ebonus[ellipsoid[i]].shape;
biglist[k].type = ELLIPSOID;
arad = radfactor*shape[0];
brad = radfactor*shape[1];
crad = radfactor*shape[2];
biglist[k].aradsqinv = 1.0/(arad*arad);
biglist[k].bradsqinv = 1.0/(brad*brad);
biglist[k].cradsqinv = 1.0/(crad*crad);
rad = MAX(arad,brad);
rad = MAX(rad,crad);
biglist[k].cutbinsq = (rad+skinhalf) * (rad+skinhalf);
}
}
}
/* ----------------------------------------------------------------------
set dynamics parameters of each big particle, owned and ghost
for ELLIPSOID, need current omega and ex,ey,ez
for SPHERE, need current omega from atom->omega or atom->angmom
called each timestep
------------------------------------------------------------------------- */
void FixSRD::big_dynamic()
{
int i;
double *shape,*quat;
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
double **omega = atom->omega;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *ellipsoid = atom->ellipsoid;
for (int k = 0; k < nbig; k++) {
i = biglist[k].index;
// sphere with omega
// set omega from atom->omega directly
if (biglist[k].type == SPHERE) {
biglist[k].omega[0] = omega[i][0];
biglist[k].omega[1] = omega[i][1];
biglist[k].omega[2] = omega[i][2];
// ellipsoid with angmom
// calculate ex,ey,ez and omega from quaternion and angmom
} else if (biglist[k].type == ELLIPSOID) {
shape = ebonus[ellipsoid[i]].shape;
quat = ebonus[ellipsoid[i]].quat;
exyz_from_q(quat,biglist[k].ex,biglist[k].ey,biglist[k].ez);
omega_from_mq(angmom[i],biglist[k].ex,biglist[k].ey,biglist[k].ez,
rmass[i],shape,biglist[k].omega);
}
}
}
/* ----------------------------------------------------------------------
set bounds for big and SRD particle movement
called at setup() and when box size changes (but not shape)
------------------------------------------------------------------------- */
void FixSRD::setup_bounds()
{
// triclinic scale factors
// convert a real distance (perpendicular to box face) to a lamda distance
double length0,length1,length2;
if (triclinic) {
double *h_inv = domain->h_inv;
length0 = sqrt(h_inv[0]*h_inv[0] + h_inv[5]*h_inv[5] + h_inv[4]*h_inv[4]);
length1 = sqrt(h_inv[1]*h_inv[1] + h_inv[3]*h_inv[3]);
length2 = h_inv[2];
}
// collision object = CO = big particle or wall
// big particles can be owned or ghost or unknown, walls are all owned
// dist_ghost = distance from sub-domain (SD) that
// owned/ghost CO may move to before reneigh,
// used to bound search bins in setup_search_bins()
// dist_srd = distance from SD at which SRD could collide with unknown CO,
// used to error check bounds of SRD movement after collisions via srdlo/hi
// dist_srd_reneigh = distance from SD at which an SRD should trigger
// a reneigh, b/c next SRD move might overlap with unknown CO,
// used for SRD triggering of reneighboring via srdlo/hi_reneigh
// onemove = max distance an SRD can move in one step
// if big_particles (and possibly walls):
// dist_ghost = cut + 1/2 skin due to moving away before reneigh
// dist_srd = cut - 1/2 skin - 1/2 diam due to ghost CO moving towards
// dist_reneigh = dist_srd - onemove
// if walls and no big particles:
// dist_ghost = 0.0, since not used
// if no big particles or walls:
// dist_ghost and dist_srd = 0.0, since not used since no search bins
// dist_srd_reneigh = subsize - onemove =
// max distance to move without being lost during comm->exchange()
// subsize = perp distance between sub-domain faces (orthog or triclinic)
double cut = MAX(neighbor->cutneighmax,comm->cutghostuser);
double onemove = dt_big*vmax;
if (bigexist) {
dist_ghost = cut + 0.5*neighbor->skin;
dist_srd = cut - 0.5*neighbor->skin - 0.5*maxbigdiam;
dist_srd_reneigh = dist_srd - onemove;
} else if (wallexist) {
dist_ghost = 4*onemove;
dist_srd = 4*onemove;
dist_srd_reneigh = 4*onemove - onemove;
} else {
dist_ghost = dist_srd = 0.0;
double subsize;
if (triclinic == 0) {
subsize = domain->prd[0]/comm->procgrid[0];
subsize = MIN(subsize,domain->prd[1]/comm->procgrid[1]);
if (dimension == 3)
subsize = MIN(subsize,domain->prd[2]/comm->procgrid[2]);
} else {
subsize = 1.0/comm->procgrid[0]/length0;
subsize = MIN(subsize,1.0/comm->procgrid[1]/length1);
if (dimension == 3)
subsize = MIN(subsize,1.0/comm->procgrid[2]/length2);
}
dist_srd_reneigh = subsize - onemove;
}
// lo/hi = bbox on this proc which SRD particles must stay inside
// lo/hi reneigh = bbox on this proc outside of which SRDs trigger a reneigh
// for triclinic, these bbox are in lamda units
if (triclinic == 0) {
srdlo[0] = domain->sublo[0] - dist_srd;
srdhi[0] = domain->subhi[0] + dist_srd;
srdlo[1] = domain->sublo[1] - dist_srd;
srdhi[1] = domain->subhi[1] + dist_srd;
srdlo[2] = domain->sublo[2] - dist_srd;
srdhi[2] = domain->subhi[2] + dist_srd;
srdlo_reneigh[0] = domain->sublo[0] - dist_srd_reneigh;
srdhi_reneigh[0] = domain->subhi[0] + dist_srd_reneigh;
srdlo_reneigh[1] = domain->sublo[1] - dist_srd_reneigh;
srdhi_reneigh[1] = domain->subhi[1] + dist_srd_reneigh;
srdlo_reneigh[2] = domain->sublo[2] - dist_srd_reneigh;
srdhi_reneigh[2] = domain->subhi[2] + dist_srd_reneigh;
} else {
srdlo[0] = domain->sublo_lamda[0] - dist_srd*length0;
srdhi[0] = domain->subhi_lamda[0] + dist_srd*length0;
srdlo[1] = domain->sublo_lamda[1] - dist_srd*length1;
srdhi[1] = domain->subhi_lamda[1] + dist_srd*length1;
srdlo[2] = domain->sublo_lamda[2] - dist_srd*length2;
srdhi[2] = domain->subhi_lamda[2] + dist_srd*length2;
srdlo_reneigh[0] = domain->sublo_lamda[0] - dist_srd_reneigh*length0;
srdhi_reneigh[0] = domain->subhi_lamda[0] + dist_srd_reneigh*length0;
srdlo_reneigh[1] = domain->sublo_lamda[1] - dist_srd_reneigh*length1;
srdhi_reneigh[1] = domain->subhi_lamda[1] + dist_srd_reneigh*length1;
srdlo_reneigh[2] = domain->sublo_lamda[2] - dist_srd_reneigh*length2;
srdhi_reneigh[2] = domain->subhi_lamda[2] + dist_srd_reneigh*length2;
}
}
/* ----------------------------------------------------------------------
setup bins used for binning SRD particles for velocity reset
gridsrd = desired bin size
also setup bin shifting parameters
also setup comm of bins that straddle processor boundaries
called at beginning of each run
called every reneighbor if box size changes, but not if box shape changes
------------------------------------------------------------------------- */
void FixSRD::setup_velocity_bins()
{
// require integer # of bins across global domain
nbin1x = static_cast<int> (domain->xprd/gridsrd + 0.5);
nbin1y = static_cast<int> (domain->yprd/gridsrd + 0.5);
nbin1z = static_cast<int> (domain->zprd/gridsrd + 0.5);
if (dimension == 2) nbin1z = 1;
if (nbin1x == 0) nbin1x = 1;
if (nbin1y == 0) nbin1y = 1;
if (nbin1z == 0) nbin1z = 1;
if (triclinic == 0) {
binsize1x = domain->xprd / nbin1x;
binsize1y = domain->yprd / nbin1y;
binsize1z = domain->zprd / nbin1z;
bininv1x = 1.0/binsize1x;
bininv1y = 1.0/binsize1y;
bininv1z = 1.0/binsize1z;
} else {
binsize1x = 1.0 / nbin1x;
binsize1y = 1.0 / nbin1y;
binsize1z = 1.0 / nbin1z;
bininv1x = nbin1x;
bininv1y = nbin1y;
bininv1z = nbin1z;
}
nbins1 = nbin1x*nbin1y*nbin1z;
// setup two shifts, 0 = no shift, 1 = shift
// initialize no shift case since static
// shift case is dynamic, has to be initialized each time shift occurs
// setup_velocity_shift allocates memory for vbin and sendlist/recvlist
double *boxlo;
if (triclinic == 0) boxlo = domain->boxlo;
else boxlo = domain->boxlo_lamda;
shifts[0].corner[0] = boxlo[0];
shifts[0].corner[1] = boxlo[1];
shifts[0].corner[2] = boxlo[2];
setup_velocity_shift(0,0);
shifts[1].corner[0] = boxlo[0];
shifts[1].corner[1] = boxlo[1];
shifts[1].corner[2] = boxlo[2];
setup_velocity_shift(1,0);
// allocate binhead based on max # of bins in either shift
int max = shifts[0].nbins;
max = MAX(max,shifts[1].nbins);
if (max > maxbin1) {
memory->destroy(binhead);
maxbin1 = max;
memory->create(binhead,max,"fix/srd:binhead");
}
// allocate sbuf,rbuf based on biggest bin message
max = 0;
for (int ishift = 0; ishift < 2; ishift++)
for (int iswap = 0; iswap < 2*dimension; iswap++) {
max = MAX(max,shifts[ishift].bcomm[iswap].nsend);
max = MAX(max,shifts[ishift].bcomm[iswap].nrecv);
}
if (max > maxbuf) {
memory->destroy(sbuf1);
memory->destroy(sbuf2);
memory->destroy(rbuf1);
memory->destroy(rbuf2);
maxbuf = max;
memory->create(sbuf1,max*VBINSIZE,"fix/srd:sbuf");
memory->create(sbuf2,max*VBINSIZE,"fix/srd:sbuf");
memory->create(rbuf1,max*VBINSIZE,"fix/srd:rbuf");
memory->create(rbuf2,max*VBINSIZE,"fix/srd:rbuf");
}
// commflag = 1 if any comm required due to bins overlapping proc boundaries
shifts[0].commflag = 0;
if (nbin1x % comm->procgrid[0]) shifts[0].commflag = 1;
if (nbin1y % comm->procgrid[1]) shifts[0].commflag = 1;
if (nbin1z % comm->procgrid[2]) shifts[0].commflag = 1;
shifts[1].commflag = 1;
}
/* ----------------------------------------------------------------------
setup velocity shift parameters
set binlo[]/binhi[] and nbins,nbinx,nbiny,nbinz for this proc
set bcomm[6] params based on bin overlaps with proc boundaries
no comm of bins across non-periodic global boundaries
set vbin owner flags for bins I am owner of
ishift = 0, dynamic = 0:
set all settings since are static
allocate and set bcomm params and vbins
do not comm bins that align with proc boundaries
ishift = 1, dynamic = 0:
set max bounds on bin counts and message sizes
allocate and set bcomm params and vbins based on max bounds
other settings will later change dynamically
ishift = 1, dynamic = 1:
set actual bin bounds and counts for specific shift
set bcomm params and vbins (already allocated)
called by setup_velocity_bins() and reset_velocities()
------------------------------------------------------------------------- */
void FixSRD::setup_velocity_shift(int ishift, int dynamic)
{
int i,j,k,m,id,nsend;
int *sendlist;
BinComm *first,*second;
BinAve *vbin;
double *sublo,*subhi;
if (triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
int *binlo = shifts[ishift].binlo;
int *binhi = shifts[ishift].binhi;
double *corner = shifts[ishift].corner;
int *procgrid = comm->procgrid;
int *myloc = comm->myloc;
binlo[0] = static_cast<int> ((sublo[0]-corner[0])*bininv1x);
binlo[1] = static_cast<int> ((sublo[1]-corner[1])*bininv1y);
binlo[2] = static_cast<int> ((sublo[2]-corner[2])*bininv1z);
if (dimension == 2) shifts[ishift].binlo[2] = 0;
binhi[0] = static_cast<int> ((subhi[0]-corner[0])*bininv1x);
binhi[1] = static_cast<int> ((subhi[1]-corner[1])*bininv1y);
binhi[2] = static_cast<int> ((subhi[2]-corner[2])*bininv1z);
if (dimension == 2) shifts[ishift].binhi[2] = 0;
if (ishift == 0) {
if (myloc[0]*nbin1x % procgrid[0] == 0)
binlo[0] = myloc[0]*nbin1x/procgrid[0];
if (myloc[1]*nbin1y % procgrid[1] == 0)
binlo[1] = myloc[1]*nbin1y/procgrid[1];
if (myloc[2]*nbin1z % procgrid[2] == 0)
binlo[2] = myloc[2]*nbin1z/procgrid[2];
if ((myloc[0]+1)*nbin1x % procgrid[0] == 0)
binhi[0] = (myloc[0]+1)*nbin1x/procgrid[0] - 1;
if ((myloc[1]+1)*nbin1y % procgrid[1] == 0)
binhi[1] = (myloc[1]+1)*nbin1y/procgrid[1] - 1;
if ((myloc[2]+1)*nbin1z % procgrid[2] == 0)
binhi[2] = (myloc[2]+1)*nbin1z/procgrid[2] - 1;
}
int nbinx = binhi[0] - binlo[0] + 1;
int nbiny = binhi[1] - binlo[1] + 1;
int nbinz = binhi[2] - binlo[2] + 1;
// allow for one extra bin if shifting will occur
if (ishift == 1 && dynamic == 0) {
nbinx++;
nbiny++;
if (dimension == 3) nbinz++;
}
int nbins = nbinx*nbiny*nbinz;
int nbinxy = nbinx*nbiny;
int nbinsq = nbinx*nbiny;
nbinsq = MAX(nbiny*nbinz,nbinsq);
nbinsq = MAX(nbinx*nbinz,nbinsq);
shifts[ishift].nbins = nbins;
shifts[ishift].nbinx = nbinx;
shifts[ishift].nbiny = nbiny;
shifts[ishift].nbinz = nbinz;
int reallocflag = 0;
if (dynamic == 0 && nbinsq > shifts[ishift].maxbinsq) {
shifts[ishift].maxbinsq = nbinsq;
reallocflag = 1;
}
// bcomm neighbors
// first = send in lo direction, recv from hi direction
// second = send in hi direction, recv from lo direction
if (dynamic == 0) {
shifts[ishift].bcomm[0].sendproc = comm->procneigh[0][0];
shifts[ishift].bcomm[0].recvproc = comm->procneigh[0][1];
shifts[ishift].bcomm[1].sendproc = comm->procneigh[0][1];
shifts[ishift].bcomm[1].recvproc = comm->procneigh[0][0];
shifts[ishift].bcomm[2].sendproc = comm->procneigh[1][0];
shifts[ishift].bcomm[2].recvproc = comm->procneigh[1][1];
shifts[ishift].bcomm[3].sendproc = comm->procneigh[1][1];
shifts[ishift].bcomm[3].recvproc = comm->procneigh[1][0];
shifts[ishift].bcomm[4].sendproc = comm->procneigh[2][0];
shifts[ishift].bcomm[4].recvproc = comm->procneigh[2][1];
shifts[ishift].bcomm[5].sendproc = comm->procneigh[2][1];
shifts[ishift].bcomm[5].recvproc = comm->procneigh[2][0];
}
// set nsend,nrecv and sendlist,recvlist for each swap in x,y,z
// set nsend,nrecv = 0 if static bins align with proc boundary
// or to prevent dynamic bin swapping across non-periodic global boundary
// allocate sendlist,recvlist only for dynamic = 0
first = &shifts[ishift].bcomm[0];
second = &shifts[ishift].bcomm[1];
first->nsend = first->nrecv = second->nsend = second->nrecv = nbiny*nbinz;
if (ishift == 0) {
if (myloc[0]*nbin1x % procgrid[0] == 0)
first->nsend = second->nrecv = 0;
if ((myloc[0]+1)*nbin1x % procgrid[0] == 0)
second->nsend = first->nrecv = 0;
} else {
if (domain->xperiodic == 0) {
if (myloc[0] == 0) first->nsend = second->nrecv = 0;
if (myloc[0] == procgrid[0]-1) second->nsend = first->nrecv = 0;
}
}
if (reallocflag) {
memory->destroy(first->sendlist);
memory->destroy(first->recvlist);
memory->destroy(second->sendlist);
memory->destroy(second->recvlist);
memory->create(first->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(first->recvlist,nbinsq,"fix/srd:sendlist");
memory->create(second->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(second->recvlist,nbinsq,"fix/srd:sendlist");
}
m = 0;
i = 0;
for (j = 0; j < nbiny; j++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
first->sendlist[m] = second->recvlist[m] = id;
m++;
}
m = 0;
i = nbinx-1;
for (j = 0; j < nbiny; j++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
second->sendlist[m] = first->recvlist[m] = id;
m++;
}
first = &shifts[ishift].bcomm[2];
second = &shifts[ishift].bcomm[3];
first->nsend = first->nrecv = second->nsend = second->nrecv = nbinx*nbinz;
if (ishift == 0) {
if (myloc[1]*nbin1y % procgrid[1] == 0)
first->nsend = second->nrecv = 0;
if ((myloc[1]+1)*nbin1y % procgrid[1] == 0)
second->nsend = first->nrecv = 0;
} else {
if (domain->yperiodic == 0) {
if (myloc[1] == 0) first->nsend = second->nrecv = 0;
if (myloc[1] == procgrid[1]-1) second->nsend = first->nrecv = 0;
}
}
if (reallocflag) {
memory->destroy(first->sendlist);
memory->destroy(first->recvlist);
memory->destroy(second->sendlist);
memory->destroy(second->recvlist);
memory->create(first->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(first->recvlist,nbinsq,"fix/srd:sendlist");
memory->create(second->sendlist,nbinsq,"fix/srd:sendlist");
memory->create(second->recvlist,nbinsq,"fix/srd:sendlist");
}
m = 0;
j = 0;
for (i = 0; i < nbinx; i++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
first->sendlist[m] = second->recvlist[m] = id;
m++;
}
m = 0;
j = nbiny-1;
for (i = 0; i < nbinx; i++)
for (k = 0; k < nbinz; k++) {
id = k*nbinxy + j*nbinx + i;
second->sendlist[m] = first->recvlist[m] = id;
m++;
}
if (dimension == 3) {
first = &shifts[ishift].bcomm[4];
second = &shifts[ishift].bcomm[5];
first->nsend = first->nrecv = second->nsend = second->nrecv = nbinx*nbiny;
if (ishift == 0) {
if (myloc[2]*nbin1z % procgrid[2] == 0)
first->nsend = second->nrecv = 0;
if ((myloc[2]+1)*nbin1z % procgrid[2] == 0)
second->nsend = first->nrecv = 0;
} else {
if (domain->zperiodic == 0) {
if (myloc[2] == 0) first->nsend = second->nrecv = 0;
if (myloc[2] == procgrid[2]-1) second->nsend = first->nrecv = 0;
}
}
if (reallocflag) {
memory->destroy(first->sendlist);
memory->destroy(first->recvlist);
memory->destroy(second->sendlist);
memory->destroy(second->recvlist);
memory->create(first->sendlist,nbinx*nbiny,"fix/srd:sendlist");
memory->create(first->recvlist,nbinx*nbiny,"fix/srd:sendlist");
memory->create(second->sendlist,nbinx*nbiny,"fix/srd:sendlist");
memory->create(second->recvlist,nbinx*nbiny,"fix/srd:sendlist");
}
m = 0;
k = 0;
for (i = 0; i < nbinx; i++)
for (j = 0; j < nbiny; j++) {
id = k*nbinxy + j*nbinx + i;
first->sendlist[m] = second->recvlist[m] = id;
m++;
}
m = 0;
k = nbinz-1;
for (i = 0; i < nbinx; i++)
for (j = 0; j < nbiny; j++) {
id = k*nbinxy + j*nbinx + i;
second->sendlist[m] = first->recvlist[m] = id;
m++;
}
}
// allocate vbins, only for dynamic = 0
if (dynamic == 0 && nbins > shifts[ishift].maxvbin) {
memory->destroy(shifts[ishift].vbin);
shifts[ishift].maxvbin = nbins;
shifts[ishift].vbin = (BinAve *)
memory->smalloc(nbins*sizeof(BinAve),"fix/srd:vbin");
}
// for vbins I own, set owner = 1
// if bin never sent to anyone, I own it
// if bin sent to lower numbered proc, I do not own it
// if bin sent to self, I do not own it on even swap (avoids double counting)
vbin = shifts[ishift].vbin;
for (i = 0; i < nbins; i++) vbin[i].owner = 1;
for (int iswap = 0; iswap < 2*dimension; iswap++) {
if (shifts[ishift].bcomm[iswap].sendproc > me) continue;
if (shifts[ishift].bcomm[iswap].sendproc == me && iswap % 2 == 0) continue;
nsend = shifts[ishift].bcomm[iswap].nsend;
sendlist = shifts[ishift].bcomm[iswap].sendlist;
for (m = 0; m < nsend; m++) vbin[sendlist[m]].owner = 0;
}
// if triclinic and streamflag:
// set xctr (in lamda units) for all nbins so can compute bin vstream
if (triclinic && streamflag) {
m = 0;
for (k = 0; k < nbinz; k++)
for (j = 0; j < nbiny; j++)
for (i = 0; i < nbinx; i++) {
vbin[m].xctr[0] = corner[0] + (i+binlo[0]+0.5)/nbin1x;
vbin[m].xctr[1] = corner[1] + (j+binlo[1]+0.5)/nbin1y;
vbin[m].xctr[2] = corner[2] + (k+binlo[2]+0.5)/nbin1z;
m++;
}
}
}
/* ----------------------------------------------------------------------
setup bins used for big and SRD particle searching
gridsearch = desired bin size
bins are orthogonal whether simulation box is orthogonal or triclinic
for orthogonal boxes, called at each setup since cutghost may change
for triclinic boxes, called at every reneigh, since tilt may change
sets the following:
nbin2 xyz = # of bins in each dim
binsize2 and bininv2 xyz = size of bins in each dim
xyz blo2 = origin of bins
------------------------------------------------------------------------- */
void FixSRD::setup_search_bins()
{
// subboxlo/hi = real space bbox which
// owned/ghost big particles or walls can be in
// start with bounding box for my sub-domain, add dist_ghost
// for triclinic, need to:
// a) convert dist_ghost to lamda space via length012
// b) lo/hi = sub-domain big particle bbox in lamda space
// c) convert lo/hi to real space bounding box via domain->bbox()
// similar to neighbor::setup_bins() and comm::cutghost[] calculation
double subboxlo[3],subboxhi[3];
if (triclinic == 0) {
subboxlo[0] = domain->sublo[0] - dist_ghost;
subboxlo[1] = domain->sublo[1] - dist_ghost;
subboxlo[2] = domain->sublo[2] - dist_ghost;
subboxhi[0] = domain->subhi[0] + dist_ghost;
subboxhi[1] = domain->subhi[1] + dist_ghost;
subboxhi[2] = domain->subhi[2] + dist_ghost;
} else {
double *h_inv = domain->h_inv;
double length0,length1,length2;
length0 = sqrt(h_inv[0]*h_inv[0] + h_inv[5]*h_inv[5] + h_inv[4]*h_inv[4]);
length1 = sqrt(h_inv[1]*h_inv[1] + h_inv[3]*h_inv[3]);
length2 = h_inv[2];
double lo[3],hi[3];
lo[0] = domain->sublo_lamda[0] - dist_ghost*length0;
lo[1] = domain->sublo_lamda[1] - dist_ghost*length1;
lo[2] = domain->sublo_lamda[2] - dist_ghost*length2;
hi[0] = domain->subhi_lamda[0] + dist_ghost*length0;
hi[1] = domain->subhi_lamda[1] + dist_ghost*length1;
hi[2] = domain->subhi_lamda[2] + dist_ghost*length2;
domain->bbox(lo,hi,subboxlo,subboxhi);
}
// require integer # of bins for that volume
nbin2x = static_cast<int> ((subboxhi[0] - subboxlo[0]) / gridsearch);
nbin2y = static_cast<int> ((subboxhi[1] - subboxlo[1]) / gridsearch);
nbin2z = static_cast<int> ((subboxhi[2] - subboxlo[2]) / gridsearch);
if (dimension == 2) nbin2z = 1;
if (nbin2x == 0) nbin2x = 1;
if (nbin2y == 0) nbin2y = 1;
if (nbin2z == 0) nbin2z = 1;
binsize2x = (subboxhi[0] - subboxlo[0]) / nbin2x;
binsize2y = (subboxhi[1] - subboxlo[1]) / nbin2y;
binsize2z = (subboxhi[2] - subboxlo[2]) / nbin2z;
bininv2x = 1.0/binsize2x;
bininv2y = 1.0/binsize2y;
bininv2z = 1.0/binsize2z;
// add bins on either end due to extent of big particles
// radmax = max distance from central bin that biggest particle overlaps
// includes skin movement
// nx,ny,nz = max # of bins to search away from central bin
double radmax = 0.5*maxbigdiam + 0.5*neighbor->skin;
int nx = static_cast<int> (radmax/binsize2x) + 1;
int ny = static_cast<int> (radmax/binsize2y) + 1;
int nz = static_cast<int> (radmax/binsize2z) + 1;
if (dimension == 2) nz = 0;
nbin2x += 2*nx;
nbin2y += 2*ny;
nbin2z += 2*nz;
xblo2 = subboxlo[0] - nx*binsize2x;
yblo2 = subboxlo[1] - ny*binsize2y;
zblo2 = subboxlo[2] - nz*binsize2z;
if (dimension == 2) zblo2 = domain->boxlo[2];
// allocate bins
// first deallocate previous bins if necessary
nbins2 = nbin2x*nbin2y*nbin2z;
if (nbins2 > maxbin2) {
memory->destroy(nbinbig);
memory->destroy(binbig);
maxbin2 = nbins2;
memory->create(nbinbig,nbins2,"fix/srd:nbinbig");
memory->create(binbig,nbins2,ATOMPERBIN,"fix/srd:binbig");
}
}
/* ----------------------------------------------------------------------
compute stencil of bin offsets for a big particle overlapping search bins
------------------------------------------------------------------------- */
void FixSRD::setup_search_stencil()
{
// radmax = max distance from central bin that any big particle overlaps
// includes skin movement
// nx,ny,nz = max # of bins to search away from central bin
double radmax = 0.5*maxbigdiam + 0.5*neighbor->skin;
double radsq = radmax*radmax;
int nx = static_cast<int> (radmax/binsize2x) + 1;
int ny = static_cast<int> (radmax/binsize2y) + 1;
int nz = static_cast<int> (radmax/binsize2z) + 1;
if (dimension == 2) nz = 0;
// allocate stencil array
// deallocate previous stencil if necessary
int max = (2*nx+1) * (2*ny+1) * (2*nz+1);
if (max > maxstencil) {
memory->destroy(stencil);
maxstencil = max;
memory->create(stencil,max,4,"fix/srd:stencil");
}
// loop over all bins
// add bin to stencil:
// if distance of closest corners of bin and central bin is within cutoff
nstencil = 0;
for (int k = -nz; k <= nz; k++)
for (int j = -ny; j <= ny; j++)
for (int i = -nx; i <= nx; i++)
if (bin_bin_distance(i,j,k) < radsq) {
stencil[nstencil][0] = i;
stencil[nstencil][1] = j;
stencil[nstencil][2] = k;
stencil[nstencil][3] = k*nbin2y*nbin2x + j*nbin2x + i;
nstencil++;
}
}
/* ----------------------------------------------------------------------
compute closest squared distance between point x and bin ibin
------------------------------------------------------------------------- */
double FixSRD::point_bin_distance(double *x, int i, int j, int k)
{
double delx,dely,delz;
double xlo = xblo2 + i*binsize2x;
double xhi = xlo + binsize2x;
double ylo = yblo2 + j*binsize2y;
double yhi = ylo + binsize2y;
double zlo = zblo2 + k*binsize2z;
double zhi = zlo + binsize2z;
if (x[0] < xlo) delx = xlo - x[0];
else if (x[0] > xhi) delx = x[0] - xhi;
else delx = 0.0;
if (x[1] < ylo) dely = ylo - x[1];
else if (x[1] > yhi) dely = x[1] - yhi;
else dely = 0.0;
if (x[2] < zlo) delz = zlo - x[2];
else if (x[2] > zhi) delz = x[2] - zhi;
else delz = 0.0;
return (delx*delx + dely*dely + delz*delz);
}
/* ----------------------------------------------------------------------
compute closest squared distance between 2 bins
central bin (0,0,0) and bin (i,j,k)
------------------------------------------------------------------------- */
double FixSRD::bin_bin_distance(int i, int j, int k)
{
double delx,dely,delz;
if (i > 0) delx = (i-1)*binsize2x;
else if (i == 0) delx = 0.0;
else delx = (i+1)*binsize2x;
if (j > 0) dely = (j-1)*binsize2y;
else if (j == 0) dely = 0.0;
else dely = (j+1)*binsize2y;
if (k > 0) delz = (k-1)*binsize2z;
else if (k == 0) delz = 0.0;
else delz = (k+1)*binsize2z;
return (delx*delx + dely*dely + delz*delz);
}
/* ----------------------------------------------------------------------
compute space-frame ex,ey,ez from current quaternion q
ex,ey,ez = space-frame coords of 1st,2nd,3rd principal axis
operation is ex = q' d q = Q d, where d is (1,0,0) = 1st axis in body frame
------------------------------------------------------------------------- */
void FixSRD::exyz_from_q(double *q, double *ex, double *ey, double *ez)
{
ex[0] = q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3];
ex[1] = 2.0 * (q[1]*q[2] + q[0]*q[3]);
ex[2] = 2.0 * (q[1]*q[3] - q[0]*q[2]);
ey[0] = 2.0 * (q[1]*q[2] - q[0]*q[3]);
ey[1] = q[0]*q[0] - q[1]*q[1] + q[2]*q[2] - q[3]*q[3];
ey[2] = 2.0 * (q[2]*q[3] + q[0]*q[1]);
ez[0] = 2.0 * (q[1]*q[3] + q[0]*q[2]);
ez[1] = 2.0 * (q[2]*q[3] - q[0]*q[1]);
ez[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
}
/* ----------------------------------------------------------------------
compute omega from angular momentum
w = omega = angular velocity in space frame
wbody = angular velocity in body frame
set wbody component to 0.0 if inertia component is 0.0
otherwise body can spin easily around that axis
project space-frame angular momentum onto body axes
and divide by principal moments
------------------------------------------------------------------------- */
void FixSRD::omega_from_mq(double *m, double *ex, double *ey, double *ez,
double mass, double *shape, double *w)
{
double inertia[3],wbody[3];
inertia[0] = 0.2*mass * (shape[1]*shape[1]+shape[2]*shape[2]);
inertia[1] = 0.2*mass * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = 0.2*mass * (shape[0]*shape[0]+shape[1]*shape[1]);
wbody[0] = (m[0]*ex[0] + m[1]*ex[1] + m[2]*ex[2]) / inertia[0];
wbody[1] = (m[0]*ey[0] + m[1]*ey[1] + m[2]*ey[2]) / inertia[1];
wbody[2] = (m[0]*ez[0] + m[1]*ez[1] + m[2]*ez[2]) / inertia[2];
w[0] = wbody[0]*ex[0] + wbody[1]*ey[0] + wbody[2]*ez[0];
w[1] = wbody[0]*ex[1] + wbody[1]*ey[1] + wbody[2]*ez[1];
w[2] = wbody[0]*ex[2] + wbody[1]*ey[2] + wbody[2]*ez[2];
}
/* ---------------------------------------------------------------------- */
int FixSRD::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (torqueflag) {
for (i = first; i < last; i++) {
buf[m++] = flocal[i][0];
buf[m++] = flocal[i][1];
buf[m++] = flocal[i][2];
buf[m++] = tlocal[i][0];
buf[m++] = tlocal[i][1];
buf[m++] = tlocal[i][2];
}
} else {
for (i = first; i < last; i++) {
buf[m++] = flocal[i][0];
buf[m++] = flocal[i][1];
buf[m++] = flocal[i][2];
}
}
return comm_reverse;
}
/* ---------------------------------------------------------------------- */
void FixSRD::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
if (torqueflag) {
for (i = 0; i < n; i++) {
j = list[i];
flocal[j][0] += buf[m++];
flocal[j][1] += buf[m++];
flocal[j][2] += buf[m++];
tlocal[j][0] += buf[m++];
tlocal[j][1] += buf[m++];
tlocal[j][2] += buf[m++];
}
} else {
for (i = 0; i < n; i++) {
j = list[i];
flocal[j][0] += buf[m++];
flocal[j][1] += buf[m++];
flocal[j][2] += buf[m++];
}
}
}
/* ----------------------------------------------------------------------
SRD stats
------------------------------------------------------------------------- */
double FixSRD::compute_vector(int n)
{
// only sum across procs one time
if (stats_flag == 0) {
stats[0] = ncheck;
stats[1] = ncollide;
stats[2] = nbounce;
stats[3] = ninside;
stats[4] = nrescale;
stats[5] = nbins2;
stats[6] = nbins1;
stats[7] = srd_bin_count;
stats[8] = srd_bin_temp;
stats[9] = bouncemaxnum;
stats[10] = bouncemax;
stats[11] = reneighcount;
MPI_Allreduce(stats,stats_all,10,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(&stats[10],&stats_all[10],1,MPI_DOUBLE,MPI_MAX,world);
if (stats_all[7] != 0.0) stats_all[8] /= stats_all[7];
stats_all[6] /= nprocs;
stats_flag = 1;
}
return stats_all[n];
}
/* ---------------------------------------------------------------------- */
void FixSRD::velocity_stats(int groupnum)
{
int bitmask = group->bitmask[groupnum];
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double vone;
double vave = 0.0;
double vmax = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & bitmask) {
vone = sqrt(v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
vave += vone;
if (vone > vmax) vmax = vone;
}
double all;
MPI_Allreduce(&vave,&all,1,MPI_DOUBLE,MPI_SUM,world);
double count = group->count(groupnum);
if (count != 0.0) vave = all/count;
else vave = 0.0;
MPI_Allreduce(&vmax,&all,1,MPI_DOUBLE,MPI_MAX,world);
vmax = all;
if (me == 0) {
if (screen)
fprintf(screen," ave/max %s velocity = %g %g\n",
group->names[groupnum],vave,vmax);
if (logfile)
fprintf(logfile," ave/max %s velocity = %g %g\n",
group->names[groupnum],vave,vmax);
}
}
/* ---------------------------------------------------------------------- */
double FixSRD::memory_usage()
{
double bytes = 0.0;
bytes += (shifts[0].nbins + shifts[1].nbins) * sizeof(BinAve);
bytes += nmax * sizeof(int);
if (bigexist) {
bytes += nbins2 * sizeof(int);
bytes += nbins2*ATOMPERBIN * sizeof(int);
}
bytes += nmax * sizeof(int);
return bytes;
}
/* ----------------------------------------------------------------------
useful debugging functions
------------------------------------------------------------------------- */
double FixSRD::distance(int i, int j)
{
double dx = atom->x[i][0] - atom->x[j][0];
double dy = atom->x[i][1] - atom->x[j][1];
double dz = atom->x[i][2] - atom->x[j][2];
return sqrt(dx*dx + dy*dy + dz*dz);
}
/* ---------------------------------------------------------------------- */
void FixSRD::print_collision(int i, int j, int ibounce,
double t_remain, double dt,
double *xscoll, double *xbcoll, double *norm,
int type)
{
double xsstart[3],xbstart[3];
double **x = atom->x;
double **v = atom->v;
if (type != WALL) {
printf("COLLISION between SRD %d and BIG %d\n",atom->tag[i],atom->tag[j]);
printf(" bounce # = %d\n",ibounce+1);
printf(" local indices: %d %d\n",i,j);
printf(" timestep = %g\n",dt);
printf(" time remaining post-collision = %g\n",t_remain);
xsstart[0] = x[i][0] - dt*v[i][0];
xsstart[1] = x[i][1] - dt*v[i][1];
xsstart[2] = x[i][2] - dt*v[i][2];
xbstart[0] = x[j][0] - dt*v[j][0];
xbstart[1] = x[j][1] - dt*v[j][1];
xbstart[2] = x[j][2] - dt*v[j][2];
printf(" SRD start position = %g %g %g\n",
xsstart[0],xsstart[1],xsstart[2]);
printf(" BIG start position = %g %g %g\n",
xbstart[0],xbstart[1],xbstart[2]);
printf(" SRD coll position = %g %g %g\n",
xscoll[0],xscoll[1],xscoll[2]);
printf(" BIG coll position = %g %g %g\n",
xbcoll[0],xbcoll[1],xbcoll[2]);
printf(" SRD end position = %g %g %g\n",x[i][0],x[i][1],x[i][2]);
printf(" BIG end position = %g %g %g\n",x[j][0],x[j][1],x[j][2]);
printf(" SRD vel = %g %g %g\n",v[i][0],v[i][1],v[i][2]);
printf(" BIG vel = %g %g %g\n",v[j][0],v[j][1],v[j][2]);
printf(" surf norm = %g %g %g\n",norm[0],norm[1],norm[2]);
double rstart = sqrt((xsstart[0]-xbstart[0])*(xsstart[0]-xbstart[0]) +
(xsstart[1]-xbstart[1])*(xsstart[1]-xbstart[1]) +
(xsstart[2]-xbstart[2])*(xsstart[2]-xbstart[2]));
double rcoll = sqrt((xscoll[0]-xbcoll[0])*(xscoll[0]-xbcoll[0]) +
(xscoll[1]-xbcoll[1])*(xscoll[1]-xbcoll[1]) +
(xscoll[2]-xbcoll[2])*(xscoll[2]-xbcoll[2]));
double rend = sqrt((x[i][0]-x[j][0])*(x[i][0]-x[j][0]) +
(x[i][1]-x[j][1])*(x[i][1]-x[j][1]) +
(x[i][2]-x[j][2])*(x[i][2]-x[j][2]));
printf(" separation at start = %g\n",rstart);
printf(" separation at coll = %g\n",rcoll);
printf(" separation at end = %g\n",rend);
} else {
int dim = wallwhich[j] / 2;
printf("COLLISION between SRD %d and WALL %d\n",atom->tag[i],j);
printf(" bounce # = %d\n",ibounce+1);
printf(" local indices: %d %d\n",i,j);
printf(" timestep = %g\n",dt);
printf(" time remaining post-collision = %g\n",t_remain);
xsstart[0] = x[i][0] - dt*v[i][0];
xsstart[1] = x[i][1] - dt*v[i][1];
xsstart[2] = x[i][2] - dt*v[i][2];
xbstart[0] = xbstart[1] = xbstart[2] = 0.0;
xbstart[dim] = xwall[j] - dt*vwall[j];
printf(" SRD start position = %g %g %g\n",
xsstart[0],xsstart[1],xsstart[2]);
printf(" WALL start position = %g\n",xbstart[dim]);
printf(" SRD coll position = %g %g %g\n",
xscoll[0],xscoll[1],xscoll[2]);
printf(" WALL coll position = %g\n",xbcoll[dim]);
printf(" SRD end position = %g %g %g\n",x[i][0],x[i][1],x[i][2]);
printf(" WALL end position = %g\n",xwall[j]);
printf(" SRD vel = %g %g %g\n",v[i][0],v[i][1],v[i][2]);
printf(" WALL vel = %g\n",vwall[j]);
printf(" surf norm = %g %g %g\n",norm[0],norm[1],norm[2]);
double rstart = xsstart[dim]-xbstart[dim];
double rcoll = xscoll[dim]-xbcoll[dim];
double rend = x[dim][0]-xwall[j];
printf(" separation at start = %g\n",rstart);
printf(" separation at coll = %g\n",rcoll);
printf(" separation at end = %g\n",rend);
}
}
diff --git a/src/SRD/fix_wall_srd.cpp b/src/SRD/fix_wall_srd.cpp
index 2f18d2883..fe38da8b4 100644
--- a/src/SRD/fix_wall_srd.cpp
+++ b/src/SRD/fix_wall_srd.cpp
@@ -1,261 +1,261 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_wall_srd.h"
#include "atom.h"
#include "modify.h"
#include "fix.h"
#include "domain.h"
#include "lattice.h"
#include "input.h"
#include "modify.h"
#include "update.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{XLO,XHI,YLO,YHI,ZLO,ZHI};
enum{NONE,EDGE,CONSTANT,VARIABLE};
/* ---------------------------------------------------------------------- */
FixWallSRD::FixWallSRD(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix wall/srd command");
+ if (narg < 4) error->all(FLERR,"Illegal fix wall/srd command");
// parse args
nwall = 0;
int scaleflag = 1;
int iarg = 3;
while (iarg < narg) {
if ((strcmp(arg[iarg],"xlo") == 0) || (strcmp(arg[iarg],"xhi") == 0) ||
(strcmp(arg[iarg],"ylo") == 0) || (strcmp(arg[iarg],"yhi") == 0) ||
(strcmp(arg[iarg],"zlo") == 0) || (strcmp(arg[iarg],"zhi") == 0)) {
- if (iarg+2 > narg) error->all("Illegal fix wall/srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix wall/srd command");
int newwall;
if (strcmp(arg[iarg],"xlo") == 0) newwall = XLO;
else if (strcmp(arg[iarg],"xhi") == 0) newwall = XHI;
else if (strcmp(arg[iarg],"ylo") == 0) newwall = YLO;
else if (strcmp(arg[iarg],"yhi") == 0) newwall = YHI;
else if (strcmp(arg[iarg],"zlo") == 0) newwall = ZLO;
else if (strcmp(arg[iarg],"zhi") == 0) newwall = ZHI;
for (int m = 0; m < nwall; m++)
if (newwall == wallwhich[m])
- error->all("Wall defined twice in fix wall/srd command");
+ error->all(FLERR,"Wall defined twice in fix wall/srd command");
wallwhich[nwall] = newwall;
if (strcmp(arg[iarg+1],"EDGE") == 0) {
wallstyle[nwall] = EDGE;
int dim = wallwhich[nwall] / 2;
int side = wallwhich[nwall] % 2;
if (side == 0) coord0[nwall] = domain->boxlo[dim];
else coord0[nwall] = domain->boxhi[dim];
} else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
wallstyle[nwall] = VARIABLE;
int n = strlen(&arg[iarg+1][2]) + 1;
varstr[nwall] = new char[n];
strcpy(varstr[nwall],&arg[iarg+1][2]);
} else {
wallstyle[nwall] = CONSTANT;
coord0[nwall] = atof(arg[iarg+1]);
}
nwall++;
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal wall/srd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal wall/srd command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix wall/srd command");
+ else error->all(FLERR,"Illegal fix wall/srd command");
iarg += 2;
- } else error->all("Illegal fix wall/srd command");
+ } else error->all(FLERR,"Illegal fix wall/srd command");
}
// error check
- if (nwall == 0) error->all("Illegal fix wall command");
+ if (nwall == 0) error->all(FLERR,"Illegal fix wall command");
for (int m = 0; m < nwall; m++) {
if ((wallwhich[m] == XLO || wallwhich[m] == XHI) && domain->xperiodic)
- error->all("Cannot use fix wall/srd in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall/srd in periodic dimension");
if ((wallwhich[m] == YLO || wallwhich[m] == YHI) && domain->yperiodic)
- error->all("Cannot use fix wall/srd in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall/srd in periodic dimension");
if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->zperiodic)
- error->all("Cannot use fix wall/srd in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall/srd in periodic dimension");
}
for (int m = 0; m < nwall; m++)
if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->dimension == 2)
- error->all("Cannot use fix wall/srd zlo/zhi for a 2d simulation");
+ error->all(FLERR,"Cannot use fix wall/srd zlo/zhi for a 2d simulation");
// setup wall force array
array_flag = 1;
size_array_rows = nwall;
size_array_cols = 3;
global_freq = 1;
extarray = 1;
memory->create(fwall,nwall,3,"wall/srd:fwall");
memory->create(fwall_all,nwall,3,"wall/srd:fwall_all");
// scale coord for CONSTANT walls
int flag = 0;
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == CONSTANT) flag = 1;
if (flag) {
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix wall with undefined lattice");
+ error->all(FLERR,"Use of fix wall with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
double scale;
for (int m = 0; m < nwall; m++) {
if (wallwhich[m] < YLO) scale = xscale;
else if (wallwhich[m] < ZLO) scale = yscale;
else scale = zscale;
if (wallstyle[m] == CONSTANT) coord0[m] *= scale;
}
}
// set overlap if walls exist in multiple dimensions
int dimflag[3];
dimflag[0] = dimflag[1] = dimflag[2] = 0;
for (int m = 0; m < nwall; m++)
dimflag[wallwhich[m]/2] = 1;
if (dimflag[0] + dimflag[1] + dimflag[2] > 1) overlap = 1;
else overlap = 0;
// set time_depend and varflag if any wall positions are variable
varflag = 0;
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == VARIABLE) time_depend = varflag = 1;
laststep = -1;
}
/* ---------------------------------------------------------------------- */
FixWallSRD::~FixWallSRD()
{
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == VARIABLE) delete [] varstr[m];
memory->destroy(fwall);
memory->destroy(fwall_all);
}
/* ---------------------------------------------------------------------- */
int FixWallSRD::setmask()
{
int mask = 0;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixWallSRD::init()
{
int flag = 0;
for (int m = 0; m < modify->nfix; m++)
if (strcmp(modify->fix[m]->style,"srd") == 0) flag = 1;
- if (!flag) error->all("Cannot use fix wall/srd without fix srd");
+ if (!flag) error->all(FLERR,"Cannot use fix wall/srd without fix srd");
for (int m = 0; m < nwall; m++) {
if (wallstyle[m] != VARIABLE) continue;
varindex[m] = input->variable->find(varstr[m]);
if (varindex[m] < 0)
- error->all("Variable name for fix wall/srd does not exist");
+ error->all(FLERR,"Variable name for fix wall/srd does not exist");
if (!input->variable->equalstyle(varindex[m]))
- error->all("Variable for fix wall/srd is invalid style");
+ error->all(FLERR,"Variable for fix wall/srd is invalid style");
}
dt = update->dt;
}
/* ----------------------------------------------------------------------
return force component on a wall
------------------------------------------------------------------------- */
double FixWallSRD::compute_array(int i, int j)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(&fwall[0][0],&fwall_all[0][0],3*nwall,
MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return fwall_all[i][j];
}
/* ----------------------------------------------------------------------
set wall position and velocity, zero forces on walls
evaluate variable if necessary, wrap with clear/add
if flag, then being called on reneighbor, so archive wall positions
------------------------------------------------------------------------- */
void FixWallSRD::wall_params(int flag)
{
double xnew;
if (varflag) modify->clearstep_compute();
bigint ntimestep = update->ntimestep;
for (int m = 0; m < nwall; m++) {
if (wallstyle[m] == VARIABLE)
xnew = input->variable->compute_equal(varindex[m]);
else xnew = coord0[m];
if (laststep < 0) {
xwall[m] = xwalllast[m] = xnew;
vwall[m] = 0.0;
} else if (laststep < ntimestep) {
xwalllast[m] = xwall[m];
xwall[m] = xnew;
vwall[m] = (xwall[m] - xwalllast[m]) / dt;
}
fwall[m][0] = fwall[m][1] = fwall[m][2] = 0.0;
}
laststep = ntimestep;
if (varflag) modify->addstep_compute(update->ntimestep + 1);
if (flag)
for (int m = 0; m < nwall; m++)
xwallhold[m] = xwall[m];
force_flag = 0;
}
diff --git a/src/USER-ATC/fix_atc.cpp b/src/USER-ATC/fix_atc.cpp
index 976b05367..dde062dc4 100644
--- a/src/USER-ATC/fix_atc.cpp
+++ b/src/USER-ATC/fix_atc.cpp
@@ -1,542 +1,542 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Reese Jones, Jon Zimmerman, Jeremy Templeton (SNL)
------------------------------------------------------------------------- */
#include "stdio.h"
#include "string.h"
#include "fix_atc.h"
#include "ATC_TransferHardy.h"
#include "ATC_TransferThermal.h"
#include "ExtrinsicModel.h"
#include "LammpsInterface.h"
#include "fix_nve.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "pointers.h"
#include "comm.h"
#include "error.h"
using namespace LAMMPS_NS;
// main page of doxygen documentation
/*! \mainpage AtC : Atom-to-Continuum methods
fix commands:
- \ref man_fix_atc (links to all related commands)
*/
/* ------------------------------------------------------------------------- */
FixATC::FixATC(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
// ID GROUP atc PHYSICSTYPE [PARAMETERFILE]
// can have either 4 or 5 args, only arg[3] and arg[4] are used by this class
- if (narg > 5 || narg < 4) lmp->error->all("Illegal fix atc command");
+ if (narg > 5 || narg < 4) lmp->error->all(FLERR,"Illegal fix atc command");
// Set LAMMPS pointer on LammpsInterface
ATC::LammpsInterface::instance()->set_lammps(lmp);
/*! \page man_fix_atc fix atc command
\section syntax
fix AtC transfer <type> <parameter_file>
- type\n
= thermal : thermal coupling with fields: temperature \n
= two_temperature : electron-phonon coupling with field: temperature and electron_temperature \n
= hardy : Hardy on-the-fly post-processing (see "related" section for possible fields) \n
- parameter_file = name of the file with material parameters. \n
note: hardy does not require a parameter file
\section examples
<TT> fix_modify AtC transfer thermal Ar_thermal.dat </TT> \n
<TT> fix_modify AtC transfer hardy </TT>
\section description
This fix is the beginning to creating a coupled FE/MD simulation and/or
an on-the-fly estimation of continuum fields. The coupled versions of this
fix do Verlet integration and the Hardy/post-processing does not.
After instantiating this fix, several other fix_modify commands will be
needed to set up the problem, e.g. define the finite element mesh and
prescribe initial and boundary conditions.
The following coupling example is typical, but non-exhaustive:\n
<TT>
# ... commands to create and initialize the MD system \n
# initial fix to designate coupling type and group to apply it to \n
# tag group physics material_file \n
fix AtC internal atc thermal Ar_thermal.mat\n \n
# create a uniform 12 x 2 x 2 mesh that covers region contain the group \n
# nx ny nz region periodicity \n
fix_modify AtC fem create mesh 12 2 2 mdRegion f p p\n \n
# specify the control method for the type of coupling \n
# physics control_type \n
fix_modify AtC transfer thermal control flux \n \n
# specify the initial values for the empirical field "temperature" \n
# field node_group value \n
fix_modify AtC transfer initial temperature all 30.\n \n
# create an output stream for nodal fields \n
# filename output_frequency \n
fix_modify AtC transfer output atc_fe_output 100\n \n
run 1000 \n
</TT>
likewise for this post-processing example: \n
<TT>
# ... commands to create and initialize the MD system \n
# initial fix to designate post-processing and the group to apply it to \n
# no material file is allowed nor required \n
fix AtC internal atc hardy \n \n
# create a uniform 1 x 1 x 1 mesh that covers region contain the group \n
# with periodicity this effectively creats a system average \n
fix_modify AtC fem create mesh 1 1 1 box p p p \n\n
# change from default lagrangian map to eulerian \n
# refreshed every 100 steps \n
fix_modify AtC atom_element_map eulerian 100 \n \n
# start with no field defined \n
fix_modify AtC transfer fields none \n \n
# add mass density, potential energy density, stress and temperature \n
fix_modify AtC transfer fields add density energy stress temperature \n\n
# create an output stream for nodal fields \n
# filename output_frequency \n
fix_modify AtC transfer output nvtFE 100 text \n
run 1000 \n
</TT>
Note coupling and post-processing can be combined in the same simulations
using separate fixes.
\n
For detailed exposition of the theory and algorithms please see:\n
- Wagner, GJ; Jones, RE; Templeton, JA; Parks, MA. <VAR> An
atomistic-to-continuum coupling method for heat transfer in solids. </VAR>
Special Issue of Computer Methods and Applied Mechanics (2008) 197:3351.
- Zimmerman, JA; Webb, EB; Hoyt, JJ;. Jones, RE; Klein, PA; Bammann, DJ,
<VAR> Calculation of stress in atomistic simulation </VAR>
Special Issue of Modelling and Simulation in Materials Science and
Engineering (2004), 12:S319
Please refer to the standard
finite element (FE) texts, e.g. T.J.R Hughes <VAR> The finite element
method </VAR>, Dover 2003, for the basics of FE simulation.
\section restrictions
Thermal and two_temperature (coupling) types use a Verlet time-integration
algorithm.
The hardy type does not contain its own time-integrator and must be used
with a separate fix that does contain one, e.g. nve, nvt, etc.
Currently,
- the coupling is restricted to thermal physics
- the FE computations are done in serial on each processor.
\section related
fix_modify commands for setup: \n
- \ref man_fem_mesh
- \ref man_mesh_nodeset
- \ref man_mesh_faceset
- \ref man_mesh_elemset
- \ref man_transfer_internal
- \ref man_transfer_boundary
- \ref man_internal_quadrature
- \ref man_time_integration
- \ref man_electron_integration
fix_modify commands for boundary and initial conditions:\n
- \ref man_initial
- \ref man_fix_nodes
- \ref man_unfix_nodes
- \ref man_fix_flux
- \ref man_unfix_flux
- \ref man_source
- \ref man_remove_source
fix_modify commands for control and filtering: \n
- \ref man_thermal_control
- \ref man_time_filter
- \ref man_filter_scale
- \ref man_equilibrium_start
- \ref man_extrinsic_exchange
fix_modify commands for output: \n
- \ref man_transfer_output
- \ref man_transfer_atomic_output
- \ref man_mesh_output
- \ref man_write_restart
- \ref man_read_restart
fix_modify commands for post-processing: \n
- \ref man_hardy_fields
- \ref man_hardy_gradients
- \ref man_hardy_rates
- \ref man_hardy_computes
- \ref man_hardy_set
- \ref man_hardy_on_the_fly
- \ref man_boundary_integral
- \ref man_contour_integral
miscellaneous fix_modify commands: \n
- \ref man_atom_element_map
- \ref man_neighbor_reset_frequency
Note: a set of example input files with the attendant material files are
included with this package
\section default
none
*/
// Construct new ATC_Transfer object
// note use "unfix" to destroy
int me = ATC::LammpsInterface::instance()->comm_rank();
string groupName(arg[1]);
// Postprocessing
try {
if (strcmp(arg[3],"hardy")==0)
{
if (narg < 5) {
if (me==0) printf("Constructing ATC transfer (hardy)\n");
atcTransfer_ = new ATC::ATC_TransferHardy(groupName);
}
else {
if (me==0) printf("Constructing ATC transfer (hardy) with parameter file %s\n",arg[4]);
std::string matParamFile = arg[4];
atcTransfer_ = new ATC::ATC_TransferHardy(groupName,matParamFile);
}
}
// PhysicsTypes
else if (strcmp(arg[3],"thermal")==0)
{
std::string matParamFile = arg[4];
if (me==0) printf("Constructing ATC transfer (thermal) with parameter file %s\n",arg[4]);
atcTransfer_ = new ATC::ATC_TransferThermal(groupName,matParamFile);
lmp->atom->add_callback(0); // NOTE what is this?
}
else if (strcmp(arg[3],"two_temperature")==0)
{
std::string matParamFile = arg[4];
if (me==0) printf("Constructing ATC transfer (two_temperature) with parameter file %s\n",arg[4]);
atcTransfer_ = new ATC::ATC_TransferThermal(groupName,matParamFile,
ATC::TWO_TEMPERATURE);
}
else
{
- lmp->error->all("Unknown physics type in ATC");
+ lmp->error->all(FLERR,"Unknown physics type in ATC");
}
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
lmp->atom->add_callback(0);
// Tell LAMMPS we want to write_restart to be called (writes fix state)
//restart_global = 1;
restart_global = 0; // NOTE : turning off ATC restart
// Tell LAMMPS we want to pack_restart to be called (writes per-atom data)
//restart_peratom = 1;
// Set output computation data based on transfer info
scalar_flag = atcTransfer_->scalar_flag();
vector_flag = atcTransfer_->vector_flag();
size_vector = atcTransfer_->size_vector();
global_freq = atcTransfer_->global_freq();
extscalar = atcTransfer_->extscalar();
extvector = atcTransfer_->extvector();
extlist = atcTransfer_->extlist();
// set comm size needed by this fix
comm_forward = 3;
}
/*----------------------------------------------------------------------- */
FixATC::~FixATC()
{
if (lmp->atom) lmp->atom->delete_callback(id,0);
if (atcTransfer_) delete atcTransfer_;
}
/* ---------------------------------------------------------------------- */
int FixATC::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= PRE_EXCHANGE;
mask |= MIN_PRE_EXCHANGE;
return mask;
}
/* ---------------------------------------------------------------------- */
int FixATC::modify_param(int narg, char** arg)
{
bool match;
// pass on to transfer layer
try {
match = atcTransfer_->modify(narg,arg);
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
if (!match) return 0;
return narg;
}
/* ----------------------------------------------------------------------
create initial list of neighbor partners via call to neighbor->build()
must be done in setup (not init) since fix init comes before neigh init
------------------------------------------------------------------------- */
void FixATC::init()
{
// Guarantee construction of full neighborlist
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
void FixATC::setup(int vflag)
{
try {
atcTransfer_->initialize();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
groupbit = atcTransfer_->get_groupbit();
}
/* ----------------------------------------------------------------------
pass throughs to atc functions to handle swapping atom data on
when they move processors
------------------------------------------------------------------------- */
void FixATC::pre_exchange()
{
atcTransfer_->pre_exchange();
}
void FixATC::min_pre_exchange()
{
atcTransfer_->pre_exchange();
}
double FixATC::memory_usage()
{
double bytes = (double) atcTransfer_->memory_usage() * sizeof(double);
return bytes;
}
void FixATC::grow_arrays(int nmax)
{
atcTransfer_->grow_arrays(nmax);
}
void FixATC::copy_arrays(int i, int j)
{
atcTransfer_->copy_arrays(i,j);
}
int FixATC::pack_exchange(int i, double * buf)
{
int num = atcTransfer_->pack_exchange(i,buf);
return num;
}
int FixATC::unpack_exchange(int nlocal, double * buf)
{
int num = atcTransfer_->unpack_exchange(nlocal,buf);
return num;
}
int FixATC::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int num = atcTransfer_->pack_comm(n, list, buf, pbc_flag, pbc);
return num;
}
void FixATC::unpack_comm(int n, int first, double *buf)
{
atcTransfer_->unpack_comm(n, first, buf);
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixATC::pack_restart(int i, double *buf){
return 0;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixATC::unpack_restart(int nlocal, int nth){
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixATC::maxsize_restart(){
return 0;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixATC::size_restart(int nlocal){
return 0;
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixATC::write_restart(FILE *fp){
// hardcode filename for now
char ** args = new char*[2];
args[0] = new char[50];
args[1] = new char[50];
sprintf(args[0],"write_restart");
sprintf(args[1],"ATC.restart");
// Then call all objects I own to write their data
if (comm->me == 0) {
atcTransfer_->modify(2,args);
}
delete [] args[0];
delete [] args[1];
delete [] args;
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixATC::restart(char *buf){
// hardcode filename for now
char ** args = new char*[2];
args[0] = new char[50];
args[1] = new char[50];
sprintf(args[0],"read_restart");
sprintf(args[1],"ATC.restart");
// Then call all objects I own to write their data
if (comm->me == 0) {
atcTransfer_->modify(2,args);
}
delete [] args[0];
delete [] args[1];
delete [] args;
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixATC::initial_integrate(int vflag)
{
try {
atcTransfer_->pre_init_integrate();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
try {
atcTransfer_->init_integrate_velocity();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
try {
atcTransfer_->mid_init_integrate();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
try {
atcTransfer_->init_integrate_position();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
try {
atcTransfer_->post_init_integrate();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
}
/* ---------------------------------------------------------------------- */
void FixATC::final_integrate()
{
// need updated ghost atom positions
comm->forward_comm_fix(this);
try {
atcTransfer_->pre_final_integrate();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
try {
atcTransfer_->final_integrate();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
try {
atcTransfer_->post_final_integrate();
}
catch (ATC::ATC_Error& atcError) {
cout << "ATC ERROR: " << atcError.get_error_description() << " processor: " << atcError.get_id() << endl;
throw;
}
}
diff --git a/src/USER-AWPMD/atom_vec_wavepacket.cpp b/src/USER-AWPMD/atom_vec_wavepacket.cpp
index dd4a0657f..5c9e789bf 100644
--- a/src/USER-AWPMD/atom_vec_wavepacket.cpp
+++ b/src/USER-AWPMD/atom_vec_wavepacket.cpp
@@ -1,1009 +1,1009 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Ilya Valuev (JIHT, Moscow, Russia)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "atom_vec_wavepacket.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "force.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecWavepacket::AtomVecWavepacket(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
comm_x_only = comm_f_only = 0;
mass_type = 1;
molecular = 0;
size_forward = 4; // coords[3]+radius[1]
size_reverse = 10; // force[3]+erforce[1]+ervelforce[1]+vforce[3]+csforce[2]
size_border = 10; // coords[3]+tag[1]+type[1]+mask[1]+q[1]+spin[1]+eradius[1]+etag[1]
size_velocity = 6; // +velocities[3]+ ervel[1]+cs[2]
size_data_atom = 11; // for input file: 1-tag 2-type 3-q 4-spin 5-eradius 6-etag 7-cs_re 8-cs_im 9-x 10-y 11-z
size_data_vel = 5; // for input file: vx vy vz ervel <??>
xcol_data = 9; // starting column for x data
atom->wavepacket_flag = 1;
atom->electron_flag = 1; // compatible with eff
atom->q_flag = atom->spin_flag = atom->eradius_flag =
atom->ervel_flag = atom->erforce_flag = 1;
atom->cs_flag = atom->csforce_flag = atom->vforce_flag = atom->ervelforce_flag = atom->etag_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom-electron arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecWavepacket::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
q = memory->grow(atom->q,nmax,"atom:q");
spin = memory->grow(atom->spin,nmax,"atom:spin");
eradius = memory->grow(atom->eradius,nmax,"atom:eradius");
ervel = memory->grow(atom->ervel,nmax,"atom:ervel");
erforce = memory->grow(atom->erforce,nmax,"atom:erforce");
cs = memory->grow(atom->cs,2*nmax,"atom:cs");
csforce = memory->grow(atom->csforce,2*nmax,"atom:csforce");
vforce = memory->grow(atom->vforce,3*nmax,"atom:vforce");
ervelforce = memory->grow(atom->ervelforce,nmax,"atom:ervelforce");
etag = memory->grow(atom->etag,nmax,"atom:etag");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecWavepacket::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
q = atom->q;
eradius = atom->eradius; ervel = atom->ervel; erforce = atom->erforce;
cs = atom->cs;
csforce = atom->csforce;
vforce = atom->vforce;
ervelforce = atom->ervelforce;
etag = atom->etag;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecWavepacket::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
q[j] = q[i];
spin[j] = spin[i];
eradius[j] = eradius[i];
ervel[j] = ervel[i];
cs[2*j] = cs[2*i];
cs[2*j+1] = cs[2*i+1];
etag[j] = etag[i];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
// this will be used as partial pack for unsplit Hartree packets (v, ervel not regarded as separate variables)
int AtomVecWavepacket::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = eradius[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = eradius[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
// this is a complete pack of all 'position' variables of AWPMD
int AtomVecWavepacket::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = eradius[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = eradius[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = eradius[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::pack_comm_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = eradius[j];
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecWavepacket::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
eradius[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecWavepacket::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
eradius[i] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
ervel[i] = buf[m++];
cs[2*i] = buf[m++];
cs[2*i+1] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::unpack_comm_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++){
eradius[i] = buf[m++];
ervel[i] = buf[m++];
cs[2*i] = buf[m++];
cs[2*i+1] = buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) { //10
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
buf[m++] = erforce[i];
buf[m++] = ervelforce[i];
buf[m++] = vforce[3*i];
buf[m++] = vforce[3*i+1];
buf[m++] = vforce[3*i+2];
buf[m++] = csforce[2*i];
buf[m++] = csforce[2*i+1];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::pack_reverse_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++){
buf[m++] = erforce[i];
buf[m++] = ervelforce[i];
buf[m++] = vforce[3*i];
buf[m++] = vforce[3*i+1];
buf[m++] = vforce[3*i+2];
buf[m++] = csforce[2*i];
buf[m++] = csforce[2*i+1];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecWavepacket::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
erforce[j] += buf[m++];
ervelforce[j] += buf[m++];
vforce[3*j] += buf[m++];
vforce[3*j+1] += buf[m++];
vforce[3*j+2] += buf[m++];
csforce[2*j] += buf[m++];
csforce[2*j+1] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::unpack_reverse_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
erforce[j] += buf[m++];
ervelforce[j] += buf[m++];
vforce[3*j] += buf[m++];
vforce[3*j+1] += buf[m++];
vforce[3*j+2] += buf[m++];
csforce[2*j] += buf[m++];
csforce[2*j+1] += buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
// will be used for Hartree unsplit version (the etag is added however)
int AtomVecWavepacket::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = etag[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = etag[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = etag[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (domain->triclinic == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = etag[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = etag[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = etag[j];
buf[m++] = ervel[j];
buf[m++] = cs[2*j];
buf[m++] = cs[2*j+1];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecWavepacket::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
spin[i] = static_cast<int> (buf[m++]);
eradius[i] = buf[m++];
etag[i] = (int)buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecWavepacket::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
spin[i] = static_cast<int> (buf[m++]);
eradius[i] = buf[m++];
etag[i] = (int)buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
ervel[i] = buf[m++];
cs[2*i] = buf[m++];
cs[2*i+1] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
q[i] = buf[m++];
spin[i] = static_cast<int> (buf[m++]);
eradius[i] = buf[m++];
etag[i] = (int)buf[m++];
ervel[i] = buf[m++];
cs[2*i] = buf[m++];
cs[2*i+1] = buf[m++];
}
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecWavepacket::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = q[i];
buf[m++] = spin[i];
buf[m++] = eradius[i];
buf[m++] = ervel[i];
buf[m++] = etag[i];
buf[m++] = cs[2*i];
buf[m++] = cs[2*i+1];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecWavepacket::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
q[nlocal] = buf[m++];
spin[nlocal] = static_cast<int> (buf[m++]);
eradius[nlocal] = buf[m++];
ervel[nlocal] = buf[m++];
etag[nlocal] = buf[m++];
cs[2*nlocal] = buf[m++];
cs[2*nlocal+1] = buf[m++];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecWavepacket::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 18 * nlocal; // Associated with pack_restart
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecWavepacket::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = q[i];
buf[m++] = spin[i];
buf[m++] = eradius[i];
buf[m++] = ervel[i];
buf[m++] = etag[i];
buf[m++] = cs[2*i];
buf[m++] = cs[2*i+1];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecWavepacket::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
q[nlocal] = buf[m++];
spin[nlocal] = static_cast<int> (buf[m++]);
eradius[nlocal] = buf[m++];
ervel[nlocal] = buf[m++];
etag[nlocal] = buf[m++];
cs[2*nlocal] = buf[m++];
cs[2*nlocal+1] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
AWPMD: creates a proton
------------------------------------------------------------------------- */
void AtomVecWavepacket::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
q[nlocal] = 1.;
spin[nlocal] = 0.;
eradius[nlocal] = 0.0;
ervel[nlocal] = 0.0;
etag[nlocal]= 0.;
cs[2*nlocal] = 0.;
cs[2*nlocal+1] = 0.;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
AWPMD: 0-tag 1-type 2-q 3-spin 4-eradius 5-etag 6-cs_re 7-cs_im
------------------------------------------------------------------------- */
void AtomVecWavepacket::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file (ID tag must be >0)");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file (ID tag must be >0)");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
q[nlocal] = atof(values[2]);
spin[nlocal] = atoi(values[3]);
eradius[nlocal] = atof(values[4]);
if (eradius[nlocal] < 0.0)
- error->one("Invalid eradius in Atoms section of data file");
+ error->one(FLERR,"Invalid eradius in Atoms section of data file");
etag[nlocal] = atoi(values[5]);
cs[2*nlocal] = atoi(values[6]);
cs[2*nlocal+1] = atof(values[7]);
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
ervel[nlocal] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecWavepacket::data_atom_hybrid(int nlocal, char **values)
{
q[nlocal] = atof(values[0]);
spin[nlocal] = atoi(values[1]);
eradius[nlocal] = atof(values[2]);
if (eradius[nlocal] < 0.0)
- error->one("Invalid eradius in Atoms section of data file");
+ error->one(FLERR,"Invalid eradius in Atoms section of data file");
etag[nlocal] = atoi(values[3]);
cs[2*nlocal] = atoi(values[4]);
cs[2*nlocal+1] = atof(values[5]);
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
ervel[nlocal] = 0.0;
return 3;
}
/* ----------------------------------------------------------------------
unpack one line from Velocities section of data file
------------------------------------------------------------------------- */
void AtomVecWavepacket::data_vel(int m, char **values)
{
v[m][0] = atof(values[0]);
v[m][1] = atof(values[1]);
v[m][2] = atof(values[2]);
ervel[m] = atof(values[3]);
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Velocities section of data file
------------------------------------------------------------------------- */
int AtomVecWavepacket::data_vel_hybrid(int m, char **values)
{
ervel[m] = atof(values[0]);
return 1;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecWavepacket::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("q")) bytes += memory->usage(q,nmax);
if (atom->memcheck("spin")) bytes += memory->usage(spin,nmax);
if (atom->memcheck("eradius")) bytes += memory->usage(eradius,nmax);
if (atom->memcheck("ervel")) bytes += memory->usage(ervel,nmax);
if (atom->memcheck("erforce")) bytes += memory->usage(erforce,nmax);
if (atom->memcheck("ervelforce")) bytes += memory->usage(ervelforce,nmax);
if (atom->memcheck("cs")) bytes += memory->usage(cs,2*nmax);
if (atom->memcheck("csforce")) bytes += memory->usage(csforce,2*nmax);
if (atom->memcheck("vforce")) bytes += memory->usage(vforce,3*nmax);
if (atom->memcheck("etag")) bytes += memory->usage(etag,nmax);
return bytes;
}
diff --git a/src/USER-AWPMD/fix_nve_awpmd.cpp b/src/USER-AWPMD/fix_nve_awpmd.cpp
index 418b942ec..5aee8958a 100644
--- a/src/USER-AWPMD/fix_nve_awpmd.cpp
+++ b/src/USER-AWPMD/fix_nve_awpmd.cpp
@@ -1,152 +1,152 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Ilya Valuev (JIHT, Moscow, Russia)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "string.h"
#include "fix_nve_awpmd.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "math.h"
#include "TCP/wpmd_split.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVEAwpmd::FixNVEAwpmd(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (!atom->wavepacket_flag)
- error->all("Fix nve/awpmd requires atom style wavepacket");
+ error->all(FLERR,"Fix nve/awpmd requires atom style wavepacket");
//if (!atom->mass_type != 1)
- // error->all("Fix nve/awpmd requires per type mass");
+ // error->all(FLERR,"Fix nve/awpmd requires per type mass");
time_integrate = 1;
}
/* ---------------------------------------------------------------------- */
int FixNVEAwpmd::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVEAwpmd::init()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
awpmd_pair=(PairAWPMDCut *)force->pair;
awpmd_pair->wpmd->norm_needed=1;
}
/* ----------------------------------------------------------------------
allow for only per-type mass
------------------------------------------------------------------------- */
void FixNVEAwpmd::initial_integrate(int vflag)
{
// update v,vr and x,radius of atoms in group
double **x = atom->x;
double *eradius = atom->eradius;
double **v = atom->v;
double *ervel = atom->ervel;
double **f = atom->f;
double *erforce = atom->erforce;
double *vforce=atom->vforce;
double *ervelforce=atom->ervelforce;
double *cs=atom->cs;
double *csforce=atom->csforce;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// x + dt * [v + 0.5 * dt * (f / m)];
// simple Euler update
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
double dtfm = dtf / mass[type[i]];
double dtfmr=dtfm;
for(int j=0;j<3;j++){
x[i][j] += dtv*vforce[3*i+j];
v[i][j] += dtfm*f[i][j];
}
eradius[i]+= dtv*ervelforce[i];
ervel[i] += dtfmr*erforce[i];
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVEAwpmd::final_integrate(){}
/* ---------------------------------------------------------------------- */
void FixNVEAwpmd::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
// innermost level - NVE update of v and x
// all other levels - NVE update of v
if (ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVEAwpmd::final_integrate_respa(int ilevel, int iloop)
{
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVEAwpmd::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}
diff --git a/src/USER-AWPMD/pair_awpmd_cut.cpp b/src/USER-AWPMD/pair_awpmd_cut.cpp
index ae276334b..4644f1a2c 100644
--- a/src/USER-AWPMD/pair_awpmd_cut.cpp
+++ b/src/USER-AWPMD/pair_awpmd_cut.cpp
@@ -1,756 +1,753 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Ilya Valuev (JIHT, Moscow, Russia)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_awpmd_cut.h"
#include "atom.h"
#include "update.h"
#include "min.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
#include "TCP/wpmd_split.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairAWPMDCut::PairAWPMDCut(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
nmax = 0;
min_var = NULL;
min_varforce = NULL;
nextra = 4;
pvector = new double[nextra];
ermscale=1.;
width_pbc=0.;
wpmd= new AWPMD_split();
half_box_length=0;
}
/* ---------------------------------------------------------------------- */
PairAWPMDCut::~PairAWPMDCut()
{
delete [] pvector;
memory->destroy(min_var);
memory->destroy(min_varforce);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
}
delete wpmd;
}
struct cmp_x{
double tol;
double **xx;
cmp_x(double **xx_=NULL, double tol_=1e-12):xx(xx_),tol(tol_){}
bool operator()(const pair<int,int> &left, const pair<int,int> &right) const {
if(left.first==right.first){
double d=xx[left.second][0]-xx[right.second][0];
if(d<-tol)
return true;
else if(d>tol)
return false;
d=xx[left.second][1]-xx[right.second][1];
if(d<-tol)
return true;
else if(d>tol)
return false;
d=xx[left.second][2]-xx[right.second][2];
if(d<-tol)
return true;
else
return false;
}
else
return left.first<right.first;
}
};
/* ---------------------------------------------------------------------- */
void PairAWPMDCut::compute(int eflag, int vflag)
{
// pvector = [KE, Pauli, ecoul, radial_restraint]
for (int i=0; i<4; i++) pvector[i] = 0.0;
if (eflag || vflag)
ev_setup(eflag,vflag);
else
evflag = vflag_fdotr = 0; //??
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
double *erforce = atom->erforce;
double *eradius = atom->eradius;
int *spin = atom->spin;
int *type = atom->type;
int *etag = atom->etag;
double **v = atom->v;
int nlocal = atom->nlocal;
int nghost = atom->nghost;
int ntot=nlocal+nghost;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
int inum = list->inum;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
// width pbc
if(width_pbc<0)
wpmd->Lextra=2*half_box_length;
else
wpmd->Lextra=width_pbc;
wpmd->newton_pair=newton_pair;
# if 1
// mapping of the LAMMPS numbers to the AWPMC numbers
vector<int> gmap(ntot,-1);
for (int ii = 0; ii < inum; ii++) {
int i = ilist[ii];
// local particles are all there
gmap[i]=0;
Vector_3 ri=Vector_3(x[i][0],x[i][1],x[i][2]);
int itype = type[i];
int *jlist = firstneigh[i];
int jnum = numneigh[i];
for (int jj = 0; jj < jnum; jj++) {
int j = jlist[jj];
j &= NEIGHMASK;
if(j>=nlocal){ // this is a ghost
Vector_3 rj=Vector_3(x[j][0],x[j][1],x[j][2]);
int jtype = type[j];
double rsq=(ri-rj).norm2();
if (rsq < cutsq[itype][jtype])
gmap[j]=0; //bingo, this ghost is really needed
}
}
}
# else // old mapping
// mapping of the LAMMPS numbers to the AWPMC numbers
vector<int> gmap(ntot,-1);
// map for filtering the clones out: [tag,image] -> id
typedef map< pair<int,int>, int, cmp_x > map_t;
cmp_x cmp(x);
map_t idmap(cmp);
for (int ii = 0; ii < inum; ii++) {
int i = ilist[ii];
// local particles are all there
idmap[make_pair(atom->tag[i],i)]=i;
bool i_local= i<nlocal ? true : false;
if(i_local)
gmap[i]=0;
else if(gmap[i]==0) // this is a ghost which already has been tested
continue;
Vector_3 ri=Vector_3(x[i][0],x[i][1],x[i][2]);
int itype = type[i];
int *jlist = firstneigh[i];
int jnum = numneigh[i];
for (int jj = 0; jj < jnum; jj++) {
int j = jlist[jj];
j &= NEIGHMASK;
pair<map_t::iterator,bool> res=idmap.insert(make_pair(make_pair(atom->tag[j],j),j));
bool have_it=!res.second;
if(have_it){ // the clone of this particle is already listed
if(res.first->second!=j) // check that was not the very same particle
gmap[j]=-1; // filter out
continue;
}
bool j_local= j<nlocal ? true : false;
if((i_local && !j_local) || (j_local && !i_local)){ // some of them is a ghost
Vector_3 rj=Vector_3(x[j][0],x[j][1],x[j][2]);
int jtype = type[j];
double rsq=(ri-rj).norm2();
if (rsq < cutsq[itype][jtype]){
if(!i_local){
gmap[i]=0; //bingo, this ghost is really needed
break; // don't need to continue j loop
}
else
gmap[j]=0; //bingo, this ghost is really needed
}
}
}
}
# endif
// prepare the solver object
wpmd->reset();
map<int,vector<int> > etmap;
// add particles to the AWPMD solver object
for (int i = 0; i < ntot; i++) {
//int i = ilist[ii];
if(gmap[i]<0) // this particle was filtered out
continue;
if(spin[i]==0) // this is an ion
gmap[i]=wpmd->add_ion(q[i], Vector_3(x[i][0],x[i][1],x[i][2]),i<nlocal ? atom->tag[i] : -atom->tag[i]);
else if(spin[i]==1 || spin[i]==-1){ // electron, sort them according to the tag
etmap[etag[i]].push_back(i);
}
else
- error->all(fmt("Invalid spin value (%d) for particle %d !",spin[i],i));
+ error->all(FLERR,fmt("Invalid spin value (%d) for particle %d !",spin[i],i));
}
// ion force vector
Vector_3 *fi=NULL;
if(wpmd->ni)
fi= new Vector_3[wpmd->ni];
// adding electrons
for(map<int,vector<int> >::iterator it=etmap.begin(); it!= etmap.end(); ++it){
vector<int> &el=it->second;
if(!el.size()) // should not happen
continue;
int s=spin[el[0]] >0 ? 0 : 1;
wpmd->add_electron(s); // starts adding the spits
for(size_t k=0;k<el.size();k++){
int i=el[k];
if(spin[el[0]]!=spin[i])
- error->all(fmt("WP splits for one electron should have the same spin (at particles %d, %d)!",el[0],i));
+ error->all(FLERR,fmt("WP splits for one electron should have the same spin (at particles %d, %d)!",el[0],i));
double m= atom->mass ? atom->mass[type[i]] : force->e_mass;
Vector_3 xx=Vector_3(x[i][0],x[i][1],x[i][2]);
Vector_3 rv=m*Vector_3(v[i][0],v[i][1],v[i][2]);
double pv=ermscale*m*atom->ervel[i];
Vector_2 cc=Vector_2(atom->cs[2*i],atom->cs[2*i+1]);
gmap[i]=wpmd->add_split(xx,rv,atom->eradius[i],pv,cc,1.,atom->q[i],i<nlocal ? atom->tag[i] : -atom->tag[i]);
// resetting for the case constraints were applied
v[i][0]=rv[0]/m;
v[i][1]=rv[1]/m;
v[i][2]=rv[2]/m;
atom->ervel[i]=pv/(m*ermscale);
}
}
wpmd->set_pbc(NULL); // not required for LAMMPS
wpmd->interaction(0x1|0x4|0x10,fi);
// get forces from the AWPMD solver object
for (int ii = 0; ii < inum; ii++) {
int i = ilist[ii];
if(gmap[i]<0) // this particle was filtered out
continue;
if(spin[i]==0){ // this is an ion, copying forces
int ion=gmap[i];
f[i][0]=fi[ion][0];
f[i][0]=fi[ion][1];
f[i][0]=fi[ion][2];
}
else { // electron
int iel=gmap[i];
int s=spin[i] >0 ? 0 : 1;
wpmd->get_wp_force(s,iel,(Vector_3 *)f[i],(Vector_3 *)(atom->vforce+3*i),atom->erforce+i,atom->ervelforce+i,(Vector_2 *)(atom->csforce+2*i));
}
}
if(fi)
delete [] fi;
// update LAMMPS energy
if (eflag_either) {
if (eflag_global){
eng_coul+= wpmd->get_energy();
// pvector = [KE, Pauli, ecoul, radial_restraint]
pvector[0] = wpmd->Ee[0]+wpmd->Ee[1];
pvector[2] = wpmd->Eii+wpmd->Eei[0]+wpmd->Eei[1]+wpmd->Eee;
pvector[1] = pvector[0] + pvector[2] - wpmd->Edk - wpmd->Edc - wpmd->Eii; // All except diagonal terms
pvector[3] = wpmd->Ew;
}
if (eflag_atom) {
// transfer per-atom energies here
for (int i = 0; i < ntot; i++) {
if(gmap[i]<0) // this particle was filtered out
continue;
if(spin[i]==0){
eatom[i]=wpmd->Eiep[gmap[i]]+wpmd->Eiip[gmap[i]];
}
else {
int s=spin[i] >0 ? 0 : 1;
eatom[i]=wpmd->Eep[s][gmap[i]]+wpmd->Eeip[s][gmap[i]]+wpmd->Eeep[s][gmap[i]]+wpmd->Ewp[s][gmap[i]];
}
}
}
}
if (vflag_fdotr) {
virial_fdotr_compute();
if (flexible_pressure_flag)
virial_eradius_compute();
}
}
/* ----------------------------------------------------------------------
electron width-specific contribution to global virial
------------------------------------------------------------------------- */
void PairAWPMDCut::virial_eradius_compute()
{
double *eradius = atom->eradius;
double *erforce = atom->erforce;
double e_virial;
int *spin = atom->spin;
// sum over force on all particles including ghosts
if (neighbor->includegroup == 0) {
int nall = atom->nlocal + atom->nghost;
for (int i = 0; i < nall; i++) {
if (spin[i]) {
e_virial = erforce[i]*eradius[i]/3;
virial[0] += e_virial;
virial[1] += e_virial;
virial[2] += e_virial;
}
}
// neighbor includegroup flag is set
// sum over force on initial nfirst particles and ghosts
} else {
int nall = atom->nfirst;
for (int i = 0; i < nall; i++) {
if (spin[i]) {
e_virial = erforce[i]*eradius[i]/3;
virial[0] += e_virial;
virial[1] += e_virial;
virial[2] += e_virial;
}
}
nall = atom->nlocal + atom->nghost;
for (int i = atom->nlocal; i < nall; i++) {
if (spin[i]) {
e_virial = erforce[i]*eradius[i]/3;
virial[0] += e_virial;
virial[1] += e_virial;
virial[2] += e_virial;
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairAWPMDCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
}
/* ---------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
// the format is: pair_style awpmd/cut [<global_cutoff|-1> [command1] [command2] ...]
// commands:
// [hartree|dproduct|uhf] -- quantum approximation level (default is hartree)
// [free|pbc <length|-1>|fix <w0|-1>|relax|harm <w0>] -- width restriction (default is free)
// [ermscale <number>] -- scaling factor between electron mass and effective width mass (used for equations of motion only) (default is 1)
// [flex_press] -- set flexible pressure flag
// -1 for length means default setting (L/2 for cutoff and L for width PBC)
void PairAWPMDCut::settings(int narg, char **arg){
- if (narg < 1) error->all("Illegal pair_style command");
+ if (narg < 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
ermscale=1.;
width_pbc=0.;
for(int i=1;i<narg;i++){
// reading commands
if(!strcmp(arg[i],"hartree"))
wpmd->approx=AWPMD::HARTREE;
else if(!strcmp(arg[i],"dproduct"))
wpmd->approx=AWPMD::DPRODUCT;
else if(!strcmp(arg[i],"uhf"))
wpmd->approx=AWPMD::UHF;
else if(!strcmp(arg[i],"free"))
wpmd->constraint=AWPMD::NONE;
else if(!strcmp(arg[i],"fix")){
wpmd->constraint=AWPMD::FIX;
i++;
if(i>=narg)
- error->all("Setting 'fix' should be followed by a number in awpmd/cut");
+ error->all(FLERR,"Setting 'fix' should be followed by a number in awpmd/cut");
wpmd->w0=force->numeric(arg[i]);
}
else if(!strcmp(arg[i],"harm")){
wpmd->constraint=AWPMD::HARM;
i++;
if(i>=narg)
- error->all("Setting 'harm' should be followed by a number in awpmd/cut");
+ error->all(FLERR,"Setting 'harm' should be followed by a number in awpmd/cut");
wpmd->w0=force->numeric(arg[i]);
wpmd->set_harm_constr(wpmd->w0);
}
else if(!strcmp(arg[i],"pbc")){
i++;
if(i>=narg)
- error->all("Setting 'pbc' should be followed by a number in awpmd/cut");
+ error->all(FLERR,"Setting 'pbc' should be followed by a number in awpmd/cut");
width_pbc=force->numeric(arg[i]);
}
else if(!strcmp(arg[i],"relax"))
wpmd->constraint=AWPMD::RELAX;
else if(!strcmp(arg[i],"ermscale")){
i++;
if(i>=narg)
- error->all("Setting 'ermscale' should be followed by a number in awpmd/cut");
+ error->all(FLERR,"Setting 'ermscale' should be followed by a number in awpmd/cut");
ermscale=force->numeric(arg[i]);
}
else if(!strcmp(arg[i],"flex_press"))
flexible_pressure_flag = 1;
}
// reset cutoffs that have been explicitly set
/*
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}*/
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
// pair settings are as usual
void PairAWPMDCut::coeff(int narg, char **arg)
{
- if (narg < 2 || narg > 3) error->all("Incorrect args for pair coefficients");
+ if (narg < 2 || narg > 3) error->all(FLERR,"Incorrect args for pair coefficients");
/*if(domain->xperiodic == 1 || domain->yperiodic == 1 ||
domain->zperiodic == 1) {*/
double delx = domain->boxhi[0]-domain->boxlo[0];
double dely = domain->boxhi[1]-domain->boxlo[1];
double delz = domain->boxhi[2]-domain->boxlo[2];
half_box_length = 0.5 * MIN(delx, MIN(dely, delz));
//}
if(cut_global<0)
cut_global=half_box_length;
if (!allocated)
allocate();
else{
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double cut_one = cut_global;
if (narg == 3) cut_one = atof(arg[2]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairAWPMDCut::init_style()
{
// error and warning checks
if (!atom->q_flag || !atom->spin_flag ||
!atom->eradius_flag || !atom->erforce_flag ) // TO DO: adjust this to match approximation used
- error->all("Pair awpmd/cut requires atom attributes "
+ error->all(FLERR,"Pair awpmd/cut requires atom attributes "
"q, spin, eradius, erforce");
/*
if(vflag_atom){ // can't compute virial per atom
//warning->
- error->all("Pair style awpmd can't compute per atom virials");
+ error->all(FLERR,"Pair style awpmd can't compute per atom virials");
}*/
// add hook to minimizer for eradius and erforce
if (update->whichflag == 2)
int ignore = update->minimize->request(this,1,0.01);
// make sure to use the appropriate timestep when using real units
/*if (update->whichflag == 1) {
if (force->qqr2e == 332.06371 && update->dt == 1.0)
- error->all("You must lower the default real units timestep for pEFF ");
+ error->all(FLERR,"You must lower the default real units timestep for pEFF ");
}*/
// need a half neigh list and optionally a granular history neigh list
//int irequest = neighbor->request(this);
//if (atom->tag_enable == 0)
- // error->all("Pair style reax requires atom IDs");
+ // error->all(FLERR,"Pair style reax requires atom IDs");
//if (force->newton_pair == 0)
- //error->all("Pair style awpmd requires newton pair on");
+ //error->all(FLERR,"Pair style awpmd requires newton pair on");
//if (strcmp(update->unit_style,"real") != 0 && comm->me == 0)
- //error->warning("Not using real units with pair reax");
+ //error->warning(FLERR,"Not using real units with pair reax");
int irequest = neighbor->request(this);
neighbor->requests[irequest]->newton = 2;
if(force->e_mass==0. || force->hhmrr2e==0. || force->mvh2r==0.)
- error->all("Pair style awpmd requires e_mass and conversions hhmrr2e, mvh2r to be properly set for unit system");
+ error->all(FLERR,"Pair style awpmd requires e_mass and conversions hhmrr2e, mvh2r to be properly set for unit system");
wpmd->me=force->e_mass;
wpmd->h2_me=force->hhmrr2e/force->e_mass;
wpmd->one_h=force->mvh2r;
wpmd->coul_pref=force->qqrd2e;
wpmd->calc_ii=1;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairAWPMDCut::init_one(int i, int j)
{
if (setflag[i][j] == 0)
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairAWPMDCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairAWPMDCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) fread(&cut[i][j],sizeof(double),1,fp);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairAWPMDCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairAWPMDCut::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
returns pointers to the log() of electron radius and corresponding force
minimizer operates on log(radius) so radius never goes negative
these arrays are stored locally by pair style
------------------------------------------------------------------------- */
void PairAWPMDCut::min_xf_pointers(int ignore, double **xextra, double **fextra)
{
// grow arrays if necessary
// need to be atom->nmax in length
int nvar=atom->nmax*(3+1+1+2); // w(1), vel(3), pw(1), cs(2)
if (nvar > nmax) {
memory->destroy(min_var);
memory->destroy(min_varforce);
nmax = nvar;
memory->create(min_var,nmax,"pair:min_var");
memory->create(min_varforce,nmax,"pair:min_varforce");
}
*xextra = min_var;
*fextra = min_varforce;
}
/* ----------------------------------------------------------------------
minimizer requests the log() of electron radius and corresponding force
calculate and store in min_eradius and min_erforce
------------------------------------------------------------------------- */
void PairAWPMDCut::min_xf_get(int ignore)
{
double *eradius = atom->eradius;
double *erforce = atom->erforce;
double **v=atom->v;
double *vforce=atom->vforce;
double *ervel=atom->ervel;
double *ervelforce=atom->ervelforce;
double *cs=atom->cs;
double *csforce=atom->csforce;
int *spin = atom->spin;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (spin[i]) {
min_var[7*i] = log(eradius[i]);
min_varforce[7*i] = eradius[i]*erforce[i];
for(int j=0;j<3;j++){
min_var[7*i+1+3*j] = v[i][j];
min_varforce[7*i+1+3*j] = vforce[3*i+j];
}
min_var[7*i+4] = ervel[i];
min_varforce[7*i+4] = ervelforce[i];
min_var[7*i+5] = cs[2*i];
min_varforce[7*i+5] = csforce[2*i];
min_var[7*i+6] = cs[2*i+1];
min_varforce[7*i+6] = csforce[2*i+1];
} else {
for(int j=0;j<7;j++)
min_var[7*i+j] = min_varforce[7*i+j] = 0.0;
}
}
/* ----------------------------------------------------------------------
propagate the minimizer values to the atom values
------------------------------------------------------------------------- */
void PairAWPMDCut::min_x_set(int ignore)
{
double *eradius = atom->eradius;
double **v=atom->v;
double *ervel=atom->ervel;
double *cs=atom->cs;
int *spin = atom->spin;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (spin[i]){
eradius[i]=exp(min_var[7*i]);
for(int j=0;j<3;j++)
v[i][j]=min_var[7*i+1+3*j];
ervel[i]=min_var[7*i+4];
cs[2*i]=min_var[7*i+5];
cs[2*i+1]=min_var[7*i+6];
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairAWPMDCut::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
bytes += 2 * nmax * sizeof(double);
return bytes;
}
diff --git a/src/USER-CG-CMM/angle_cg_cmm.cpp b/src/USER-CG-CMM/angle_cg_cmm.cpp
index a818b061f..7d9800808 100644
--- a/src/USER-CG-CMM/angle_cg_cmm.cpp
+++ b/src/USER-CG-CMM/angle_cg_cmm.cpp
@@ -1,434 +1,434 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Special Angle Potential for the CMM coarse grained MD potentials.
Contributing author: Axel Kohlmeyer <akohlmey@gmail.com>
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_cg_cmm.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleCGCMM::AngleCGCMM(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleCGCMM::~AngleCGCMM()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(theta0);
memory->destroy(cg_type);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(rcut);
}
}
/* ---------------------------------------------------------------------- */
void AngleCGCMM::ev_tally_lj13(int i, int j, int nlocal, int newton_bond,
double evdwl, double fpair,
double delx, double dely, double delz)
{
double v[6];
if (eflag_either) {
if (eflag_global) {
if (newton_bond) {
energy += evdwl;
} else {
if (i < nlocal)
energy += 0.5*evdwl;
if (j < nlocal)
energy += 0.5*evdwl;
}
}
if (eflag_atom) {
if (newton_bond || i < nlocal) eatom[i] += 0.5*evdwl;
if (newton_bond || j < nlocal) eatom[i] += 0.5*evdwl;
}
}
if (vflag_either) {
v[0] = delx*delx*fpair;
v[1] = dely*dely*fpair;
v[2] = delz*delz*fpair;
v[3] = delx*dely*fpair;
v[4] = delx*delz*fpair;
v[5] = dely*delz*fpair;
if (vflag_global) {
if (newton_bond) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
if (j < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
}
}
if (vflag_atom) {
if (newton_bond || i < nlocal) {
vatom[i][0] += 0.5*v[0];
vatom[i][1] += 0.5*v[1];
vatom[i][2] += 0.5*v[2];
vatom[i][3] += 0.5*v[3];
vatom[i][4] += 0.5*v[4];
vatom[i][5] += 0.5*v[5];
}
if (newton_bond || j < nlocal) {
vatom[j][0] += 0.5*v[0];
vatom[j][1] += 0.5*v[1];
vatom[j][2] += 0.5*v[2];
vatom[j][3] += 0.5*v[3];
vatom[j][4] += 0.5*v[4];
vatom[j][5] += 0.5*v[5];
}
}
}
}
/* ---------------------------------------------------------------------- */
void AngleCGCMM::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2,delx3,dely3,delz3;
double eangle,f1[3],f3[3],e13,f13;
double dtheta,tk;
double rsq1,rsq2,rsq3,r1,r2,r3,c,s,a,a11,a12,a22;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// angle (cos and sin)
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
s = 1.0/s;
// 1-3 LJ interaction.
// we only want to use the repulsive part,
// so this has to be done here and not in the
// general non-bonded code.
delx3 = x[i1][0] - x[i3][0];
dely3 = x[i1][1] - x[i3][1];
delz3 = x[i1][2] - x[i3][2];
domain->minimum_image(delx3,dely3,delz3);
rsq3 = delx3*delx3 + dely3*dely3 + delz3*delz3;
r3 = sqrt(rsq3);
f13=0.0;
e13=0.0;
if (r3 < rcut[type]) {
const int cgt = cg_type[type];
const double cgpow1 = cg_pow1[cgt];
const double cgpow2 = cg_pow2[cgt];
const double cgpref = cg_prefact[cgt];
const double ratio = sigma[type]/r3;
const double eps = epsilon[type];
f13 = cgpref*eps / rsq3 * (cgpow1*pow(ratio,cgpow1)
- cgpow2*pow(ratio,cgpow2));
if (eflag) e13 = eps + cgpref*eps * (pow(ratio,cgpow1)
- pow(ratio,cgpow2));
}
// force & energy
dtheta = acos(c) - theta0[type];
tk = k[type] * dtheta;
if (eflag) eangle = tk*dtheta;
a = -2.0 * tk * s;
a11 = a*c / rsq1;
a12 = -a / (r1*r2);
a22 = a*c / rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0] + f13*delx3;
f[i1][1] += f1[1] + f13*dely3;
f[i1][2] += f1[2] + f13*delz3;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0] - f13*delx3;
f[i3][1] += f3[1] - f13*dely3;
f[i3][2] += f3[2] - f13*delz3;
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
if (evflag) ev_tally_lj13(i1,i3,nlocal,newton_bond,
e13,f13,delx3,dely3,delz3);
}
}
/* ---------------------------------------------------------------------- */
void AngleCGCMM::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(k,n+1,"angle:k");
memory->create(theta0,n+1,"angle:theta0");
memory->create(epsilon,n+1,"angle:epsilon");
memory->create(sigma,n+1,"angle:sigma");
memory->create(rcut,n+1,"angle:rcut");
memory->create(cg_type,n+1,"angle:cg_type");
memory->create(setflag,n+1,"angle:setflag");
for (int i = 1; i <= n; i++) {
cg_type[i] = CG_NOT_SET;
setflag[i] = 0;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void AngleCGCMM::coeff(int narg, char **arg)
{
- if (narg != 6) error->all("Incorrect args for angle coefficients");
+ if (narg != 6) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double k_one = atof(arg[1]);
double theta0_one = atof(arg[2]);
int cg_type_one=find_cg_type(arg[3]);
- if (cg_type_one == CG_NOT_SET) error->all("Error reading CG type flag.");
+ if (cg_type_one == CG_NOT_SET) error->all(FLERR,"Error reading CG type flag.");
double epsilon_one = atof(arg[4]);
double sigma_one = atof(arg[5]);
// find minimum of LJ potential. we only want to include
// the repulsive part of the 1-3 LJ.
double rcut_one = sigma_one*exp(
1.0/(cg_pow1[cg_type_one]-cg_pow2[cg_type_one])
*log(cg_pow1[cg_type_one]/cg_pow2[cg_type_one])
);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = k_one;
// convert theta0 from degrees to radians
theta0[i] = theta0_one/180.0 * PI;
epsilon[i] = epsilon_one;
sigma[i] = sigma_one;
rcut[i] = rcut_one;
cg_type[i] = cg_type_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleCGCMM::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleCGCMM::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
fwrite(&epsilon[1],sizeof(double),atom->nangletypes,fp);
fwrite(&sigma[1],sizeof(double),atom->nangletypes,fp);
fwrite(&rcut[1],sizeof(double),atom->nangletypes,fp);
fwrite(&cg_type[1],sizeof(int),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleCGCMM::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nangletypes,fp);
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
fread(&epsilon[1],sizeof(double),atom->nangletypes,fp);
fread(&sigma[1],sizeof(double),atom->nangletypes,fp);
fread(&rcut[1],sizeof(double),atom->nangletypes,fp);
fread(&cg_type[1],sizeof(int),atom->nangletypes,fp);
}
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&epsilon[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&rcut[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&cg_type[1],atom->nangletypes,MPI_INT,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleCGCMM::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// 1-3 LJ interaction.
double delx3 = x[i1][0] - x[i3][0];
double dely3 = x[i1][1] - x[i3][1];
double delz3 = x[i1][2] - x[i3][2];
domain->minimum_image(delx3,dely3,delz3);
const double r3 = sqrt(delx3*delx3 + dely3*dely3 + delz3*delz3);
double e13=0.0;
if (r3 < rcut[type]) {
const int cgt = cg_type[type];
const double cgpow1 = cg_pow1[cgt];
const double cgpow2 = cg_pow2[cgt];
const double cgpref = cg_prefact[cgt];
const double ratio = sigma[type]/r3;
const double eps = epsilon[type];
e13 = eps + cgpref*eps * (pow(ratio,cgpow1)
- pow(ratio,cgpow2));
}
double dtheta = acos(c) - theta0[type];
double tk = k[type] * dtheta;
return tk*dtheta + e13;
}
diff --git a/src/USER-CG-CMM/pair_cg_cmm_coul_cut.cpp b/src/USER-CG-CMM/pair_cg_cmm_coul_cut.cpp
index 7b270b351..10cee8919 100644
--- a/src/USER-CG-CMM/pair_cg_cmm_coul_cut.cpp
+++ b/src/USER-CG-CMM/pair_cg_cmm_coul_cut.cpp
@@ -1,246 +1,241 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
CMM coarse grained MD potentials. Coulomb with cutoff version.
Contributing author: Axel Kohlmeyer <akohlmey@gmail.com>
------------------------------------------------------------------------- */
+#include "string.h"
#include "pair_cg_cmm_coul_cut.h"
#include "memory.h"
#include "atom.h"
-#include "string.h"
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
using namespace LAMMPS_NS;
-
-/* ---------------------------------------------------------------------- */
PairCGCMMCoulCut::PairCGCMMCoulCut(LAMMPS *lmp) : PairCMMCommon(lmp)
{
respa_enable = 0;
single_enable = 0;
}
/* ---------------------------------------------------------------------- */
PairCGCMMCoulCut::~PairCGCMMCoulCut()
{
if (allocated_coul) {
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
allocated_coul=0;
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::allocate()
{
PairCMMCommon::allocate();
allocated_coul = 1;
int n = atom->ntypes;
memory->create(cut_lj,n+1,n+1,"paircg:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"paircg:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"paircg:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"paircg:cut_coulsq");
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::init_style()
{
if (!atom->q_flag)
- error->all("Pair style cg/cut/coul/cut requires atom attribute q");
+ error->all(FLERR,"Pair style cg/cut/coul/cut requires atom attribute q");
PairCMMCommon::init_style();
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulCut::init_one(int i, int j)
{
double mycut = PairCMMCommon::init_one(i,j);
// check interior rRESPA cutoff
if (cut_respa && MIN(cut_lj[i][j],cut_coul[i][j]) < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
return mycut;
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- *
* the real compute work is done in the PairCMMCommon::eval_XXX<>() templates
* in the common PairCG class. Through using templates we can have one
* implementation for all CG varieties _and_ gain speed through having
* the compiler optimize away conditionals within the innerloops that
* can be predetermined outside the loop through instantiation of the
* different combination of template flags.
* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::compute(int eflag, int vflag)
{
if (eflag || vflag) {
ev_setup(eflag,vflag);
} else {
evflag = vflag_fdotr = 0;
}
if (evflag) {
if (eflag) {
if (force->newton_pair) {
return eval_verlet<1,1,1,CG_COUL_CUT>();
} else {
return eval_verlet<1,1,0,CG_COUL_CUT>();
}
} else {
if (force->newton_pair) {
return eval_verlet<1,0,1,CG_COUL_CUT>();
} else {
return eval_verlet<1,0,0,CG_COUL_CUT>();
}
}
} else {
if (force->newton_pair) {
return eval_verlet<0,0,1,CG_COUL_CUT>();
} else {
return eval_verlet<0,0,0,CG_COUL_CUT>();
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::compute_inner()
{
if (force->newton_pair) {
return eval_inner<1,CG_COUL_CUT>();
} else {
return eval_inner<0,CG_COUL_CUT>();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::compute_middle()
{
if (force->newton_pair) {
return eval_middle<1,CG_COUL_CUT>();
} else {
return eval_middle<0,CG_COUL_CUT>();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::compute_outer(int eflag, int vflag)
{
if (eflag || vflag) {
ev_setup(eflag,vflag);
} else {
evflag = 0;
}
if (evflag) {
if (eflag) {
if (vflag) {
if (force->newton_pair) {
return eval_outer<1,1,1,1,CG_COUL_CUT>();
} else {
return eval_outer<1,1,1,0,CG_COUL_CUT>();
}
} else {
if (force->newton_pair) {
return eval_outer<1,1,0,1,CG_COUL_CUT>();
} else {
return eval_outer<1,1,0,0,CG_COUL_CUT>();
}
}
} else {
if (vflag) {
if (force->newton_pair) {
return eval_outer<1,0,1,1,CG_COUL_CUT>();
} else {
return eval_outer<1,0,1,0,CG_COUL_CUT>();
}
} else {
if (force->newton_pair) {
return eval_outer<1,0,0,1,CG_COUL_CUT>();
} else {
return eval_outer<1,0,0,0,CG_COUL_CUT>();
}
}
}
} else {
if (force->newton_pair) {
return eval_outer<0,0,0,1,CG_COUL_CUT>();
} else {
return eval_outer<0,0,0,0,CG_COUL_CUT>();
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
PairCMMCommon::write_restart(fp);
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
PairCMMCommon::read_restart(fp);
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulCut::memory_usage()
{
double bytes=PairCMMCommon::memory_usage();
int n = atom->ntypes;
// cut_coul/cut_coulsq/cut_lj/cut_ljsq;
bytes += (n+1)*(n+1)*sizeof(double)*4;
return bytes;
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulCut::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj, double &fforce)
{
return eval_single(CG_COUL_CUT,i,j,itype,jtype,rsq,factor_coul,factor_lj,fforce);
}
diff --git a/src/USER-CG-CMM/pair_cg_cmm_coul_long.cpp b/src/USER-CG-CMM/pair_cg_cmm_coul_long.cpp
index 2947b3ce6..fa7769927 100644
--- a/src/USER-CG-CMM/pair_cg_cmm_coul_long.cpp
+++ b/src/USER-CG-CMM/pair_cg_cmm_coul_long.cpp
@@ -1,454 +1,452 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
CMM coarse grained MD potentials. Coulomb with k-space version.
Contributing author: Axel Kohlmeyer <akohlmey@gmail.com>
------------------------------------------------------------------------- */
+#include "string.h"
#include "pair_cg_cmm_coul_long.h"
#include "memory.h"
#include "atom.h"
#include "force.h"
#include "kspace.h"
-#include "string.h"
+using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define EWALD_F 1.12837917
-using namespace LAMMPS_NS;
-
/* ---------------------------------------------------------------------- */
PairCGCMMCoulLong::PairCGCMMCoulLong(LAMMPS *lmp) : PairCMMCommon(lmp)
{
respa_enable = 0;
single_enable = 0;
}
/* ---------------------------------------------------------------------- */
PairCGCMMCoulLong::~PairCGCMMCoulLong()
{
if (allocated_coul) {
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
allocated_coul=0;
}
if (ftable) free_tables();
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::allocate()
{
PairCMMCommon::allocate();
allocated_coul = 1;
int n = atom->ntypes;
memory->create(cut_lj,n+1,n+1,"paircg:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"paircg:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"paircg:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"paircg:cut_coulsq");
}
/* ----------------------------------------------------------------------
free memory for tables used in pair computations
------------------------------------------------------------------------- */
void PairCGCMMCoulLong::free_tables()
{
memory->destroy(rtable);
memory->destroy(drtable);
memory->destroy(ftable);
memory->destroy(dftable);
memory->destroy(ctable);
memory->destroy(dctable);
memory->destroy(etable);
memory->destroy(detable);
memory->destroy(vtable);
memory->destroy(dvtable);
memory->destroy(ptable);
memory->destroy(dptable);
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::init_style()
{
if (!atom->q_flag)
- error->all("Pair style cg/cut/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style cg/cut/coul/long requires atom attribute q");
PairCMMCommon::init_style();
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
// ensure use of KSpace long-range solver, set g_ewald
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulLong::init_one(int i, int j)
{
double mycut = PairCMMCommon::init_one(i,j);
// check interior rRESPA cutoff
if (cut_respa && MIN(cut_lj[i][j],cut_coul_global) < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
return mycut;
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::init_tables()
{
int masklo,maskhi;
double r,grij,expm2,derfc,rsw;
double qqrd2e = force->qqrd2e;
tabinnersq = tabinner*tabinner;
init_bitmap(tabinner,cut_coul_global,ncoultablebits,
masklo,maskhi,ncoulmask,ncoulshiftbits);
int ntable = 1;
for (int i = 0; i < ncoultablebits; i++) ntable *= 2;
// linear lookup tables of length N = 2^ncoultablebits
// stored value = value at lower edge of bin
// d values = delta from lower edge to upper edge of bin
if (ftable) free_tables();
memory->create(rtable,ntable,"pair:rtable");
memory->create(ftable,ntable,"pair:ftable");
memory->create(ctable,ntable,"pair:ctable");
memory->create(etable,ntable,"pair:etable");
memory->create(drtable,ntable,"pair:drtable");
memory->create(dftable,ntable,"pair:dftable");
memory->create(dctable,ntable,"pair:dctable");
memory->create(detable,ntable,"pair:detable");
if (cut_respa == NULL) {
vtable = ptable = dvtable = dptable = NULL;
} else {
memory->create(vtable,ntable,"pair:vtable");
memory->create(ptable,ntable,"pair:ptable");
memory->create(dvtable,ntable,"pair:dvtable");
memory->create(dptable,ntable,"pair:dptable");
}
union_int_float_t rsq_lookup;
union_int_float_t minrsq_lookup;
int itablemin;
minrsq_lookup.i = 0 << ncoulshiftbits;
minrsq_lookup.i |= maskhi;
for (int i = 0; i < ntable; i++) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tabinnersq) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= maskhi;
}
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
etable[i] = qqrd2e/r * derfc;
} else {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
ctable[i] = 0.0;
etable[i] = qqrd2e/r * derfc;
ptable[i] = qqrd2e/r;
vtable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
ftable[i] += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
ctable[i] = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
}
}
}
minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f);
}
tabinnersq = minrsq_lookup.f;
int ntablem1 = ntable - 1;
for (int i = 0; i < ntablem1; i++) {
drtable[i] = 1.0/(rtable[i+1] - rtable[i]);
dftable[i] = ftable[i+1] - ftable[i];
dctable[i] = ctable[i+1] - ctable[i];
detable[i] = etable[i+1] - etable[i];
}
if (cut_respa) {
for (int i = 0; i < ntablem1; i++) {
dvtable[i] = vtable[i+1] - vtable[i];
dptable[i] = ptable[i+1] - ptable[i];
}
}
// get the delta values for the last table entries
// tables are connected periodically between 0 and ntablem1
drtable[ntablem1] = 1.0/(rtable[0] - rtable[ntablem1]);
dftable[ntablem1] = ftable[0] - ftable[ntablem1];
dctable[ntablem1] = ctable[0] - ctable[ntablem1];
detable[ntablem1] = etable[0] - etable[ntablem1];
if (cut_respa) {
dvtable[ntablem1] = vtable[0] - vtable[ntablem1];
dptable[ntablem1] = ptable[0] - ptable[ntablem1];
}
// get the correct delta values at itablemax
// smallest r is in bin itablemin
// largest r is in bin itablemax, which is itablemin-1,
// or ntablem1 if itablemin=0
// deltas at itablemax only needed if corresponding rsq < cut*cut
// if so, compute deltas between rsq and cut*cut
double f_tmp,c_tmp,e_tmp,p_tmp,v_tmp;
itablemin = minrsq_lookup.i & ncoulmask;
itablemin >>= ncoulshiftbits;
int itablemax = itablemin - 1;
if (itablemin == 0) itablemax = ntablem1;
rsq_lookup.i = itablemax << ncoulshiftbits;
rsq_lookup.i |= maskhi;
if (rsq_lookup.f < cut_coulsq_global) {
rsq_lookup.f = cut_coulsq_global;
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
e_tmp = qqrd2e/r * derfc;
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
c_tmp = 0.0;
e_tmp = qqrd2e/r * derfc;
p_tmp = qqrd2e/r;
v_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
f_tmp += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
c_tmp = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
}
}
}
drtable[itablemax] = 1.0/(rsq_lookup.f - rtable[itablemax]);
dftable[itablemax] = f_tmp - ftable[itablemax];
dctable[itablemax] = c_tmp - ctable[itablemax];
detable[itablemax] = e_tmp - etable[itablemax];
if (cut_respa) {
dvtable[itablemax] = v_tmp - vtable[itablemax];
dptable[itablemax] = p_tmp - ptable[itablemax];
}
}
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- *
* the real compute work is done in the PairCMMCommon::eval_XXX<>() templates
* in the common PairCG class. Through using templates we can have one
* implementation for all CG varieties _and_ gain speed through having
* the compiler optimize away conditionals within the innerloops that
* can be predetermined outside the loop through instantiation of the
* different combination of template flags.
* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::compute(int eflag, int vflag)
{
if (eflag || vflag) {
ev_setup(eflag,vflag);
} else {
evflag = vflag_fdotr = 0;
}
if (evflag) {
if (eflag) {
if (force->newton_pair) {
return eval_verlet<1,1,1,CG_COUL_LONG>();
} else {
return eval_verlet<1,1,0,CG_COUL_LONG>();
}
} else {
if (force->newton_pair) {
return eval_verlet<1,0,1,CG_COUL_LONG>();
} else {
return eval_verlet<1,0,0,CG_COUL_LONG>();
}
}
} else {
if (force->newton_pair) {
return eval_verlet<0,0,1,CG_COUL_LONG>();
} else {
return eval_verlet<0,0,0,CG_COUL_LONG>();
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::compute_inner()
{
if (force->newton_pair) {
return eval_inner<1,CG_COUL_LONG>();
} else {
return eval_inner<0,CG_COUL_LONG>();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::compute_middle()
{
if (force->newton_pair) {
return eval_middle<1,CG_COUL_LONG>();
} else {
return eval_middle<0,CG_COUL_LONG>();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::compute_outer(int eflag, int vflag)
{
if (eflag || vflag) {
ev_setup(eflag,vflag);
} else {
evflag = 0;
}
if (evflag) {
if (eflag) {
if (vflag) {
if (force->newton_pair) {
return eval_outer<1,1,1,1,CG_COUL_LONG>();
} else {
return eval_outer<1,1,1,0,CG_COUL_LONG>();
}
} else {
if (force->newton_pair) {
return eval_outer<1,1,0,1,CG_COUL_LONG>();
} else {
return eval_outer<1,1,0,0,CG_COUL_LONG>();
}
}
} else {
if (vflag) {
if (force->newton_pair) {
return eval_outer<1,0,1,1,CG_COUL_LONG>();
} else {
return eval_outer<1,0,1,0,CG_COUL_LONG>();
}
} else {
if (force->newton_pair) {
return eval_outer<1,0,0,1,CG_COUL_LONG>();
} else {
return eval_outer<1,0,0,0,CG_COUL_LONG>();
}
}
}
} else {
if (force->newton_pair) {
return eval_outer<0,0,0,1,CG_COUL_LONG>();
} else {
return eval_outer<0,0,0,0,CG_COUL_LONG>();
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::write_restart(FILE *fp)
{
write_restart_settings(fp);
PairCMMCommon::write_restart(fp);
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLong::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
PairCMMCommon::read_restart(fp);
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulLong::memory_usage()
{
double bytes=PairCMMCommon::memory_usage();
int n = atom->ntypes;
// cut_coul/cut_coulsq/cut_ljsq
bytes += (n+1)*(n+1)*sizeof(double)*4;
return bytes;
}
/* ---------------------------------------------------------------------- */
double PairCGCMMCoulLong::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj, double &fforce)
{
return eval_single(CG_COUL_LONG,i,j,itype,jtype,rsq,factor_coul,factor_lj,fforce);
}
/* ---------------------------------------------------------------------- */
void *PairCGCMMCoulLong::extract(char *str, int &dim)
{
dim = 0;
if (strcmp(str,"cut_coul") == 0) return (void *) &cut_coul_global;
return NULL;
}
diff --git a/src/USER-CG-CMM/pair_cmm_common.cpp b/src/USER-CG-CMM/pair_cmm_common.cpp
index 043716e9f..81d142f56 100644
--- a/src/USER-CG-CMM/pair_cmm_common.cpp
+++ b/src/USER-CG-CMM/pair_cmm_common.cpp
@@ -1,476 +1,475 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Common functionality for the CMM coarse grained MD potentials.
Contributing author: Axel Kohlmeyer <akohlmey@gmail.com>
------------------------------------------------------------------------- */
#include "pair_cmm_common.h"
#include "memory.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "math.h"
using namespace LAMMPS_NS;
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define SMALL 1.0e-6
/* ---------------------------------------------------------------------- */
PairCMMCommon::PairCMMCommon(class LAMMPS *lmp) : Pair(lmp)
{
ftable = NULL;
allocated_coul = 0;
kappa = 0.0;
respa_enable = 0;
single_enable = 0;
}
/* ---------------------------------------------------------------------- *
* clean up common arrays *
* ---------------------------------------------------------------------- */
PairCMMCommon::~PairCMMCommon() {
if (allocated) {
memory->destroy(setflag);
memory->destroy(cg_type);
memory->destroy(cut);
memory->destroy(cutsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(offset);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
allocated = 0;
}
}
/* ---------------------------------------------------------------------- *
* allocate common arrays *
* ---------------------------------------------------------------------- */
void PairCMMCommon::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"paircg:setflag");
memory->create(cg_type,n+1,n+1,"paircg:cg_type");
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
setflag[i][j] = 0;
cg_type[i][j] = CG_NOT_SET;
}
}
memory->create(cut,n+1,n+1,"paircg:cut");
memory->create(cutsq,n+1,n+1,"paircg:cutsq");
memory->create(epsilon,n+1,n+1,"paircg:epsilon");
memory->create(sigma,n+1,n+1,"paircg:sigma");
memory->create(offset,n+1,n+1,"paircg:offset");
memory->create(lj1,n+1,n+1,"paircg:lj1");
memory->create(lj2,n+1,n+1,"paircg:lj2");
memory->create(lj3,n+1,n+1,"paircg:lj3");
memory->create(lj4,n+1,n+1,"paircg:lj4");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
// arguments to the pair_style command (global version)
// args = cutoff (cutoff2 (kappa))
void PairCMMCommon::settings(int narg, char **arg)
{
- if ((narg < 1) || (narg > 3)) error->all("Illegal pair_style command");
+ if ((narg < 1) || (narg > 3)) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul_global = cut_lj_global;
else cut_coul_global = force->numeric(arg[1]);
cut_coulsq_global = cut_coul_global*cut_coul_global;
// exponential coulomb screening (optional)
if (narg == 3) kappa = force->numeric(arg[2]);
if (fabs(kappa) < SMALL) kappa=0.0;
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++) {
for (j = i+1; j <= atom->ntypes; j++) {
if (setflag[i][j]) {
cut[i][j] = cut_lj_global;
if (allocated_coul) {
cut[i][j] = MAX(cut_lj_global,cut_coul_global);
cut_lj[i][j] = cut_lj_global;
cut_coul[i][j] = cut_coul_global;
}
}
}
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairCMMCommon::coeff(int narg, char **arg)
{
- if (narg < 5 || narg > 7) error->all("Incorrect args for pair coefficients");
+ if (narg < 5 || narg > 7) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
int cg_type_one=find_cg_type(arg[2]);
- if (cg_type_one == CG_NOT_SET) error->all("Error reading CG type flag.");
+ if (cg_type_one == CG_NOT_SET) error->all(FLERR,"Error reading CG type flag.");
double epsilon_one = force->numeric(arg[3]);
double sigma_one = force->numeric(arg[4]);
double cut_lj_one = cut_lj_global;
double cut_coul_one = cut_coul_global;
if (narg >= 6) cut_lj_one = force->numeric(arg[5]);
if (narg == 7) cut_coul_one = force->numeric(arg[6]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
cg_type[i][j] = cg_type_one;
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
setflag[i][j] = 1;
if (allocated_coul) {
cut_lj[i][j] = cut_lj_one;
cut_coul[i][j] = cut_coul_one;
} else {
cut[i][j] = cut_lj_one;
}
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairCMMCommon::init_style()
{
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
} else irequest = neighbor->request(this);
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
regular or rRESPA
------------------------------------------------------------------------- */
void PairCMMCommon::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listinner = ptr;
else if (id == 2) listmiddle = ptr;
else if (id == 3) listouter = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairCMMCommon::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
- error->all("for CG styles, epsilon and sigma need to be set explicitly for all pairs.");
+ error->all(FLERR,"for CG styles, epsilon and sigma need to be set explicitly for all pairs.");
}
const int cgt = cg_type[i][j];
if (cgt == CG_NOT_SET)
- error->all("unrecognized LJ parameter flag");
+ error->all(FLERR,"unrecognized LJ parameter flag");
lj1[i][j] = cg_prefact[cgt] * cg_pow1[cgt] * epsilon[i][j] * pow(sigma[i][j],cg_pow1[cgt]);
lj2[i][j] = cg_prefact[cgt] * cg_pow2[cgt] * epsilon[i][j] * pow(sigma[i][j],cg_pow2[cgt]);
lj3[i][j] = cg_prefact[cgt] * epsilon[i][j] * pow(sigma[i][j],cg_pow1[cgt]);
lj4[i][j] = cg_prefact[cgt] * epsilon[i][j] * pow(sigma[i][j],cg_pow2[cgt]);
double mycut = cut[i][j];
if (offset_flag) {
double ratio = sigma[i][j] / mycut;
offset[i][j] = cg_prefact[cgt] * epsilon[i][j] * (pow(ratio,cg_pow1[cgt]) - pow(ratio,cg_pow2[cgt]));
} else offset[i][j] = 0.0;
if (allocated_coul) {
mycut = MAX(cut_lj[i][j],cut_coul[i][j]);
cut[i][j] = mycut;
cut_ljsq[i][j]=cut_lj[i][j]*cut_lj[i][j];
cut_coulsq[i][j]=cut_coul[i][j]*cut_coul[i][j];
if (offset_flag) {
double ratio = sigma[i][j] / cut_lj[i][j];
offset[i][j] = cg_prefact[cgt] * epsilon[i][j] * (pow(ratio,cg_pow1[cgt]) - pow(ratio,cg_pow2[cgt]));
} else offset[i][j] = 0.0;
}
// make sure data is stored symmetrically
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
cg_type[j][i] = cg_type[i][j];
cut[j][i] = mycut;
if (allocated_coul) {
cut_lj[j][i]=cut_lj[i][j];
cut_ljsq[j][i]=cut_ljsq[i][j];
cut_coul[j][i]=cut_coul[i][j];
cut_coulsq[j][i]=cut_coulsq[i][j];
}
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
#if 1
- error->all("tail correction not (yet) supported by CG potentials.");
+ error->all(FLERR,"tail correction not (yet) supported by CG potentials.");
#else
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig2 = sigma[i][j]*sigma[i][j];
double sig6 = sig2*sig2*sig2;
double rc3 = cut[i][j]*cut[i][j]*cut[i][j];
double rc6 = rc3*rc3;
double rc9 = rc3*rc6;
etail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig6 - 3.0*rc6) / (9.0*rc9);
ptail_ij = 16.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9);
#endif
}
return mycut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairCMMCommon::write_restart(FILE *fp)
{
int i,j;
for (i = 1; i <= atom->ntypes; i++) {
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&cg_type[i][j],sizeof(int),1,fp);
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
if (allocated_coul) {
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
fwrite(&cut_coul[i][j],sizeof(double),1,fp);
}
}
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairCMMCommon::read_restart(FILE *fp)
{
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++) {
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&cg_type[i][j],sizeof(int),1,fp);
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
if(allocated_coul) {
fread(&cut_lj[i][j],sizeof(double),1,fp);
fread(&cut_coul[i][j],sizeof(double),1,fp);
}
}
MPI_Bcast(&cg_type[i][j],1,MPI_INT,0,world);
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
if (allocated_coul) {
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul[i][j],1,MPI_DOUBLE,0,world);
}
}
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairCMMCommon::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul_global,sizeof(double),1,fp);
fwrite(&kappa,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairCMMCommon::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul_global,sizeof(double),1,fp);
fread(&kappa,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&kappa,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
cut_coulsq_global = cut_coul_global*cut_coul_global;
}
/* ---------------------------------------------------------------------- */
double PairCMMCommon::memory_usage()
{
double bytes=Pair::memory_usage();
int n = atom->ntypes;
// setflag/cg_type
bytes += (n+1)*(n+1)*sizeof(int)*2;
// cut/cutsq/epsilon/sigma/offset/lj1/lj2/lj3/lj4
bytes += (n+1)*(n+1)*sizeof(double)*9;
return bytes;
}
/* ------------------------------------------------------------------------ */
double PairCMMCommon::eval_single(int coul_type, int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
double lj_force, lj_erg, coul_force, coul_erg;
lj_force=lj_erg=coul_force=coul_erg=0.0;
if (rsq < cut_ljsq[itype][jtype]) {
const int cgt = cg_type[itype][jtype];
const double cgpow1 = cg_pow1[cgt];
const double cgpow2 = cg_pow2[cgt];
const double cgpref = cg_prefact[cgt];
const double ratio = sigma[itype][jtype]/sqrt(rsq);
const double eps = epsilon[itype][jtype];
lj_force = cgpref*eps * (cgpow1*pow(ratio,cgpow1)
- cgpow2*pow(ratio,cgpow2))/rsq;
lj_erg = cgpref*eps * (pow(ratio,cgpow1) - pow(ratio,cgpow2));
}
if (rsq < cut_coul[itype][jtype]) {
if(coul_type == CG_COUL_LONG) {
- error->all("single energy computation with long-range coulomb not supported by CG potentials.");
+ error->all(FLERR,"single energy computation with long-range coulomb not supported by CG potentials.");
} else if ((coul_type == CG_COUL_CUT) || (coul_type == CG_COUL_DEBYE)) {
const double r2inv = 1.0/rsq;
const double rinv = sqrt(r2inv);
const double qscreen=exp(-kappa*sqrt(rsq));
coul_force = force->qqrd2e * atom->q[i]*atom->q[j]*rinv * qscreen * (kappa + rinv);
coul_erg = force->qqrd2e * atom->q[i]*atom->q[j]*rinv * qscreen;
- // error->all("single energy computation with coulomb not supported by CG potentials.");
+ // error->all(FLERR,"single energy computation with coulomb not supported by CG potentials.");
} else if (coul_type == CG_COUL_NONE) {
; // do nothing
} else {
- error->all("unknown coulomb type with CG potentials.");
+ error->all(FLERR,"unknown coulomb type with CG potentials.");
}
}
fforce = factor_lj*lj_force + factor_coul*coul_force;
return factor_lj*lj_erg + factor_coul*coul_erg;
}
diff --git a/src/USER-CUDA/atom_vec_angle_cuda.cpp b/src/USER-CUDA/atom_vec_angle_cuda.cpp
index 323a1bedf..b816b690b 100644
--- a/src/USER-CUDA/atom_vec_angle_cuda.cpp
+++ b/src/USER-CUDA/atom_vec_angle_cuda.cpp
@@ -1,476 +1,476 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "atom_vec_angle_cuda.h"
#include "comm_cuda_cu.h"
#include "atom_vec_angle_cuda_cu.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
#include "universe.h"
#include "comm.h"
using namespace LAMMPS_NS;
#define DELTA 10000
#define BUFFACTOR 1.5
#define BUFEXTRA 1000
#define NCUDAEXCHANGE 12 //nextra x y z vx vy vz tag type mask image molecule
#define BUF_FLOAT double
/* ---------------------------------------------------------------------- */
AtomVecAngleCuda::AtomVecAngleCuda(LAMMPS *lmp, int narg, char **arg) :
AtomVecAngle(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
maxsend=0;
cudable=true;
cuda_init_done=false;
max_nsend=0;
cu_copylist=NULL;
copylist=NULL;
copylist2=NULL;
}
void AtomVecAngleCuda::grow_copylist(int new_max_nsend)
{
max_nsend=new_max_nsend;
delete cu_copylist;
delete [] copylist2;
if(copylist) CudaWrapper_FreePinnedHostData((void*) copylist);
copylist = (int*) CudaWrapper_AllocPinnedHostData(max_nsend*sizeof(int),false);
copylist2 = new int[max_nsend];
cu_copylist = new cCudaData<int, int, xx > (copylist, max_nsend);
}
void AtomVecAngleCuda::grow_send(int n,double** buf_send,int flag) //need to be able to grow the comm send_buffer since the array sahll be copied from the gpu in whole
{
int old_maxsend=*maxsend+BUFEXTRA;
*maxsend = static_cast<int> (BUFFACTOR * n);
if (flag)
{
if(cuda->pinned)
{
double* tmp = new double[old_maxsend];
memcpy((void*) tmp,(void*) *buf_send,old_maxsend*sizeof(double));
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
memcpy(*buf_send,tmp,old_maxsend*sizeof(double));
delete [] tmp;
}
else
{
*buf_send = (double *)
memory->srealloc(*buf_send,(*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
else {
if(cuda->pinned)
{
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
}
else
{
memory->sfree(*buf_send);
*buf_send = (double *) memory->smalloc((*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
}
void AtomVecAngleCuda::grow_both(int n)
{
if(cuda->finished_setup)
cuda->downloadAll();
AtomVecAngle::grow(n);
if(cuda->finished_setup)
{
cuda->checkResize();
cuda->uploadAll();
}
}
int AtomVecAngleCuda::pack_comm(int n, int* iswap, double *buf,
int pbc_flag, int *pbc) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAngle::pack_comm(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackComm(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
int AtomVecAngleCuda::pack_comm_vel(int n, int* iswap, double *buf,
int pbc_flag, int *pbc) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAngle::pack_comm_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackCommVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAngleCuda::unpack_comm(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAngle::unpack_comm(n,first,buf); return;}
Cuda_CommCuda_UnpackComm(&cuda->shared_data,n,first,(void*)buf);
}
void AtomVecAngleCuda::unpack_comm_vel(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAngle::unpack_comm_vel(n,first,buf); return;}
Cuda_CommCuda_UnpackCommVel(&cuda->shared_data,n,first,(void*)buf);
}
/* ---------------------------------------------------------------------- */
int AtomVecAngleCuda::pack_reverse(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only forces are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAngle::pack_reverse(n,first,buf);
int i,m,last;
cuda->cu_f->download();
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
cuda->cu_f->upload();
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAngleCuda::unpack_reverse(int n, int *list, double *buf)//usually this should not be called since comm->communicate handles the communication if only forces are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAngle::unpack_reverse(n,list,buf); return;}
int i,j,m;
m = 0;
cuda->cu_f->download();
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
cuda->cu_f->upload();
}
/* ---------------------------------------------------------------------- */
int AtomVecAngleCuda::pack_border(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAngle::pack_border(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecAngleCuda_PackBorder(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
int AtomVecAngleCuda::pack_border_vel(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAngle::pack_border_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecAngleCuda_PackBorderVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAngleCuda::unpack_border(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAngle::unpack_border(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax) //ensure there is enough space on device to unpack data
{
grow_both(0);
}
int flag=Cuda_AtomVecAngleCuda_UnpackBorder(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
void AtomVecAngleCuda::unpack_border_vel(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAngle::unpack_border_vel(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax) //ensure there is enough space on device to unpack data
{
grow_both(0);
}
int flag=Cuda_AtomVecAngleCuda_UnpackBorderVel(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecAngleCuda::pack_exchange(int dim, double *buf)
{
if(cuda->oncpu)
return AtomVecAngle::pack_exchange(dim,buf);
if(not cuda_init_done||domain->box_change)
{
Cuda_AtomVecAngleCuda_Init(&cuda->shared_data);
cuda_init_done=true;
}
double** buf_pointer=(double**) buf;
if(*maxsend<atom->nghost || *buf_pointer==NULL)
{
grow_send(atom->nghost>*maxsend?atom->nghost:*maxsend,buf_pointer,0);
*maxsend=atom->nghost>*maxsend?atom->nghost:*maxsend;
}
if(max_nsend==0) grow_copylist(200);
int nsend_atoms = Cuda_AtomVecAngleCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
if(nsend_atoms>max_nsend) grow_copylist(nsend_atoms+100);
if(nsend_atoms*NCUDAEXCHANGE>*maxsend)
{
grow_send((int) (nsend_atoms+100)*NCUDAEXCHANGE,buf_pointer,0);
Cuda_AtomVecAngleCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
}
int nlocal=atom->nlocal-nsend_atoms;
for(int i=0;i<nsend_atoms;i++) copylist2[i]=1;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i>=nlocal) copylist2[i-nlocal]=-1;
}
int actpos=0;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i<nlocal)
{
while(copylist2[actpos]==-1) actpos++;
copylist[j-1]=nlocal+actpos;
actpos++;
}
}
cu_copylist->upload();
cuda->shared_data.atom.nlocal=nlocal;
int m = Cuda_AtomVecAngleCuda_PackExchange(&cuda->shared_data,nsend_atoms,*buf_pointer,cu_copylist->dev_data());
timespec time1,time2;
clock_gettime(CLOCK_REALTIME,&time1);
double* buf_p=*buf_pointer;
for(int j=0;j<nsend_atoms;j++)
{
int i=static_cast <int> (buf_p[j+1]);
int nextra=0;
int k;
buf_p[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf_p[m++] = bond_type[i][k];
buf_p[m++] = bond_atom[i][k];
}
nextra+=2*num_bond[i]+1;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
buf_p[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf_p[m++] = angle_type[i][k];
buf_p[m++] = angle_atom1[i][k];
buf_p[m++] = angle_atom2[i][k];
buf_p[m++] = angle_atom3[i][k];
}
nextra+=4*num_angle[i]+1;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
buf_p[m++] = nspecial[i][0];
buf_p[m++] = nspecial[i][1];
buf_p[m++] = nspecial[i][2];
for (k = 0; k < nspecial[i][2]; k++) buf_p[m++] = special[i][k];
nextra+=nspecial[i][2]+3;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
{
int dm= modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf_p[m]);
m+=dm;
nextra+=dm;
if(i<nlocal)modify->fix[atom->extra_grow[iextra]]->copy_arrays(copylist[j],i);
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
}
if(i<nlocal)AtomVecAngle::copy(copylist[j],i,1);
(*buf_pointer)[j+1] = nextra;
}
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_exchange_cpu_pack+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
(*buf_pointer)[0] = nsend_atoms;
atom->nlocal-=nsend_atoms;
cuda->shared_data.atom.update_nlocal=2;
//printf("End Pack Exchange\n");
if(m==1) return 0;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAngleCuda::unpack_exchange(double *buf)
{
// printf("Begin UnPack Exchange\n");
if(cuda->oncpu)
return AtomVecAngle::unpack_exchange(buf);
double *sublo,*subhi;
int dim=cuda->shared_data.exchange_dim;
if(domain->box_change)
Cuda_AtomVecAngleCuda_Init(&cuda->shared_data);
if (domain->triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
int mfirst=0;
for(int pi=0;pi<(comm->procgrid[dim]>2?2:1);pi++)
{
int nlocal = atom->nlocal;
int nsend_atoms=static_cast<int> (buf[0]);
if(nsend_atoms>max_nsend) grow_copylist(nsend_atoms+100);
if (nlocal+nsend_atoms+atom->nghost>=atom->nmax) grow_both(nlocal+nsend_atoms*2+atom->nghost); //ensure there is enough space on device to unpack data
int naccept = Cuda_AtomVecAngleCuda_UnpackExchange(&cuda->shared_data,nsend_atoms,buf,cu_copylist->dev_data());
cu_copylist->download();
int m = nsend_atoms*NCUDAEXCHANGE + 1;
nlocal+=naccept;
timespec time1,time2;
clock_gettime(CLOCK_REALTIME,&time1);
for(int j=0;j<nsend_atoms;j++)
{
if(copylist[j]>-1)
{
int k;
int i=copylist[j];
num_bond[i] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[i]; k++) {
bond_type[i][k] = static_cast<int> (buf[m++]);
bond_atom[i][k] = static_cast<int> (buf[m++]);
}
num_angle[i] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[i]; k++) {
angle_type[i][k] = static_cast<int> (buf[m++]);
angle_atom1[i][k] = static_cast<int> (buf[m++]);
angle_atom2[i][k] = static_cast<int> (buf[m++]);
angle_atom3[i][k] = static_cast<int> (buf[m++]);
}
nspecial[i][0] = static_cast<int> (buf[m++]);
nspecial[i][1] = static_cast<int> (buf[m++]);
nspecial[i][2] = static_cast<int> (buf[m++]);
for (k = 0; k < nspecial[i][2]; k++)
special[i][k] = static_cast<int> (buf[m++]);
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(i,&buf[m]);
}
else
m+=static_cast <int> (buf[j+1]);
}
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_exchange_cpu_pack+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
cuda->shared_data.atom.nlocal=nlocal;
cuda->shared_data.atom.update_nlocal=2;
atom->nlocal=nlocal;
mfirst+=m;
buf=&buf[m];
}
return mfirst;
}
diff --git a/src/USER-CUDA/atom_vec_atomic_cuda.cpp b/src/USER-CUDA/atom_vec_atomic_cuda.cpp
index c57e0654f..b6bb14422 100644
--- a/src/USER-CUDA/atom_vec_atomic_cuda.cpp
+++ b/src/USER-CUDA/atom_vec_atomic_cuda.cpp
@@ -1,407 +1,407 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "atom_vec_atomic_cuda.h"
#include "comm_cuda_cu.h"
#include "atom_vec_atomic_cuda_cu.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
#include "comm.h"
using namespace LAMMPS_NS;
#define DELTA 10000
#define BUFFACTOR 1.5
#define BUFEXTRA 1000
#define NCUDAEXCHANGE 11 //nextra x y z vx vy vz tag type mask image
#define BUF_FLOAT double
/* ---------------------------------------------------------------------- */
AtomVecAtomicCuda::AtomVecAtomicCuda(LAMMPS *lmp, int narg, char **arg) :
AtomVecAtomic(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
maxsend=0;
cudable=true;
cuda_init_done=false;
max_nsend=0;
cu_copylist=NULL;
copylist=NULL;
copylist2=NULL;
}
void AtomVecAtomicCuda::grow_copylist(int new_max_nsend)
{
max_nsend=new_max_nsend;
delete cu_copylist;
delete [] copylist2;
if(copylist) CudaWrapper_FreePinnedHostData((void*) copylist);
copylist = (int*) CudaWrapper_AllocPinnedHostData(max_nsend*sizeof(int),false);
copylist2 = new int[max_nsend];
cu_copylist = new cCudaData<int, int, xx > (copylist, max_nsend);
}
void AtomVecAtomicCuda::grow_send(int n,double** buf_send,int flag)
{
int old_maxsend=*maxsend+BUFEXTRA;
*maxsend = static_cast<int> (BUFFACTOR * n);
if (flag)
{
if(cuda->pinned)
{
double* tmp = new double[old_maxsend];
memcpy((void*) tmp,(void*) *buf_send,old_maxsend*sizeof(double));
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
memcpy(*buf_send,tmp,old_maxsend*sizeof(double));
delete [] tmp;
}
else
{
*buf_send = (double *)
memory->srealloc(*buf_send,(*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
else {
if(cuda->pinned)
{
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
}
else
{
memory->sfree(*buf_send);
*buf_send = (double *) memory->smalloc((*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
}
void AtomVecAtomicCuda::grow_both(int n)
{
if(cuda->finished_setup)
cuda->downloadAll();
AtomVecAtomic::grow(n);
if(cuda->finished_setup)
{
cuda->checkResize();
cuda->uploadAll();
}
}
int AtomVecAtomicCuda::pack_comm(int n, int* iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAtomic::pack_comm(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackComm(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
int AtomVecAtomicCuda::pack_comm_vel(int n, int* iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAtomic::pack_comm_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackCommVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomicCuda::unpack_comm(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAtomic::unpack_comm(n,first,buf); return;}
Cuda_CommCuda_UnpackComm(&cuda->shared_data,n,first,(void*)buf);
}
void AtomVecAtomicCuda::unpack_comm_vel(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAtomic::unpack_comm_vel(n,first,buf); return;}
Cuda_CommCuda_UnpackCommVel(&cuda->shared_data,n,first,(void*)buf);
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomicCuda::pack_reverse(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAtomic::pack_reverse(n,first,buf);
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomicCuda::unpack_reverse(int n, int *list, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAtomic::unpack_reverse(n,list,buf); return;}
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomicCuda::pack_border(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAtomic::pack_border(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecAtomicCuda_PackBorder(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
int AtomVecAtomicCuda::pack_border_vel(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecAtomic::pack_border_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecAtomicCuda_PackBorderVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomicCuda::unpack_border(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAtomic::unpack_border(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax)
{
grow_both(0);
}
int flag=Cuda_AtomVecAtomicCuda_UnpackBorder(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
void AtomVecAtomicCuda::unpack_border_vel(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecAtomic::unpack_border_vel(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax)
{
grow_both(0);
}
int flag=Cuda_AtomVecAtomicCuda_UnpackBorderVel(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecAtomicCuda::pack_exchange(int dim, double *buf)
{
if(cuda->oncpu)
return AtomVecAtomic::pack_exchange(dim,buf);
if(not cuda_init_done||domain->box_change)
{
Cuda_AtomVecAtomicCuda_Init(&cuda->shared_data);
cuda_init_done=true;
}
double** buf_pointer=(double**) buf;
if(*maxsend<atom->nghost || *buf_pointer==NULL)
{
grow_send(atom->nghost>*maxsend?atom->nghost:*maxsend,buf_pointer,0);
*maxsend=atom->nghost>*maxsend?atom->nghost:*maxsend;
}
if(max_nsend==0) grow_copylist(200);
int nsend_atoms = Cuda_AtomVecAtomicCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
if(nsend_atoms>max_nsend) {grow_copylist(nsend_atoms+100);}
if(nsend_atoms*NCUDAEXCHANGE>*maxsend)
{
grow_send((int) (nsend_atoms+100)*NCUDAEXCHANGE,buf_pointer,0);
Cuda_AtomVecAtomicCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
}
int nlocal=atom->nlocal-nsend_atoms;
for(int i=0;i<nsend_atoms;i++) copylist2[i]=1;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i>=nlocal) copylist2[i-nlocal]=-1;
}
int actpos=0;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i<nlocal)
{
while(copylist2[actpos]==-1) actpos++;
copylist[j-1]=nlocal+actpos;
actpos++;
}
}
cu_copylist->upload();
cuda->shared_data.atom.nlocal=nlocal;
int m = Cuda_AtomVecAtomicCuda_PackExchange(&cuda->shared_data,nsend_atoms,*buf_pointer,cu_copylist->dev_data());
if (atom->nextra_grow)
for(int j=0;j<nsend_atoms;j++)
{
int i=static_cast <int> ((*buf_pointer)[j+1]);
int nextra=0;
for (int iextra = 0; iextra < atom->nextra_grow; iextra++) {
int dm = modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&((*buf_pointer)[m]));
m+=dm;
nextra+=dm;
if(i<nlocal)modify->fix[atom->extra_grow[iextra]]->copy_arrays(copylist[j],i);
if(m>*maxsend) grow_send(m,buf_pointer,1);
}
(*buf_pointer)[j+1] = nextra;
}
(*buf_pointer)[0] = nsend_atoms;
atom->nlocal-=nsend_atoms;
cuda->shared_data.atom.update_nlocal=2;
if(m==1) return 0;//m is at least 1 in cuda since buf[0] contains number of atoms
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomicCuda::unpack_exchange(double *buf)
{
//printf("Unpack Begin\n");
if(cuda->oncpu)
return AtomVecAtomic::unpack_exchange(buf);
double *sublo,*subhi;
int dim=cuda->shared_data.exchange_dim;
if(domain->box_change)
Cuda_AtomVecAtomicCuda_Init(&cuda->shared_data);
if (domain->triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
int mfirst=0;
for(int pi=0;pi<(comm->procgrid[dim]>2?2:1);pi++)
{
int nlocal = atom->nlocal;
int nsend_atoms=static_cast<int> (buf[0]);
if(nsend_atoms>max_nsend) grow_copylist(nsend_atoms+100);
if (nlocal+nsend_atoms+atom->nghost>=atom->nmax) grow_both(nlocal+nsend_atoms*2+atom->nghost);
int naccept = Cuda_AtomVecAtomicCuda_UnpackExchange(&cuda->shared_data,nsend_atoms,buf,cu_copylist->dev_data());
cu_copylist->download();
int m = nsend_atoms*NCUDAEXCHANGE + 1;
nlocal+=naccept;
if (atom->nextra_grow)
for(int j=0;j<nsend_atoms;j++)
{
if(copylist[j]>-1)
{
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(copylist[j],&buf[m]);
}
else
{
m+=static_cast <int> (buf[j+1]);
}
}
cuda->shared_data.atom.nlocal=nlocal;
cuda->shared_data.atom.update_nlocal=2;
atom->nlocal=nlocal;
mfirst+=m;
buf=&buf[m];
}
return mfirst;
}
diff --git a/src/USER-CUDA/atom_vec_charge_cuda.cpp b/src/USER-CUDA/atom_vec_charge_cuda.cpp
index e05725360..a15836c45 100644
--- a/src/USER-CUDA/atom_vec_charge_cuda.cpp
+++ b/src/USER-CUDA/atom_vec_charge_cuda.cpp
@@ -1,407 +1,407 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "atom_vec_charge_cuda.h"
#include "comm_cuda_cu.h"
#include "atom_vec_charge_cuda_cu.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
#include "comm.h"
using namespace LAMMPS_NS;
#define DELTA 10000
#define BUFFACTOR 1.5
#define BUFEXTRA 1000
#define NCUDAEXCHANGE 12 //nextra x y z vx vy vz tag type mask image q
#define BUF_FLOAT double
/* ---------------------------------------------------------------------- */
AtomVecChargeCuda::AtomVecChargeCuda(LAMMPS *lmp, int narg, char **arg) :
AtomVecCharge(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
maxsend=0;
cudable=true;
cuda_init_done=false;
max_nsend=0;
cu_copylist=NULL;
copylist=NULL;
copylist2=NULL;
}
void AtomVecChargeCuda::grow_copylist(int new_max_nsend)
{
max_nsend=new_max_nsend;
delete cu_copylist;
delete [] copylist2;
if(copylist) CudaWrapper_FreePinnedHostData((void*) copylist);
copylist = (int*) CudaWrapper_AllocPinnedHostData(max_nsend*sizeof(int),false);
copylist2 = new int[max_nsend];
cu_copylist = new cCudaData<int, int, xx > (copylist, max_nsend);
}
void AtomVecChargeCuda::grow_send(int n,double** buf_send,int flag) //need to be able to grow the comm send_buffer since the array sahll be copied from the gpu in whole
{
int old_maxsend=*maxsend+BUFEXTRA;
*maxsend = static_cast<int> (BUFFACTOR * n);
if (flag)
{
if(cuda->pinned)
{
double* tmp = new double[old_maxsend];
memcpy((void*) tmp,(void*) *buf_send,old_maxsend*sizeof(double));
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
memcpy(*buf_send,tmp,old_maxsend*sizeof(double));
delete [] tmp;
}
else
{
*buf_send = (double *)
memory->srealloc(*buf_send,(*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
else {
if(cuda->pinned)
{
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
}
else
{
memory->sfree(*buf_send);
*buf_send = (double *) memory->smalloc((*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
}
void AtomVecChargeCuda::grow_both(int n)
{
if(cuda->finished_setup)
cuda->downloadAll();
AtomVecCharge::grow(n);
if(cuda->finished_setup)
{
cuda->checkResize();
cuda->uploadAll();
}
}
int AtomVecChargeCuda::pack_comm(int n, int* iswap, double *buf,
int pbc_flag, int *pbc) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecCharge::pack_comm(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackComm(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
int AtomVecChargeCuda::pack_comm_vel(int n, int* iswap, double *buf,
int pbc_flag, int *pbc) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecCharge::pack_comm_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackCommVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecChargeCuda::unpack_comm(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecCharge::unpack_comm(n,first,buf); return;}
Cuda_CommCuda_UnpackComm(&cuda->shared_data,n,first,(void*)buf);
}
void AtomVecChargeCuda::unpack_comm_vel(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecCharge::unpack_comm_vel(n,first,buf); return;}
Cuda_CommCuda_UnpackCommVel(&cuda->shared_data,n,first,(void*)buf);
}
/* ---------------------------------------------------------------------- */
int AtomVecChargeCuda::pack_reverse(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only forces are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecCharge::pack_reverse(n,first,buf);
int i,m,last;
cuda->cu_f->download();
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
cuda->cu_f->upload();
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecChargeCuda::unpack_reverse(int n, int *list, double *buf)//usually this should not be called since comm->communicate handles the communication if only forces are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecCharge::unpack_reverse(n,list,buf); return;}
int i,j,m;
m = 0;
cuda->cu_f->download();
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
cuda->cu_f->upload();
}
/* ---------------------------------------------------------------------- */
int AtomVecChargeCuda::pack_border(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecCharge::pack_border(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecChargeCuda_PackBorder(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
int AtomVecChargeCuda::pack_border_vel(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecCharge::pack_border_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecChargeCuda_PackBorderVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecChargeCuda::unpack_border(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecCharge::unpack_border(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax) //ensure there is enough space on device to unpack data
{
grow_both(0);
}
int flag=Cuda_AtomVecChargeCuda_UnpackBorder(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
void AtomVecChargeCuda::unpack_border_vel(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecCharge::unpack_border_vel(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax) //ensure there is enough space on device to unpack data
{
grow_both(0);
}
int flag=Cuda_AtomVecChargeCuda_UnpackBorderVel(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecChargeCuda::pack_exchange(int dim, double *buf)
{
if(cuda->oncpu)
return AtomVecCharge::pack_exchange(dim,buf);
if(not cuda_init_done||domain->box_change)
{
Cuda_AtomVecChargeCuda_Init(&cuda->shared_data);
cuda_init_done=true;
}
double** buf_pointer=(double**) buf;
if(*maxsend<atom->nghost || *buf_pointer==NULL)
{
grow_send(atom->nghost>*maxsend?atom->nghost:*maxsend,buf_pointer,0);
*maxsend=atom->nghost>*maxsend?atom->nghost:*maxsend;
}
if(max_nsend==0) grow_copylist(200);
int nsend_atoms = Cuda_AtomVecChargeCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
if(nsend_atoms>max_nsend) grow_copylist(nsend_atoms+100);
if(nsend_atoms*NCUDAEXCHANGE>*maxsend)
{
grow_send((int) (nsend_atoms+100)*NCUDAEXCHANGE,buf_pointer,0);
Cuda_AtomVecChargeCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
}
int nlocal=atom->nlocal-nsend_atoms;
for(int i=0;i<nsend_atoms;i++) copylist2[i]=1;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i>=nlocal) copylist2[i-nlocal]=-1;
}
int actpos=0;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i<nlocal)
{
while(copylist2[actpos]==-1) actpos++;
copylist[j-1]=nlocal+actpos;
actpos++;
}
}
cu_copylist->upload();
cuda->shared_data.atom.nlocal=nlocal;
int m = Cuda_AtomVecChargeCuda_PackExchange(&cuda->shared_data,nsend_atoms,*buf_pointer,cu_copylist->dev_data());
if (atom->nextra_grow)
for(int j=0;j<nsend_atoms;j++)
{
int i=static_cast <int> ((*buf_pointer)[j+1]);
int nextra=0;
for (int iextra = 0; iextra < atom->nextra_grow; iextra++) {
int dm = modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&((*buf_pointer)[m]));
m+=dm;
nextra+=dm;
if(i<nlocal)modify->fix[atom->extra_grow[iextra]]->copy_arrays(copylist[j],i);
if(m>*maxsend) grow_send(m,buf_pointer,1);
}
(*buf_pointer)[j+1] = nextra;
}
(*buf_pointer)[0] = nsend_atoms;
atom->nlocal-=nsend_atoms;
cuda->shared_data.atom.update_nlocal=2;
if(m==1) return 0;//m is at least 1 in cuda since buf[0] contains number of atoms
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecChargeCuda::unpack_exchange(double *buf)
{
if(cuda->oncpu)
return AtomVecCharge::unpack_exchange(buf);
double *sublo,*subhi;
int dim=cuda->shared_data.exchange_dim;
if(domain->box_change)
Cuda_AtomVecChargeCuda_Init(&cuda->shared_data);
if (domain->triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
int mfirst=0;
for(int pi=0;pi<(comm->procgrid[dim]>2?2:1);pi++)
{
int nlocal = atom->nlocal;
int nsend_atoms=static_cast<int> (buf[0]);
if(nsend_atoms>max_nsend) grow_copylist(nsend_atoms+100);
if (nlocal+nsend_atoms+atom->nghost>=atom->nmax) grow_both(nlocal+nsend_atoms*2+atom->nghost);
int naccept = Cuda_AtomVecChargeCuda_UnpackExchange(&cuda->shared_data,nsend_atoms,buf,cu_copylist->dev_data());
cu_copylist->download();
int m = nsend_atoms*NCUDAEXCHANGE + 1;
nlocal+=naccept;
if (atom->nextra_grow)
for(int j=0;j<nsend_atoms;j++)
{
if(copylist[j]>-1)
{
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(copylist[j],&buf[m]);
}
else
m+=static_cast <int> (buf[j+1]);
}
cuda->shared_data.atom.nlocal=nlocal;
cuda->shared_data.atom.update_nlocal=2;
atom->nlocal=nlocal;
mfirst+=m;
buf=&buf[m];
}
return mfirst;
}
diff --git a/src/USER-CUDA/atom_vec_full_cuda.cpp b/src/USER-CUDA/atom_vec_full_cuda.cpp
index f010181ce..9e656ed58 100644
--- a/src/USER-CUDA/atom_vec_full_cuda.cpp
+++ b/src/USER-CUDA/atom_vec_full_cuda.cpp
@@ -1,516 +1,516 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "atom_vec_full_cuda.h"
#include "comm_cuda_cu.h"
#include "atom_vec_full_cuda_cu.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
#include "universe.h"
#include "comm.h"
using namespace LAMMPS_NS;
#define DELTA 10000
#define BUFFACTOR 1.5
#define BUFEXTRA 1000
#define NCUDAEXCHANGE 13 //nextra x y z vx vy vz tag type mask image q molecule
#define BUF_FLOAT double
/* ---------------------------------------------------------------------- */
AtomVecFullCuda::AtomVecFullCuda(LAMMPS *lmp, int narg, char **arg) :
AtomVecFull(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
maxsend=0;
cudable=true;
cuda_init_done=false;
max_nsend=0;
cu_copylist=NULL;
copylist=NULL;
copylist2=NULL;
}
void AtomVecFullCuda::grow_copylist(int new_max_nsend)
{
max_nsend=new_max_nsend;
delete cu_copylist;
delete [] copylist2;
if(copylist) CudaWrapper_FreePinnedHostData((void*) copylist);
copylist = (int*) CudaWrapper_AllocPinnedHostData(max_nsend*sizeof(int),false);
copylist2 = new int[max_nsend];
cu_copylist = new cCudaData<int, int, xx > (copylist, max_nsend);
}
void AtomVecFullCuda::grow_send(int n,double** buf_send,int flag) //need to be able to grow the comm send_buffer since the array sahll be copied from the gpu in whole
{
int old_maxsend=*maxsend+BUFEXTRA;
*maxsend = static_cast<int> (BUFFACTOR * n);
if (flag)
{
if(cuda->pinned)
{
double* tmp = new double[old_maxsend];
memcpy((void*) tmp,(void*) *buf_send,old_maxsend*sizeof(double));
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
memcpy(*buf_send,tmp,old_maxsend*sizeof(double));
delete [] tmp;
}
else
{
*buf_send = (double *)
memory->srealloc(*buf_send,(*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
else {
if(cuda->pinned)
{
if(*buf_send) CudaWrapper_FreePinnedHostData((void*) (*buf_send));
*buf_send = (double*) CudaWrapper_AllocPinnedHostData((*maxsend+BUFEXTRA)*sizeof(double),false);
}
else
{
memory->sfree(*buf_send);
*buf_send = (double *) memory->smalloc((*maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
}
}
void AtomVecFullCuda::grow_both(int n)
{
if(cuda->finished_setup)
cuda->downloadAll();
AtomVecFull::grow(n);
if(cuda->finished_setup)
{
cuda->checkResize();
cuda->uploadAll();
}
}
int AtomVecFullCuda::pack_comm(int n, int* iswap, double *buf,
int pbc_flag, int *pbc) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecFull::pack_comm(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackComm(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
int AtomVecFullCuda::pack_comm_vel(int n, int* iswap, double *buf,
int pbc_flag, int *pbc) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecFull::pack_comm_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_CommCuda_PackCommVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
if((sizeof(X_FLOAT)!=sizeof(double)) && m)
m=(m+1)*sizeof(X_FLOAT)/sizeof(double);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecFullCuda::unpack_comm(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecFull::unpack_comm(n,first,buf); return;}
Cuda_CommCuda_UnpackComm(&cuda->shared_data,n,first,(void*)buf);
}
void AtomVecFullCuda::unpack_comm_vel(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only positions are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecFull::unpack_comm_vel(n,first,buf); return;}
Cuda_CommCuda_UnpackCommVel(&cuda->shared_data,n,first,(void*)buf);
}
/* ---------------------------------------------------------------------- */
int AtomVecFullCuda::pack_reverse(int n, int first, double *buf) //usually this should not be called since comm->communicate handles the communication if only forces are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecFull::pack_reverse(n,first,buf);
int i,m,last;
cuda->cu_f->download();
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
cuda->cu_f->upload();
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecFullCuda::unpack_reverse(int n, int *list, double *buf)//usually this should not be called since comm->communicate handles the communication if only forces are exchanged
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecFull::unpack_reverse(n,list,buf); return;}
int i,j,m;
m = 0;
cuda->cu_f->download();
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
cuda->cu_f->upload();
}
/* ---------------------------------------------------------------------- */
int AtomVecFullCuda::pack_border(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecFull::pack_border(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecFullCuda_PackBorder(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
int AtomVecFullCuda::pack_border_vel(int n, int *iswap, double *buf,
int pbc_flag, int *pbc)
{
if(not cuda->finished_setup || cuda->oncpu)
return AtomVecFull::pack_border_vel(n,iswap,buf,pbc_flag,pbc);
int m = Cuda_AtomVecFullCuda_PackBorderVel(&cuda->shared_data,n,*iswap,(void*) buf,pbc,pbc_flag);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecFullCuda::unpack_border(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecFull::unpack_border(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax) //ensure there is enough space on device to unpack data
{
grow_both(0);
}
int flag=Cuda_AtomVecFullCuda_UnpackBorder(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
void AtomVecFullCuda::unpack_border_vel(int n, int first, double *buf)
{
if(not cuda->finished_setup || cuda->oncpu)
{AtomVecFull::unpack_border_vel(n,first,buf); return;}
while(atom->nghost+atom->nlocal+n>=cuda->shared_data.atom.nmax) //ensure there is enough space on device to unpack data
{
grow_both(0);
}
int flag=Cuda_AtomVecFullCuda_UnpackBorderVel(&cuda->shared_data,n,first,(void*)buf);
if(flag) {printf(" # CUDA: Error: Failed to unpack Border atoms (This might be a bug).\n");}
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecFullCuda::pack_exchange(int dim, double *buf)
{
if(cuda->oncpu)
return AtomVecFull::pack_exchange(dim,buf);
if(not cuda_init_done||domain->box_change)
{
Cuda_AtomVecFullCuda_Init(&cuda->shared_data);
cuda_init_done=true;
}
double** buf_pointer=(double**) buf;
if(*maxsend<atom->nghost || *buf_pointer==NULL)
{
grow_send(atom->nghost>*maxsend?atom->nghost:*maxsend,buf_pointer,0);
*maxsend=atom->nghost>*maxsend?atom->nghost:*maxsend;
}
if(max_nsend==0) grow_copylist(200);
int nsend_atoms = Cuda_AtomVecFullCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
if(nsend_atoms>max_nsend) grow_copylist(nsend_atoms+100);
if(nsend_atoms*NCUDAEXCHANGE>*maxsend)
{
grow_send((int) (nsend_atoms+100)*NCUDAEXCHANGE,buf_pointer,0);
Cuda_AtomVecFullCuda_PackExchangeList(&cuda->shared_data,*maxsend,dim,*buf_pointer);
}
int nlocal=atom->nlocal-nsend_atoms;
for(int i=0;i<nsend_atoms;i++) copylist2[i]=1;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i>=nlocal) copylist2[i-nlocal]=-1;
}
int actpos=0;
for(int j=1;j<nsend_atoms+1;j++)
{
int i = static_cast <int> ((*buf_pointer)[j]);
if(i<nlocal)
{
while(copylist2[actpos]==-1) actpos++;
copylist[j-1]=nlocal+actpos;
actpos++;
}
}
cu_copylist->upload();
cuda->shared_data.atom.nlocal=nlocal;
int m = Cuda_AtomVecFullCuda_PackExchange(&cuda->shared_data,nsend_atoms,*buf_pointer,cu_copylist->dev_data());
timespec time1,time2;
clock_gettime(CLOCK_REALTIME,&time1);
double* buf_p=*buf_pointer;
for(int j=0;j<nsend_atoms;j++)
{
int i=static_cast <int> (buf_p[j+1]);
int nextra=0;
int k;
buf_p[m++] = num_bond[i];
for (k = 0; k < num_bond[i]; k++) {
buf_p[m++] = bond_type[i][k];
buf_p[m++] = bond_atom[i][k];
}
nextra+=2*num_bond[i]+1;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
buf_p[m++] = num_angle[i];
for (k = 0; k < num_angle[i]; k++) {
buf_p[m++] = angle_type[i][k];
buf_p[m++] = angle_atom1[i][k];
buf_p[m++] = angle_atom2[i][k];
buf_p[m++] = angle_atom3[i][k];
}
nextra+=4*num_angle[i]+1;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
buf_p[m++] = num_dihedral[i];
for (k = 0; k < num_dihedral[i]; k++) {
buf_p[m++] = dihedral_type[i][k];
buf_p[m++] = dihedral_atom1[i][k];
buf_p[m++] = dihedral_atom2[i][k];
buf_p[m++] = dihedral_atom3[i][k];
buf_p[m++] = dihedral_atom4[i][k];
}
nextra+=5*num_dihedral[i]+1;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
buf_p[m++] = num_improper[i];
for (k = 0; k < num_improper[i]; k++) {
buf_p[m++] = improper_type[i][k];
buf_p[m++] = improper_atom1[i][k];
buf_p[m++] = improper_atom2[i][k];
buf_p[m++] = improper_atom3[i][k];
buf_p[m++] = improper_atom4[i][k];
}
nextra+=5*num_improper[i]+1;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
buf_p[m++] = nspecial[i][0];
buf_p[m++] = nspecial[i][1];
buf_p[m++] = nspecial[i][2];
for (k = 0; k < nspecial[i][2]; k++) buf_p[m++] = special[i][k];
nextra+=nspecial[i][2]+3;
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
{
int dm= modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf_p[m]);
m+=dm;
nextra+=dm;
if(i<nlocal)modify->fix[atom->extra_grow[iextra]]->copy_arrays(copylist[j],i);
if(m>*maxsend) {grow_send(m,buf_pointer,1); buf_p=*buf_pointer;}
}
if(i<nlocal)AtomVecFull::copy(copylist[j],i,1);
(*buf_pointer)[j+1] = nextra;
}
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_exchange_cpu_pack+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
(*buf_pointer)[0] = nsend_atoms;
atom->nlocal-=nsend_atoms;
cuda->shared_data.atom.update_nlocal=2;
//printf("End Pack Exchange\n");
if(m==1) return 0;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecFullCuda::unpack_exchange(double *buf)
{
// printf("Begin UnPack Exchange\n");
if(cuda->oncpu)
return AtomVecFull::unpack_exchange(buf);
double *sublo,*subhi;
int dim=cuda->shared_data.exchange_dim;
if(domain->box_change)
Cuda_AtomVecFullCuda_Init(&cuda->shared_data);
if (domain->triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
int mfirst=0;
for(int pi=0;pi<(comm->procgrid[dim]>2?2:1);pi++)
{
int nlocal = atom->nlocal;
int nsend_atoms=static_cast<int> (buf[0]);
if(nsend_atoms>max_nsend) grow_copylist(nsend_atoms+100);
if (nlocal+nsend_atoms+atom->nghost>=atom->nmax) grow_both(nlocal+nsend_atoms*2+atom->nghost); //ensure there is enough space on device to unpack data
int naccept = Cuda_AtomVecFullCuda_UnpackExchange(&cuda->shared_data,nsend_atoms,buf,cu_copylist->dev_data());
cu_copylist->download();
int m = nsend_atoms*NCUDAEXCHANGE + 1;
nlocal+=naccept;
timespec time1,time2;
clock_gettime(CLOCK_REALTIME,&time1);
for(int j=0;j<nsend_atoms;j++)
{
if(copylist[j]>-1)
{
int k;
int i=copylist[j];
num_bond[i] = static_cast<int> (buf[m++]);
for (k = 0; k < num_bond[i]; k++) {
bond_type[i][k] = static_cast<int> (buf[m++]);
bond_atom[i][k] = static_cast<int> (buf[m++]);
}
num_angle[i] = static_cast<int> (buf[m++]);
for (k = 0; k < num_angle[i]; k++) {
angle_type[i][k] = static_cast<int> (buf[m++]);
angle_atom1[i][k] = static_cast<int> (buf[m++]);
angle_atom2[i][k] = static_cast<int> (buf[m++]);
angle_atom3[i][k] = static_cast<int> (buf[m++]);
}
num_dihedral[i] = static_cast<int> (buf[m++]);
for (k = 0; k < num_dihedral[i]; k++) {
dihedral_type[i][k] = static_cast<int> (buf[m++]);
dihedral_atom1[i][k] = static_cast<int> (buf[m++]);
dihedral_atom2[i][k] = static_cast<int> (buf[m++]);
dihedral_atom3[i][k] = static_cast<int> (buf[m++]);
dihedral_atom4[i][k] = static_cast<int> (buf[m++]);
}
num_improper[i] = static_cast<int> (buf[m++]);
for (k = 0; k < num_improper[i]; k++) {
improper_type[i][k] = static_cast<int> (buf[m++]);
improper_atom1[i][k] = static_cast<int> (buf[m++]);
improper_atom2[i][k] = static_cast<int> (buf[m++]);
improper_atom3[i][k] = static_cast<int> (buf[m++]);
improper_atom4[i][k] = static_cast<int> (buf[m++]);
}
nspecial[i][0] = static_cast<int> (buf[m++]);
nspecial[i][1] = static_cast<int> (buf[m++]);
nspecial[i][2] = static_cast<int> (buf[m++]);
for (k = 0; k < nspecial[i][2]; k++)
special[i][k] = static_cast<int> (buf[m++]);
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(i,&buf[m]);
}
else
m+=static_cast <int> (buf[j+1]);
}
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_exchange_cpu_pack+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
cuda->shared_data.atom.nlocal=nlocal;
cuda->shared_data.atom.update_nlocal=2;
atom->nlocal=nlocal;
mfirst+=m;
buf=&buf[m];
}
return mfirst;
}
diff --git a/src/USER-CUDA/comm_cuda.cpp b/src/USER-CUDA/comm_cuda.cpp
index 4a7a822ae..8e75f93ba 100644
--- a/src/USER-CUDA/comm_cuda.cpp
+++ b/src/USER-CUDA/comm_cuda.cpp
@@ -1,1433 +1,1430 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author (triclinic) : Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include "comm_cuda.h"
#include "atom.h"
#include "atom_vec.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "neighbor.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "compute.h"
#include "cuda.h"
#include "error.h"
#include "memory.h"
#include "comm_cuda_cu.h"
using namespace LAMMPS_NS;
#define BUFFACTOR 1.5
#define BUFMIN 1000
#define BUFEXTRA 1000
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define BIG 1.0e20
enum{SINGLE,MULTI};
/* ----------------------------------------------------------------------
setup MPI and allocate buffer space
------------------------------------------------------------------------- */
CommCuda::CommCuda(LAMMPS *lmp):Comm(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
cu_pbc=NULL;
cu_slablo=NULL;
cu_slabhi=NULL;
cu_multilo=NULL;
cu_multihi=NULL;
cu_sendlist=NULL;
memory->sfree(buf_send);
memory->sfree(buf_recv);
buf_send = NULL;
buf_recv = NULL;
Comm::free_swap();
allocate_swap(maxswap);
}
/* ---------------------------------------------------------------------- */
CommCuda::~CommCuda()
{
delete cu_sendlist;
if(cuda->pinned)
{
CudaWrapper_FreePinnedHostData((void*)buf_send);
CudaWrapper_FreePinnedHostData((void*)buf_recv);
}
else
{
memory->sfree(buf_send);
memory->sfree(buf_recv);
}
buf_send=NULL;
buf_recv=NULL;
}
/* ---------------------------------------------------------------------- */
void CommCuda::init()
{
int factor = 1;
if(cuda->shared_data.overlap_comm) factor=maxswap;
if(not buf_send)
grow_send(maxsend,0);
if(not buf_recv)
grow_recv(maxrecv);
if(not cu_sendlist)
{
cu_sendlist=new cCudaData<int, int, xy> ((int*)sendlist,maxswap,BUFMIN);
cuda->shared_data.comm.sendlist.dev_data=cu_sendlist->dev_data();
cuda->shared_data.comm.maxswap=maxswap;
cuda->shared_data.comm.maxlistlength=BUFMIN;
cu_sendlist->upload();
}
delete cu_pbc;
cu_pbc=new cCudaData<int, int, xy> ((int*)pbc,cuda->shared_data.comm.maxswap,6);
cu_pbc->upload();
delete cu_slablo;
cu_slablo = new cCudaData<double, X_FLOAT,x>(slablo,cuda->shared_data.comm.maxswap);
cu_slablo->upload();
delete cu_slabhi;
cu_slabhi = new cCudaData<double, X_FLOAT,x>(slabhi,cuda->shared_data.comm.maxswap);
cu_slabhi->upload();
cuda->shared_data.comm.pbc.dev_data=cu_pbc->dev_data();
cuda->shared_data.comm.slablo.dev_data=cu_slablo->dev_data();
cuda->shared_data.comm.slabhi.dev_data=cu_slabhi->dev_data();
Comm::init();
}
/* ----------------------------------------------------------------------
setup spatial-decomposition communication patterns
function of neighbor cutoff(s) & cutghostuser & current box size
single style sets slab boundaries (slablo,slabhi) based on max cutoff
multi style sets type-dependent slab boundaries (multilo,multihi)
------------------------------------------------------------------------- */
void CommCuda::setup()
{
Comm::setup();
//upload changed geometry to device
if(style == SINGLE)
{
if(cu_slablo) cu_slablo->upload();
if(cu_slabhi) cu_slabhi->upload();
}
else
{
if(cu_multilo) cu_multilo->upload();
if(cu_multihi) cu_multihi->upload();
}
}
/* ----------------------------------------------------------------------
forward communication of atom coords every timestep
other per-atom attributes may also be sent via pack/unpack routines
------------------------------------------------------------------------- */
void CommCuda::forward_comm(int mode)
{
if(mode==0) return forward_comm_cuda();
if(mode==1) return forward_comm_pack_cuda();
if(mode==2) return forward_comm_transfer_cuda();
if(mode==3) return forward_comm_unpack_cuda();
}
void CommCuda::forward_comm_cuda()
{
static int count=0;
static double kerneltime=0.0;
static double copytime=0.0;
timespec time1,time2,time3;
int n;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **x = atom->x;
cuda->shared_data.domain.xy=domain->xy;
cuda->shared_data.domain.xz=domain->xz;
cuda->shared_data.domain.yz=domain->yz;
cuda->shared_data.domain.prd[0]=domain->prd[0];
cuda->shared_data.domain.prd[1]=domain->prd[1];
cuda->shared_data.domain.prd[2]=domain->prd[2];
cuda->shared_data.domain.triclinic=domain->triclinic;
if(not comm_x_only && not avec->cudable)
{
cuda->downloadAll();
Comm::forward_comm();
cuda->uploadAll();
return;
}
// exchange data with another proc
// if other proc is self, just copy
// if comm_x_only set, exchange or copy directly to x, don't unpack
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap] != me)
{
if (comm_x_only)
{
int size_forward_recv_now=0;
if((sizeof(X_FLOAT)!=sizeof(double)) && size_forward_recv[iswap]) //some complicated way to safe some transfer size if single precision is used
size_forward_recv_now=(size_forward_recv[iswap]+1)*sizeof(X_FLOAT)/sizeof(double);
else
size_forward_recv_now=size_forward_recv[iswap];
clock_gettime(CLOCK_REALTIME,&time1);
MPI_Irecv(buf_recv,size_forward_recv_now,MPI_DOUBLE,
recvproc[iswap],0,world,&request);
n = Cuda_CommCuda_PackComm(&cuda->shared_data,sendnum[iswap],iswap,(void*) buf_send,pbc[iswap],pbc_flag[iswap]);
clock_gettime(CLOCK_REALTIME,&time2);
if((sizeof(X_FLOAT)!=sizeof(double)) && n) //some complicated way to safe some transfer size if single precision is used
n=(n+1)*sizeof(X_FLOAT)/sizeof(double);
//printf("RecvSize: %i SendSize: %i\n",size_forward_recv_now,n);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
clock_gettime(CLOCK_REALTIME,&time3);
cuda->shared_data.cuda_timings.comm_forward_mpi_upper+=
time3.tv_sec-time1.tv_sec+1.0*(time3.tv_nsec-time1.tv_nsec)/1000000000;
cuda->shared_data.cuda_timings.comm_forward_mpi_lower+=
time3.tv_sec-time2.tv_sec+1.0*(time3.tv_nsec-time2.tv_nsec)/1000000000;
Cuda_CommCuda_UnpackComm(&cuda->shared_data,recvnum[iswap],firstrecv[iswap],(void*)buf_recv,iswap); //Unpack for cpu exchange happens implicitely since buf==x[firstrecv]
}
else if (ghost_velocity)
{
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
if(avec->cudable)
n = avec->pack_comm_vel(sendnum[iswap],&iswap,
buf_send,pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_recv);
}
else
{
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
if(avec->cudable)
n = avec->pack_comm(sendnum[iswap],&iswap,
buf_send,pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_recv);
}
}
else //sendproc == me
{
cuda->self_comm=1;
if (comm_x_only)
{
if (sendnum[iswap])
{
n = Cuda_CommCuda_PackComm_Self(&cuda->shared_data,sendnum[iswap],iswap,firstrecv[iswap],pbc[iswap],pbc_flag[iswap]);
- if(n<0) error->all(" # CUDA ERRROR on PackComm_Self");
+ if(n<0) error->all(FLERR," # CUDA ERRROR on PackComm_Self");
if((sizeof(X_FLOAT)!=sizeof(double)) && n)
n=(n+1)*sizeof(X_FLOAT)/sizeof(double);
}
}
else if (ghost_velocity)
{
n = avec->pack_comm_vel(sendnum[iswap],&iswap,
(double*) firstrecv,pbc_flag[iswap],pbc[iswap]);
//avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],(double*) firstrecv);
}
else
{
n = avec->pack_comm(sendnum[iswap],&iswap,
(double*) firstrecv,pbc_flag[iswap],pbc[iswap]);
//avec->unpack_comm(recvnum[iswap],firstrecv[iswap],(double*) firstrecv);
}
cuda->self_comm=0;
}
}
}
void CommCuda::forward_comm_pack_cuda()
{
static int count=0;
static double kerneltime=0.0;
static double copytime=0.0;
timespec time1,time2,time3;
int n; // initialize comm buffers & exchange memory
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **x = atom->x;
cuda->shared_data.domain.xy=domain->xy;
cuda->shared_data.domain.xz=domain->xz;
cuda->shared_data.domain.yz=domain->yz;
cuda->shared_data.domain.prd[0]=domain->prd[0];
cuda->shared_data.domain.prd[1]=domain->prd[1];
cuda->shared_data.domain.prd[2]=domain->prd[2];
cuda->shared_data.domain.triclinic=domain->triclinic;
if(not comm_x_only && not avec->cudable) cuda->downloadAll(); //if not comm_x_only the communication routine of the atom_vec style class is used
// exchange data with another proc
// if other proc is self, just copy
// if comm_x_only set, exchange or copy directly to x, don't unpack
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap] != me)
{
if (comm_x_only)
{
clock_gettime(CLOCK_REALTIME,&time1);
// n = Cuda_CommCuda_PackComm(&cuda->shared_data,sendnum[iswap],iswap,(void*) cuda->shared_data.comm.buf_send[iswap],pbc[iswap],pbc_flag[iswap]);
n = Cuda_CommCuda_PackComm(&cuda->shared_data,sendnum[iswap],iswap,(void*)buf_send,pbc[iswap],pbc_flag[iswap]);
clock_gettime(CLOCK_REALTIME,&time2);
if((sizeof(X_FLOAT)!=sizeof(double)) && n) //some complicated way to safe some transfer size if single precision is used
n=(n+1)*sizeof(X_FLOAT)/sizeof(double);
cuda->shared_data.comm.send_size[iswap]=n;
}
else if (ghost_velocity)
{
clock_gettime(CLOCK_REALTIME,&time1);
// n = Cuda_CommCuda_PackComm_Vel(&cuda->shared_data,sendnum[iswap],iswap,(void*) &buf_send[iswap*maxsend],pbc[iswap],pbc_flag[iswap]);
clock_gettime(CLOCK_REALTIME,&time2);
if((sizeof(X_FLOAT)!=sizeof(double)) && n) //some complicated way to safe some transfer size if single precision is used
n=(n+1)*sizeof(X_FLOAT)/sizeof(double);
cuda->shared_data.comm.send_size[iswap]=n;
}
else
{
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
if(avec->cudable)
n = avec->pack_comm(sendnum[iswap],&iswap,
cuda->shared_data.comm.buf_send[iswap],pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
cuda->shared_data.comm.buf_send[iswap],pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_recv);
}
}
else //sendproc == me
{
if (comm_x_only)
{
if (sendnum[iswap])
{
n = Cuda_CommCuda_PackComm_Self(&cuda->shared_data,sendnum[iswap],iswap,firstrecv[iswap],pbc[iswap],pbc_flag[iswap]);
- if(n<0) error->all(" # CUDA ERRROR on PackComm_Self");
+ if(n<0) error->all(FLERR," # CUDA ERRROR on PackComm_Self");
if((sizeof(X_FLOAT)!=sizeof(double)) && n)
n=(n+1)*sizeof(X_FLOAT)/sizeof(double);
}
}
else if (ghost_velocity)
{
n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_send);
}
else
{
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_send);
}
}
}
if(not comm_x_only && not avec->cudable) cuda->uploadAll();
}
void CommCuda::forward_comm_transfer_cuda()
{
static int count=0;
static double kerneltime=0.0;
static double copytime=0.0;
timespec time1,time2,time3;
int n;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **x = atom->x;
cuda->shared_data.domain.xy=domain->xy;
cuda->shared_data.domain.xz=domain->xz;
cuda->shared_data.domain.yz=domain->yz;
cuda->shared_data.domain.prd[0]=domain->prd[0];
cuda->shared_data.domain.prd[1]=domain->prd[1];
cuda->shared_data.domain.prd[2]=domain->prd[2];
cuda->shared_data.domain.triclinic=domain->triclinic;
if(not comm_x_only && not avec->cudable) cuda->downloadAll(); //if not comm_x_only the communication routine of the atom_vec style class is used
//printf("A\n");
// exchange data with another proc
// if other proc is self, just copy
// if comm_x_only set, exchange or copy directly to x, don't unpack
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap] != me)
{
if (comm_x_only)
{
int size_forward_recv_now=0;
if((sizeof(X_FLOAT)!=sizeof(double)) && size_forward_recv[iswap]) //some complicated way to safe some transfer size if single precision is used
size_forward_recv_now=(size_forward_recv[iswap]+1)*sizeof(X_FLOAT)/sizeof(double);
else
size_forward_recv_now=size_forward_recv[iswap];
//printf("A: %i \n",size_forward_recv_now/1024*4);
//MPI_Irecv(cuda->shared_data.comm.buf_recv[iswap],size_forward_recv_now,MPI_DOUBLE,
// recvproc[iswap],0,world,&request);
MPI_Irecv(buf_recv,size_forward_recv_now,MPI_DOUBLE,
recvproc[iswap],0,world,&request);
//printf("%p %p %i\n",buf_send, cuda->shared_data.comm.buf_send_dev[iswap], cuda->shared_data.comm.send_size[iswap]*sizeof(double));
//memcpy(buf_send,cuda->shared_data.comm.buf_send[iswap],cuda->shared_data.comm.send_size[iswap]*sizeof(double));
// CudaWrapper_SyncStream(1);
//printf("B: %i \n",cuda->shared_data.comm.send_size[iswap]/1024*4);
CudaWrapper_DownloadCudaDataAsync((void*) buf_send, cuda->shared_data.comm.buf_send_dev[iswap], cuda->shared_data.comm.send_size[iswap]*sizeof(double),2);
//MPI_Send(cuda->shared_data.comm.buf_send[iswap],cuda->shared_data.comm.send_size[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
clock_gettime(CLOCK_REALTIME,&time1);
CudaWrapper_SyncStream(2);
//printf("C: %i \n",cuda->shared_data.comm.send_size[iswap]/1024*4);
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_forward_download+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
MPI_Send(buf_send,cuda->shared_data.comm.send_size[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
//printf("D: %i \n",cuda->shared_data.comm.send_size[iswap]/1024*4);
CudaWrapper_UploadCudaDataAsync((void*) buf_recv,cuda->shared_data.comm.buf_recv_dev[iswap], size_forward_recv_now*sizeof(double),2);
clock_gettime(CLOCK_REALTIME,&time1);
CudaWrapper_SyncStream(2);
//printf("E: %i \n",cuda->shared_data.comm.send_size[iswap]/1024*4);
//memcpy(cuda->shared_data.comm.buf_recv[iswap],buf_recv,size_forward_recv_now*sizeof(double));
//printf("RecvSize: %i SendSize: %i\n",size_forward_recv_now*sizeof(double),cuda->shared_data.comm.send_size[iswap]*sizeof(double));
clock_gettime(CLOCK_REALTIME,&time3);
cuda->shared_data.cuda_timings.comm_forward_upload+=
time3.tv_sec-time1.tv_sec+1.0*(time3.tv_nsec-time1.tv_nsec)/1000000000;
cuda->shared_data.cuda_timings.comm_forward_mpi_lower+=
time3.tv_sec-time2.tv_sec+1.0*(time3.tv_nsec-time2.tv_nsec)/1000000000;
clock_gettime(CLOCK_REALTIME,&time3);
cuda->shared_data.cuda_timings.comm_forward_mpi_upper+=
time3.tv_sec-time1.tv_sec+1.0*(time3.tv_nsec-time1.tv_nsec)/1000000000;
}
else if (ghost_velocity)
{
/* int size_forward_recv_now=0;
if((sizeof(X_FLOAT)!=sizeof(double)) && size_forward_recv[iswap]) //some complicated way to safe some transfer size if single precision is used
size_forward_recv_now=(size_forward_recv[iswap]+1)*sizeof(X_FLOAT)/sizeof(double);
else
size_forward_recv_now=size_forward_recv[iswap];
clock_gettime(CLOCK_REALTIME,&time1);
MPI_Irecv(cuda->shared_data.comm.buf_recv[iswap],size_forward_recv_now,MPI_DOUBLE,
recvproc[iswap],0,world,&request);
clock_gettime(CLOCK_REALTIME,&time2);
MPI_Send(cuda->shared_data.comm.buf_send[iswap],cuda->shared_data.comm.send_size[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
clock_gettime(CLOCK_REALTIME,&time3);
cuda->shared_data.cuda_timings.comm_forward_mpi_upper+=
time3.tv_sec-time1.tv_sec+1.0*(time3.tv_nsec-time1.tv_nsec)/1000000000;
cuda->shared_data.cuda_timings.comm_forward_mpi_lower+=
time3.tv_sec-time2.tv_sec+1.0*(time3.tv_nsec-time2.tv_nsec)/1000000000;*/
}
else
{
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
if(avec->cudable)
n = avec->pack_comm(sendnum[iswap],&iswap,
buf_send,pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_recv);
}
}
else //sendproc == me
{
if (comm_x_only)
{
if (sendnum[iswap])
{
}
}
else if (ghost_velocity)
{
}
else
{
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_send);
}
}
}
if(not comm_x_only && not avec->cudable) cuda->uploadAll();
}
void CommCuda::forward_comm_unpack_cuda()
{
static int count=0;
static double kerneltime=0.0;
static double copytime=0.0;
timespec time1,time2,time3;
int n;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **x = atom->x;
cuda->shared_data.domain.xy=domain->xy;
cuda->shared_data.domain.xz=domain->xz;
cuda->shared_data.domain.yz=domain->yz;
cuda->shared_data.domain.prd[0]=domain->prd[0];
cuda->shared_data.domain.prd[1]=domain->prd[1];
cuda->shared_data.domain.prd[2]=domain->prd[2];
cuda->shared_data.domain.triclinic=domain->triclinic;
if(not comm_x_only && not avec->cudable) cuda->downloadAll(); //if not comm_x_only the communication routine of the atom_vec style class is used
// exchange data with another proc
// if other proc is self, just copy
// if comm_x_only set, exchange or copy directly to x, don't unpack
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap] != me)
{
if (comm_x_only)
{
//Cuda_CommCuda_UnpackComm(&cuda->shared_data,recvnum[iswap],firstrecv[iswap],cuda->shared_data.comm.buf_recv[iswap],iswap); //Unpack for cpu exchange happens implicitely since buf==x[firstrecv]
Cuda_CommCuda_UnpackComm(&cuda->shared_data,recvnum[iswap],firstrecv[iswap],buf_recv,iswap); //Unpack for cpu exchange happens implicitely since buf==x[firstrecv]
}
else if (ghost_velocity)
{
//Cuda_CommCuda_UnpackComm_Vel(&cuda->shared_data,recvnum[iswap],firstrecv[iswap],(void*)&buf_recv[iswap*maxrecv]); //Unpack for cpu exchange happens implicitely since buf==x[firstrecv]
}
else
{
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
if(avec->cudable)
n = avec->pack_comm(sendnum[iswap],&iswap,
buf_send,pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_recv);
}
}
else //sendproc == me
{
if (comm_x_only)
{
if (sendnum[iswap])
{
}
}
else if (ghost_velocity)
{
}
else
{
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_send);
}
}
}
if(not comm_x_only && not avec->cudable) cuda->uploadAll();
}
void CommCuda::forward_comm_pair(Pair *pair)
{
if(not cuda->shared_data.pair.cudable_force)
{
return Comm::forward_comm_pair(pair);
}
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = 0; iswap < nswap; iswap++) {
// pack buffer
n = pair->pack_comm(sendnum[iswap],&iswap,
buf_send,pbc_flag[iswap],pbc[iswap]);
int nrecv = recvnum[iswap]*n;
if(nrecv<0) nrecv=-(nrecv+1)/2;
int nsend = sendnum[iswap]*n;
if(nsend<0) nsend=-(nsend+1)/2;
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,nrecv,MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Send(buf_send,nsend,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
pair->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
}
}
/* ----------------------------------------------------------------------
reverse communication of forces on atoms every timestep
other per-atom attributes may also be sent via pack/unpack routines
------------------------------------------------------------------------- */
void CommCuda::reverse_comm()
{
int n;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **f = atom->f;
double *buf;
if(not comm_f_only && not avec->cudable) cuda->downloadAll(); //not yet implemented in CUDA but only needed for non standard atom styles
// exchange data with another proc
// if other proc is self, just copy
// if comm_f_only set, exchange or copy directly from f, don't pack
for (int iswap = nswap-1; iswap >= 0; iswap--) {
if (sendproc[iswap] != me) {
if (comm_f_only) {
int size_recv_now=size_reverse_recv[iswap];
if((sizeof(F_FLOAT)!=sizeof(double))&& size_reverse_recv[iswap])
size_recv_now=(size_recv_now+1)*sizeof(F_FLOAT)/sizeof(double);
MPI_Irecv(buf_recv,size_recv_now,MPI_DOUBLE,
sendproc[iswap],0,world,&request);
buf=buf_send;
if (size_reverse_send[iswap])
{
Cuda_CommCuda_PackReverse(&cuda->shared_data,size_reverse_send[iswap]/3,firstrecv[iswap],buf);
}
else buf=NULL;
int size_reverse_send_now=size_reverse_send[iswap];
if((sizeof(F_FLOAT)!=sizeof(double))&& size_reverse_send[iswap])
size_reverse_send_now=(size_reverse_send_now+1)*sizeof(F_FLOAT)/sizeof(double);
MPI_Send(buf,size_reverse_send_now,MPI_DOUBLE,
recvproc[iswap],0,world);
MPI_Wait(&request,&status);
Cuda_CommCuda_UnpackReverse(&cuda->shared_data,sendnum[iswap],iswap,buf_recv);
} else {
MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,
sendproc[iswap],0,world,&request);
n = avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],buf_recv);
}
} else {
if (comm_f_only) {
if (sendnum[iswap])
Cuda_CommCuda_UnpackReverse_Self(&cuda->shared_data,sendnum[iswap],iswap,firstrecv[iswap]);
} else {
n = avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],buf_send);
}
}
}
if(not comm_f_only && not avec->cudable) cuda->uploadAll(); //not yet implemented in CUDA but only needed for non standard atom styles
}
/* ----------------------------------------------------------------------
exchange: move atoms to correct processors
atoms exchanged with all 6 stencil neighbors
send out atoms that have left my box, receive ones entering my box
atoms will be lost if not inside some proc's box
can happen if atom moves outside of non-periodic bounary
or if atom moves more than one proc away
this routine called before every reneighboring
for triclinic, atoms must be in lamda coords (0-1) before exchange is called
------------------------------------------------------------------------- */
void CommCuda::exchange()
{
AtomVec *avec = atom->avec;
if(not cuda->oncpu && avec->cudable)
return exchange_cuda();
if(not cuda->oncpu) cuda->downloadAll();
Comm::exchange();
}
void CommCuda::exchange_cuda()
{
int i,m,nsend,nrecv,nrecv1,nrecv2,nlocal;
double lo,hi,value;
double **x;
double *sublo,*subhi,*buf;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
timespec time1,time2,time3;
// clear global->local map for owned and ghost atoms
// b/c atoms migrate to new procs in exchange() and
// new ghosts are created in borders()
// map_set() is done at end of borders()
if(map_style) cuda->cu_tag->download();
if (map_style) atom->map_clear();
// subbox bounds for orthogonal or triclinic
if (triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
// loop over dimensions
for (int dim = 0; dim < 3; dim++) {
// fill buffer with atoms leaving my box, using < and >=
// when atom is deleted, fill it in with last atom
cuda->shared_data.exchange_dim=dim;
nlocal = atom->nlocal;
avec->maxsend=&maxsend;
nsend=avec->pack_exchange(dim,(double*) &buf_send);
nlocal = atom->nlocal;
atom->nlocal = nlocal;
// send/recv atoms in both directions
// if 1 proc in dimension, no send/recv, set recv buf to send buf
// if 2 procs in dimension, single send/recv
// if more than 2 procs in dimension, send/recv to both neighbors
clock_gettime(CLOCK_REALTIME,&time1);
if (procgrid[dim] == 1) {
nrecv = nsend;
buf = buf_send;
} else {
MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][0],0,
&nrecv1,1,MPI_INT,procneigh[dim][1],0,world,&status);
nrecv = nrecv1;
if (procgrid[dim] > 2) {
MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][1],0,
&nrecv2,1,MPI_INT,procneigh[dim][0],0,world,&status);
nrecv += nrecv2;
}
if (nrecv+1 > maxrecv) grow_recv(nrecv+1);
MPI_Irecv(buf_recv,nrecv1,MPI_DOUBLE,procneigh[dim][1],0,
world,&request);
MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][0],0,world);
MPI_Wait(&request,&status);
if (procgrid[dim] > 2) {
MPI_Irecv(&buf_recv[nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0,
world,&request);
MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][1],0,world);
MPI_Wait(&request,&status);
if((nrecv1==0)||(nrecv2==0)) buf_recv[nrecv]=0;
}
buf = buf_recv;
}
//printf("nsend: %i nrecv: %i\n",nsend,nrecv);
// check incoming atoms to see if they are in my box
// if so, add to my list
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_exchange_mpi+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
if(nrecv)
{
avec->maxsend=&maxsend;
avec->unpack_exchange(buf);
}
}
if(atom->firstgroupname) cuda->downloadAll();
if(atom->firstgroupname) atom->first_reorder();
if(atom->firstgroupname) cuda->uploadAll();
}
/* ----------------------------------------------------------------------
borders: list nearby atoms to send to neighboring procs at every timestep
one list is created for every swap that will be made
as list is made, actually do swaps
this does equivalent of a communicate (so don't need to explicitly
call communicate routine on reneighboring timestep)
this routine is called before every reneighboring
for triclinic, atoms must be in lamda coords (0-1) before borders is called
------------------------------------------------------------------------- */
void CommCuda::borders()
{
AtomVec *avec = atom->avec;
if(not cuda->oncpu && avec->cudable)
{
if(cuda->shared_data.overlap_comm&&cuda->finished_setup)
borders_cuda_overlap_forward_comm();
else
borders_cuda();
return;
}
Comm::borders();
cuda->setSystemParams();
if(cuda->finished_setup) {cuda->checkResize(); cuda->uploadAll();}
cuda->shared_data.atom.nghost=atom->nghost;
cu_sendlist->upload();
}
void CommCuda::borders_cuda()
{
int i,n,itype,iswap,dim,ineed,maxneed,smax,rmax;
int nsend,nrecv,nfirst,nlast,ngroup;
double lo,hi;
int *type;
double **x;
double *buf,*mlo,*mhi;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
timespec time1,time2,time3;
// clear old ghosts
atom->nghost = 0;
// do swaps over all 3 dimensions
iswap = 0;
smax = rmax = 0;
cuda->shared_data.comm.nsend=0;
for (dim = 0; dim < 3; dim++) {
nlast = 0;
maxneed = 2*need[dim];
for (ineed = 0; ineed < maxneed; ineed++) {
// find atoms within slab boundaries lo/hi using <= and >=
// check atoms between nfirst and nlast
// for first swaps in a dim, check owned and ghost
// for later swaps in a dim, only check newly arrived ghosts
// store sent atom indices in list for use in future timesteps
x = atom->x;
if (style == SINGLE) {
lo = slablo[iswap];
hi = slabhi[iswap];
} else {
type = atom->type;
mlo = multilo[iswap];
mhi = multihi[iswap];
}
if (ineed % 2 == 0) {
nfirst = nlast;
nlast = atom->nlocal + atom->nghost;
}
nsend = 0;
// find send atoms according to SINGLE vs MULTI
// all atoms eligible versus atoms in bordergroup
// only need to limit loop to bordergroup for first sends (ineed < 2)
// on these sends, break loop in two: owned (in group) and ghost
do
{
if(nsend>=maxsendlist[iswap]) grow_list(iswap,static_cast <int> (nsend*1.05));
nsend=Cuda_CommCuda_BuildSendlist(&cuda->shared_data,bordergroup,ineed,style==SINGLE?1:0,atom->nfirst,nfirst,nlast,dim,iswap);
}while(nsend>=maxsendlist[iswap]);
// pack up list of border atoms
if (nsend*size_border > maxsend)
grow_send(nsend*size_border,0);
if (ghost_velocity)
n = avec->pack_border_vel(nsend,&iswap,buf_send,
pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_border(nsend,&iswap,buf_send,
pbc_flag[iswap],pbc[iswap]);
// swap atoms with other proc
// put incoming ghosts at end of my atom arrays
// if swapping with self, simply copy, no messages
clock_gettime(CLOCK_REALTIME,&time1);
if (sendproc[iswap] != me) {
MPI_Sendrecv(&nsend,1,MPI_INT,sendproc[iswap],0,
&nrecv,1,MPI_INT,recvproc[iswap],0,world,&status);
if (nrecv*size_border > maxrecv)
grow_recv(nrecv*size_border);
MPI_Irecv(buf_recv,nrecv*size_border,MPI_DOUBLE,
recvproc[iswap],0,world,&request);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else {
nrecv = nsend;
buf = buf_send;
}
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_border_mpi+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
// unpack buffer
if (ghost_velocity)
avec->unpack_border_vel(nrecv,atom->nlocal+atom->nghost,buf);
else
avec->unpack_border(nrecv,atom->nlocal+atom->nghost,buf);
// set all pointers & counters
smax = MAX(smax,nsend);
rmax = MAX(rmax,nrecv);
sendnum[iswap] = nsend;
recvnum[iswap] = nrecv;
size_forward_recv[iswap] = nrecv*size_forward;
size_reverse_send[iswap] = nrecv*size_reverse;
size_reverse_recv[iswap] = nsend*size_reverse;
firstrecv[iswap] = atom->nlocal + atom->nghost;
atom->nghost += nrecv;
iswap++;
}
}
// insure send/recv buffers are long enough for all forward & reverse comm
int max = MAX(maxforward*smax,maxreverse*rmax);
if (max > maxsend) grow_send(max,0);
max = MAX(maxforward*rmax,maxreverse*smax);
if (max > maxrecv) grow_recv(max);
// reset global->local map
if(map_style)
{
cuda->cu_tag->download();
atom->map_set();
}
cuda->setSystemParams();
cuda->shared_data.atom.nghost+=n;
}
void CommCuda::borders_cuda_overlap_forward_comm()
{
int i,n,itype,iswap,dim,ineed,maxneed,smax,rmax;
int nsend,nrecv,nfirst,nlast,ngroup;
double lo,hi;
int *type;
double **x;
double *buf,*mlo,*mhi;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
timespec time1,time2,time3;
// clear old ghosts
atom->nghost = 0;
// do swaps over all 3 dimensions
iswap = 0;
smax = rmax = 0;
cuda->shared_data.comm.nsend=0;
for (dim = 0; dim < 3; dim++) {
nlast = 0;
maxneed = 2*need[dim];
for (ineed = 0; ineed < maxneed; ineed++) {
// find atoms within slab boundaries lo/hi using <= and >=
// check atoms between nfirst and nlast
// for first swaps in a dim, check owned and ghost
// for later swaps in a dim, only check newly arrived ghosts
// store sent atom indices in list for use in future timesteps
x = atom->x;
if (style == SINGLE) {
lo = slablo[iswap];
hi = slabhi[iswap];
} else {
type = atom->type;
mlo = multilo[iswap];
mhi = multihi[iswap];
}
if (ineed % 2 == 0) {
nfirst = nlast;
nlast = atom->nlocal + atom->nghost;
}
nsend = 0;
// find send atoms according to SINGLE vs MULTI
// all atoms eligible versus atoms in bordergroup
// only need to limit loop to bordergroup for first sends (ineed < 2)
// on these sends, break loop in two: owned (in group) and ghost
do
{
if(nsend>=maxsendlist[iswap]) grow_list(iswap,static_cast <int> (nsend*1.05));
nsend=Cuda_CommCuda_BuildSendlist(&cuda->shared_data,bordergroup,ineed,style==SINGLE?1:0,atom->nfirst,nfirst,nlast,dim,iswap);
}while(nsend>=maxsendlist[iswap]);
cuda->shared_data.comm.nsend_swap[iswap]=nsend;
// pack up list of border atoms
if (nsend*size_border > maxsend)
grow_send(nsend*size_border,0);
if (ghost_velocity)
n = avec->pack_border_vel(nsend,&iswap,buf_send,
pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_border(nsend,&iswap,buf_send,
pbc_flag[iswap],pbc[iswap]);
// swap atoms with other proc
// put incoming ghosts at end of my atom arrays
// if swapping with self, simply copy, no messages
clock_gettime(CLOCK_REALTIME,&time1);
if (sendproc[iswap] != me) {
MPI_Sendrecv(&nsend,1,MPI_INT,sendproc[iswap],0,
&nrecv,1,MPI_INT,recvproc[iswap],0,world,&status);
if (nrecv*size_border > maxrecv)
grow_recv(nrecv*size_border);
MPI_Irecv(buf_recv,nrecv*size_border,MPI_DOUBLE,
recvproc[iswap],0,world,&request);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else {
nrecv = nsend;
buf = buf_send;
}
clock_gettime(CLOCK_REALTIME,&time2);
cuda->shared_data.cuda_timings.comm_border_mpi+=
time2.tv_sec-time1.tv_sec+1.0*(time2.tv_nsec-time1.tv_nsec)/1000000000;
// unpack buffer
if (ghost_velocity)
avec->unpack_border_vel(nrecv,atom->nlocal+atom->nghost,buf);
else
avec->unpack_border(nrecv,atom->nlocal+atom->nghost,buf);
// set all pointers & counters
smax = MAX(smax,nsend);
rmax = MAX(rmax,nrecv);
sendnum[iswap] = nsend;
recvnum[iswap] = nrecv;
size_forward_recv[iswap] = nrecv*size_forward;
size_reverse_send[iswap] = nrecv*size_reverse;
size_reverse_recv[iswap] = nsend*size_reverse;
firstrecv[iswap] = atom->nlocal + atom->nghost;
atom->nghost += nrecv;
iswap++;
}
}
// insure send/recv buffers are long enough for all forward & reverse comm
int max = MAX(maxforward*smax,maxreverse*rmax);
if (max > maxsend) grow_send(max,0);
max = MAX(maxforward*rmax,maxreverse*smax);
if (max > maxrecv) grow_recv(max);
// reset global->local map
if(map_style)
{
cuda->cu_tag->download();
atom->map_set();
}
cuda->setSystemParams();
cuda->shared_data.atom.nghost+=n;
}
void CommCuda::forward_comm_fix(Fix *fix)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = 0; iswap < nswap; iswap++) {
// pack buffer
if(fix->cudable_comm&&cuda->finished_setup)
{
int swap=iswap;
if(sendproc[iswap] == me) {swap=-iswap-1; buf=(double*)&(firstrecv[iswap]);}
else buf=buf_send;
n = fix->pack_comm(sendnum[iswap],&swap,
buf,pbc_flag[iswap],pbc[iswap]);
if(sendproc[iswap] == me)
{
continue;
}
}
else
n = fix->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
fix->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
}
}
void CommCuda::grow_send(int n, int flag)
{
int oldmaxsend = (maxsend+BUFEXTRA)*sizeof(double);
maxsend = static_cast<int> (BUFFACTOR * n);
if (flag){
if(cuda->pinned)
{
double* tmp = new double[oldmaxsend];
memcpy((void*) tmp,(void*) buf_send,oldmaxsend*sizeof(double));
if(buf_send) CudaWrapper_FreePinnedHostData((void*) (buf_send));
buf_send = (double*) CudaWrapper_AllocPinnedHostData((maxsend+BUFEXTRA)*sizeof(double),false);
memcpy(buf_send,tmp,oldmaxsend*sizeof(double));
delete [] tmp;
}
else
{
buf_send = (double *)
memory->srealloc(buf_send,(maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");printf("srealloc\n");
}
}
else {
if(cuda->pinned)
{
if(buf_send) CudaWrapper_FreePinnedHostData((void*) buf_send);
buf_send = (double*) CudaWrapper_AllocPinnedHostData((maxsend+BUFEXTRA)*sizeof(double),false);
}
else
{
memory->sfree(buf_send);
buf_send = (double *) memory->smalloc((maxsend+BUFEXTRA)*sizeof(double),
"comm:buf_send");
}
for(int i=0;i<maxswap;i++)
{
if(cuda->shared_data.comm.buf_send_dev[i]) CudaWrapper_FreeCudaData(cuda->shared_data.comm.buf_send_dev[i],oldmaxsend);
cuda->shared_data.comm.buf_send_dev[i]=CudaWrapper_AllocCudaData((maxsend+BUFEXTRA)*sizeof(double));
}
}
}
/* ----------------------------------------------------------------------
free/malloc the size of the recv buffer as needed with BUFFACTOR
------------------------------------------------------------------------- */
void CommCuda::grow_recv(int n)
{
int oldmaxrecv = maxrecv*sizeof(double);
maxrecv = static_cast<int> (BUFFACTOR * n);
if(cuda->pinned)
{
if(buf_recv) CudaWrapper_FreePinnedHostData((void*)buf_recv);
buf_recv = (double*) CudaWrapper_AllocPinnedHostData(maxrecv*sizeof(double), false,true);
}
else
{
memory->sfree(buf_recv);
buf_recv = (double *) memory->smalloc(maxrecv*sizeof(double),
"comm:buf_recv");
}
for(int i=0;i<maxswap;i++)
{
if(cuda->shared_data.comm.buf_recv_dev[i]) CudaWrapper_FreeCudaData(cuda->shared_data.comm.buf_recv_dev[i],oldmaxrecv);
cuda->shared_data.comm.buf_recv_dev[i]=CudaWrapper_AllocCudaData((maxrecv)*sizeof(double));
}
}
/* ----------------------------------------------------------------------
realloc the size of the iswap sendlist as needed with BUFFACTOR
------------------------------------------------------------------------- */
void CommCuda::grow_list(int iswap, int n)
{
MYDBG(printf(" # CUDA CommCuda::grow_list\n");)
if(cuda->finished_setup&&cu_sendlist) cu_sendlist->download();
if(!cu_sendlist||n*BUFFACTOR>cu_sendlist->get_dim()[1]||n*BUFFACTOR>maxsendlist[iswap])
{
for(int i=0;i<maxswap;i++)
{
maxsendlist[i] = static_cast<int> (BUFFACTOR * n);
sendlist[i] = (int *)
memory->srealloc(sendlist[i],maxsendlist[i]*sizeof(int),
"comm:sendlist[iswap]");
}
delete cu_sendlist;
cu_sendlist=new cCudaData<int, int, xy> ((int*)sendlist,maxswap,maxsendlist[iswap]);
cuda->shared_data.comm.sendlist.dev_data=cu_sendlist->dev_data();
cuda->shared_data.comm.maxlistlength=maxsendlist[iswap];
cu_sendlist->upload();
}
}
/* ----------------------------------------------------------------------
realloc the buffers needed for swaps
------------------------------------------------------------------------- */
void CommCuda::grow_swap(int n)
{
int oldmaxswap=maxswap;
Comm::grow_swap(n);
if(n>cu_sendlist->get_dim()[0])
{
MYDBG(printf(" # CUDA CommCuda::grow_swap\n");)
delete cu_sendlist;
cu_sendlist=new cCudaData<int, int, xy> ((int*)sendlist,n,BUFMIN);
cuda->shared_data.comm.sendlist.dev_data=cu_sendlist->dev_data();
cuda->shared_data.comm.maxlistlength=BUFMIN;
cuda->shared_data.comm.maxswap=n;
cuda->shared_data.comm.nsend_swap=new int[n];
cuda->shared_data.comm.send_size=new int[n];
cuda->shared_data.comm.recv_size=new int[n];
}
for(int i=0;i<oldmaxswap;i++)
{
if(cuda->shared_data.comm.buf_recv_dev[i]) CudaWrapper_FreeCudaData(cuda->shared_data.comm.buf_recv_dev[i],maxrecv*sizeof(double));
if(cuda->shared_data.comm.buf_send_dev[i]) CudaWrapper_FreeCudaData(cuda->shared_data.comm.buf_send_dev[i],maxsend*sizeof(double));
cuda->shared_data.comm.buf_recv_dev[i]=NULL;
cuda->shared_data.comm.buf_send_dev[i]=NULL;
}
cuda->shared_data.comm.buf_send= new double*[n];
cuda->shared_data.comm.buf_recv= new double*[n];
cuda->shared_data.comm.buf_send_dev= new void*[n];
cuda->shared_data.comm.buf_recv_dev= new void*[n];
for(int i=0;i<n;i++)
{
cuda->shared_data.comm.buf_recv[i]=NULL;
cuda->shared_data.comm.buf_send[i]=NULL;
cuda->shared_data.comm.buf_recv_dev[i]=NULL;
cuda->shared_data.comm.buf_send_dev[i]=NULL;
}
grow_send(maxsend,0);
grow_recv(maxrecv);
maxswap=n;
}
/* ----------------------------------------------------------------------
allocation of swap info
------------------------------------------------------------------------- */
void CommCuda::allocate_swap(int n)
{
Comm::allocate_swap(n);
delete cu_pbc;
delete cu_slablo;
delete cu_slabhi;
cuda->shared_data.comm.maxswap=n;
if(cu_sendlist)
{
cu_pbc=new cCudaData<int, int, xy> ((int*)pbc,n,6);
cu_slablo = new cCudaData<double, X_FLOAT,x>(slablo,n);
cu_slabhi = new cCudaData<double, X_FLOAT,x>(slabhi,n);
cuda->shared_data.comm.pbc.dev_data=cu_pbc->dev_data();
cuda->shared_data.comm.slablo.dev_data=cu_slablo->dev_data();
cuda->shared_data.comm.slabhi.dev_data=cu_slabhi->dev_data();
}
cuda->shared_data.comm.nsend_swap=new int[n];
cuda->shared_data.comm.send_size=new int[n];
cuda->shared_data.comm.recv_size=new int[n];
cuda->shared_data.comm.buf_send= new double*[n];
cuda->shared_data.comm.buf_recv= new double*[n];
cuda->shared_data.comm.buf_send_dev= new void*[n];
cuda->shared_data.comm.buf_recv_dev= new void*[n];
for(int i=0;i<n;i++) cuda->shared_data.comm.buf_send_dev[i]=NULL;
for(int i=0;i<n;i++) cuda->shared_data.comm.buf_recv_dev[i]=NULL;
}
/* ----------------------------------------------------------------------
allocation of multi-type swap info
------------------------------------------------------------------------- */
void CommCuda::allocate_multi(int n)
{
Comm::allocate_multi(n);
delete cu_multilo;
delete cu_multihi;
cu_multilo = new cCudaData<double, X_FLOAT,xy>(slablo,n,atom->ntypes+1);
cu_multihi = new cCudaData<double, X_FLOAT,xy>(slabhi,n,atom->ntypes+1);
cuda->shared_data.comm.multilo.dev_data=cu_multilo->dev_data();
cuda->shared_data.comm.multihi.dev_data=cu_multihi->dev_data();
}
/* ----------------------------------------------------------------------
free memory for swaps
------------------------------------------------------------------------- */
void CommCuda::free_swap()
{
Comm::free_swap();
delete cuda->shared_data.comm.nsend_swap; cuda->shared_data.comm.nsend_swap=NULL;
delete cu_pbc; cu_pbc = NULL;
delete cu_slablo; cu_slablo = NULL;
delete cu_slabhi; cu_slabhi = NULL;
for(int i=0;i<maxswap;i++)
{
if(cuda->shared_data.comm.buf_recv_dev[i]) CudaWrapper_FreeCudaData(cuda->shared_data.comm.buf_recv_dev[i],maxrecv*sizeof(double));
if(cuda->shared_data.comm.buf_send_dev[i]) CudaWrapper_FreeCudaData(cuda->shared_data.comm.buf_send_dev[i],maxsend*sizeof(double));
}
}
/* ----------------------------------------------------------------------
free memory for multi-type swaps
------------------------------------------------------------------------- */
void CommCuda::free_multi()
{
Comm::free_multi();
delete cu_multilo; cu_multilo = NULL;
delete cu_multihi; cu_multihi = NULL;
}
diff --git a/src/USER-CUDA/compute_pressure_cuda.cpp b/src/USER-CUDA/compute_pressure_cuda.cpp
index aceb06a36..27de7e585 100644
--- a/src/USER-CUDA/compute_pressure_cuda.cpp
+++ b/src/USER-CUDA/compute_pressure_cuda.cpp
@@ -1,97 +1,97 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cstring>
#include <cstdlib>
#include "compute_pressure_cuda.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
enum{DUMMY0,INVOKED_SCALAR,INVOKED_VECTOR,DUMMMY3,INVOKED_PERATOM};
/* ---------------------------------------------------------------------- */
ComputePressureCuda::ComputePressureCuda(LAMMPS *lmp, int narg, char **arg) :
ComputePressure(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
cudable = 1;
// store temperature ID used by pressure computation
// insure it is valid for temperature computation
int n = strlen(arg[3]) + 1;
char* id_temp = new char[n];
strcpy(id_temp,arg[3]);
int icompute = modify->find_compute(id_temp);
delete [] id_temp;
if (modify->compute[icompute]->cudable == 0)
{
- error->warning("Compute pressure/cuda temperature ID is not cudable! Try a temp/cuda style.");
+ error->warning(FLERR,"Compute pressure/cuda temperature ID is not cudable! Try a temp/cuda style.");
cudable = 0;
}
}
double ComputePressureCuda::compute_scalar()
{
if(not temperature->cudable && cuda->finished_setup) cuda->downloadAll();
- ComputePressure::compute_scalar();
+ return ComputePressure::compute_scalar();
}
void ComputePressureCuda::compute_vector()
{
if(not temperature->cudable && cuda->finished_setup) cuda->downloadAll();
ComputePressure::compute_vector();
}
diff --git a/src/USER-CUDA/compute_temp_cuda.cpp b/src/USER-CUDA/compute_temp_cuda.cpp
index 0e13f67c1..0b560f536 100644
--- a/src/USER-CUDA/compute_temp_cuda.cpp
+++ b/src/USER-CUDA/compute_temp_cuda.cpp
@@ -1,212 +1,212 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "compute_temp_cuda.h"
#include "compute_temp_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeTempCuda::ComputeTempCuda(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg != 3) error->all("Illegal compute temp/cuda command");
+ if (narg != 3) error->all(FLERR,"Illegal compute temp/cuda command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
vector = new double[6];
cu_t_vector = 0;
cu_t_scalar = 0;
cudable=true;
}
/* ---------------------------------------------------------------------- */
ComputeTempCuda::~ComputeTempCuda()
{
delete [] vector;
delete cu_t_vector;
delete cu_t_scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempCuda::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ---------------------------------------------------------------------- */
void ComputeTempCuda::dof_compute()
{
double natoms = group->count(igroup);
dof = domain->dimension * natoms;
dof -= extra_dof + fix_dof;
if (dof > 0.0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempCuda::compute_scalar()
{
if(cuda->begin_setup)
{
if(not cu_t_vector) cu_t_vector = new cCudaData<double, ENERGY_FLOAT, x> (t_vector,6);
if(not cu_t_scalar) cu_t_scalar = new cCudaData<double, ENERGY_FLOAT, x> (&t_scalar,1);
invoked_scalar = update->ntimestep;
Cuda_ComputeTempCuda_Scalar(&cuda->shared_data,groupbit,(ENERGY_FLOAT*) cu_t_scalar->dev_data());
cu_t_scalar->download();
}
else
{
invoked_scalar = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
mass[type[i]];
}
t_scalar=t;
}
MPI_Allreduce(&t_scalar,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
if(scalar>1e15)
{
cuda->cu_v->download();
cuda->cu_x->download();
cuda->cu_type->download();
double **v = atom->v;
double **x = atom->x;
printf("Out of v-range atoms: \n");
for(int i=0;i<atom->nlocal;i++)
if((v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2])>1e5)
printf("%i %i // %lf %lf %lf // %lf %lf %lf\n",atom->tag[i],atom->type[i],x[i][0], x[i][1], x[i][2],v[i][0], v[i][1], v[i][2]);
- error->all("Temperature out of range. Simulations will be abortet.\n");
+ error->all(FLERR,"Temperature out of range. Simulations will be abortet.\n");
}
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempCuda::compute_vector()
{
int i;
if(cuda->begin_setup)
{
if(not cu_t_vector) cu_t_vector = new cCudaData<double, ENERGY_FLOAT, x> (t_vector,6);
if(not cu_t_scalar) cu_t_scalar = new cCudaData<double, ENERGY_FLOAT, x> (&t_scalar,1);
invoked_vector = update->ntimestep;
Cuda_ComputeTempCuda_Vector(&cuda->shared_data,groupbit,(ENERGY_FLOAT*) cu_t_vector->dev_data());
cu_t_vector->download();
}
else
{
invoked_vector = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * v[i][0]*v[i][0];
t[1] += massone * v[i][1]*v[i][1];
t[2] += massone * v[i][2]*v[i][2];
t[3] += massone * v[i][0]*v[i][1];
t[4] += massone * v[i][0]*v[i][2];
t[5] += massone * v[i][1]*v[i][2];
}
for (i = 0; i < 6; i++) t_vector[i]=t[i];
}
MPI_Allreduce(t_vector,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
diff --git a/src/USER-CUDA/compute_temp_partial_cuda.cpp b/src/USER-CUDA/compute_temp_partial_cuda.cpp
index c9a126a18..e39484c83 100644
--- a/src/USER-CUDA/compute_temp_partial_cuda.cpp
+++ b/src/USER-CUDA/compute_temp_partial_cuda.cpp
@@ -1,357 +1,357 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "compute_temp_partial_cuda.h"
#include "compute_temp_partial_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeTempPartialCuda::ComputeTempPartialCuda(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg != 6) error->all("Illegal compute temp/partial command");
+ if (narg != 6) error->all(FLERR,"Illegal compute temp/partial command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
xflag = atoi(arg[3]);
yflag = atoi(arg[4]);
zflag = atoi(arg[5]);
if (zflag && domain->dimension == 2)
- error->all("Compute temp/partial cannot use vz for 2d systemx");
+ error->all(FLERR,"Compute temp/partial cannot use vz for 2d systemx");
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
cu_t_vector = 0;
cu_t_scalar = 0;
cu_vbiasall=NULL;
cudable=true;
}
/* ---------------------------------------------------------------------- */
ComputeTempPartialCuda::~ComputeTempPartialCuda()
{
memory->destroy(vbiasall);
delete [] vector;
delete cu_t_vector;
delete cu_t_scalar;
delete cu_vbiasall;
}
/* ---------------------------------------------------------------------- */
void ComputeTempPartialCuda::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ---------------------------------------------------------------------- */
void ComputeTempPartialCuda::dof_compute()
{
double natoms = group->count(igroup);
int nper = xflag+yflag+zflag;
dof = nper * natoms;
dof -= (1.0*nper/domain->dimension)*fix_dof + extra_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
int ComputeTempPartialCuda::dof_remove(int i)
{
int nper = xflag+yflag+zflag;
return (domain->dimension - nper);
}
/* ---------------------------------------------------------------------- */
double ComputeTempPartialCuda::compute_scalar()
{
if(cuda->begin_setup)
{
if(not cu_t_vector) cu_t_vector = new cCudaData<double, ENERGY_FLOAT, x> (t_vector,6);
if(not cu_t_scalar) cu_t_scalar = new cCudaData<double, ENERGY_FLOAT, x> (&t_scalar,1);
invoked_scalar = update->ntimestep;
Cuda_ComputeTempPartialCuda_Scalar(&cuda->shared_data,groupbit,(ENERGY_FLOAT*) cu_t_scalar->dev_data(),xflag,yflag,zflag);
cu_t_scalar->download();
}
else
{
invoked_scalar = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (xflag*v[i][0]*v[i][0] + yflag*v[i][1]*v[i][1] + zflag*v[i][2]*v[i][2]) * rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (xflag*v[i][0]*v[i][0] + yflag*v[i][1]*v[i][1] + zflag*v[i][2]*v[i][2]) *
mass[type[i]];
}
t_scalar=t;
}
MPI_Allreduce(&t_scalar,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
if(scalar>1e15)
{
cuda->cu_v->download();
cuda->cu_x->download();
cuda->cu_type->download();
double **v = atom->v;
double **x = atom->x;
printf("Out of v-range atoms: \n");
for(int i=0;i<atom->nlocal;i++)
if((v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2])>1e5)
printf("%i %i // %lf %lf %lf // %lf %lf %lf\n",atom->tag[i],atom->type[i],x[i][0], x[i][1], x[i][2],v[i][0], v[i][1], v[i][2]);
- error->all("Temperature out of range. Simulations will be abortet.\n");
+ error->all(FLERR,"Temperature out of range. Simulations will be abortet.\n");
}
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempPartialCuda::compute_vector()
{
int i;
if(cuda->begin_setup)
{
if(not cu_t_vector) cu_t_vector = new cCudaData<double, ENERGY_FLOAT, x> (t_vector,6);
if(not cu_t_scalar) cu_t_scalar = new cCudaData<double, ENERGY_FLOAT, x> (&t_scalar,1);
invoked_vector = update->ntimestep;
Cuda_ComputeTempPartialCuda_Vector(&cuda->shared_data,groupbit,(ENERGY_FLOAT*) cu_t_vector->dev_data(),xflag,yflag,zflag);
cu_t_vector->download();
}
else
{
invoked_vector = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * xflag*v[i][0]*v[i][0];
t[1] += massone * yflag*v[i][1]*v[i][1];
t[2] += massone * zflag*v[i][2]*v[i][2];
t[3] += massone * xflag*yflag*v[i][0]*v[i][1];
t[4] += massone * xflag*zflag*v[i][0]*v[i][2];
t[5] += massone * yflag*zflag*v[i][1]*v[i][2];
}
for (i = 0; i < 6; i++) t_vector[i]=t[i];
}
MPI_Allreduce(t_vector,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempPartialCuda::remove_bias(int i, double *v)
{
if (!xflag) {
vbias[0] = v[0];
v[0] = 0.0;
}
if (!yflag) {
vbias[1] = v[1];
v[1] = 0.0;
}
if (!zflag) {
vbias[2] = v[2];
v[2] = 0.0;
}
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempPartialCuda::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/partial:vbiasall");
delete cu_vbiasall;
cu_vbiasall = new cCudaData<double, V_FLOAT, yx> ((double*)vbiasall, atom->nmax, 3);
}
if(cuda->begin_setup)
{
Cuda_ComputeTempPartialCuda_RemoveBiasAll(&cuda->shared_data,groupbit,xflag,yflag,zflag,cu_vbiasall->dev_data());
}
else
{
if (!xflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vbiasall[i][0] = v[i][0];
v[i][0] = 0.0;
}
}
if (!yflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vbiasall[i][1] = v[i][1];
v[i][1] = 0.0;
}
}
if (!zflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vbiasall[i][2] = v[i][2];
v[i][2] = 0.0;
}
}
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempPartialCuda::restore_bias(int i, double *v)
{
if (!xflag) v[0] += vbias[0];
if (!yflag) v[1] += vbias[1];
if (!zflag) v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempPartialCuda::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if(cuda->begin_setup)
{
Cuda_ComputeTempPartialCuda_RestoreBiasAll(&cuda->shared_data,groupbit,xflag,yflag,zflag,cu_vbiasall->dev_data());
}
else
{
if (!xflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][0] += vbiasall[i][0];
}
if (!yflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][1] += vbiasall[i][1];
}
if (!zflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][2] += vbiasall[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
double ComputeTempPartialCuda::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/USER-CUDA/cuda.cpp b/src/USER-CUDA/cuda.cpp
index 66273775e..39261bd7c 100644
--- a/src/USER-CUDA/cuda.cpp
+++ b/src/USER-CUDA/cuda.cpp
@@ -1,837 +1,835 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "cuda.h"
#include "atom.h"
#include "domain.h"
#include "force.h"
#include "pair.h"
#include "update.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "universe.h"
#include "input.h"
#include "error.h"
#include "cuda_neigh_list.h"
//#include "pre_binning_cu.h"
#include "binning_cu.h"
//#include "reverse_binning_cu.h"
#include <ctime>
#include <cmath>
#include "cuda_pair_cu.h"
#include "cuda_cu.h"
using namespace LAMMPS_NS;
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
Cuda::Cuda(LAMMPS *lmp) : Pointers(lmp)
{
cuda_exists=true;
lmp->cuda=this;
if(universe->me==0)
printf("# Using LAMMPS_CUDA \n");
shared_data.me=universe->me;
device_set=false;
Cuda_Cuda_GetCompileSettings(&shared_data);
if(shared_data.compile_settings.prec_glob!=sizeof(CUDA_FLOAT)/4) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: Global Precision: cuda %i cpp %i\n\n",shared_data.compile_settings.prec_glob, sizeof(CUDA_FLOAT)/4);
if(shared_data.compile_settings.prec_x!=sizeof(X_FLOAT)/4) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: X Precision: cuda %i cpp %i\n\n",shared_data.compile_settings.prec_x, sizeof(X_FLOAT)/4);
if(shared_data.compile_settings.prec_v!=sizeof(V_FLOAT)/4) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: V Precision: cuda %i cpp %i\n\n",shared_data.compile_settings.prec_v, sizeof(V_FLOAT)/4);
if(shared_data.compile_settings.prec_f!=sizeof(F_FLOAT)/4) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: F Precision: cuda %i cpp %i\n\n",shared_data.compile_settings.prec_f, sizeof(F_FLOAT)/4);
if(shared_data.compile_settings.prec_pppm!=sizeof(PPPM_FLOAT)/4) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: PPPM Precision: cuda %i cpp %i\n\n",shared_data.compile_settings.prec_pppm, sizeof(PPPM_FLOAT)/4);
if(shared_data.compile_settings.prec_fft!=sizeof(FFT_FLOAT)/4) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: FFT Precision: cuda %i cpp %i\n\n",shared_data.compile_settings.prec_fft, sizeof(FFT_FLOAT)/4);
#ifdef FFT_CUFFT
if(shared_data.compile_settings.cufft!=1) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: cufft: cuda %i cpp %i\n\n",shared_data.compile_settings.cufft, 1);
#else
if(shared_data.compile_settings.cufft!=0) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: cufft: cuda %i cpp %i\n\n",shared_data.compile_settings.cufft, 0);
#endif
if(shared_data.compile_settings.arch!=CUDA_ARCH) printf("\n\n # CUDA WARNING: Compile Settings of cuda and cpp code differ! \n # CUDA WARNING: arch: cuda %i cpp %i\n\n",shared_data.compile_settings.cufft, CUDA_ARCH);
cu_x = 0;
cu_v = 0;
cu_f = 0;
cu_tag = 0;
cu_type = 0;
cu_mask = 0;
cu_image = 0;
cu_xhold = 0;
cu_q = 0;
cu_rmass = 0;
cu_mass = 0;
cu_virial = 0;
cu_eatom = 0;
cu_vatom = 0;
cu_radius = 0;
cu_density = 0;
cu_omega = 0;
cu_torque = 0;
cu_special = 0;
cu_nspecial = 0;
cu_molecule = 0;
cu_x_type = 0;
x_type = 0;
cu_v_radius = 0;
v_radius = 0;
cu_omega_rmass = 0;
omega_rmass = 0;
binned_id = 0;
cu_binned_id = 0;
binned_idnew = 0;
cu_binned_idnew = 0;
cu_map_array = 0;
copy_buffer=0;
copy_buffersize=0;
neighbor_decide_by_integrator=0;
pinned=true;
debugdata=0;
new int[2*CUDA_MAX_DEBUG_SIZE];
finished_setup = false;
begin_setup = false;
finished_run = false;
setSharedDataZero();
uploadtime=0;
downloadtime=0;
dotiming=false;
dotestatom = false;
testatom = 0;
oncpu = true;
self_comm = 0;
MYDBG( printf("# CUDA: Cuda::Cuda Done...\n");)
//cCudaData<double, float, yx >
}
Cuda::~Cuda()
{
print_timings();
if(universe->me==0) printf("# CUDA: Free memory...\n");
delete cu_q;
delete cu_x;
delete cu_v;
delete cu_f;
delete cu_tag;
delete cu_type;
delete cu_mask;
delete cu_image;
delete cu_xhold;
delete cu_mass;
delete cu_rmass;
delete cu_virial;
delete cu_eng_vdwl;
delete cu_eng_coul;
delete cu_eatom;
delete cu_vatom;
delete cu_radius;
delete cu_density;
delete cu_omega;
delete cu_torque;
delete cu_molecule;
delete cu_x_type;
delete [] x_type;
delete cu_v_radius;
delete [] v_radius;
delete cu_omega_rmass;
delete [] omega_rmass;
delete cu_map_array;
std::map<NeighList*, CudaNeighList*>::iterator p = neigh_lists.begin();
while(p != neigh_lists.end())
{
delete p->second;
++p;
}
}
void Cuda::accelerator(int narg, char** arg)
{
if(device_set) return;
if(universe->me==0)
printf("# CUDA: Activate GPU \n");
int* devicelist=NULL;
int pppn=2;
for(int i=0;i<narg;i++)
{
if(strcmp(arg[i],"gpu/node")==0)
{
if(++i==narg)
- error->all("Invalid Options for 'accelerator' command. Expecting a number or keyword 'special' after 'gpu/node' option.");
+ error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting a number or keyword 'special' after 'gpu/node' option.");
if(strcmp(arg[i],"special")==0)
{
if(++i==narg)
- error->all("Invalid Options for 'accelerator' command. Expecting number of GPUs to be used per node after keyword 'gpu/node special'.");
+ error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting number of GPUs to be used per node after keyword 'gpu/node special'.");
pppn=atoi(arg[i]);
- if(pppn<1) error->all("Invalid Options for 'accelerator' command. Expecting number of GPUs to be used per node after keyword 'gpu/node special'.");
+ if(pppn<1) error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting number of GPUs to be used per node after keyword 'gpu/node special'.");
if(i+pppn==narg)
- error->all("Invalid Options for 'accelerator' command. Expecting list of device ids after keyword 'gpu/node special'.");
+ error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting list of device ids after keyword 'gpu/node special'.");
devicelist=new int[pppn];
for(int k=0;k<pppn;k++)
{i++;devicelist[k]=atoi(arg[i]);}
}
else
pppn=atoi(arg[i]);
}
if(strcmp(arg[i],"pinned")==0)
{
if(++i==narg)
- error->all("Invalid Options for 'accelerator' command. Expecting a number after 'pinned' option.");
+ error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting a number after 'pinned' option.");
pinned=atoi(arg[i])==0?false:true;
if((pinned==false)&&(universe->me==0)) printf(" #CUDA: Pinned memory is not used for communication\n");
}
if(strcmp(arg[i],"dotiming")==0)
{
dotiming=true;
}
if(strcmp(arg[i],"suffix")==0)
{
if(++i==narg)
- error->all("Invalid Options for 'accelerator' command. Expecting a string after 'suffix' option.");
+ error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting a string after 'suffix' option.");
strcpy(lmp->suffix,arg[i]);
}
if(strcmp(arg[i],"overlap_comm")==0)
{
shared_data.overlap_comm=1;
}
if(strcmp(arg[i],"dotest")==0)
{
if(++i==narg)
- error->all("Invalid Options for 'accelerator' command. Expecting a number after 'dotest' option.");
+ error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting a number after 'dotest' option.");
testatom=atof(arg[i]);
dotestatom=true;
}
if(strcmp(arg[i],"override_bpa")==0)
{
if(++i==narg)
- error->all("Invalid Options for 'accelerator' command. Expecting a number after 'override_bpa' option.");
+ error->all(FLERR,"Invalid Options for 'accelerator' command. Expecting a number after 'override_bpa' option.");
shared_data.pair.override_block_per_atom = atoi(arg[i]);
}
}
CudaWrapper_Init(0, (char**)0,universe->me,pppn,devicelist);
//if(shared_data.overlap_comm)
CudaWrapper_AddStreams(3);
cu_x = 0;
cu_v = 0;
cu_f = 0;
cu_tag = 0;
cu_type = 0;
cu_mask = 0;
cu_image = 0;
cu_xhold = 0;
cu_q = 0;
cu_rmass = 0;
cu_mass = 0;
cu_virial = 0;
cu_eatom = 0;
cu_vatom = 0;
cu_radius = 0;
cu_density = 0;
cu_omega = 0;
cu_torque = 0;
cu_special = 0;
cu_nspecial = 0;
cu_molecule = 0;
cu_x_type = 0;
cu_v_radius = 0;
cu_omega_rmass = 0;
cu_binned_id = 0;
cu_binned_idnew = 0;
device_set=true;
allocate();
delete devicelist;
}
void Cuda::setSharedDataZero()
{
MYDBG(printf("# CUDA: Cuda::setSharedDataZero ...\n");)
shared_data.atom.nlocal = 0;
shared_data.atom.nghost = 0;
shared_data.atom.nall = 0;
shared_data.atom.nmax = 0;
shared_data.atom.ntypes = 0;
shared_data.atom.q_flag = 0;
shared_data.atom.need_eatom = 0;
shared_data.atom.need_vatom = 0;
shared_data.pair.cudable_force = 0;
shared_data.pair.collect_forces_later = 0;
shared_data.pair.use_block_per_atom = 0;
shared_data.pair.override_block_per_atom = -1;
shared_data.pair.cut = 0;
shared_data.pair.cutsq = 0;
shared_data.pair.cut_inner = 0;
shared_data.pair.cut_coul = 0;
shared_data.pair.special_lj = 0;
shared_data.pair.special_coul = 0;
shared_data.pppm.cudable_force = 0;
shared_data.buffersize = 0;
shared_data.buffer_new = 1;
shared_data.buffer = NULL;
shared_data.comm.comm_phase=0;
shared_data.overlap_comm=0;
shared_data.comm.buffer = NULL;
shared_data.comm.buffer_size=0;
shared_data.comm.overlap_split_ratio=0;
// setTimingsZero();
}
void Cuda::allocate()
{
accelerator(0,NULL);
MYDBG(printf("# CUDA: Cuda::allocate ...\n");)
if(not cu_virial)
{
cu_virial = new cCudaData<double, ENERGY_FLOAT, x > (NULL, & shared_data.pair.virial , 6);
cu_eng_vdwl = new cCudaData<double, ENERGY_FLOAT, x > (NULL, & shared_data.pair.eng_vdwl ,1);
cu_eng_coul = new cCudaData<double, ENERGY_FLOAT, x > (NULL, & shared_data.pair.eng_coul ,1);
cu_extent = new cCudaData<double, double, x> (extent, 6);
shared_data.flag = CudaWrapper_AllocCudaData(sizeof(int));
int size=2*CUDA_MAX_DEBUG_SIZE;
debugdata = new int[size];
cu_debugdata = new cCudaData<int, int, x > (debugdata , size);
shared_data.debugdata=cu_debugdata->dev_data();
}
checkResize();
setSystemParams();
MYDBG(printf("# CUDA: Cuda::allocate done...\n");)
}
void Cuda::setSystemParams()
{
MYDBG(printf("# CUDA: Cuda::setSystemParams ...\n");)
shared_data.atom.nlocal = atom->nlocal;
shared_data.atom.nghost = atom->nghost;
shared_data.atom.nall = atom->nlocal + atom->nghost;
shared_data.atom.ntypes = atom->ntypes;
shared_data.atom.q_flag = atom->q_flag;
shared_data.atom.rmass_flag = atom->rmass_flag;
MYDBG(printf("# CUDA: Cuda::setSystemParams done ...\n");)
}
void Cuda::setDomainParams()
{
MYDBG(printf("# CUDA: Cuda::setDomainParams ...\n");)
cuda_shared_domain* cu_domain = &shared_data.domain;
cu_domain->triclinic = domain->triclinic;
for(short i=0; i<3; ++i)
{
cu_domain->periodicity[i] = domain->periodicity[i];
cu_domain->sublo[i] = domain->sublo[i];
cu_domain->subhi[i] = domain->subhi[i];
cu_domain->boxlo[i] = domain->boxlo[i];
cu_domain->boxhi[i] = domain->boxhi[i];
cu_domain->prd[i] = domain->prd[i];
}
if(domain->triclinic)
{
for(short i=0; i<3; ++i)
{
cu_domain->boxlo_lamda[i] = domain->boxlo_lamda[i];
cu_domain->boxhi_lamda[i] = domain->boxhi_lamda[i];
cu_domain->prd_lamda[i] = domain->prd_lamda[i];
}
cu_domain->xy = domain->xy;
cu_domain->xz = domain->xz;
cu_domain->yz = domain->yz;
}
for(int i=0;i<6;i++)
{
cu_domain->h[i]=domain->h[i];
cu_domain->h_inv[i]=domain->h_inv[i];
cu_domain->h_rate[i]=domain->h_rate[i];
}
cu_domain->update=2;
MYDBG(printf("# CUDA: Cuda::setDomainParams done ...\n");)
}
void Cuda::checkResize()
{
MYDBG(printf("# CUDA: Cuda::checkResize ...\n");)
accelerator(0,NULL);
cuda_shared_atom* cu_atom = & shared_data.atom;
cuda_shared_pair* cu_pair = & shared_data.pair;
cu_atom->q_flag = atom->q_flag;
cu_atom->rmass_flag = atom->rmass ? 1 : 0;
cu_atom->nall = atom->nlocal + atom->nghost;
cu_atom->nlocal = atom->nlocal;
cu_atom->nghost = atom->nghost;
// do we have more atoms to upload than currently allocated memory on device? (also true if nothing yet allocated)
if(atom->nmax > cu_atom->nmax || cu_tag == NULL)
{
delete cu_x; cu_x = new cCudaData<double, X_FLOAT, yx> ((double*)atom->x , & cu_atom->x , atom->nmax, 3,0,true); //cu_x->set_buffer(&(shared_data.buffer),&(shared_data.buffersize),true);
delete cu_v; cu_v = new cCudaData<double, V_FLOAT, yx> ((double*)atom->v, & cu_atom->v , atom->nmax, 3);
delete cu_f; cu_f = new cCudaData<double, F_FLOAT, yx> ((double*)atom->f, & cu_atom->f , atom->nmax, 3,0,true);
delete cu_tag; cu_tag = new cCudaData<int , int , x > (atom->tag , & cu_atom->tag , atom->nmax );
delete cu_type; cu_type = new cCudaData<int , int , x > (atom->type , & cu_atom->type , atom->nmax );
delete cu_mask; cu_mask = new cCudaData<int , int , x > (atom->mask , & cu_atom->mask , atom->nmax );
delete cu_image; cu_image = new cCudaData<int , int , x > (atom->image , & cu_atom->image , atom->nmax );
if(atom->rmass)
{delete cu_rmass; cu_rmass = new cCudaData<double, V_FLOAT, x > (atom->rmass , & cu_atom->rmass , atom->nmax );}
if(cu_atom->q_flag)
{delete cu_q; cu_q = new cCudaData<double, F_FLOAT, x > ((double*)atom->q, & cu_atom->q , atom->nmax );}// cu_q->set_buffer(&(copy_buffer),&(copy_buffersize),true);}
/*
if(force->pair)
if(force->pair->eatom)
{delete cu_eatom; cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > (force->pair->eatom, & cu_atom->eatom , atom->nmax );}// cu_eatom->set_buffer(&(copy_buffer),&(copy_buffersize),true);}
if(force->pair)
if(force->pair->vatom)
{delete cu_vatom; cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)force->pair->vatom, & cu_atom->vatom , atom->nmax,6 );}// cu_vatom->set_buffer(&(copy_buffer),&(copy_buffersize),true);}
*/
if(atom->radius)
{
delete cu_radius; cu_radius = new cCudaData<double, X_FLOAT, x > (atom->radius , & cu_atom->radius , atom->nmax );
delete cu_v_radius; cu_v_radius = new cCudaData<V_FLOAT, V_FLOAT, x> (v_radius , & cu_atom->v_radius , atom->nmax*4);
delete cu_omega_rmass; cu_omega_rmass = new cCudaData<V_FLOAT, V_FLOAT, x> (omega_rmass , & cu_atom->omega_rmass , atom->nmax*4);
}
/*
if(atom->density)
{delete cu_density; cu_density = new cCudaData<double, F_FLOAT, x > (atom->density , & cu_atom->density , atom->nmax );}
*/
if(atom->omega)
{delete cu_omega; cu_omega = new cCudaData<double, V_FLOAT, yx > (((double*) atom->omega) , & cu_atom->omega , atom->nmax,3 );}
if(atom->torque)
{delete cu_torque; cu_torque = new cCudaData<double, F_FLOAT, yx > (((double*) atom->torque) , & cu_atom->torque , atom->nmax,3 );}
if(atom->special)
{delete cu_special; cu_special = new cCudaData<int, int, yx > (((int*) &(atom->special[0][0])) , & cu_atom->special , atom->nmax,atom->maxspecial ); shared_data.atom.maxspecial=atom->maxspecial;}
if(atom->nspecial)
{delete cu_nspecial; cu_nspecial = new cCudaData<int, int, yx > (((int*) atom->nspecial) , & cu_atom->nspecial , atom->nmax,3 );}
if(atom->molecule)
{delete cu_molecule; cu_molecule = new cCudaData<int, int, x > (((int*) atom->molecule) , & cu_atom->molecule , atom->nmax );}
shared_data.atom.special_flag = neighbor->special_flag;
shared_data.atom.molecular = atom->molecular;
cu_atom->update_nmax = 2;
cu_atom->nmax = atom->nmax;
//delete [] x_type; x_type = new X_FLOAT4[atom->nmax];
delete cu_x_type; cu_x_type = new cCudaData<X_FLOAT, X_FLOAT, x> (x_type , & cu_atom->x_type , atom->nmax*4);
// shared_data.buffer_new = 2;
}
if(((cu_xhold==NULL)||(cu_xhold->get_dim()[0]<neighbor->maxhold))&&neighbor->xhold)
{
delete cu_xhold; cu_xhold = new cCudaData<double, X_FLOAT, yx> ((double*)neighbor->xhold, & cu_atom->xhold , neighbor->maxhold, 3);
shared_data.atom.maxhold=neighbor->maxhold;
}
if(atom->mass && !cu_mass)
{cu_mass = new cCudaData<double, V_FLOAT, x > (atom->mass , & cu_atom->mass , atom->ntypes+1);}
cu_atom->mass_host = atom->mass;
if(atom->map_style==1)
{
if((cu_map_array==NULL))
{
cu_map_array = new cCudaData<int, int, x > (atom->get_map_array() , & cu_atom->map_array , atom->get_map_size() );
}
}
// if any of the host pointers have changed (e.g. re-allocated somewhere else), set to correct pointer
if(cu_x ->get_host_data() != atom->x) cu_x ->set_host_data((double*) (atom->x));
if(cu_v ->get_host_data() != atom->v) cu_v ->set_host_data((double*) (atom->v));
if(cu_f ->get_host_data() != atom->f) cu_f ->set_host_data((double*) (atom->f));
if(cu_tag ->get_host_data() != atom->tag) cu_tag ->set_host_data(atom->tag);
if(cu_type->get_host_data() != atom->type) cu_type->set_host_data(atom->type);
if(cu_mask->get_host_data() != atom->mask) cu_mask->set_host_data(atom->mask);
if(cu_image->get_host_data() != atom->image) cu_mask->set_host_data(atom->image);
if(cu_xhold)
if(cu_xhold->get_host_data()!= neighbor->xhold) cu_xhold->set_host_data((double*)(neighbor->xhold));
if(atom->rmass)
if(cu_rmass->get_host_data() != atom->rmass) cu_rmass->set_host_data((double*) (atom->rmass));
if(cu_atom->q_flag)
if(cu_q->get_host_data() != atom->q) cu_q->set_host_data((double*) (atom->q));
if(atom->radius)
if(cu_radius->get_host_data() != atom->radius) cu_radius->set_host_data((double*) (atom->radius));
/*
if(atom->density)
if(cu_density->get_host_data() != atom->density) cu_density->set_host_data((double*) (atom->density));
*/
if(atom->omega)
if(cu_omega->get_host_data() != atom->omega) cu_omega->set_host_data((double*) (atom->omega));
if(atom->torque)
if(cu_torque->get_host_data() != atom->torque) cu_torque->set_host_data((double*) (atom->torque));
if(atom->special)
if(cu_special->get_host_data() != atom->special)
{delete cu_special; cu_special = new cCudaData<int, int, yx > (((int*) atom->special) , & cu_atom->special , atom->nmax,atom->maxspecial ); shared_data.atom.maxspecial=atom->maxspecial;}
if(atom->nspecial)
if(cu_nspecial->get_host_data() != atom->nspecial) cu_nspecial->set_host_data((int*) (atom->nspecial));
if(atom->molecule)
if(cu_molecule->get_host_data() != atom->molecule) cu_molecule->set_host_data((int*) (atom->molecule));
if(force)
if(cu_virial ->get_host_data() != force->pair->virial) cu_virial ->set_host_data(force->pair->virial);
if(force)
if(cu_eng_vdwl ->get_host_data() != &force->pair->eng_vdwl) cu_eng_vdwl ->set_host_data(&force->pair->eng_vdwl);
if(force)
if(cu_eng_coul ->get_host_data() != &force->pair->eng_coul) cu_eng_coul ->set_host_data(&force->pair->eng_coul);
cu_atom->update_nlocal = 2;
MYDBG(printf("# CUDA: Cuda::checkResize done...\n");)
}
void Cuda::evsetup_eatom_vatom(int eflag_atom,int vflag_atom)
{
if(eflag_atom)
{
if(not cu_eatom)
cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > (force->pair->eatom, & (shared_data.atom.eatom) , atom->nmax );// cu_eatom->set_buffer(&(copy_buffer),&(copy_buffersize),true);}
cu_eatom->set_host_data(force->pair->eatom);
cu_eatom->memset_device(0);
}
if(vflag_atom)
{
if(not cu_vatom)
cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)force->pair->vatom, & (shared_data.atom.vatom) , atom->nmax ,6 );// cu_vatom->set_buffer(&(copy_buffer),&(copy_buffersize),true);}
cu_vatom->set_host_data((double*)force->pair->vatom);
cu_vatom->memset_device(0);
}
}
void Cuda::uploadAll()
{
MYDBG(printf("# CUDA: Cuda::uploadAll() ... start\n");)
timespec starttime;
timespec endtime;
if(atom->nmax!=shared_data.atom.nmax) checkResize();
clock_gettime(CLOCK_REALTIME,&starttime);
cu_x ->upload();
cu_v ->upload();
cu_f ->upload();
cu_tag ->upload();
cu_type->upload();
cu_mask->upload();
cu_image->upload();
if(shared_data.atom.q_flag) cu_q ->upload();
//printf("A3\n");
//if(shared_data.atom.need_eatom) cu_eatom->upload();
//printf("A4\n");
//if(shared_data.atom.need_vatom) cu_vatom->upload();
//printf("A5\n");
if(atom->rmass) cu_rmass->upload();
if(atom->radius) cu_radius->upload();
// if(atom->density) cu_density->upload();
if(atom->omega) cu_omega->upload();
if(atom->torque) cu_torque->upload();
if(atom->special) cu_special->upload();
if(atom->nspecial) cu_nspecial->upload();
if(atom->molecule) cu_molecule->upload();
if(cu_eatom) cu_eatom->upload();
if(cu_vatom) cu_vatom->upload();
clock_gettime(CLOCK_REALTIME,&endtime);
uploadtime+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
CUDA_IF_BINNING(Cuda_PreBinning(& shared_data);)
CUDA_IF_BINNING(Cuda_Binning (& shared_data);)
shared_data.atom.triggerneighsq=neighbor->triggersq;
MYDBG(printf("# CUDA: Cuda::uploadAll() ... end\n");)
}
void Cuda::downloadAll()
{
MYDBG(printf("# CUDA: Cuda::downloadAll() ... start\n");)
timespec starttime;
timespec endtime;
if(atom->nmax!=shared_data.atom.nmax) checkResize();
CUDA_IF_BINNING( Cuda_ReverseBinning(& shared_data); )
clock_gettime(CLOCK_REALTIME,&starttime);
cu_x ->download();
cu_v ->download();
cu_f ->download();
cu_type->download();
cu_tag ->download();
cu_mask->download();
cu_image->download();
//if(shared_data.atom.need_eatom) cu_eatom->download();
//if(shared_data.atom.need_vatom) cu_vatom->download();
if(shared_data.atom.q_flag) cu_q ->download();
if(atom->rmass) cu_rmass->download();
if(atom->radius) cu_radius->download();
// if(atom->density) cu_density->download();
if(atom->omega) cu_omega->download();
if(atom->torque) cu_torque->download();
if(atom->special) cu_special->download();
if(atom->nspecial) cu_nspecial->download();
if(atom->molecule) cu_molecule->download();
if(cu_eatom) cu_eatom->download();
if(cu_vatom) cu_vatom->download();
clock_gettime(CLOCK_REALTIME,&endtime);
downloadtime+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
MYDBG(printf("# CUDA: Cuda::downloadAll() ... end\n");)
}
void Cuda::downloadX()
{
Cuda_Pair_RevertXType(& this->shared_data);
cu_x->download();
}
CudaNeighList* Cuda::registerNeighborList(class NeighList* neigh_list)
{
MYDBG(printf("# CUDA: Cuda::registerNeighborList() ... start a\n");)
std::map<NeighList*, CudaNeighList*>::iterator p = neigh_lists.find(neigh_list);
if(p != neigh_lists.end()) return p->second;
else
{
CudaNeighList* neigh_list_cuda = new CudaNeighList(lmp, neigh_list);
neigh_lists.insert(std::pair<NeighList*, CudaNeighList*>(neigh_list, neigh_list_cuda));
return neigh_list_cuda;
}
MYDBG(printf("# CUDA: Cuda::registerNeighborList() ... end b\n");)
}
void Cuda::uploadAllNeighborLists()
{
MYDBG(printf("# CUDA: Cuda::uploadAllNeighborList() ... start\n");)
std::map<NeighList*, CudaNeighList*>::iterator p = neigh_lists.begin();
while(p != neigh_lists.end())
{
p->second->nl_upload();
if(not (p->second->neigh_list->cuda_list->build_cuda))
for(int i=0;i<atom->nlocal;i++)
p->second->sneighlist.maxneighbors=MAX(p->second->neigh_list->numneigh[i],p->second->sneighlist.maxneighbors) ;
++p;
}
MYDBG(printf("# CUDA: Cuda::uploadAllNeighborList() ... done\n");)
}
void Cuda::downloadAllNeighborLists()
{
MYDBG(printf("# CUDA: Cuda::downloadAllNeighborList() ... start\n");)
std::map<NeighList*, CudaNeighList*>::iterator p = neigh_lists.begin();
while(p != neigh_lists.end())
{
p->second->nl_download();
++p;
}
}
void Cuda::update_xhold(int &maxhold,double* xhold)
{
if(this->shared_data.atom.maxhold<atom->nmax)
{
maxhold = atom->nmax;
delete this->cu_xhold; this->cu_xhold = new cCudaData<double, X_FLOAT, yx> ((double*)xhold, & this->shared_data.atom.xhold , maxhold, 3);
}
this->shared_data.atom.maxhold=maxhold;
CudaWrapper_CopyData(this->cu_xhold->dev_data(),this->cu_x->dev_data(),3*atom->nmax*sizeof(X_FLOAT));
}
void Cuda::setTimingsZero()
{
shared_data.cuda_timings.test1=0;
shared_data.cuda_timings.test2=0;
//communication
shared_data.cuda_timings.comm_forward_total = 0;
shared_data.cuda_timings.comm_forward_mpi_upper = 0;
shared_data.cuda_timings.comm_forward_mpi_lower = 0;
shared_data.cuda_timings.comm_forward_kernel_pack = 0;
shared_data.cuda_timings.comm_forward_kernel_unpack = 0;
shared_data.cuda_timings.comm_forward_upload = 0;
shared_data.cuda_timings.comm_forward_download = 0;
shared_data.cuda_timings.comm_exchange_total = 0;
shared_data.cuda_timings.comm_exchange_mpi = 0;
shared_data.cuda_timings.comm_exchange_kernel_pack = 0;
shared_data.cuda_timings.comm_exchange_kernel_unpack = 0;
shared_data.cuda_timings.comm_exchange_kernel_fill = 0;
shared_data.cuda_timings.comm_exchange_cpu_pack= 0;
shared_data.cuda_timings.comm_exchange_upload = 0;
shared_data.cuda_timings.comm_exchange_download = 0;
shared_data.cuda_timings.comm_border_total = 0;
shared_data.cuda_timings.comm_border_mpi = 0;
shared_data.cuda_timings.comm_border_kernel_pack = 0;
shared_data.cuda_timings.comm_border_kernel_unpack = 0;
shared_data.cuda_timings.comm_border_kernel_buildlist = 0;
shared_data.cuda_timings.comm_border_kernel_self = 0;
shared_data.cuda_timings.comm_border_upload = 0;
shared_data.cuda_timings.comm_border_download = 0;
//pair forces
shared_data.cuda_timings.pair_xtype_conversion = 0;
shared_data.cuda_timings.pair_kernel = 0;
shared_data.cuda_timings.pair_virial = 0;
shared_data.cuda_timings.pair_force_collection = 0;
//neighbor
shared_data.cuda_timings.neigh_bin = 0;
shared_data.cuda_timings.neigh_build = 0;
shared_data.cuda_timings.neigh_special = 0;
//PPPM
shared_data.cuda_timings.pppm_particle_map;
shared_data.cuda_timings.pppm_make_rho;
shared_data.cuda_timings.pppm_brick2fft;
shared_data.cuda_timings.pppm_poisson;
shared_data.cuda_timings.pppm_fillbrick;
shared_data.cuda_timings.pppm_fieldforce;
shared_data.cuda_timings.pppm_compute;
CudaWrapper_CheckUploadTime(true);
CudaWrapper_CheckDownloadTime(true);
CudaWrapper_CheckCPUBufUploadTime(true);
CudaWrapper_CheckCPUBufDownloadTime(true);
}
void Cuda::print_timings()
{
if(universe->me!=0) return;
if(not dotiming) return;
printf("\n # CUDA: Special timings\n\n");
printf("\n Transfer Times\n");
printf(" PCIe Upload: \t %lf s\n",CudaWrapper_CheckUploadTime());
printf(" PCIe Download:\t %lf s\n",CudaWrapper_CheckDownloadTime());
printf(" CPU Tempbbuf Upload: \t %lf \n",CudaWrapper_CheckCPUBufUploadTime());
printf(" CPU Tempbbuf Download: \t %lf \n",CudaWrapper_CheckCPUBufDownloadTime());
printf("\n Communication \n");
printf(" Forward Total \t %lf \n",shared_data.cuda_timings.comm_forward_total);
printf(" Forward MPI Upper Bound \t %lf \n",shared_data.cuda_timings.comm_forward_mpi_upper);
printf(" Forward MPI Lower Bound \t %lf \n",shared_data.cuda_timings.comm_forward_mpi_lower);
printf(" Forward Kernel Pack \t %lf \n",shared_data.cuda_timings.comm_forward_kernel_pack);
printf(" Forward Kernel Unpack \t %lf \n",shared_data.cuda_timings.comm_forward_kernel_unpack);
printf(" Forward Kernel Self \t %lf \n",shared_data.cuda_timings.comm_forward_kernel_self);
printf(" Forward Upload \t %lf \n",shared_data.cuda_timings.comm_forward_upload);
printf(" Forward Download \t %lf \n",shared_data.cuda_timings.comm_forward_download);
printf(" Forward Overlap Split Ratio\t %lf \n",shared_data.comm.overlap_split_ratio);
printf("\n");
printf(" Exchange Total \t %lf \n",shared_data.cuda_timings.comm_exchange_total);
printf(" Exchange MPI \t %lf \n",shared_data.cuda_timings.comm_exchange_mpi);
printf(" Exchange Kernel Pack \t %lf \n",shared_data.cuda_timings.comm_exchange_kernel_pack);
printf(" Exchange Kernel Unpack \t %lf \n",shared_data.cuda_timings.comm_exchange_kernel_unpack);
printf(" Exchange Kernel Fill \t %lf \n",shared_data.cuda_timings.comm_exchange_kernel_fill);
printf(" Exchange CPU Pack \t %lf \n",shared_data.cuda_timings.comm_exchange_cpu_pack);
printf(" Exchange Upload \t %lf \n",shared_data.cuda_timings.comm_exchange_upload);
printf(" Exchange Download \t %lf \n",shared_data.cuda_timings.comm_exchange_download);
printf("\n");
printf(" Border Total \t %lf \n",shared_data.cuda_timings.comm_border_total);
printf(" Border MPI \t %lf \n",shared_data.cuda_timings.comm_border_mpi);
printf(" Border Kernel Pack \t %lf \n",shared_data.cuda_timings.comm_border_kernel_pack);
printf(" Border Kernel Unpack \t %lf \n",shared_data.cuda_timings.comm_border_kernel_unpack);
printf(" Border Kernel Self \t %lf \n",shared_data.cuda_timings.comm_border_kernel_self);
printf(" Border Kernel BuildList \t %lf \n",shared_data.cuda_timings.comm_border_kernel_buildlist);
printf(" Border Upload \t %lf \n",shared_data.cuda_timings.comm_border_upload);
printf(" Border Download \t %lf \n",shared_data.cuda_timings.comm_border_download);
printf("\n");
//pair forces
printf(" Pair XType Conversion \t %lf \n",shared_data.cuda_timings.pair_xtype_conversion );
printf(" Pair Kernel \t %lf \n",shared_data.cuda_timings.pair_kernel );
printf(" Pair Virial \t %lf \n",shared_data.cuda_timings.pair_virial );
printf(" Pair Force Collection \t %lf \n",shared_data.cuda_timings.pair_force_collection );
printf("\n");
//neighbor
printf(" Neighbor Binning \t %lf \n",shared_data.cuda_timings.neigh_bin );
printf(" Neighbor Build \t %lf \n",shared_data.cuda_timings.neigh_build );
printf(" Neighbor Special \t %lf \n",shared_data.cuda_timings.neigh_special );
printf("\n");
//pppm
if(force->kspace)
{
printf(" PPPM Total \t %lf \n",shared_data.cuda_timings.pppm_compute );
printf(" PPPM Particle Map \t %lf \n",shared_data.cuda_timings.pppm_particle_map );
printf(" PPPM Make Rho \t %lf \n",shared_data.cuda_timings.pppm_make_rho );
printf(" PPPM Brick2fft \t %lf \n",shared_data.cuda_timings.pppm_brick2fft );
printf(" PPPM Poisson \t %lf \n",shared_data.cuda_timings.pppm_poisson );
printf(" PPPM Fillbrick \t %lf \n",shared_data.cuda_timings.pppm_fillbrick );
printf(" PPPM Fieldforce \t %lf \n",shared_data.cuda_timings.pppm_fieldforce );
printf("\n");
}
printf(" Debug Test 1 \t %lf \n",shared_data.cuda_timings.test1);
printf(" Debug Test 2 \t %lf \n",shared_data.cuda_timings.test2);
printf("\n");
}
diff --git a/src/USER-CUDA/cuda_neigh_list.cpp b/src/USER-CUDA/cuda_neigh_list.cpp
index 9a88797e8..ef9edf5ef 100644
--- a/src/USER-CUDA/cuda_neigh_list.cpp
+++ b/src/USER-CUDA/cuda_neigh_list.cpp
@@ -1,184 +1,184 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include "cuda_neigh_list.h"
#include "neigh_list.h"
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include "cuda.h"
#include "atom.h"
#include "error.h"
using namespace LAMMPS_NS;
CudaNeighList::CudaNeighList(LAMMPS *lmp, class NeighList* neigh_list) : Pointers(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
MYDBG(printf("# CUDA: CudaNeighList::cudaNeighList() ... start\n");)
this->neigh_list = neigh_list;
neigh_list->cuda_list=this;
sneighlist.maxlocal = neigh_list->get_maxlocal();
sneighlist.maxneighbors = 32;
sneighlist.maxcut = 0.0;
sneighlist.cutneighsq = NULL;
cu_neighbors = NULL;
cu_neighbors_border = NULL;
cu_neighbors_inner = NULL;
cu_numneigh_border = NULL;
cu_numneigh_inner = NULL;
cu_numneigh = NULL;
cu_ilist = NULL;
cu_ilist_border = NULL;
cu_inum_border = NULL;
inum_border = 0;
neighbors = NULL;
neighbors_inner = NULL;
neighbors_border = NULL;
numneigh_border = NULL;
numneigh_inner = NULL;
ilist_border = NULL;
build_cuda = false;
sneighlist.binned_id=NULL;
sneighlist.bin_dim=new int[3];
sneighlist.bin_dim[0]=0;
sneighlist.bin_dim[1]=0;
sneighlist.bin_dim[2]=0;
cu_ex_type = NULL;
cu_ex1_bit = NULL;
cu_ex2_bit = NULL;
cu_ex_mol_bit = NULL;
sneighlist.nex_type=0;
sneighlist.nex_group=0;
sneighlist.nex_mol=0;
sneighlist.bin_nmax=0;
sneighlist.bin_extraspace=0.05;
MYDBG(printf("# CUDA: CudaNeighList::cudaNeighList() ... end\n");)
}
CudaNeighList::~CudaNeighList()
{
dev_free();
}
void CudaNeighList::dev_alloc()
{
MYDBG( printf("# CUDA: CudaNeighList::dev_alloc() ... start\n"); )
cu_ilist = new cCudaData<int , int , x> (neigh_list->ilist , & sneighlist.ilist , sneighlist.maxlocal );
cu_numneigh = new cCudaData<int , int , x> (neigh_list->numneigh, & sneighlist.numneigh , sneighlist.maxlocal );
neighbors = new int[atom->nmax*sneighlist.maxneighbors];
cu_neighbors= new cCudaData<int, int, x> (neighbors , & sneighlist.neighbors, atom->nmax*sneighlist.maxneighbors );
if(cuda->shared_data.overlap_comm)
{
ilist_border = new int[sneighlist.maxlocal];
numneigh_border = new int[sneighlist.maxlocal];
numneigh_inner = new int[sneighlist.maxlocal];
cu_inum_border = new cCudaData<int , int , x> (&inum_border , & sneighlist.inum_border , 1 );
cu_ilist_border = new cCudaData<int , int , x> (ilist_border , & sneighlist.ilist_border , sneighlist.maxlocal );
cu_numneigh_border = new cCudaData<int , int , x> (numneigh_border , & sneighlist.numneigh_border , sneighlist.maxlocal );
cu_numneigh_inner = new cCudaData<int , int , x> (numneigh_inner , & sneighlist.numneigh_inner , sneighlist.maxlocal );
neighbors_border = new int[sneighlist.maxlocal*sneighlist.maxneighbors];
cu_neighbors_border= new cCudaData<int, int, x> (neighbors_border , & sneighlist.neighbors_border, sneighlist.maxlocal*sneighlist.maxneighbors );
neighbors_inner = new int[sneighlist.maxlocal*sneighlist.maxneighbors];
cu_neighbors_inner = new cCudaData<int, int, x> (neighbors_inner , & sneighlist.neighbors_inner , sneighlist.maxlocal*sneighlist.maxneighbors );
}
MYDBG( printf("# CUDA: CudaNeighList::dev_alloc() ... end\n"); )
}
void CudaNeighList::dev_free()
{
MYDBG( printf("# CUDA: CudaNeighList::dev_free() ... start\n"); )
delete cu_numneigh;
delete cu_ilist;
delete [] neighbors;
delete cu_neighbors;
if(cuda->shared_data.overlap_comm)
{
delete [] ilist_border;
delete [] numneigh_border;
delete [] numneigh_inner;
delete [] neighbors_border;
delete [] neighbors_inner;
delete cu_inum_border;
delete cu_neighbors_border;
delete cu_neighbors_inner;
delete cu_numneigh_border;
delete cu_numneigh_inner;
delete cu_ilist_border;
}
MYDBG( printf("# CUDA: CudaNeighList::dev_free() ... end\n"); )
}
void CudaNeighList::grow_device()
{
MYDBG(printf("# CUDA: CudaNeighList::grow_device() ... start\n");)
// if host has allocated more memory for atom arrays than device has, then allocate more memory on device
int new_maxlocal = neigh_list->get_maxlocal();
if(sneighlist.maxlocal < new_maxlocal)
{
sneighlist.maxlocal = new_maxlocal;
dev_free();
dev_alloc();
}
if(!cu_ilist || !cu_numneigh) dev_alloc();
// check, if hosts data has been allocated somewhere else
if(cu_ilist ->get_host_data() != neigh_list->ilist) cu_ilist ->set_host_data(neigh_list->ilist);
if(cu_numneigh->get_host_data() != neigh_list->numneigh) cu_numneigh->set_host_data(neigh_list->numneigh);
MYDBG(printf("# CUDA: CudaNeighList::grow_device() ... end\n");)
}
void CudaNeighList::nl_upload(bool will_be_changed)
{
//return;
MYDBG(printf("# CUDA: CudaNeighList::nl_upload() ... start\n");)
if(cu_ilist)
cu_ilist->upload();
if(cu_numneigh)
cu_numneigh->upload();
MYDBG(printf("# CUDA: CudaNeighList::nl_upload() ... end\n");)
}
void CudaNeighList::nl_download(bool will_be_changed)
{
MYDBG(printf("# CUDA: CudaNeighList::nl_download() ... start\n");)
if(cu_ilist)
cu_ilist->download();
if(cu_numneigh)
cu_numneigh->download();
MYDBG(printf("# CUDA: CudaNeighList::nl_download() ... end\n");)
}
diff --git a/src/USER-CUDA/domain_cuda.cpp b/src/USER-CUDA/domain_cuda.cpp
index 37aa38c19..b241b16a2 100644
--- a/src/USER-CUDA/domain_cuda.cpp
+++ b/src/USER-CUDA/domain_cuda.cpp
@@ -1,273 +1,271 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author (triclinic) : Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "math.h"
#include "domain_cuda.h"
#include "style_region.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "fix_deform.h"
#include "region.h"
#include "lattice.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
#include "domain_cu.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
#define SMALL 1.0e-4
#define DELTA 1
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp
/* ----------------------------------------------------------------------
default is periodic
------------------------------------------------------------------------- */
DomainCuda::DomainCuda(LAMMPS *lmp) : Domain(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
}
/* ---------------------------------------------------------------------- */
void DomainCuda::init()
{
cuda->accelerator(0,NULL);
Domain::init();
if(not cuda->finished_run)
{
cuda->setDomainParams();
Cuda_Domain_Init(&cuda->shared_data);
}
}
/* ----------------------------------------------------------------------
set global box params
assumes boxlo/hi and triclinic tilts are already set
------------------------------------------------------------------------- */
void DomainCuda::set_global_box()
{
Domain::set_global_box();
if(not cuda->finished_run)
{
cuda->setDomainParams();
}
}
/* ----------------------------------------------------------------------
set lamda box params, only need be done one time
assumes global box is defined and proc assignment has been made by comm
for uppermost proc, insure subhi = 1.0 (in case round-off occurs)
------------------------------------------------------------------------- */
void DomainCuda::set_lamda_box()
{
Domain::set_lamda_box();
if(not cuda->finished_run)
{
cuda->setDomainParams();
}
}
/* ----------------------------------------------------------------------
set local subbox params
assumes global box is defined and proc assignment has been made
for uppermost proc, insure subhi = boxhi (in case round-off occurs)
------------------------------------------------------------------------- */
void DomainCuda::set_local_box()
{
Domain::set_local_box();
if(not cuda->finished_run)
{
// cuda->setDomainParams();
//Cuda_Domain_Init(&cuda->shared_data);
}
}
/* ----------------------------------------------------------------------
reset global & local boxes due to global box boundary changes
if shrink-wrapped, determine atom extent and reset boxlo/hi
if shrink-wrapped and triclinic, perform shrink-wrap in box coords
------------------------------------------------------------------------- */
void DomainCuda::reset_box()
{
if (nonperiodic == 2) {
// convert back to box coords for shrink-wrap operation
if (triclinic) lamda2x(atom->nlocal);
// compute extent of atoms on this proc
double extent[3][2],all[3][2];
extent[2][0] = extent[1][0] = extent[0][0] = BIG;
extent[2][1] = extent[1][1] = extent[0][1] = -BIG;
double **x = atom->x;
int nlocal = atom->nlocal;
if (cuda->finished_setup&&(!cuda->oncpu))
{
extent[0][0]=cuda->extent[0];
extent[0][1]=cuda->extent[1];
extent[1][0]=cuda->extent[2];
extent[1][1]=cuda->extent[3];
extent[2][0]=cuda->extent[4];
extent[2][1]=cuda->extent[5];
}
else
for (int i = 0; i < nlocal; i++) {
extent[0][0] = MIN(extent[0][0],x[i][0]);
extent[0][1] = MAX(extent[0][1],x[i][0]);
extent[1][0] = MIN(extent[1][0],x[i][1]);
extent[1][1] = MAX(extent[1][1],x[i][1]);
extent[2][0] = MIN(extent[2][0],x[i][2]);
extent[2][1] = MAX(extent[2][1],x[i][2]);
}
// compute extent across all procs
// flip sign of MIN to do it in one Allreduce MAX
extent[0][0] = -extent[0][0];
extent[1][0] = -extent[1][0];
extent[2][0] = -extent[2][0];
MPI_Allreduce(extent,all,6,MPI_DOUBLE,MPI_MAX,world);
// in shrink-wrapped dims, set box by atom extent
// if minimum set, enforce min box size settings
if (xperiodic == 0) {
if (boundary[0][0] == 2) boxlo[0] = -all[0][0] - SMALL;
else if (boundary[0][0] == 3) boxlo[0] = MIN(-all[0][0]-SMALL,minxlo);
if (boundary[0][1] == 2) boxhi[0] = all[0][1] + SMALL;
else if (boundary[0][1] == 3) boxhi[0] = MAX(all[0][1]+SMALL,minxhi);
- if (boxlo[0] > boxhi[0]) error->all("Illegal simulation box");
+ if (boxlo[0] > boxhi[0]) error->all(FLERR,"Illegal simulation box");
}
if (yperiodic == 0) {
if (boundary[1][0] == 2) boxlo[1] = -all[1][0] - SMALL;
else if (boundary[1][0] == 3) boxlo[1] = MIN(-all[1][0]-SMALL,minylo);
if (boundary[1][1] == 2) boxhi[1] = all[1][1] + SMALL;
else if (boundary[1][1] == 3) boxhi[1] = MAX(all[1][1]+SMALL,minyhi);
- if (boxlo[1] > boxhi[1]) error->all("Illegal simulation box");
+ if (boxlo[1] > boxhi[1]) error->all(FLERR,"Illegal simulation box");
}
if (zperiodic == 0) {
if (boundary[2][0] == 2) boxlo[2] = -all[2][0] - SMALL;
else if (boundary[2][0] == 3) boxlo[2] = MIN(-all[2][0]-SMALL,minzlo);
if (boundary[2][1] == 2) boxhi[2] = all[2][1] + SMALL;
else if (boundary[2][1] == 3) boxhi[2] = MAX(all[2][1]+SMALL,minzhi);
- if (boxlo[2] > boxhi[2]) error->all("Illegal simulation box");
+ if (boxlo[2] > boxhi[2]) error->all(FLERR,"Illegal simulation box");
}
}
set_global_box();
set_local_box();
if(not cuda->finished_run)
{
cuda->setDomainParams();
Cuda_Domain_Init(&cuda->shared_data);
}
// if shrink-wrapped, convert to lamda coords for new box
// must re-invoke pbc() b/c x2lamda result can be outside 0,1 due to roundoff
if (nonperiodic == 2 && triclinic) {
x2lamda(atom->nlocal);
pbc();
}
}
/* ----------------------------------------------------------------------
enforce PBC and modify box image flags for each atom
called every reneighboring and by other commands that change atoms
resulting coord must satisfy lo <= coord < hi
MAX is important since coord - prd < lo can happen when coord = hi
if fix deform, remap velocity of fix group atoms by box edge velocities
for triclinic, atoms must be in lamda coords (0-1) before pbc is called
image = 10 bits for each dimension
increment/decrement in wrap-around fashion
------------------------------------------------------------------------- */
void DomainCuda::pbc()
{
if(cuda->finished_setup&&(!cuda->oncpu))
{
cuda->setDomainParams();
Cuda_Domain_PBC(&cuda->shared_data, deform_vremap, deform_groupbit,cuda->extent);
return;
}
Domain::pbc();
}
/* ----------------------------------------------------------------------
convert triclinic 0-1 lamda coords to box coords for all N atoms
x = H lamda + x0;
------------------------------------------------------------------------- */
void DomainCuda::lamda2x(int n)
{
if(cuda->finished_setup&&(!cuda->oncpu))
{
Cuda_Domain_lamda2x(&cuda->shared_data,n);
return;
}
Domain::lamda2x(n);
}
/* ----------------------------------------------------------------------
convert box coords to triclinic 0-1 lamda coords for all N atoms
lamda = H^-1 (x - x0)
------------------------------------------------------------------------- */
void DomainCuda::x2lamda(int n)
{
if(cuda->finished_setup&&(!cuda->oncpu))
{
Cuda_Domain_x2lamda(&cuda->shared_data,n);
return;
}
Domain::x2lamda(n);
}
diff --git a/src/USER-CUDA/fft3d_cuda.cpp b/src/USER-CUDA/fft3d_cuda.cpp
index bb1278bb7..c6882f459 100644
--- a/src/USER-CUDA/fft3d_cuda.cpp
+++ b/src/USER-CUDA/fft3d_cuda.cpp
@@ -1,608 +1,609 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Jim Shepherd (GA Tech) added SGI SCSL support
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include "fft3d_cuda.h"
#include "fft3d_cuda_cu.h"
#include "remap.h"
#include <ctime>
#include "cuda_wrapper_cu.h"
#ifdef FFT_CUFFT
#endif
+
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
/* ----------------------------------------------------------------------
Data layout for 3d FFTs:
data set of Nfast x Nmid x Nslow elements is owned by P procs
on input, each proc owns a subsection of the elements
on output, each proc will own a (possibly different) subsection
my subsection must not overlap with any other proc's subsection,
i.e. the union of all proc's input (or output) subsections must
exactly tile the global Nfast x Nmid x Nslow data set
when called from C, all subsection indices are
C-style from 0 to N-1 where N = Nfast or Nmid or Nslow
when called from F77, all subsection indices are
F77-style from 1 to N where N = Nfast or Nmid or Nslow
a proc can own 0 elements on input or output
by specifying hi index < lo index
on both input and output, data is stored contiguously on a processor
with a fast-varying, mid-varying, and slow-varying index
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Perform 3d FFT
Arguments:
in starting address of input data on this proc
out starting address of where output data for this proc
will be placed (can be same as in)
flag 1 for forward FFT, -1 for inverse FFT
plan plan returned by previous call to fft_3d_create_plan
------------------------------------------------------------------------- */
void fft_3d_cuda(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan)
{
#ifdef FFT_CUFFT
plan->iterate++;
timespec starttime,starttime2;
timespec endtime,endtime2;
int i,total,length,offset,num;
double norm;
FFT_DATA *data,*copy;
// system specific constants
// pre-remap to prepare for 1st FFTs if needed
// copy = loc for remap result
int nprocs=plan->nprocs;
if(nprocs>1)
{
if(plan->init)
clock_gettime(CLOCK_REALTIME,&starttime);
if (plan->pre_plan) {
if (plan->pre_target == 0) copy = out;
else copy = plan->copy;
if(plan->init) remap_3d((double *) in, (double *) out, (double *) plan->scratch,plan->pre_plan);
data = out;
}
else
data = in;
}
cufftResult retvalc;
if(plan->init)
{
if(nprocs>1)
{
if(sizeof(FFT_FLOAT)==sizeof(double))cudaMemcpy((void*) (plan->cudata2), (void*) data, plan->cudatasize/2,cudaMemcpyHostToDevice);
if(sizeof(FFT_FLOAT)==sizeof(float)) cudaMemcpy((void*) (plan->cudata2), (void*) data, plan->cudatasize,cudaMemcpyHostToDevice);
initfftdata((double*)plan->cudata2,(FFT_FLOAT*)plan->cudata,plan->nfast,plan->nmid,plan->nslow);
}
}
if (flag == -1)
{
retvalc=cufft(plan->plan_3d, plan->cudata, plan->cudata2,CUFFT_FORWARD);
}
else
{
retvalc=cufft(plan->plan_3d, plan->cudata, plan->cudata2,CUFFT_INVERSE);
}
if(retvalc!=CUFFT_SUCCESS) {printf("ErrorCUFFT: %i\n",retvalc);exit(EXIT_FAILURE);}
FFTsyncthreads();
#endif
}
/* ----------------------------------------------------------------------
Create plan for performing a 3d FFT
Arguments:
comm MPI communicator for the P procs which own the data
nfast,nmid,nslow size of global 3d matrix
in_ilo,in_ihi input bounds of data I own in fast index
in_jlo,in_jhi input bounds of data I own in mid index
in_klo,in_khi input bounds of data I own in slow index
out_ilo,out_ihi output bounds of data I own in fast index
out_jlo,out_jhi output bounds of data I own in mid index
out_klo,out_khi output bounds of data I own in slow index
scaled 0 = no scaling of result, 1 = scaling
permute permutation in storage order of indices on output
0 = no permutation
1 = permute once = mid->fast, slow->mid, fast->slow
2 = permute twice = slow->fast, fast->mid, mid->slow
nbuf returns size of internal storage buffers used by FFT
------------------------------------------------------------------------- */
struct fft_plan_3d *fft_3d_create_plan_cuda(
MPI_Comm comm, int nfast, int nmid, int nslow,
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
int in_klo, int in_khi,
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
int out_klo, int out_khi,
int scaled, int permute, int *nbuf,bool ainit)
{
#ifdef FFT_CUFFT
struct fft_plan_3d *plan;
int me,nprocs;
int i,num,flag,remapflag,fftflag;
int first_ilo,first_ihi,first_jlo,first_jhi,first_klo,first_khi;
int second_ilo,second_ihi,second_jlo,second_jhi,second_klo,second_khi;
int third_ilo,third_ihi,third_jlo,third_jhi,third_klo,third_khi;
int out_size,first_size,second_size,third_size,copy_size,scratch_size;
int np1,np2,ip1,ip2;
int list[50];
// system specific variables
// query MPI info
MPI_Comm_rank(comm,&me);
MPI_Comm_size(comm,&nprocs);
#ifndef FFT_CUFFT
- error->all("ERROR: Trying to use cuda fft without FFT_CUFFT set. Recompile with make option 'cufft=1'.");
+ error->all(FLERR,"ERROR: Trying to use cuda fft without FFT_CUFFT set. Recompile with make option 'cufft=1'.");
#endif
// compute division of procs in 2 dimensions not on-processor
bifactor_cuda(nprocs,&np1,&np2);
ip1 = me % np1;
ip2 = me/np1;
// in case of CUDA FFT every proc does the full FFT in order to avoid data transfers (the problem is other wise heavily bandwidth limited)
int ip1out = ip1;
int ip2out = ip2;
int np1out = np1;
int np2out = np2;
ip1 = 0;
ip2 = 0;
np1 = 1;
np2 = 1;
// allocate memory for plan data struct
plan = (struct fft_plan_3d *) malloc(sizeof(struct fft_plan_3d));
if (plan == NULL) return NULL;
plan->init=ainit;
// remap from initial distribution to layout needed for 1st set of 1d FFTs
// not needed if all procs own entire fast axis initially
// first indices = distribution after 1st set of FFTs
if (in_ilo == 0 && in_ihi == nfast-1)
flag = 0;
else
flag = 1;
if(nprocs>1)flag=1;
MPI_Allreduce(&flag,&remapflag,1,MPI_INT,MPI_MAX,comm);
if (remapflag == 0) {
first_ilo = in_ilo;
first_ihi = in_ihi;
first_jlo = in_jlo;
first_jhi = in_jhi;
first_klo = in_klo;
first_khi = in_khi;
plan->pre_plan = NULL;
}
else {
first_ilo = 0;
first_ihi = nfast - 1;
first_jlo = ip1*nmid/np1;
first_jhi = (ip1+1)*nmid/np1 - 1;
first_klo = ip2*nslow/np2;
first_khi = (ip2+1)*nslow/np2 - 1;
int members=2;
if(plan->init) members=1;
plan->pre_plan =
remap_3d_create_plan(comm,in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
first_ilo,first_ihi,first_jlo,first_jhi,
first_klo,first_khi,
members,0,0,2);
if (plan->pre_plan == NULL) return NULL;
}
// 1d FFTs along fast axis
plan->length1 = nfast;
plan->total1 = nfast * nmid * nslow;
// remap from 1st to 2nd FFT
// choose which axis is split over np1 vs np2 to minimize communication
// second indices = distribution after 2nd set of FFTs
second_ilo = ip1*nfast/np1;
second_ihi = (ip1+1)*nfast/np1 - 1;
second_jlo = 0;
second_jhi = nmid - 1;
second_klo = ip2*nslow/np2;
second_khi = (ip2+1)*nslow/np2 - 1;
plan->mid1_plan =
remap_3d_create_plan(comm,
first_ilo,first_ihi,first_jlo,first_jhi,
first_klo,first_khi,
second_ilo,second_ihi,second_jlo,second_jhi,
second_klo,second_khi,
2,1,0,2);
if (plan->mid1_plan == NULL) return NULL;
// 1d FFTs along mid axis
plan->length2 = nmid;
plan->total2 = nfast * nmid * nslow;
// remap from 2nd to 3rd FFT
// if final distribution is permute=2 with all procs owning entire slow axis
// then this remapping goes directly to final distribution
// third indices = distribution after 3rd set of FFTs
flag=1;
MPI_Allreduce(&flag,&remapflag,1,MPI_INT,MPI_MAX,comm);
if (remapflag == 0) {
third_ilo = out_ilo;
third_ihi = out_ihi;
third_jlo = out_jlo;
third_jhi = out_jhi;
third_klo = out_klo;
third_khi = out_khi;
}
else {
third_ilo = ip1*nfast/np1;
third_ihi = (ip1+1)*nfast/np1 - 1;
third_jlo = ip2*nmid/np2;
third_jhi = (ip2+1)*nmid/np2 - 1;
third_klo = 0;
third_khi = nslow - 1;
}
plan->mid2_plan =
remap_3d_create_plan(comm,
second_jlo,second_jhi,second_klo,second_khi,
second_ilo,second_ihi,
third_jlo,third_jhi,third_klo,third_khi,
third_ilo,third_ihi,
2,1,0,2);
if (plan->mid2_plan == NULL) return NULL;
// 1d FFTs along slow axis
plan->length3 = nslow;
plan->total3 = nfast * nmid * nslow;
// remap from 3rd FFT to final distribution
// not needed if permute = 2 and third indices = out indices on all procs
flag=1;
MPI_Allreduce(&flag,&remapflag,1,MPI_INT,MPI_MAX,comm);
if (remapflag == 0)
plan->post_plan = NULL;
else {
plan->post_plan =
remap_3d_create_plan(comm,
third_klo,third_khi,third_ilo,third_ihi,
third_jlo,third_jhi,
out_klo,out_khi,out_ilo,out_ihi,
out_jlo,out_jhi,
2,(permute+1)%3,0,2);
if (plan->post_plan == NULL) return NULL;
}
// configure plan memory pointers and allocate work space
// out_size = amount of memory given to FFT by user
// first/second/third_size = amount of memory needed after pre,mid1,mid2 remaps
// copy_size = amount needed internally for extra copy of data
// scratch_size = amount needed internally for remap scratch space
// for each remap:
// out space used for result if big enough, else require copy buffer
// accumulate largest required remap scratch space
out_size = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) * (out_khi-out_klo+1);
first_size = (first_ihi-first_ilo+1) * (first_jhi-first_jlo+1) *
(first_khi-first_klo+1);
second_size = (second_ihi-second_ilo+1) * (second_jhi-second_jlo+1) *
(second_khi-second_klo+1);
third_size = (third_ihi-third_ilo+1) * (third_jhi-third_jlo+1) *
(third_khi-third_klo+1);
plan->ihi_out=out_ihi;
plan->ilo_out=out_ilo;
plan->jhi_out=out_jhi;
plan->jlo_out=out_jlo;
plan->khi_out=out_khi;
plan->klo_out=out_klo;
copy_size = 0;
scratch_size = 0;
if (plan->pre_plan) {
if (first_size <= out_size)
plan->pre_target = 0;
else {
plan->pre_target = 1;
copy_size = MAX(copy_size,first_size);
}
scratch_size = MAX(scratch_size,first_size);
}
if (plan->mid1_plan) {
if (second_size <= out_size)
plan->mid1_target = 0;
else {
plan->mid1_target = 1;
copy_size = MAX(copy_size,second_size);
}
scratch_size = MAX(scratch_size,second_size);
}
if (plan->mid2_plan) {
if (third_size <= out_size)
plan->mid2_target = 0;
else {
plan->mid2_target = 1;
copy_size = MAX(copy_size,third_size);
}
scratch_size = MAX(scratch_size,third_size);
}
if (plan->post_plan)
scratch_size = MAX(scratch_size,out_size);
*nbuf = copy_size + scratch_size;
if (copy_size) {
plan->copy = (FFT_DATA *) malloc(copy_size*sizeof(FFT_DATA));
if (plan->copy == NULL) return NULL;
}
else plan->copy = NULL;
if (scratch_size) {
plan->scratch = (FFT_DATA *) malloc(scratch_size*sizeof(FFT_DATA));
if (plan->scratch == NULL) return NULL;
}
else plan->scratch = NULL;
// system specific pre-computation of 1d FFT coeffs
// and scaling normalization
cufftResult retvalc;
int nfft = (in_ihi-in_ilo+1) * (in_jhi-in_jlo+1) *
(in_khi-in_klo+1);
int nfft_brick = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
(out_khi-out_klo+1);
int nfft_both = MAX(nfft,nfft_brick);
nfft_both=nfast*nmid*nslow;
plan->cudatasize=nfft_both*sizeof(FFT_DATA);
//retvalc=cufftPlan1d(&(plan->plan_fast), nfast, CUFFT_PLAN,plan->total1/nfast);
//if(retvalc!=CUFFT_SUCCESS) printf("ErrorCUFFT1: %i\n",retvalc);
plan->nfast=nfast;
//retvalc=cufftPlan1d(&(plan->plan_mid), nmid, CUFFT_PLAN,plan->total2/nmid);
//if(retvalc!=CUFFT_SUCCESS) printf("ErrorCUFFT2: %i\n",retvalc);
plan->nmid=nmid;
//retvalc=cufftPlan1d(&(plan->plan_slow), nslow, CUFFT_PLAN,plan->total3/nslow);
//if(retvalc!=CUFFT_SUCCESS) printf("ErrorCUFFT3: %i\n",retvalc);
plan->nslow=nslow;
retvalc=cufftPlan3d(&(plan->plan_3d), nslow,nmid,nfast, CUFFT_PLAN);
if(retvalc!=CUFFT_SUCCESS) printf("ErrorCUFFT3: %i\n",retvalc);
plan->nprocs=nprocs;
plan->me=me;
if (scaled == 0)
plan->scaled = 0;
else {
plan->scaled = 1;
plan->norm = 1.0/(nfast*nmid*nslow);
plan->normnum = (out_ihi-out_ilo+1) * (out_jhi-out_jlo+1) *
(out_khi-out_klo+1);
}
plan->coretime=0;
plan->iterate=0;
plan->ffttime=0;
return plan;
#endif
}
/* ----------------------------------------------------------------------
Destroy a 3d fft plan
------------------------------------------------------------------------- */
void fft_3d_destroy_plan_cuda(struct fft_plan_3d *plan)
{
#ifdef FFT_CUFFT
if (plan->pre_plan) remap_3d_destroy_plan(plan->pre_plan);
if (plan->mid1_plan) remap_3d_destroy_plan(plan->mid1_plan);
if (plan->mid2_plan) remap_3d_destroy_plan(plan->mid2_plan);
if (plan->post_plan) remap_3d_destroy_plan(plan->post_plan);
if (plan->copy) free(plan->copy);
if (plan->scratch) free(plan->scratch);
//cufftDestroy(plan->plan_fast);
//cufftDestroy(plan->plan_mid);
//cufftDestroy(plan->plan_slow);
cufftDestroy(plan->plan_3d);
free(plan);
#endif
}
/* ----------------------------------------------------------------------
recursively divide n into small factors, return them in list
------------------------------------------------------------------------- */
void factor_cuda(int n, int *num, int *list)
{
if (n == 1) {
return;
}
else if (n % 2 == 0) {
*list = 2;
(*num)++;
factor_cuda(n/2,num,list+1);
}
else if (n % 3 == 0) {
*list = 3;
(*num)++;
factor_cuda(n/3,num,list+1);
}
else if (n % 5 == 0) {
*list = 5;
(*num)++;
factor_cuda(n/5,num,list+1);
}
else if (n % 7 == 0) {
*list = 7;
(*num)++;
factor_cuda(n/7,num,list+1);
}
else if (n % 11 == 0) {
*list = 11;
(*num)++;
factor_cuda(n/11,num,list+1);
}
else if (n % 13 == 0) {
*list = 13;
(*num)++;
factor_cuda(n/13,num,list+1);
}
else {
*list = n;
(*num)++;
return;
}
}
/* ----------------------------------------------------------------------
divide n into 2 factors of as equal size as possible
------------------------------------------------------------------------- */
void bifactor_cuda(int n, int *factor1, int *factor2)
{
int n1,n2,facmax;
facmax = static_cast<int> (sqrt((double) n));
for (n1 = facmax; n1 > 0; n1--) {
n2 = n/n1;
if (n1*n2 == n) {
*factor1 = n1;
*factor2 = n2;
return;
}
}
}
/* ----------------------------------------------------------------------
perform just the 1d FFTs needed by a 3d FFT, no data movement
used for timing purposes
Arguments:
in starting address of input data on this proc, all set to 0.0
nsize size of in
flag 1 for forward FFT, -1 for inverse FFT
plan plan returned by previous call to fft_3d_create_plan
------------------------------------------------------------------------- */
void fft_1d_only_cuda(FFT_DATA *data, int nsize, int flag, struct fft_plan_3d *plan)
{
#ifdef FFT_CUFFT
int i,total,length,offset,num;
double norm;
// system specific constants
// total = size of data needed in each dim
// length = length of 1d FFT in each dim
// total/length = # of 1d FFTs in each dim
// if total > nsize, limit # of 1d FFTs to available size of data
int total1 = plan->total1;
int length1 = plan->length1;
int total2 = plan->total2;
int length2 = plan->length2;
int total3 = plan->total3;
int length3 = plan->length3;
if (total1 > nsize) total1 = (nsize/length1) * length1;
if (total2 > nsize) total2 = (nsize/length2) * length2;
if (total3 > nsize) total3 = (nsize/length3) * length3;
// perform 1d FFTs in each of 3 dimensions
// data is just an array of 0.0
cudaMemcpy((void**) &(plan->cudata), (void*) data, plan->cudatasize,cudaMemcpyHostToDevice);
if (flag == -1) {
cufft(plan->plan_3d, plan->cudata, plan->cudata,CUFFT_FORWARD);
/*cufft(plan->plan_fast, plan->cudata, plan->cudata,CUFFT_FORWARD);
cufft(plan->plan_mid, plan->cudata, plan->cudata,CUFFT_FORWARD);
cufft(plan->plan_slow, plan->cudata, plan->cudata,CUFFT_FORWARD);*/
} else {
cufft(plan->plan_3d, plan->cudata, plan->cudata,CUFFT_FORWARD);
/*cufft(plan->plan_fast, plan->cudata, plan->cudata,CUFFT_INVERSE);
cufft(plan->plan_mid,plan->cudata, plan->cudata,CUFFT_INVERSE);
cufft(plan->plan_slow, plan->cudata, plan->cudata,CUFFT_INVERSE);*/
}
cudaMemcpy((void*) data, (void**) &(plan->cudata), plan->cudatasize,cudaMemcpyDeviceToHost);
// scaling if required
// limit num to size of data
#endif
}
diff --git a/src/USER-CUDA/fft3d_wrap_cuda.cpp b/src/USER-CUDA/fft3d_wrap_cuda.cpp
index 5fa45bd85..eab2f82e7 100644
--- a/src/USER-CUDA/fft3d_wrap_cuda.cpp
+++ b/src/USER-CUDA/fft3d_wrap_cuda.cpp
@@ -1,111 +1,111 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "fft3d_wrap_cuda.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FFT3dCuda::FFT3dCuda(LAMMPS *lmp, MPI_Comm comm, int nfast, int nmid, int nslow,
int in_ilo, int in_ihi, int in_jlo, int in_jhi,
int in_klo, int in_khi,
int out_ilo, int out_ihi, int out_jlo, int out_jhi,
int out_klo, int out_khi,
int scaled, int permute, int *nbuf,bool init) : Pointers(lmp)
{
#ifdef FFT_CUFFT
plan = fft_3d_create_plan_cuda(comm,nfast,nmid,nslow,
in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
out_ilo,out_ihi,out_jlo,out_jhi,out_klo,out_khi,
scaled,permute,nbuf,init);
#endif
#ifndef FFT_CUFFT
plan = fft_3d_create_plan(comm,nfast,nmid,nslow,
in_ilo,in_ihi,in_jlo,in_jhi,in_klo,in_khi,
out_ilo,out_ihi,out_jlo,out_jhi,out_klo,out_khi,
scaled,permute,nbuf);
#endif
- if (plan == NULL) error->one("Could not create 3d FFT plan");
+ if (plan == NULL) error->one(FLERR,"Could not create 3d FFT plan");
}
/* ---------------------------------------------------------------------- */
FFT3dCuda::~FFT3dCuda()
{
#ifdef FFT_CUFFT
fft_3d_destroy_plan_cuda(plan);
#endif
#ifndef FFT_CUFFT
fft_3d_destroy_plan(plan);
#endif
}
/* ---------------------------------------------------------------------- */
void FFT3dCuda::compute(double *in, double *out, int flag)
{
#ifdef FFT_CUFFT
fft_3d_cuda((FFT_DATA *) in,(FFT_DATA *) out,flag,plan);
#endif
#ifndef FFT_CUFFT
fft_3d((FFT_DATA *) in,(FFT_DATA *) out,flag,plan);
#endif
}
/* ---------------------------------------------------------------------- */
void FFT3dCuda::timing1d(double *in, int nsize, int flag)
{
#ifdef FFT_CUFFT
fft_1d_only_cuda((FFT_DATA *) in,nsize,flag,plan);
#endif
#ifndef FFT_CUFFT
fft_1d_only((FFT_DATA *) in,nsize,flag,plan);
#endif
}
#ifdef FFT_CUFFT
void FFT3dCuda::set_cudata(void* cudata,void* cudata2)
{
plan->cudata=(cufftData*) cudata;
plan->cudata2=(cufftData*) cudata2;
}
#endif
diff --git a/src/USER-CUDA/fix_addforce_cuda.cpp b/src/USER-CUDA/fix_addforce_cuda.cpp
index acf4d6d7e..218110acf 100644
--- a/src/USER-CUDA/fix_addforce_cuda.cpp
+++ b/src/USER-CUDA/fix_addforce_cuda.cpp
@@ -1,190 +1,190 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cstring>
#include <cstdlib>
#include "fix_addforce_cuda.h"
#include "fix_addforce_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "domain.h"
#include "cuda.h"
#include "memory.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixAddForceCuda::FixAddForceCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg < 6) error->all("Illegal fix addforce/cuda command");
+ if (narg < 6) error->all(FLERR,"Illegal fix addforce/cuda command");
scalar_flag = 1;
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extscalar = 1;
extvector = 1;
xvalue = atof(arg[3]);
yvalue = atof(arg[4]);
zvalue = atof(arg[5]);
// optional args
iregion = -1;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix addforce/cuda command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix addforce/cuda command");
iregion = domain->find_region(arg[iarg+1]);
- if (iregion == -1) error->all("Fix addforce/cuda region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Fix addforce/cuda region ID does not exist");
iarg += 2;
- } else error->all("Illegal fix addforce/cuda command");
+ } else error->all(FLERR,"Illegal fix addforce/cuda command");
}
- if(iregion!=-1) error->all("Error: fix addforce/cuda does not currently support 'region' option");
+ if(iregion!=-1) error->all(FLERR,"Error: fix addforce/cuda does not currently support 'region' option");
force_flag = 0;
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
cu_foriginal = NULL;
}
/* ---------------------------------------------------------------------- */
int FixAddForceCuda::setmask()
{
int mask = 0;
mask |= POST_FORCE_CUDA;
mask |= THERMO_ENERGY_CUDA;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAddForceCuda::init()
{
if(not cu_foriginal)
cu_foriginal = new cCudaData<double, F_FLOAT, x> (foriginal,4);
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixAddForceCuda::setup(int vflag)
{
MYDBG( printf("# CUDA: FixAddForceCuda::setup\n"); )
if (strstr(update->integrate_style,"verlet"))
{
Cuda_FixAddForceCuda_Init(&cuda->shared_data);
cuda->cu_f->upload();
post_force(vflag);
cuda->cu_f->download();
}
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
cuda->cu_f->download();
post_force_respa(vflag,nlevels_respa-1,0);
cuda->cu_f->upload();
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
MYDBG( printf("# CUDA: FixAddForceCuda::setup done\n"); )
}
/* ---------------------------------------------------------------------- */
void FixAddForceCuda::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAddForceCuda::post_force(int vflag)
{
MYDBG( printf("# CUDA: FixAddForceCuda::postforce start\n"); )
force_flag = 0;
cu_foriginal->memset_device(0);
Cuda_FixAddForceCuda_PostForce(&cuda->shared_data, groupbit, xvalue, yvalue,zvalue,(F_FLOAT*) cu_foriginal->dev_data());
cu_foriginal->download();
}
/* ---------------------------------------------------------------------- */
void FixAddForceCuda::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAddForceCuda::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
potential energy of added force
------------------------------------------------------------------------- */
double FixAddForceCuda::compute_scalar()
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[0];
}
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixAddForceCuda::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[n+1];
}
diff --git a/src/USER-CUDA/fix_aveforce_cuda.cpp b/src/USER-CUDA/fix_aveforce_cuda.cpp
index 10b4555e8..3a80fc1b3 100644
--- a/src/USER-CUDA/fix_aveforce_cuda.cpp
+++ b/src/USER-CUDA/fix_aveforce_cuda.cpp
@@ -1,229 +1,229 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cstring>
#include <cstdlib>
#include "fix_aveforce_cuda.h"
#include "fix_aveforce_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "domain.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixAveForceCuda::FixAveForceCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg != 6) error->all("Illegal fix aveforce command");
+ if (narg != 6) error->all(FLERR,"Illegal fix aveforce command");
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extvector = 1;
xflag = yflag = zflag = 1;
if (strcmp(arg[3],"NULL") == 0) xflag = 0;
else xvalue = atof(arg[3]);
if (strcmp(arg[4],"NULL") == 0) yflag = 0;
else yvalue = atof(arg[4]);
if (strcmp(arg[5],"NULL") == 0) zflag = 0;
else zvalue = atof(arg[5]);
// optional args
iregion = -1;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix aveforce command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix aveforce command");
iregion = domain->find_region(arg[iarg+1]);
- if (iregion == -1) error->all("Fix aveforce region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Fix aveforce region ID does not exist");
iarg += 2;
- } else error->all("Illegal fix aveforce command");
+ } else error->all(FLERR,"Illegal fix aveforce command");
}
- if(iregion!=-1) error->all("Error: fix aveforce/cuda does not currently support 'region' option");
+ if(iregion!=-1) error->all(FLERR,"Error: fix aveforce/cuda does not currently support 'region' option");
foriginal_all[0] = foriginal_all[1] = foriginal_all[2] = foriginal_all[3] = 0.0;
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
cu_foriginal = NULL;
}
/* ---------------------------------------------------------------------- */
int FixAveForceCuda::setmask()
{
int mask = 0;
mask |= POST_FORCE_CUDA;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAveForceCuda::init()
{
if(not cu_foriginal)
cu_foriginal = new cCudaData<double, F_FLOAT, x> (foriginal,4);
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
// ncount = total # of atoms in group
int *mask = atom->mask;
int nlocal = atom->nlocal;
}
/* ---------------------------------------------------------------------- */
void FixAveForceCuda::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
{
Cuda_FixAveForceCuda_Init(&cuda->shared_data);
cuda->cu_f->upload();
post_force(vflag);
cuda->cu_f->download();
}
else
{
cuda->cu_f->download();
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
cuda->cu_f->upload();
}
}
/* ---------------------------------------------------------------------- */
void FixAveForceCuda::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAveForceCuda::post_force(int vflag)
{
// sum forces on participating atoms
cu_foriginal->memset_device(0);
Cuda_FixAveForceCuda_PostForce_FOrg(&cuda->shared_data, groupbit,(F_FLOAT*) cu_foriginal->dev_data());
cu_foriginal->download();
// average the force on participating atoms
// add in requested amount
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
int ncount = static_cast<int> (foriginal_all[3]);
if (ncount == 0) return;
double fave[3];
fave[0] = foriginal_all[0]/ncount + xvalue;
fave[1] = foriginal_all[1]/ncount + yvalue;
fave[2] = foriginal_all[2]/ncount + zvalue;
// set force of all participating atoms to same value
// only for active dimensions
Cuda_FixAveForceCuda_PostForce_Set(&cuda->shared_data, groupbit,xflag,yflag,zflag,fave[0],fave[1],fave[2]);
}
/* ---------------------------------------------------------------------- */
void FixAveForceCuda::post_force_respa(int vflag, int ilevel, int iloop)
{
// ave + extra force on outermost level
// just ave on inner levels
if (ilevel == nlevels_respa-1) post_force(vflag);
else {
cuda->cu_f->download();
cuda->cu_mask->download();
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double foriginal[4];
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
foriginal[0] += f[i][0];
foriginal[1] += f[i][1];
foriginal[2] += f[i][2];
foriginal[3] += 1;
}
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
int ncount = static_cast<int> (foriginal_all[3]);
if (ncount == 0) return;
double fave[3];
fave[0] = foriginal_all[0]/ncount;
fave[1] = foriginal_all[1]/ncount;
fave[2] = foriginal_all[2]/ncount;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (xflag) f[i][0] = fave[0];
if (yflag) f[i][1] = fave[1];
if (zflag) f[i][2] = fave[2];
}
cuda->cu_f->upload();
}
}
/* ---------------------------------------------------------------------- */
void FixAveForceCuda::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixAveForceCuda::compute_vector(int n)
{
return foriginal_all[n];
}
diff --git a/src/USER-CUDA/fix_enforce2d_cuda.cpp b/src/USER-CUDA/fix_enforce2d_cuda.cpp
index 91a1661c0..d660814f2 100644
--- a/src/USER-CUDA/fix_enforce2d_cuda.cpp
+++ b/src/USER-CUDA/fix_enforce2d_cuda.cpp
@@ -1,169 +1,169 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstring>
#include "fix_enforce2d_cuda.h"
#include "fix_enforce2d_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "respa.h"
#include "error.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixEnforce2DCuda::FixEnforce2DCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg != 3) error->all("Illegal fix enforce2d command");
+ if (narg != 3) error->all(FLERR,"Illegal fix enforce2d command");
}
/* ---------------------------------------------------------------------- */
int FixEnforce2DCuda::setmask()
{
int mask = 0;
mask |= POST_FORCE_CUDA;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixEnforce2DCuda::init()
{
if (domain->dimension == 3)
- error->all("Cannot use fix enforce2d/cuda with 3d simulation");
+ error->all(FLERR,"Cannot use fix enforce2d/cuda with 3d simulation");
if (atom->omega_flag)
- error->warning("Enforce2d/cuda does not support omega_flag on gpu yet. Will be handled on cpu.");
+ error->warning(FLERR,"Enforce2d/cuda does not support omega_flag on gpu yet. Will be handled on cpu.");
if (atom->angmom_flag)
- error->warning("Enforce2d/cuda does not support angmom_flag (angular momentum) on gpu yet. Will be handled on cpu.");
+ error->warning(FLERR,"Enforce2d/cuda does not support angmom_flag (angular momentum) on gpu yet. Will be handled on cpu.");
if (atom->torque_flag)
- error->warning("Enforce2d/cuda does not support torque_flag on gpu yet. Will be handled on cpu.");
+ error->warning(FLERR,"Enforce2d/cuda does not support torque_flag on gpu yet. Will be handled on cpu.");
}
/* ---------------------------------------------------------------------- */
void FixEnforce2DCuda::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
{
Cuda_FixEnforce2dCuda_Init(&cuda->shared_data);
cuda->cu_f->upload();
cuda->cu_v->upload();
post_force(vflag);
cuda->cu_f->download();
cuda->cu_v->download();
}
else {
int nlevels_respa = ((Respa *) update->integrate)->nlevels;
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
}
}
/* ---------------------------------------------------------------------- */
void FixEnforce2DCuda::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixEnforce2DCuda::post_force(int vflag)
{
Cuda_FixEnforce2dCuda_PostForce(&cuda->shared_data, groupbit);
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (atom->omega_flag) {
double **omega = atom->omega;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
omega[i][0] = 0.0;
omega[i][1] = 0.0;
}
}
if (atom->angmom_flag) {
double **angmom = atom->angmom;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
angmom[i][0] = 0.0;
angmom[i][1] = 0.0;
}
}
if (atom->torque_flag) {
double **torque = atom->torque;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
}
}
}
/* ---------------------------------------------------------------------- */
void FixEnforce2DCuda::post_force_respa(int vflag, int ilevel, int iloop)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixEnforce2DCuda::min_post_force(int vflag)
{
post_force(vflag);
}
diff --git a/src/USER-CUDA/fix_freeze_cuda.cpp b/src/USER-CUDA/fix_freeze_cuda.cpp
index d52642280..9e8f81c5f 100644
--- a/src/USER-CUDA/fix_freeze_cuda.cpp
+++ b/src/USER-CUDA/fix_freeze_cuda.cpp
@@ -1,135 +1,135 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cstring>
#include <cstdlib>
#include "fix_freeze_cuda.h"
#include "fix_freeze_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "cuda.h"
#include "memory.h"
#include "modify.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixFreezeCuda::FixFreezeCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg != 3) error->all("Illegal fix freeze command");
+ if (narg != 3) error->all(FLERR,"Illegal fix freeze command");
if (!atom->torque_flag)
- error->all("Fix freeze requires atom attribute torque");
+ error->all(FLERR,"Fix freeze requires atom attribute torque");
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extvector = 1;
force_flag = 0;
foriginal[0] = foriginal[1] = foriginal[2] = 0.0;
cu_foriginal=NULL;
}
/* ---------------------------------------------------------------------- */
int FixFreezeCuda::setmask()
{
int mask = 0;
mask |= POST_FORCE_CUDA;
mask |= THERMO_ENERGY_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixFreezeCuda::init()
{
if(not cu_foriginal)
cu_foriginal = new cCudaData<double, F_FLOAT, x> (foriginal,3);
int count = 0;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"freeze") == 0) count++;
- if (count > 1) error->all("More than one fix freeze");
+ if (count > 1) error->all(FLERR,"More than one fix freeze");
}
/* ---------------------------------------------------------------------- */
void FixFreezeCuda::setup(int vflag)
{
MYDBG( printf("# CUDA: FixFreezeCuda::setup\n"); )
if (strstr(update->integrate_style,"verlet"))
{
Cuda_FixFreezeCuda_Init(&cuda->shared_data);
cuda->cu_f->upload();
post_force(vflag);
cuda->cu_f->download();
}
MYDBG( printf("# CUDA: FixFreezeCuda::setup done\n"); )
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void FixFreezeCuda::post_force(int vflag)
{
MYDBG( printf("# CUDA: FixFreezeCuda::postforce start\n"); )
force_flag = 0;
cu_foriginal->memset_device(0);
Cuda_FixFreezeCuda_PostForce(&cuda->shared_data, groupbit, (F_FLOAT*) cu_foriginal->dev_data());
cu_foriginal->download();
}
/* ---------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixFreezeCuda::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,3,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[n+1];
}
diff --git a/src/USER-CUDA/fix_gravity_cuda.cpp b/src/USER-CUDA/fix_gravity_cuda.cpp
index 0c69dffcc..8c6d8488c 100644
--- a/src/USER-CUDA/fix_gravity_cuda.cpp
+++ b/src/USER-CUDA/fix_gravity_cuda.cpp
@@ -1,181 +1,181 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include "fix_gravity_cuda.h"
#include "fix_gravity_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "respa.h"
#include "error.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
enum{CHUTE,SPHERICAL,GRADIENT,VECTOR};
/* ---------------------------------------------------------------------- */
FixGravityCuda::FixGravityCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg < 5) error->all("Illegal fix gravity command");
+ if (narg < 5) error->all(FLERR,"Illegal fix gravity command");
time_depend = 1;
magnitude = atof(arg[3]);
if (strcmp(arg[4],"chute") == 0) {
- if (narg != 6) error->all("Illegal fix gravity command");
+ if (narg != 6) error->all(FLERR,"Illegal fix gravity command");
style = CHUTE;
phi = 0.0;
theta = 180.0 - atof(arg[5]);
} else if (strcmp(arg[4],"spherical") == 0) {
- if (narg != 7) error->all("Illegal fix gravity command");
+ if (narg != 7) error->all(FLERR,"Illegal fix gravity command");
style = SPHERICAL;
phi = atof(arg[5]);
theta = atof(arg[6]);
} else if (strcmp(arg[4],"gradient") == 0) {
- if (narg != 9) error->all("Illegal fix gravity command");
+ if (narg != 9) error->all(FLERR,"Illegal fix gravity command");
style = GRADIENT;
phi = atof(arg[5]);
theta = atof(arg[6]);
phigrad = atof(arg[7]);
thetagrad = atof(arg[8]);
} else if (strcmp(arg[4],"vector") == 0) {
- if (narg != 8) error->all("Illegal fix gravity command");
+ if (narg != 8) error->all(FLERR,"Illegal fix gravity command");
style = VECTOR;
xdir = atof(arg[5]);
ydir = atof(arg[6]);
zdir = atof(arg[7]);
- } else error->all("Illegal fix gravity command");
+ } else error->all(FLERR,"Illegal fix gravity command");
double PI = 4.0*atan(1.0);
degree2rad = PI/180.0;
if (style == CHUTE || style == SPHERICAL || style == GRADIENT) {
if (domain->dimension == 3) {
xgrav = sin(degree2rad * theta) * cos(degree2rad * phi);
ygrav = sin(degree2rad * theta) * sin(degree2rad * phi);
zgrav = cos(degree2rad * theta);
} else {
xgrav = sin(degree2rad * theta);
ygrav = cos(degree2rad * theta);
zgrav = 0.0;
}
} else if (style == VECTOR) {
if (domain->dimension == 3) {
double length = sqrt(xdir*xdir + ydir*ydir + zdir*zdir);
xgrav = xdir/length;
ygrav = ydir/length;
zgrav = zdir/length;
} else {
double length = sqrt(xdir*xdir + ydir*ydir);
xgrav = xdir/length;
ygrav = ydir/length;
zgrav = 0.0;
}
}
time_origin = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
int FixGravityCuda::setmask()
{
int mask = 0;
mask |= POST_FORCE_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixGravityCuda::init()
{
dt = update->dt;
xacc = magnitude*xgrav;
yacc = magnitude*ygrav;
zacc = magnitude*zgrav;
}
/* ---------------------------------------------------------------------- */
void FixGravityCuda::setup(int vflag)
{
MYDBG( printf("# CUDA: FixGravityCuda::setup\n"); )
if (strstr(update->integrate_style,"verlet"))
{
Cuda_FixGravityCuda_Init(&cuda->shared_data);
cuda->cu_f->upload();
post_force(vflag);
cuda->cu_f->download();
}
else {
}
MYDBG( printf("# CUDA: FixGravityCuda::setup done\n"); )
}
/* ---------------------------------------------------------------------- */
void FixGravityCuda::post_force(int vflag)
{
// update direction of gravity vector if gradient style
if (style == GRADIENT) {
if (domain->dimension == 3) {
double phi_current = degree2rad *
(phi + (update->ntimestep - time_origin)*dt*phigrad*360.0);
double theta_current = degree2rad *
(theta + (update->ntimestep - time_origin)*dt*thetagrad*360.0);
xgrav = sin(theta_current) * cos(phi_current);
ygrav = sin(theta_current) * sin(phi_current);
zgrav = cos(theta_current);
} else {
double theta_current = degree2rad *
(theta + (update->ntimestep - time_origin)*dt*thetagrad*360.0);
xgrav = sin(theta_current);
ygrav = cos(theta_current);
}
xacc = magnitude*xgrav;
yacc = magnitude*ygrav;
zacc = magnitude*zgrav;
}
MYDBG( printf("# CUDA: FixGravityCuda::postforce start\n"); )
Cuda_FixGravityCuda_PostForce(&cuda->shared_data, groupbit, xacc,yacc,zacc);
}
diff --git a/src/USER-CUDA/fix_nh_cuda.cpp b/src/USER-CUDA/fix_nh_cuda.cpp
index 281ffaf0f..cfbd3f788 100644
--- a/src/USER-CUDA/fix_nh_cuda.cpp
+++ b/src/USER-CUDA/fix_nh_cuda.cpp
@@ -1,2078 +1,2075 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Mark Stevens (SNL), Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include <cstring>
#include <cstdlib>
#include <cmath>
#include "fix_nh_cuda.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "modify.h"
#include "fix_deform.h"
#include "compute.h"
#include "kspace.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
#include "math_extra.h"
#include "cuda.h"
#include "fix_nh_cuda_cu.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
enum{NOBIAS,BIAS};
enum{NONE,XYZ,XY,YZ,XZ};
enum{ISO,ANISO,TRICLINIC};
/* ----------------------------------------------------------------------
NVT,NPH,NPT integrators for improved Nose-Hoover equations of motion
---------------------------------------------------------------------- */
FixNHCuda::FixNHCuda(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg < 4) error->all("Illegal fix nvt/npt/nph command");
+ if (narg < 4) error->all(FLERR,"Illegal fix nvt/npt/nph command");
restart_global = 1;
time_integrate = 1;
scalar_flag = 1;
vector_flag = 1;
global_freq = 1;
extscalar = 1;
extvector = 0;
triggerneighsq = -1;
// default values
pcouple = NONE;
drag = 0.0;
allremap = 1;
mtchain = mpchain = 3;
nc_tchain = nc_pchain = 1;
mtk_flag = 1;
deviatoric_flag = 0;
nreset_h0 = 0;
// Used by FixNVTSllod to preserve non-default value
mtchain_default_flag = 1;
tstat_flag = 0;
double t_period = 0.0;
double p_period[6];
for (int i = 0; i < 6; i++) {
p_start[i] = p_stop[i] = p_period[i] = 0.0;
p_flag[i] = 0;
}
// process keywords
dimension = domain->dimension;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
tstat_flag = 1;
t_start = atof(arg[iarg+1]);
t_stop = atof(arg[iarg+2]);
t_period = atof(arg[iarg+3]);
if (t_start < 0.0 || t_stop <= 0.0)
- error->all("Target T for fix nvt/npt/nph cannot be 0.0");
+ error->all(FLERR,"Target T for fix nvt/npt/nph cannot be 0.0");
iarg += 4;
} else if (strcmp(arg[iarg],"iso") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
pcouple = XYZ;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"aniso") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
pcouple = NONE;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"tri") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
pcouple = NONE;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
p_start[3] = p_start[4] = p_start[5] = 0.0;
p_stop[3] = p_stop[4] = p_stop[5] = 0.0;
p_period[3] = p_period[4] = p_period[5] = atof(arg[iarg+3]);
p_flag[3] = p_flag[4] = p_flag[5] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
p_start[3] = p_stop[3] = p_period[3] = 0.0;
p_flag[3] = 0;
p_start[4] = p_stop[4] = p_period[4] = 0.0;
p_flag[4] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"x") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[0] = atof(arg[iarg+1]);
p_stop[0] = atof(arg[iarg+2]);
p_period[0] = atof(arg[iarg+3]);
p_flag[0] = 1;
deviatoric_flag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"y") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[1] = atof(arg[iarg+1]);
p_stop[1] = atof(arg[iarg+2]);
p_period[1] = atof(arg[iarg+3]);
p_flag[1] = 1;
deviatoric_flag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"z") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[2] = atof(arg[iarg+1]);
p_stop[2] = atof(arg[iarg+2]);
p_period[2] = atof(arg[iarg+3]);
p_flag[2] = 1;
deviatoric_flag = 1;
iarg += 4;
if (dimension == 2)
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
} else if (strcmp(arg[iarg],"yz") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[3] = atof(arg[iarg+1]);
p_stop[3] = atof(arg[iarg+2]);
p_period[3] = atof(arg[iarg+3]);
p_flag[3] = 1;
deviatoric_flag = 1;
iarg += 4;
if (dimension == 2)
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
} else if (strcmp(arg[iarg],"xz") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[4] = atof(arg[iarg+1]);
p_stop[4] = atof(arg[iarg+2]);
p_period[4] = atof(arg[iarg+3]);
p_flag[4] = 1;
deviatoric_flag = 1;
iarg += 4;
if (dimension == 2)
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
} else if (strcmp(arg[iarg],"xy") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[5] = atof(arg[iarg+1]);
p_stop[5] = atof(arg[iarg+2]);
p_period[5] = atof(arg[iarg+3]);
p_flag[5] = 1;
deviatoric_flag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"couple") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"xyz") == 0) pcouple = XYZ;
else if (strcmp(arg[iarg+1],"xy") == 0) pcouple = XY;
else if (strcmp(arg[iarg+1],"yz") == 0) pcouple = YZ;
else if (strcmp(arg[iarg+1],"xz") == 0) pcouple = XZ;
else if (strcmp(arg[iarg+1],"none") == 0) pcouple = NONE;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"drag") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
drag = atof(arg[iarg+1]);
- if (drag < 0.0) error->all("Illegal fix nvt/npt/nph command");
+ if (drag < 0.0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"dilate") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"all") == 0) allremap = 1;
else if (strcmp(arg[iarg+1],"partial") == 0) allremap = 0;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"tchain") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
mtchain = atoi(arg[iarg+1]);
- if (mtchain < 1) error->all("Illegal fix nvt/npt/nph command");
+ if (mtchain < 1) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"pchain") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
mpchain = atoi(arg[iarg+1]);
- if (mpchain < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (mpchain < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"mtk") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"yes") == 0) mtk_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) mtk_flag = 0;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"tloop") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
nc_tchain = atoi(arg[iarg+1]);
- if (nc_tchain < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (nc_tchain < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"ploop") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
nc_pchain = atoi(arg[iarg+1]);
- if (nc_pchain < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (nc_pchain < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"nreset") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
nreset_h0 = atoi(arg[iarg+1]);
- if (nreset_h0 < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (nreset_h0 < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
- } else error->all("Illegal fix nvt/npt/nph command");
+ } else error->all(FLERR,"Illegal fix nvt/npt/nph command");
}
// error checks
if (dimension == 2 && (p_flag[2] || p_flag[3] || p_flag[4]))
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
if (dimension == 2 && (pcouple == YZ || pcouple == XZ))
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
if (pcouple == XYZ && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == XYZ && dimension == 3 && p_flag[2] == 0)
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == XY && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == YZ && (p_flag[1] == 0 || p_flag[2] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == XZ && (p_flag[0] == 0 || p_flag[2] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (p_flag[0] && domain->xperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a non-periodic dimension");
if (p_flag[1] && domain->yperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a non-periodic dimension");
if (p_flag[2] && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a non-periodic dimension");
if (p_flag[3] && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
if (p_flag[4] && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
if (p_flag[5] && domain->yperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
if (!domain->triclinic && (p_flag[3] || p_flag[4] || p_flag[5]))
- error->all("Can not specify Pxy/Pxz/Pyz in "
+ error->all(FLERR,"Can not specify Pxy/Pxz/Pyz in "
"fix nvt/npt/nph with non-triclinic box");
if (pcouple == XYZ && dimension == 3 &&
(p_start[0] != p_start[1] || p_start[0] != p_start[2] ||
p_stop[0] != p_stop[1] || p_stop[0] != p_stop[2] ||
p_period[0] != p_period[1] || p_period[0] != p_period[2]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == XYZ && dimension == 2 &&
(p_start[0] != p_start[1] || p_stop[0] != p_stop[1] ||
p_period[0] != p_period[1]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == XY &&
(p_start[0] != p_start[1] || p_stop[0] != p_stop[1] ||
p_period[0] != p_period[1]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == YZ &&
(p_start[1] != p_start[2] || p_stop[1] != p_stop[2] ||
p_period[1] != p_period[2]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == XZ &&
(p_start[0] != p_start[2] || p_stop[0] != p_stop[2] ||
p_period[0] != p_period[2]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if ((tstat_flag && t_period <= 0.0) ||
(p_flag[0] && p_period[0] <= 0.0) ||
(p_flag[1] && p_period[1] <= 0.0) ||
(p_flag[2] && p_period[2] <= 0.0) ||
(p_flag[3] && p_period[3] <= 0.0) ||
(p_flag[4] && p_period[4] <= 0.0) ||
(p_flag[5] && p_period[5] <= 0.0))
- error->all("Fix nvt/npt/nph damping parameters must be > 0.0");
+ error->all(FLERR,"Fix nvt/npt/nph damping parameters must be > 0.0");
// set pstat_flag and box change variables
pstat_flag = 0;
for (int i = 0; i < 6; i++)
if (p_flag[i]) pstat_flag = 1;
if (pstat_flag) {
box_change = 1;
if (p_flag[0] || p_flag[1] || p_flag[2]) box_change_size = 1;
if (p_flag[3] || p_flag[4] || p_flag[5]) box_change_shape = 1;
no_change_box = 1;
if (allremap == 0) restart_pbc = 1;
}
// pstyle = TRICLINIC if any off-diagonal term is controlled -> 6 dof
// else pstyle = ISO if XYZ coupling or XY coupling in 2d -> 1 dof
// else pstyle = ANISO -> 3 dof
if (p_flag[3] || p_flag[4] || p_flag[5]) pstyle = TRICLINIC;
else if (pcouple == XYZ || (dimension == 2 && pcouple == XY)) pstyle = ISO;
else pstyle = ANISO;
// convert input periods to frequencies
t_freq = 0.0;
p_freq[0] = p_freq[1] = p_freq[2] = p_freq[3] = p_freq[4] = p_freq[5] = 0.0;
if (tstat_flag) t_freq = 1.0 / t_period;
if (p_flag[0]) p_freq[0] = 1.0 / p_period[0];
if (p_flag[1]) p_freq[1] = 1.0 / p_period[1];
if (p_flag[2]) p_freq[2] = 1.0 / p_period[2];
if (p_flag[3]) p_freq[3] = 1.0 / p_period[3];
if (p_flag[4]) p_freq[4] = 1.0 / p_period[4];
if (p_flag[5]) p_freq[5] = 1.0 / p_period[5];
// Nose/Hoover temp and pressure init
size_vector = 0;
if (tstat_flag) {
int ich;
eta = new double[mtchain];
// add one extra dummy thermostat, set to zero
eta_dot = new double[mtchain+1];
eta_dot[mtchain] = 0.0;
eta_dotdot = new double[mtchain];
for (ich = 0; ich < mtchain; ich++) {
eta[ich] = eta_dot[ich] = eta_dotdot[ich] = 0.0;
}
eta_mass = new double[mtchain];
size_vector += 2*2*mtchain;
}
if (pstat_flag) {
omega[0] = omega[1] = omega[2] = 0.0;
omega_dot[0] = omega_dot[1] = omega_dot[2] = 0.0;
omega_mass[0] = omega_mass[1] = omega_mass[2] = 0.0;
omega[3] = omega[4] = omega[5] = 0.0;
omega_dot[3] = omega_dot[4] = omega_dot[5] = 0.0;
omega_mass[3] = omega_mass[4] = omega_mass[5] = 0.0;
if (pstyle == ISO) size_vector += 2*2*1;
else if (pstyle == ANISO) size_vector += 2*2*3;
else if (pstyle == TRICLINIC) size_vector += 2*2*6;
if (mpchain) {
int ich;
etap = new double[mpchain];
// add one extra dummy thermostat, set to zero
etap_dot = new double[mpchain+1];
etap_dot[mpchain] = 0.0;
etap_dotdot = new double[mpchain];
for (ich = 0; ich < mpchain; ich++) {
etap[ich] = etap_dot[ich] =
etap_dotdot[ich] = 0.0;
}
etap_mass = new double[mpchain];
size_vector += 2*2*mpchain;
}
if (deviatoric_flag) size_vector += 1;
}
nrigid = 0;
rfix = NULL;
// initialize vol0,t0 to zero to signal uninitialized
// values then assigned in init(), if necessary
vol0 = t0 = 0.0;
}
/* ---------------------------------------------------------------------- */
FixNHCuda::~FixNHCuda()
{
delete [] rfix;
// delete temperature and pressure if fix created them
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
if (tstat_flag) {
delete [] eta;
delete [] eta_dot;
delete [] eta_dotdot;
delete [] eta_mass;
}
if (pstat_flag) {
if (pflag) modify->delete_compute(id_press);
delete [] id_press;
if (mpchain) {
delete [] etap;
delete [] etap_dot;
delete [] etap_dotdot;
delete [] etap_mass;
}
}
}
/* ---------------------------------------------------------------------- */
int FixNHCuda::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE_CUDA;
mask |= FINAL_INTEGRATE_CUDA;
mask |= THERMO_ENERGY_CUDA;
//mask |= INITIAL_INTEGRATE_RESPA;
//mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNHCuda::init()
{
// insure no conflict with fix deform
if (pstat_flag)
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
int *dimflag = ((FixDeform *) modify->fix[i])->dimflag;
if ((p_flag[0] && dimflag[0]) || (p_flag[1] && dimflag[1]) ||
(p_flag[2] && dimflag[2]) || (p_flag[3] && dimflag[3]) ||
(p_flag[4] && dimflag[4]) || (p_flag[5] && dimflag[5]))
- error->all("Cannot use fix npt and fix deform on "
+ error->all(FLERR,"Cannot use fix npt and fix deform on "
"same component of stress tensor");
}
// set temperature and pressure ptrs
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix nvt/nph/npt does not exist");
+ error->all(FLERR,"Temperature ID for fix nvt/nph/npt does not exist");
temperature = modify->compute[icompute];
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
if (pstat_flag) {
icompute = modify->find_compute(id_press);
- if (icompute < 0) error->all("Pressure ID for fix npt/nph does not exist");
+ if (icompute < 0) error->all(FLERR,"Pressure ID for fix npt/nph does not exist");
pressure = modify->compute[icompute];
}
// set timesteps and frequencies
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dthalf = 0.5 * update->dt;
dt4 = 0.25 * update->dt;
dt8 = 0.125 * update->dt;
dto = dthalf;
p_freq_max = 0.0;
if (pstat_flag) {
p_freq_max = MAX(p_freq[0],p_freq[1]);
p_freq_max = MAX(p_freq_max,p_freq[2]);
if (pstyle == TRICLINIC) {
p_freq_max = MAX(p_freq_max,p_freq[3]);
p_freq_max = MAX(p_freq_max,p_freq[4]);
p_freq_max = MAX(p_freq_max,p_freq[5]);
}
pdrag_factor = 1.0 - (update->dt * p_freq_max * drag / nc_pchain);
}
if (tstat_flag)
tdrag_factor = 1.0 - (update->dt * t_freq * drag / nc_tchain);
// tally the number of dimensions that are barostatted
// also compute the initial volume and reference cell
// set initial volume and reference cell, if not already done
if (pstat_flag) {
pdim = p_flag[0] + p_flag[1] + p_flag[2];
if (vol0 == 0.0) {
if (dimension == 3) vol0 = domain->xprd * domain->yprd * domain->zprd;
else vol0 = domain->xprd * domain->yprd;
h0_inv[0] = domain->h_inv[0];
h0_inv[1] = domain->h_inv[1];
h0_inv[2] = domain->h_inv[2];
h0_inv[3] = domain->h_inv[3];
h0_inv[4] = domain->h_inv[4];
h0_inv[5] = domain->h_inv[5];
}
}
boltz = force->boltz;
nktv2p = force->nktv2p;
if (force->kspace) kspace_flag = 1;
else kspace_flag = 0;
if (strcmp(update->integrate_style,"respa") == 0) {
nlevels_respa = ((Respa *) update->integrate)->nlevels;
step_respa = ((Respa *) update->integrate)->step;
dto = 0.5*step_respa[0];
}
// detect if any rigid fixes exist so rigid bodies move when box is remapped
// rfix[] = indices to each fix rigid
delete [] rfix;
nrigid = 0;
rfix = NULL;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) nrigid++;
if (nrigid) {
rfix = new int[nrigid];
nrigid = 0;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) rfix[nrigid++] = i;
}
triggerneighsq= cuda->shared_data.atom.triggerneighsq;
cuda->neighbor_decide_by_integrator=1;
Cuda_FixNHCuda_Init(&cuda->shared_data,dtv,dtf);
}
/* ----------------------------------------------------------------------
compute T,P before integrator starts
------------------------------------------------------------------------- */
void FixNHCuda::setup(int vflag)
{
// initialize some quantities that were not available earlier
//if (mtk_flag) mtk_factor = 1.0 + 1.0/atom->natoms;
//else mtk_factor = 1.0;
tdof = temperature->dof;
// t_target is used by compute_scalar(), even for NPH
if (tstat_flag) t_target = t_start;
else if (pstat_flag) {
// t0 = initial value for piston mass and energy conservation
// cannot be done in init() b/c temperature cannot be called there
// is b/c Modify::init() inits computes after fixes due to dof dependence
// guesstimate a unit-dependent t0 if actual T = 0.0
// if it was read in from a restart file, leave it be
if (t0 == 0.0) {
t0 = temperature->compute_scalar();
if (t0 == 0.0) {
if (strcmp(update->unit_style,"lj") == 0) t0 = 1.0;
else t0 = 300.0;
}
}
t_target = t0;
}
if (pstat_flag) compute_press_target();
t_current = temperature->compute_scalar();
if (pstat_flag) {
if (pstyle == ISO) double tmp = pressure->compute_scalar();
else pressure->compute_vector();
couple();
pressure->addstep(update->ntimestep+1);
}
// initial forces on thermostat variables
if (tstat_flag) {
eta_mass[0] = tdof * boltz * t_target / (t_freq*t_freq);
for (int ich = 1; ich < mtchain; ich++)
eta_mass[ich] = boltz * t_target / (t_freq*t_freq);
for (int ich = 1; ich < mtchain; ich++) {
eta_dotdot[ich] = (eta_mass[ich-1]*eta_dot[ich-1]*eta_dot[ich-1] -
boltz*t_target) / eta_mass[ich];
}
}
if (pstat_flag) {
double kt = boltz * t_target;
double nkt = atom->natoms * kt;
for (int i = 0; i < 3; i++)
if (p_flag[i])
omega_mass[i] = nkt/(p_freq[i]*p_freq[i]);
if (pstyle == TRICLINIC) {
for (int i = 3; i < 6; i++)
if (p_flag[i]) omega_mass[i] = nkt/(p_freq[i]*p_freq[i]);
}
// initial forces on barostat thermostat variables
if (mpchain) {
etap_mass[0] = boltz * t_target / (p_freq_max*p_freq_max);
for (int ich = 1; ich < mpchain; ich++)
etap_mass[ich] = boltz * t_target / (p_freq_max*p_freq_max);
for (int ich = 1; ich < mpchain; ich++)
etap_dotdot[ich] =
(etap_mass[ich-1]*etap_dot[ich-1]*etap_dot[ich-1] -
boltz*t_target) / etap_mass[ich];
}
// compute appropriately coupled elements of mvv_current
//if (mtk_flag) couple_ke();
}
}
/* ----------------------------------------------------------------------
1st half of Verlet update
------------------------------------------------------------------------- */
void FixNHCuda::initial_integrate(int vflag)
{
if(!temperature->cudable) cuda->downloadAll();
if(triggerneighsq!=cuda->shared_data.atom.triggerneighsq)
{
triggerneighsq= cuda->shared_data.atom.triggerneighsq;
Cuda_FixNHCuda_Init(&cuda->shared_data,dtv,dtf);
}
// update eta_press_dot
if (pstat_flag && mpchain) nhc_press_integrate();
// update eta_dot
if (tstat_flag) {
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
t_target = t_start + delta * (t_stop-t_start);
eta_mass[0] = tdof * boltz * t_target / (t_freq*t_freq);
for (int ich = 1; ich < mtchain; ich++)
eta_mass[ich] = boltz * t_target / (t_freq*t_freq);
nhc_temp_integrate();
}
// need to recompute pressure to account for change in KE
// t_current is up-to-date, but compute_temperature is not
// compute appropriately coupled elements of mvv_current
if (pstat_flag) {
if (pstyle == ISO) {
temperature->compute_scalar();
double tmp = pressure->compute_scalar();
} else {
temperature->compute_vector();
pressure->compute_vector();
}
couple();
pressure->addstep(update->ntimestep+1);
//if (mtk_flag) couple_ke();
}
if(which==NOBIAS)
{
if (pstat_flag) {
compute_press_target();
nh_omega_dot();
factor[0] = exp(-dt4*(omega_dot[0]+mtk_term2));
factor[1] = exp(-dt4*(omega_dot[1]+mtk_term2));
factor[2] = exp(-dt4*(omega_dot[2]+mtk_term2));
Cuda_FixNHCuda_nh_v_press_and_nve_v_NoBias(&cuda->shared_data, groupbit, factor,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal,(pstyle == TRICLINIC)?1:0);
}
else
Cuda_FixNHCuda_nve_v(&cuda->shared_data,groupbit,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal);
}
else if(which==BIAS)
{
if(pstat_flag)
{
compute_press_target();
nh_omega_dot();
factor[0] = exp(-dt4*(omega_dot[0]+mtk_term2));
factor[1] = exp(-dt4*(omega_dot[1]+mtk_term2));
factor[2] = exp(-dt4*(omega_dot[2]+mtk_term2));
if(!temperature->cudable)
{
nh_v_press();
cuda->cu_v->upload();
}
else
{
int groupbit_org=temperature->groupbit;
temperature->groupbit=groupbit;
temperature->remove_bias_all();
Cuda_FixNHCuda_nh_v_press(&cuda->shared_data, groupbit, factor,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal,(pstyle == TRICLINIC)?1:0);
temperature->restore_bias_all();
temperature->groupbit=groupbit_org;
}
}
Cuda_FixNHCuda_nve_v(&cuda->shared_data,groupbit,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal);
}
// remap simulation box by 1/2 step
if (pstat_flag) remap();
Cuda_FixNHCuda_nve_x(&cuda->shared_data,groupbit,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal);
// remap simulation box by 1/2 step
// redo KSpace coeffs since volume has changed
if (pstat_flag) {
remap();
if (kspace_flag) force->kspace->setup();
}
}
/* ----------------------------------------------------------------------
2nd half of Verlet update
------------------------------------------------------------------------- */
void FixNHCuda::final_integrate()
{
if(!temperature->cudable) cuda->downloadAll();
if(which==NOBIAS)
{
if(pstat_flag)
{
factor[0] = exp(-dt4*(omega_dot[0]+mtk_term2));
factor[1] = exp(-dt4*(omega_dot[1]+mtk_term2));
factor[2] = exp(-dt4*(omega_dot[2]+mtk_term2));
Cuda_FixNHCuda_nve_v_and_nh_v_press_NoBias(&cuda->shared_data, groupbit, factor,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal,(pstyle == TRICLINIC)?1:0);
}
else
Cuda_FixNHCuda_nve_v(&cuda->shared_data,groupbit,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal);
}
else if(which==BIAS)
{
Cuda_FixNHCuda_nve_v(&cuda->shared_data,groupbit,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal);
if(pstat_flag)
{
factor[0] = exp(-dt4*(omega_dot[0]+mtk_term2));
factor[1] = exp(-dt4*(omega_dot[1]+mtk_term2));
factor[2] = exp(-dt4*(omega_dot[2]+mtk_term2));
if(!temperature->cudable)
{
cuda->cu_v->download();
nh_v_press();
cuda->cu_v->upload();
}
else
{
int groupbit_org=temperature->groupbit;
temperature->groupbit=groupbit;
temperature->remove_bias_all();
Cuda_FixNHCuda_nh_v_press(&cuda->shared_data, groupbit, factor,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal,(pstyle == TRICLINIC)?1:0);
temperature->restore_bias_all();
temperature->groupbit=groupbit_org;
}
}
}
// compute new T,P
// compute appropriately coupled elements of mvv_current
if(!temperature->cudable) cuda->cu_v->download();
t_current = temperature->compute_scalar();
if (pstat_flag) {
if (pstyle == ISO) double tmp = pressure->compute_scalar();
else pressure->compute_vector();
couple();
pressure->addstep(update->ntimestep+1);
}
if (pstat_flag) nh_omega_dot();
// update eta_dot
// update eta_press_dot
if (tstat_flag) nhc_temp_integrate();
if (pstat_flag && mpchain) nhc_press_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNHCuda::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
int i;
// set timesteps by level
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
dthalf = 0.5 * step_respa[ilevel];
// outermost level - update eta_dot and omega_dot, apply to v, remap box
// all other levels - NVE update of v
// x,v updates only performed for atoms in group
if (ilevel == nlevels_respa-1) {
// update eta_press_dot
if (pstat_flag && mpchain) nhc_press_integrate();
// update eta_dot
if (tstat_flag) {
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
t_target = t_start + delta * (t_stop-t_start);
eta_mass[0] = tdof * boltz * t_target / (t_freq*t_freq);
for (int ich = 1; ich < mtchain; ich++)
eta_mass[ich] = boltz * t_target / (t_freq*t_freq);
nhc_temp_integrate();
}
// recompute pressure to account for change in KE
// t_current is up-to-date, but compute_temperature is not
// compute appropriately coupled elements of mvv_current
if (pstat_flag) {
if (pstyle == ISO) {
temperature->compute_scalar();
double tmp = pressure->compute_scalar();
} else {
temperature->compute_vector();
pressure->compute_vector();
}
couple();
pressure->addstep(update->ntimestep+1);
if (mtk_flag) couple_ke();
}
if (pstat_flag) {
compute_press_target();
nh_omega_dot();
nh_v_press();
}
nve_v();
} else nve_v();
// innermost level - also update x only for atoms in group
// if barostat, perform 1/2 step remap before and after
if (ilevel == 0) {
if (pstat_flag) remap();
nve_x();
if (pstat_flag) remap();
}
// if barostat, redo KSpace coeffs at outermost level,
// since volume has changed
if (ilevel == nlevels_respa-1 && kspace_flag && pstat_flag)
force->kspace->setup();
}
/* ---------------------------------------------------------------------- */
void FixNHCuda::final_integrate_respa(int ilevel, int iloop)
{
// set timesteps by level
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
dthalf = 0.5 * step_respa[ilevel];
// outermost level - update eta_dot and omega_dot, apply via final_integrate
// all other levels - NVE update of v
if (ilevel == nlevels_respa-1) final_integrate();
else nve_v();
}
/* ---------------------------------------------------------------------- */
void FixNHCuda::couple()
{
double *tensor = pressure->vector;
if (pstyle == ISO)
p_current[0] = p_current[1] = p_current[2] = pressure->scalar;
else if (pcouple == XYZ) {
double ave = 1.0/3.0 * (tensor[0] + tensor[1] + tensor[2]);
p_current[0] = p_current[1] = p_current[2] = ave;
} else if (pcouple == XY) {
double ave = 0.5 * (tensor[0] + tensor[1]);
p_current[0] = p_current[1] = ave;
p_current[2] = tensor[2];
} else if (pcouple == YZ) {
double ave = 0.5 * (tensor[1] + tensor[2]);
p_current[1] = p_current[2] = ave;
p_current[0] = tensor[0];
} else if (pcouple == XZ) {
double ave = 0.5 * (tensor[0] + tensor[2]);
p_current[0] = p_current[2] = ave;
p_current[1] = tensor[1];
} else {
p_current[0] = tensor[0];
p_current[1] = tensor[1];
p_current[2] = tensor[2];
}
// switch order from xy-xz-yz to Voigt
if (pstyle == TRICLINIC) {
p_current[3] = tensor[5];
p_current[4] = tensor[4];
p_current[5] = tensor[3];
}
}
/* ---------------------------------------------------------------------- */
void FixNHCuda::couple_ke()
{
double *tensor = temperature->vector;
if (pstyle == ISO)
mvv_current[0] = mvv_current[1] = mvv_current[2] =
tdof * boltz * t_current/dimension;
else if (pcouple == XYZ) {
double ave = 1.0/3.0 * (tensor[0] + tensor[1] + tensor[2]);
mvv_current[0] = mvv_current[1] = mvv_current[2] = ave;
} else if (pcouple == XY) {
double ave = 0.5 * (tensor[0] + tensor[1]);
mvv_current[0] = mvv_current[1] = ave;
mvv_current[2] = tensor[2];
} else if (pcouple == YZ) {
double ave = 0.5 * (tensor[1] + tensor[2]);
mvv_current[1] = mvv_current[2] = ave;
mvv_current[0] = tensor[0];
} else if (pcouple == XZ) {
double ave = 0.5 * (tensor[0] + tensor[2]);
mvv_current[0] = mvv_current[2] = ave;
mvv_current[1] = tensor[1];
} else {
mvv_current[0] = tensor[0];
mvv_current[1] = tensor[1];
mvv_current[2] = tensor[2];
}
}
/* ----------------------------------------------------------------------
change box size
remap all atoms or fix group atoms depending on allremap flag
if rigid bodies exist, scale rigid body centers-of-mass
------------------------------------------------------------------------- */
void FixNHCuda::remap()
{
int i;
double oldlo,oldhi,ctr;
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
// omega is not used, except for book-keeping
for (int i = 0; i < 6; i++) omega[i] += dto*omega_dot[i];
// convert pertinent atoms and rigid bodies to lamda coords
if (allremap) domain->x2lamda(nlocal);
else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->x2lamda(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(0);
// reset global and local box to new size/shape
// This operation corresponds to applying the
// translate and scale operations
// corresponding to the solution of the following ODE:
//
// h_dot = omega_dot * h
//
// where h_dot, omega_dot and h are all upper-triangular
// 3x3 tensors. In Voigt notation, the elements of the
// RHS product tensor are:
// h_dot = [0*0, 1*1, 2*2, 1*3+3*2, 0*4+5*3+4*2, 0*5+5*1]
//
// Ordering of operations preserves time symmetry.
double dto2 = dto/2.0;
double dto4 = dto/4.0;
double dto8 = dto/8.0;
if (pstyle == TRICLINIC) {
h[4] *= exp(dto8*omega_dot[0]);
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= exp(dto8*omega_dot[0]);
h[3] *= exp(dto4*omega_dot[1]);
h[3] += dto2*(omega_dot[3]*h[2]);
h[3] *= exp(dto4*omega_dot[1]);
h[5] *= exp(dto4*omega_dot[0]);
h[5] += dto2*(omega_dot[5]*h[1]);
h[5] *= exp(dto4*omega_dot[0]);
h[4] *= exp(dto8*omega_dot[0]);
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= exp(dto8*omega_dot[0]);
}
for (i = 0; i < 3; i++) {
if (p_flag[i]) {
oldlo = domain->boxlo[i];
oldhi = domain->boxhi[i];
ctr = 0.5 * (oldlo + oldhi);
domain->boxlo[i] = (oldlo-ctr)*exp(dto*omega_dot[i]) + ctr;
domain->boxhi[i] = (oldhi-ctr)*exp(dto*omega_dot[i]) + ctr;
}
}
if (pstyle == TRICLINIC) {
h[4] *= exp(dto8*omega_dot[0]);
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= exp(dto8*omega_dot[0]);
h[3] *= exp(dto4*omega_dot[1]);
h[3] += dto2*(omega_dot[3]*h[2]);
h[3] *= exp(dto4*omega_dot[1]);
h[5] *= exp(dto4*omega_dot[0]);
h[5] += dto2*(omega_dot[5]*h[1]);
h[5] *= exp(dto4*omega_dot[0]);
h[4] *= exp(dto8*omega_dot[0]);
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= exp(dto8*omega_dot[0]);
domain->yz = h[3];
domain->xz = h[4];
domain->xy = h[5];
if (domain->yz < -0.5*domain->yprd || domain->yz > 0.5*domain->yprd ||
domain->xz < -0.5*domain->xprd || domain->xz > 0.5*domain->xprd ||
domain->xy < -0.5*domain->xprd || domain->xy > 0.5*domain->xprd)
- error->all("Fix npt/nph has tilted box too far - "
+ error->all(FLERR,"Fix npt/nph has tilted box too far - "
"box flips are not yet implemented");
}
domain->set_global_box();
domain->set_local_box();
// convert pertinent atoms and rigid bodies back to box coords
if (allremap) domain->lamda2x(nlocal);
else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->lamda2x(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(1);
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixNHCuda::write_restart(FILE *fp)
{
int nsize = 2;
if (tstat_flag) nsize += 1 + 2*mtchain;
if (pstat_flag) {
nsize += 16 + 2*mpchain;
if (deviatoric_flag) nsize += 6;
}
double* list = (double *) memory->smalloc(nsize*sizeof(double),"nh:list");
int n = 0;
list[n++] = tstat_flag;
if (tstat_flag) {
list[n++] = mtchain;
for (int ich = 0; ich < mtchain; ich++)
list[n++] = eta[ich];
for (int ich = 0; ich < mtchain; ich++)
list[n++] = eta_dot[ich];
}
list[n++] = pstat_flag;
if (pstat_flag) {
list[n++] = omega[0];
list[n++] = omega[1];
list[n++] = omega[2];
list[n++] = omega[3];
list[n++] = omega[4];
list[n++] = omega[5];
list[n++] = omega_dot[0];
list[n++] = omega_dot[1];
list[n++] = omega_dot[2];
list[n++] = omega_dot[3];
list[n++] = omega_dot[4];
list[n++] = omega_dot[5];
list[n++] = vol0;
list[n++] = t0;
list[n++] = mpchain;
if (mpchain) {
for (int ich = 0; ich < mpchain; ich++)
list[n++] = etap[ich];
for (int ich = 0; ich < mpchain; ich++)
list[n++] = etap_dot[ich];
}
list[n++] = deviatoric_flag;
if (deviatoric_flag) {
list[n++] = h0_inv[0];
list[n++] = h0_inv[1];
list[n++] = h0_inv[2];
list[n++] = h0_inv[3];
list[n++] = h0_inv[4];
list[n++] = h0_inv[5];
}
}
if (comm->me == 0) {
int size = nsize * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),nsize,fp);
}
memory->sfree(list);
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixNHCuda::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
int flag = static_cast<int> (list[n++]);
if (flag) {
int m = static_cast<int> (list[n++]);
if (tstat_flag && m == mtchain) {
for (int ich = 0; ich < mtchain; ich++)
eta[ich] = list[n++];
for (int ich = 0; ich < mtchain; ich++)
eta_dot[ich] = list[n++];
} else n += 2*m;
}
flag = static_cast<int> (list[n++]);
if (flag) {
omega[0] = list[n++];
omega[1] = list[n++];
omega[2] = list[n++];
omega[3] = list[n++];
omega[4] = list[n++];
omega[5] = list[n++];
omega_dot[0] = list[n++];
omega_dot[1] = list[n++];
omega_dot[2] = list[n++];
omega_dot[3] = list[n++];
omega_dot[4] = list[n++];
omega_dot[5] = list[n++];
vol0 = list[n++];
t0 = list[n++];
int m = static_cast<int> (list[n++]);
if (pstat_flag && m == mpchain) {
for (int ich = 0; ich < mpchain; ich++)
etap[ich] = list[n++];
for (int ich = 0; ich < mpchain; ich++)
etap_dot[ich] = list[n++];
} else n+=2*m;
flag = static_cast<int> (list[n++]);
if (flag) {
h0_inv[0] = list[n++];
h0_inv[1] = list[n++];
h0_inv[2] = list[n++];
h0_inv[3] = list[n++];
h0_inv[4] = list[n++];
h0_inv[5] = list[n++];
}
}
}
/* ---------------------------------------------------------------------- */
int FixNHCuda::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != 0 && comm->me == 0)
- error->warning("Temperature for fix modify is not for group all");
+ error->warning(FLERR,"Temperature for fix modify is not for group all");
// reset id_temp of pressure to new temperature ID
if (pstat_flag) {
icompute = modify->find_compute(id_press);
if (icompute < 0)
- error->all("Pressure ID for fix modify does not exist");
+ error->all(FLERR,"Pressure ID for fix modify does not exist");
modify->compute[icompute]->reset_extra_compute_fix(id_temp);
}
return 2;
} else if (strcmp(arg[0],"press") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
- if (!pstat_flag) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
+ if (!pstat_flag) error->all(FLERR,"Illegal fix_modify command");
if (pflag) {
modify->delete_compute(id_press);
pflag = 0;
}
delete [] id_press;
int n = strlen(arg[1]) + 1;
id_press = new char[n];
strcpy(id_press,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify pressure ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify pressure ID");
pressure = modify->compute[icompute];
if (pressure->pressflag == 0)
- error->all("Fix_modify pressure ID does not compute pressure");
+ error->all(FLERR,"Fix_modify pressure ID does not compute pressure");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
double FixNHCuda::compute_scalar()
{
int i;
double volume;
double energy;
double kt = boltz * t_target;
double lkt = tdof * kt;
double lkt_press = kt;
int ich;
if (dimension == 3) volume = domain->xprd * domain->yprd * domain->zprd;
else volume = domain->xprd * domain->yprd;
energy = 0.0;
// thermostat chain energy is equivalent to Eq. (2) in
// Martyna, Tuckerman, Tobias, Klein, Mol Phys, 87, 1117
// Sum(0.5*p_eta_k^2/Q_k,k=1,M) + L*k*T*eta_1 + Sum(k*T*eta_k,k=2,M),
// where L = tdof
// M = mtchain
// p_eta_k = Q_k*eta_dot[k-1]
// Q_1 = L*k*T/t_freq^2
// Q_k = k*T/t_freq^2, k > 1
if (tstat_flag) {
energy += lkt * eta[0] + 0.5*eta_mass[0]*eta_dot[0]*eta_dot[0];
for (ich = 1; ich < mtchain; ich++)
energy += kt * eta[ich] + 0.5*eta_mass[ich]*eta_dot[ich]*eta_dot[ich];
}
// barostat energy is equivalent to Eq. (8) in
// Martyna, Tuckerman, Tobias, Klein, Mol Phys, 87, 1117
// Sum(0.5*p_omega^2/W + P*V),
// where N = natoms
// p_omega = W*omega_dot
// W = N*k*T/p_freq^2
// sum is over barostatted dimensions
if (pstat_flag) {
for (i = 0; i < 3; i++)
if (p_flag[i])
energy += 0.5*omega_dot[i]*omega_dot[i]*omega_mass[i] +
p_hydro*(volume-vol0) / (pdim*nktv2p);
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i])
energy += 0.5*omega_dot[i]*omega_dot[i]*omega_mass[i];
}
// extra contributions from thermostat chain for barostat
if (mpchain) {
energy += lkt_press * etap[0] + 0.5*etap_mass[0]*etap_dot[0]*etap_dot[0];
for (ich = 1; ich < mpchain; ich++)
energy += kt * etap[ich] +
0.5*etap_mass[ich]*etap_dot[ich]*etap_dot[ich];
}
// extra contribution from strain energy
if (deviatoric_flag) energy += compute_strain_energy();
}
return energy;
}
/* ----------------------------------------------------------------------
return a single element of the following vectors, in this order:
eta[tchain], eta_dot[tchain], omega[ndof], omega_dot[ndof]
etap[pchain], etap_dot[pchain], PE_eta[tchain], KE_eta_dot[tchain]
PE_omega[ndof], KE_omega_dot[ndof], PE_etap[pchain], KE_etap_dot[pchain]
PE_strain[1]
if no thermostat exists, related quantities are omitted from the list
if no barostat exists, related quantities are omitted from the list
ndof = 1,3,6 degrees of freedom for pstyle = ISO,ANISO,TRI
------------------------------------------------------------------------- */
double FixNHCuda::compute_vector(int n)
{
int ilen;
if (tstat_flag) {
ilen = mtchain;
if (n < ilen) return eta[n];
n -= ilen;
ilen = mtchain;
if (n < ilen) return eta_dot[n];
n -= ilen;
}
if (pstat_flag) {
if (pstyle == ISO) {
ilen = 1;
if (n < ilen) return omega[n];
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen) return omega[n];
n -= ilen;
} else {
ilen = 6;
if (n < ilen) return omega[n];
n -= ilen;
}
if (pstyle == ISO) {
ilen = 1;
if (n < ilen) return omega_dot[n];
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen) return omega_dot[n];
n -= ilen;
} else {
ilen = 6;
if (n < ilen) return omega_dot[n];
n -= ilen;
}
if (mpchain) {
ilen = mpchain;
if (n < ilen) return etap[n];
n -= ilen;
ilen = mpchain;
if (n < ilen) return etap_dot[n];
n -= ilen;
}
}
int i;
double volume;
double kt = boltz * t_target;
double lkt = tdof * kt;
double lkt_press = kt;
int ich;
if (dimension == 3) volume = domain->xprd * domain->yprd * domain->zprd;
else volume = domain->xprd * domain->yprd;
if (tstat_flag) {
ilen = mtchain;
if (n < ilen) {
ich = n;
if (ich == 0)
return lkt * eta[0];
else
return kt * eta[ich];
}
n -= ilen;
ilen = mtchain;
if (n < ilen) {
ich = n;
if (ich == 0)
return 0.5*eta_mass[0]*eta_dot[0]*eta_dot[0];
else
return 0.5*eta_mass[ich]*eta_dot[ich]*eta_dot[ich];
}
n -= ilen;
}
if (pstat_flag) {
if (pstyle == ISO) {
ilen = 1;
if (n < ilen)
return p_hydro*(volume-vol0) / nktv2p;
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen)
if (p_flag[n])
return p_hydro*(volume-vol0) / (pdim*nktv2p);
else
return 0.0;
n -= ilen;
} else {
ilen = 6;
if (n < ilen)
if (n > 2) return 0.0;
else if (p_flag[n])
return p_hydro*(volume-vol0) / (pdim*nktv2p);
else
return 0.0;
n -= ilen;
}
if (pstyle == ISO) {
ilen = 1;
if (n < ilen)
return pdim*0.5*omega_dot[n]*omega_dot[n]*omega_mass[n];
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen)
if (p_flag[n])
return 0.5*omega_dot[n]*omega_dot[n]*omega_mass[n];
else return 0.0;
n -= ilen;
} else {
ilen = 6;
if (n < ilen)
if (p_flag[n])
return 0.5*omega_dot[n]*omega_dot[n]*omega_mass[n];
else return 0.0;
n -= ilen;
}
if (mpchain) {
ilen = mpchain;
if (n < ilen) {
ich = n;
if (ich == 0) return lkt_press * etap[0];
else return kt * etap[ich];
}
n -= ilen;
ilen = mpchain;
if (n < ilen) {
ich = n;
if (ich == 0)
return 0.5*etap_mass[0]*etap_dot[0]*etap_dot[0];
else
return 0.5*etap_mass[ich]*etap_dot[ich]*etap_dot[ich];
}
n -= ilen;
}
if (deviatoric_flag) {
ilen = 1;
if (n < ilen)
return compute_strain_energy();
n -= ilen;
}
}
return 0.0;
}
/* ---------------------------------------------------------------------- */
void FixNHCuda::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dthalf = 0.5 * update->dt;
dt4 = 0.25 * update->dt;
dt8 = 0.125 * update->dt;
dto = dthalf;
// If using respa, then remap is performed in innermost level
if (strcmp(update->integrate_style,"respa") == 0)
dto = 0.5*step_respa[0];
p_freq_max = 0.0;
if (pstat_flag) {
p_freq_max = MAX(p_freq[0],p_freq[1]);
p_freq_max = MAX(p_freq_max,p_freq[2]);
if (pstyle == TRICLINIC) {
p_freq_max = MAX(p_freq_max,p_freq[3]);
p_freq_max = MAX(p_freq_max,p_freq[4]);
p_freq_max = MAX(p_freq_max,p_freq[5]);
}
pdrag_factor = 1.0 - (update->dt * p_freq_max * drag / nc_pchain);
}
if (tstat_flag)
tdrag_factor = 1.0 - (update->dt * t_freq * drag / nc_tchain);
}
/* ----------------------------------------------------------------------
perform half-step update of chain thermostat variables
------------------------------------------------------------------------- */
void FixNHCuda::nhc_temp_integrate()
{
int ich;
double expfac;
double lkt = tdof * boltz * t_target;
double kecurrent = tdof * boltz * t_current;
eta_dotdot[0] = (kecurrent - lkt)/eta_mass[0];
double ncfac = 1.0/nc_tchain;
for (int iloop = 0; iloop < nc_tchain; iloop++) {
for (ich = mtchain-1; ich > 0; ich--) {
expfac = exp(-ncfac*dt8*eta_dot[ich+1]);
eta_dot[ich] *= expfac;
eta_dot[ich] += eta_dotdot[ich] * ncfac*dt4;
eta_dot[ich] *= tdrag_factor;
eta_dot[ich] *= expfac;
}
expfac = exp(-ncfac*dt8*eta_dot[1]);
eta_dot[0] *= expfac;
eta_dot[0] += eta_dotdot[0] * ncfac*dt4;
eta_dot[0] *= tdrag_factor;
eta_dot[0] *= expfac;
factor_eta = exp(-ncfac*dthalf*eta_dot[0]);
if(which==NOBIAS)
Cuda_FixNHCuda_nh_v_temp(&cuda->shared_data,groupbit,factor_eta,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal);
else if(which==BIAS)
{
if(!temperature->cudable)
{
cuda->downloadAll();
nh_v_temp();
cuda->cu_v->upload();
}
else
{
int groupbit_org=temperature->groupbit;
temperature->groupbit=groupbit;
temperature->remove_bias_all();
Cuda_FixNHCuda_nh_v_temp(&cuda->shared_data,groupbit,factor_eta,(igroup == atom->firstgroup)?atom->nfirst:atom->nlocal);
temperature->restore_bias_all();
temperature->groupbit=groupbit_org;
}
}
// rescale temperature due to velocity scaling
// should not be necessary to explicitly recompute the temperature
t_current *= factor_eta*factor_eta;
kecurrent = tdof * boltz * t_current;
eta_dotdot[0] = (kecurrent - lkt)/eta_mass[0];
for (ich = 0; ich < mtchain; ich++)
eta[ich] += ncfac*dthalf*eta_dot[ich];
eta_dot[0] *= expfac;
eta_dot[0] += eta_dotdot[0] * ncfac*dt4;
eta_dot[0] *= expfac;
for (ich = 1; ich < mtchain; ich++) {
expfac = exp(-ncfac*dt8*eta_dot[ich+1]);
eta_dot[ich] *= expfac;
eta_dotdot[ich] = (eta_mass[ich-1]*eta_dot[ich-1]*eta_dot[ich-1]
- boltz * t_target)/eta_mass[ich];
eta_dot[ich] += eta_dotdot[ich] * ncfac*dt4;
eta_dot[ich] *= expfac;
}
}
}
/* ----------------------------------------------------------------------
perform half-step update of chain thermostat variables for barostat
scale barostat velocities
------------------------------------------------------------------------- */
void FixNHCuda::nhc_press_integrate()
{
int ich,i;
double expfac,factor_etap,wmass,kecurrent;
double kt = boltz * t_target;
double lkt_press = kt;
kecurrent = 0.0;
for (i = 0; i < 3; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
}
etap_dotdot[0] = (kecurrent - lkt_press)/etap_mass[0];
double ncfac = 1.0/nc_pchain;
for (int iloop = 0; iloop < nc_pchain; iloop++) {
for (ich = mpchain-1; ich > 0; ich--) {
expfac = exp(-ncfac*dt8*etap_dot[ich+1]);
etap_dot[ich] *= expfac;
etap_dot[ich] += etap_dotdot[ich] * ncfac*dt4;
etap_dot[ich] *= pdrag_factor;
etap_dot[ich] *= expfac;
}
expfac = exp(-ncfac*dt8*etap_dot[1]);
etap_dot[0] *= expfac;
etap_dot[0] += etap_dotdot[0] * ncfac*dt4;
etap_dot[0] *= pdrag_factor;
etap_dot[0] *= expfac;
for (ich = 0; ich < mpchain; ich++)
etap[ich] += ncfac*dthalf*etap_dot[ich];
factor_etap = exp(-ncfac*dthalf*etap_dot[0]);
for (i = 0; i < 3; i++)
if (p_flag[i]) omega_dot[i] *= factor_etap;
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i]) omega_dot[i] *= factor_etap;
}
kecurrent = 0.0;
for (i = 0; i < 3; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
}
etap_dotdot[0] = (kecurrent - lkt_press)/etap_mass[0];
etap_dot[0] *= expfac;
etap_dot[0] += etap_dotdot[0] * ncfac*dt4;
etap_dot[0] *= expfac;
for (ich = 1; ich < mpchain; ich++) {
expfac = exp(-ncfac*dt8*etap_dot[ich+1]);
etap_dot[ich] *= expfac;
etap_dotdot[ich] =
(etap_mass[ich-1]*etap_dot[ich-1]*etap_dot[ich-1] - boltz*t_target) /
etap_mass[ich];
etap_dot[ich] += etap_dotdot[ich] * ncfac*dt4;
etap_dot[ich] *= expfac;
}
}
}
/* ----------------------------------------------------------------------
perform half-step barostat scaling of velocities
-----------------------------------------------------------------------*/
void FixNHCuda::nh_v_press()
{
double factor[3];
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
factor[0] = exp(-dt4*(omega_dot[0]+mtk_term2));
factor[1] = exp(-dt4*(omega_dot[1]+mtk_term2));
factor[2] = exp(-dt4*(omega_dot[2]+mtk_term2));
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
if (pstyle == TRICLINIC) {
v[i][0] += -dthalf*(v[i][1]*omega_dot[5] + v[i][2]*omega_dot[4]);
v[i][1] += -dthalf*v[i][2]*omega_dot[3];
}
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
}
}
} else if (which == BIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
if (pstyle == TRICLINIC) {
v[i][0] += -dthalf*(v[i][1]*omega_dot[5] + v[i][2]*omega_dot[4]);
v[i][1] += -dthalf*v[i][2]*omega_dot[3];
}
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
temperature->restore_bias(i,v[i]);
}
}
}
}
/* ----------------------------------------------------------------------
perform half-step update of velocities
-----------------------------------------------------------------------*/
void FixNHCuda::nve_v()
{
double dtfm;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm*f[i][0];
v[i][1] += dtfm*f[i][1];
v[i][2] += dtfm*f[i][2];
}
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm*f[i][0];
v[i][1] += dtfm*f[i][1];
v[i][2] += dtfm*f[i][2];
}
}
}
}
/* ----------------------------------------------------------------------
perform full-step update of positions
-----------------------------------------------------------------------*/
void FixNHCuda::nve_x()
{
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// x update by full step only for atoms in group
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
}
/* ----------------------------------------------------------------------
perform half-step thermostat scaling of velocities
-----------------------------------------------------------------------*/
void FixNHCuda::nh_v_temp()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] *= factor_eta;
v[i][1] *= factor_eta;
v[i][2] *= factor_eta;
}
}
} else if (which == BIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= factor_eta;
v[i][1] *= factor_eta;
v[i][2] *= factor_eta;
temperature->restore_bias(i,v[i]);
}
}
}
}
/* ----------------------------------------------------------------------
compute sigma tensor
needed whenever p_target or h0_inv changes
-----------------------------------------------------------------------*/
void FixNHCuda::compute_sigma()
{
// if nreset_h0 > 0, reset vol0 and h0_inv
// every nreset_h0 timesteps
if (nreset_h0 > 0) {
int delta = update->ntimestep - update->beginstep;
if (delta % nreset_h0 == 0) {
if (dimension == 3) vol0 = domain->xprd * domain->yprd * domain->zprd;
else vol0 = domain->xprd * domain->yprd;
h0_inv[0] = domain->h_inv[0];
h0_inv[1] = domain->h_inv[1];
h0_inv[2] = domain->h_inv[2];
h0_inv[3] = domain->h_inv[3];
h0_inv[4] = domain->h_inv[4];
h0_inv[5] = domain->h_inv[5];
}
}
// generate upper-triangular half of
// sigma = vol0*h0inv*(p_target-p_hydro)*h0inv^t
// units of sigma are are PV/L^2 e.g. atm.A
//
// [ 0 5 4 ] [ 0 5 4 ] [ 0 5 4 ] [ 0 - - ]
// [ 5 1 3 ] = [ - 1 3 ] [ 5 1 3 ] [ 5 1 - ]
// [ 4 3 2 ] [ - - 2 ] [ 4 3 2 ] [ 4 3 2 ]
sigma[0] =
vol0*(h0_inv[0]*((p_target[0]-p_hydro)*h0_inv[0] +
p_target[5]*h0_inv[5]+p_target[4]*h0_inv[4]) +
h0_inv[5]*(p_target[5]*h0_inv[0] +
(p_target[1]-p_hydro)*h0_inv[5]+p_target[3]*h0_inv[4]) +
h0_inv[4]*(p_target[4]*h0_inv[0]+p_target[3]*h0_inv[5] +
(p_target[2]-p_hydro)*h0_inv[4]));
sigma[1] =
vol0*(h0_inv[1]*((p_target[1]-p_hydro)*h0_inv[1] +
p_target[3]*h0_inv[3]) +
h0_inv[3]*(p_target[3]*h0_inv[1] +
(p_target[2]-p_hydro)*h0_inv[3]));
sigma[2] =
vol0*(h0_inv[2]*((p_target[2]-p_hydro)*h0_inv[2]));
sigma[3] =
vol0*(h0_inv[1]*(p_target[3]*h0_inv[2]) +
h0_inv[3]*((p_target[2]-p_hydro)*h0_inv[2]));
sigma[4] =
vol0*(h0_inv[0]*(p_target[4]*h0_inv[2]) +
h0_inv[5]*(p_target[3]*h0_inv[2]) +
h0_inv[4]*((p_target[2]-p_hydro)*h0_inv[2]));
sigma[5] =
vol0*(h0_inv[0]*(p_target[5]*h0_inv[1]+p_target[4]*h0_inv[3]) +
h0_inv[5]*((p_target[1]-p_hydro)*h0_inv[1]+p_target[3]*h0_inv[3]) +
h0_inv[4]*(p_target[3]*h0_inv[1]+(p_target[2]-p_hydro)*h0_inv[3]));
}
/* ----------------------------------------------------------------------
compute strain energy
-----------------------------------------------------------------------*/
double FixNHCuda::compute_strain_energy()
{
// compute strain energy = 0.5*Tr(sigma*h*h^t) in energy units
double* h = domain->h;
double d0,d1,d2;
d0 =
sigma[0]*(h[0]*h[0]+h[5]*h[5]+h[4]*h[4]) +
sigma[5]*( h[1]*h[5]+h[3]*h[4]) +
sigma[4]*( h[2]*h[4]);
d1 =
sigma[5]*( h[5]*h[1]+h[4]*h[3]) +
sigma[1]*( h[1]*h[1]+h[3]*h[3]) +
sigma[3]*( h[2]*h[3]);
d2 =
sigma[4]*( h[4]*h[2]) +
sigma[3]*( h[3]*h[2]) +
sigma[2]*( h[2]*h[2]);
double energy = 0.5*(d0+d1+d2)/nktv2p;
return energy;
}
/* ----------------------------------------------------------------------
compute deviatoric barostat force = h*sigma*h^t
-----------------------------------------------------------------------*/
void FixNHCuda::compute_deviatoric()
{
// generate upper-triangular part of h*sigma*h^t
// units of fdev are are PV, e.g. atm*A^3
// [ 0 5 4 ] [ 0 5 4 ] [ 0 5 4 ] [ 0 - - ]
// [ 5 1 3 ] = [ - 1 3 ] [ 5 1 3 ] [ 5 1 - ]
// [ 4 3 2 ] [ - - 2 ] [ 4 3 2 ] [ 4 3 2 ]
double* h = domain->h;
fdev[0] =
h[0]*(sigma[0]*h[0]+sigma[5]*h[5]+sigma[4]*h[4]) +
h[5]*(sigma[5]*h[0]+sigma[1]*h[5]+sigma[3]*h[4]) +
h[4]*(sigma[4]*h[0]+sigma[3]*h[5]+sigma[2]*h[4]);
fdev[1] =
h[1]*( sigma[1]*h[1]+sigma[3]*h[3]) +
h[3]*( sigma[3]*h[1]+sigma[2]*h[3]);
fdev[2] =
h[2]*( sigma[2]*h[2]);
fdev[3] =
h[1]*( sigma[3]*h[2]) +
h[3]*( sigma[2]*h[2]);
fdev[4] =
h[0]*( sigma[4]*h[2]) +
h[5]*( sigma[3]*h[2]) +
h[4]*( sigma[2]*h[2]);
fdev[5] =
h[0]*( sigma[5]*h[1]+sigma[4]*h[3]) +
h[5]*( sigma[1]*h[1]+sigma[3]*h[3]) +
h[4]*( sigma[3]*h[1]+sigma[2]*h[3]);
}
/* ----------------------------------------------------------------------
compute hydrostatic target pressure
-----------------------------------------------------------------------*/
void FixNHCuda::compute_press_target()
{
double delta = update->ntimestep - update->beginstep;
if (update->endstep > update->beginstep)
delta /= update->endstep - update->beginstep;
else delta = 0.0;
p_hydro = 0.0;
for (int i = 0; i < 3; i++)
if (p_flag[i]) {
p_target[i] = p_start[i] + delta * (p_stop[i]-p_start[i]);
p_hydro += p_target[i];
}
p_hydro /= pdim;
if (pstyle == TRICLINIC)
for (int i = 3; i < 6; i++)
p_target[i] = p_start[i] + delta * (p_stop[i]-p_start[i]);
// if deviatoric, recompute sigma each time p_target changes
if (deviatoric_flag) compute_sigma();
}
/* ----------------------------------------------------------------------
update omega_dot, omega, dilation
-----------------------------------------------------------------------*/
void FixNHCuda::nh_omega_dot()
{
double f_omega,volume;
if (dimension == 3) volume = domain->xprd*domain->yprd*domain->zprd;
else volume = domain->xprd*domain->yprd;
if (deviatoric_flag) compute_deviatoric();
mtk_term1 = 0.0;
if (mtk_flag)
if (pstyle == ISO) {
mtk_term1 = tdof * boltz * t_current;
mtk_term1 /= pdim * atom->natoms;
} else {
double *mvv_current = temperature->vector;
for (int i = 0; i < 3; i++)
if (p_flag[i])
mtk_term1 += mvv_current[i];
mtk_term1 /= pdim * atom->natoms;
}
for (int i = 0; i < 3; i++)
if (p_flag[i]) {
f_omega = (p_current[i]-p_hydro)*volume /
(omega_mass[i] * nktv2p) + mtk_term1 / omega_mass[i];
if (deviatoric_flag) f_omega -= fdev[i]/(omega_mass[i] * nktv2p);
omega_dot[i] += f_omega*dthalf;
omega_dot[i] *= pdrag_factor;
}
mtk_term2 = 0.0;
if (mtk_flag) {
for (int i = 0; i < 3; i++)
if (p_flag[i])
mtk_term2 += omega_dot[i];
mtk_term2 /= pdim * atom->natoms;
}
if (pstyle == TRICLINIC) {
for (int i = 3; i < 6; i++) {
if (p_flag[i]) {
f_omega = p_current[i]*volume/(omega_mass[i] * nktv2p);
if (deviatoric_flag)
f_omega -= fdev[i]/(omega_mass[i] * nktv2p);
omega_dot[i] += f_omega*dthalf;
omega_dot[i] *= pdrag_factor;
}
}
}
}
diff --git a/src/USER-CUDA/fix_npt_cuda.cpp b/src/USER-CUDA/fix_npt_cuda.cpp
index 3ad0d74ef..dbd395cbc 100644
--- a/src/USER-CUDA/fix_npt_cuda.cpp
+++ b/src/USER-CUDA/fix_npt_cuda.cpp
@@ -1,71 +1,71 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstring>
#include "fix_npt_cuda.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPTCuda::FixNPTCuda(LAMMPS *lmp, int narg, char **arg) :
FixNHCuda(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
if (!tstat_flag)
- error->all("Temperature control must be used with fix npt");
+ error->all(FLERR,"Temperature control must be used with fix npt");
if (!pstat_flag)
- error->all("Pressure control must be used with fix npt");
+ error->all(FLERR,"Pressure control must be used with fix npt");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp/cuda";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure/cuda";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/USER-CUDA/fix_nve_cuda.cpp b/src/USER-CUDA/fix_nve_cuda.cpp
index 88ef34dbf..f498169c3 100644
--- a/src/USER-CUDA/fix_nve_cuda.cpp
+++ b/src/USER-CUDA/fix_nve_cuda.cpp
@@ -1,155 +1,155 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstdio>
#include <cstring>
#include "fix_nve_cuda.h"
#include "fix_nve_cuda_cu.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVECuda::FixNVECuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
if (strcmp(style,"nve/sphere") != 0 && narg < 3)
- error->all("Illegal fix nve command");
+ error->all(FLERR,"Illegal fix nve command");
time_integrate = 1;
}
/* ---------------------------------------------------------------------- */
int FixNVECuda::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE_CUDA;
mask |= FINAL_INTEGRATE_CUDA;
// mask |= INITIAL_INTEGRATE_RESPA_CUDA;
// mask |= FINAL_INTEGRATE_RESPA_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVECuda::init()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
triggerneighsq= cuda->shared_data.atom.triggerneighsq;
cuda->neighbor_decide_by_integrator=1;
Cuda_FixNVECuda_Init(&cuda->shared_data,dtv,dtf);
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixNVECuda::initial_integrate(int vflag)
{
if(triggerneighsq!=cuda->shared_data.atom.triggerneighsq)
{
triggerneighsq= cuda->shared_data.atom.triggerneighsq;
Cuda_FixNVECuda_Init(&cuda->shared_data,dtv,dtf);
}
int nlocal = atom->nlocal;
if(igroup == atom->firstgroup) nlocal = atom->nfirst;
Cuda_FixNVECuda_InitialIntegrate(& cuda->shared_data, groupbit,nlocal);
}
/* ---------------------------------------------------------------------- */
void FixNVECuda::final_integrate()
{
int nlocal = atom->nlocal;
if(igroup == atom->firstgroup) nlocal = atom->nfirst;
Cuda_FixNVECuda_FinalIntegrate(& cuda->shared_data, groupbit,nlocal);
}
/* ---------------------------------------------------------------------- */
void FixNVECuda::initial_integrate_respa(int vflag, int ilevel, int flag)
{
//this point should not be reached yet since RESPA is not supported
if (flag) return; // only used by NPT,NPH
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
// innermost level - NVE update of v and x
// all other levels - NVE update of v
if(ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVECuda::final_integrate_respa(int ilevel, int iloop)
{
//this point should not be reached yet since RESPA is not supported
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVECuda::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
Cuda_FixNVECuda_Init(&cuda->shared_data,dtv,dtf);
}
diff --git a/src/USER-CUDA/fix_nvt_cuda.cpp b/src/USER-CUDA/fix_nvt_cuda.cpp
index 49a3c6301..3d66a67e4 100644
--- a/src/USER-CUDA/fix_nvt_cuda.cpp
+++ b/src/USER-CUDA/fix_nvt_cuda.cpp
@@ -1,48 +1,48 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstring>
#include "fix_nvt_cuda.h"
#include "group.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVTCuda::FixNVTCuda(LAMMPS *lmp, int narg, char **arg) :
FixNHCuda(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix nvt");
+ error->all(FLERR,"Temperature control must be used with fix nvt");
if (pstat_flag)
- error->all("Pressure control can not be used with fix nvt");
+ error->all(FLERR,"Pressure control can not be used with fix nvt");
// create a new compute temp style
// id = fix-ID + temp
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/cuda";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
diff --git a/src/USER-CUDA/fix_set_force_cuda.cpp b/src/USER-CUDA/fix_set_force_cuda.cpp
index bd9665c8c..e54f64d22 100644
--- a/src/USER-CUDA/fix_set_force_cuda.cpp
+++ b/src/USER-CUDA/fix_set_force_cuda.cpp
@@ -1,181 +1,181 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cstring>
#include <cstdlib>
#include "fix_set_force_cuda.h"
#include "fix_set_force_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "cuda.h"
#include "memory.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixSetForceCuda::FixSetForceCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg != 6) error->all("Illegal fix setforce/cuda command");
+ if (narg != 6) error->all(FLERR,"Illegal fix setforce/cuda command");
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extvector = 1;
flagx = flagy = flagz = 1;
if (strcmp(arg[3],"NULL") == 0) flagx = 0;
else xvalue = atof(arg[3]);
if (strcmp(arg[4],"NULL") == 0) flagy = 0;
else yvalue = atof(arg[4]);
if (strcmp(arg[5],"NULL") == 0) flagz = 0;
else zvalue = atof(arg[5]);
force_flag = 0;
foriginal[0] = foriginal[1] = foriginal[2] = 0.0;
cu_foriginal=NULL;
}
/* ---------------------------------------------------------------------- */
int FixSetForceCuda::setmask()
{
int mask = 0;
mask |= POST_FORCE_CUDA;
mask |= THERMO_ENERGY_CUDA;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixSetForceCuda::init()
{
if(not cu_foriginal)
cu_foriginal = new cCudaData<double, F_FLOAT, x> (foriginal,3);
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixSetForceCuda::setup(int vflag)
{
MYDBG( printf("# CUDA: FixSetForceCuda::setup\n"); )
if (strstr(update->integrate_style,"verlet"))
{
Cuda_FixSetForceCuda_Init(&cuda->shared_data);
cuda->cu_f->upload();
post_force(vflag);
cuda->cu_f->download();
}
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
cuda->cu_f->download();
post_force_respa(vflag,nlevels_respa-1,0);
cuda->cu_f->upload();
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
MYDBG( printf("# CUDA: FixSetForceCuda::setup done\n"); )
}
/* ---------------------------------------------------------------------- */
void FixSetForceCuda::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixSetForceCuda::post_force(int vflag)
{
MYDBG( printf("# CUDA: FixSetForceCuda::postforce start\n"); )
force_flag = 0;
cu_foriginal->memset_device(0);
Cuda_FixSetForceCuda_PostForce(&cuda->shared_data, groupbit, xvalue, yvalue,zvalue,(F_FLOAT*) cu_foriginal->dev_data(),flagx,flagy,flagz);
cu_foriginal->download();
}
/* ---------------------------------------------------------------------- */
void FixSetForceCuda::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
else {
cuda->cu_f->download();
cuda->cu_mask->download();
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
foriginal[0] = foriginal[1] = foriginal[2] = 0.0;
force_flag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
foriginal[0] += f[i][0];
foriginal[1] += f[i][1];
foriginal[2] += f[i][2];
if (flagx) f[i][0] = 0.0;
if (flagy) f[i][1] = 0.0;
if (flagz) f[i][2] = 0.0;
}
cuda->cu_f->upload();
}
}
/* ---------------------------------------------------------------------- */
void FixSetForceCuda::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixSetForceCuda::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,3,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[n+1];
}
diff --git a/src/USER-CUDA/fix_shake_cuda.cpp b/src/USER-CUDA/fix_shake_cuda.cpp
index 20883889c..219ac679b 100644
--- a/src/USER-CUDA/fix_shake_cuda.cpp
+++ b/src/USER-CUDA/fix_shake_cuda.cpp
@@ -1,2619 +1,2617 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <ctime>
#include "fix_shake_cuda.h"
#include "fix_shake_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "modify.h"
#include "domain.h"
#include "force.h"
#include "bond.h"
#include "angle.h"
#include "comm.h"
#include "group.h"
#include "fix_respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
#define MASSDELTA 0.1
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
/* ---------------------------------------------------------------------- */
FixShakeCuda::FixShakeCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
cuda->accelerator(0,NULL);
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
neighbor_step=true;
PI = 4.0*atan(1.0);
virial_flag = 1;
create_attribute = 1;
// error check
if (atom->molecular == 0)
- error->all("Cannot use fix shake with non-molecular system");
+ error->all(FLERR,"Cannot use fix shake with non-molecular system");
// perform initial allocation of atom-based arrays
// register with Atom class
shake_flag = NULL;
shake_atom = shake_type = NULL;
xshake = NULL;
cu_shake_flag = NULL;
cu_shake_atom = NULL;
cu_shake_type = NULL;
cu_xshake = NULL;
cu_list = NULL;
cu_bond_distance = NULL;
cu_angle_distance = NULL;
cu_virial = new cCudaData<double , ENERGY_FLOAT , xx >(virial,6);
grow_arrays(atom->nmax);
atom->add_callback(0);
// set comm size needed by this fix
comm_forward = 3;
// parse SHAKE args
- if (narg < 8) error->all("Illegal fix shake command");
+ if (narg < 8) error->all(FLERR,"Illegal fix shake command");
tolerance = atof(arg[3]);
max_iter = atoi(arg[4]);
output_every = atoi(arg[5]);
// parse SHAKE args for bond and angle types
// will be used by find_clusters
// store args for "b" "a" "t" as flags in (1:n) list for fast access
// store args for "m" in list of length nmass for looping over
// for "m" verify that atom masses have been set
bond_flag = new int[atom->nbondtypes+1];
for (int i = 1; i <= atom->nbondtypes; i++) bond_flag[i] = 0;
angle_flag = new int[atom->nangletypes+1];
for (int i = 1; i <= atom->nangletypes; i++) angle_flag[i] = 0;
type_flag = new int[atom->ntypes+1];
for (int i = 1; i <= atom->ntypes; i++) type_flag[i] = 0;
mass_list = new double[atom->ntypes];
nmass = 0;
char mode = '\0';
int next = 6;
while (next < narg) {
if (strcmp(arg[next],"b") == 0) mode = 'b';
else if (strcmp(arg[next],"a") == 0) mode = 'a';
else if (strcmp(arg[next],"t") == 0) mode = 't';
else if (strcmp(arg[next],"m") == 0) {
mode = 'm';
atom->check_mass();
} else if (mode == 'b') {
int i = atoi(arg[next]);
if (i < 1 || i > atom->nbondtypes)
- error->all("Invalid bond type index for fix shake");
+ error->all(FLERR,"Invalid bond type index for fix shake");
bond_flag[i] = 1;
} else if (mode == 'a') {
int i = atoi(arg[next]);
if (i < 1 || i > atom->nangletypes)
- error->all("Invalid angle type index for fix shake");
+ error->all(FLERR,"Invalid angle type index for fix shake");
angle_flag[i] = 1;
} else if (mode == 't') {
int i = atoi(arg[next]);
if (i < 1 || i > atom->ntypes)
- error->all("Invalid atom type index for fix shake");
+ error->all(FLERR,"Invalid atom type index for fix shake");
type_flag[i] = 1;
} else if (mode == 'm') {
double massone = atof(arg[next]);
- if (massone == 0.0) error->all("Invalid atom mass for fix shake");
- if (nmass == atom->ntypes) error->all("Too many masses for fix shake");
+ if (massone == 0.0) error->all(FLERR,"Invalid atom mass for fix shake");
+ if (nmass == atom->ntypes) error->all(FLERR,"Too many masses for fix shake");
mass_list[nmass++] = massone;
- } else error->all("Illegal fix shake command");
+ } else error->all(FLERR,"Illegal fix shake command");
next++;
}
// allocate bond and angle distance arrays, indexed from 1 to n
bond_distance = new double[atom->nbondtypes+1];
angle_distance = new double[atom->nangletypes+1];
cu_bond_distance = new cCudaData<double, X_FLOAT, xx> (bond_distance, atom->nbondtypes+1);
cu_angle_distance = new cCudaData<double, X_FLOAT, xx> (angle_distance, atom->nangletypes+1);
// allocate statistics arrays
if (output_every) {
int nb = atom->nbondtypes + 1;
b_count = new int[nb];
b_count_all = new int[nb];
b_ave = new double[nb];
b_ave_all = new double[nb];
b_max = new double[nb];
b_max_all = new double[nb];
b_min = new double[nb];
b_min_all = new double[nb];
int na = atom->nangletypes + 1;
a_count = new int[na];
a_count_all = new int[na];
a_ave = new double[na];
a_ave_all = new double[na];
a_max = new double[na];
a_max_all = new double[na];
a_min = new double[na];
a_min_all = new double[na];
}
cudable_comm=true;
// identify all SHAKE clusters
find_clusters();
// initialize list of SHAKE clusters to constrain
maxlist = 0;
list = NULL;
Cuda_FixShakeCuda_Init(&cuda->shared_data,dtv, dtfsq,
cu_shake_flag->dev_data(),cu_shake_atom->dev_data(),cu_shake_type->dev_data(), cu_xshake->dev_data(),
cu_bond_distance->dev_data(),cu_angle_distance->dev_data(),cu_virial->dev_data(),
max_iter,tolerance);
}
/* ---------------------------------------------------------------------- */
FixShakeCuda::~FixShakeCuda()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
// set bond_type and angle_type back to positive for SHAKE clusters
// must set for all SHAKE bonds and angles stored by each atom
int **bond_type = atom->bond_type;
int **angle_type = atom->angle_type;
int nlocal = atom->nlocal;
int n;
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
else if (shake_flag[i] == 1) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = anglefind(i,shake_atom[i][1],shake_atom[i][2]);
if (n >= 0) angle_type[i][n] = -angle_type[i][n];
} else if (shake_flag[i] == 2) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 3) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 4) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][3]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
}
}
// delete locally stored arrays
memory->destroy(shake_flag);
memory->destroy(shake_atom);
memory->destroy(shake_type);
memory->destroy(xshake);
delete [] bond_flag;
delete [] angle_flag;
delete [] type_flag;
delete [] mass_list;
delete [] bond_distance;
delete [] angle_distance;
if (output_every) {
delete [] b_count;
delete [] b_count_all;
delete [] b_ave;
delete [] b_ave_all;
delete [] b_max;
delete [] b_max_all;
delete [] b_min;
delete [] b_min_all;
delete [] a_count;
delete [] a_count_all;
delete [] a_ave;
delete [] a_ave_all;
delete [] a_max;
delete [] a_max_all;
delete [] a_min;
delete [] a_min_all;
}
memory->destroy(list);
delete cu_shake_flag;
delete cu_shake_atom;
delete cu_shake_type;
delete cu_xshake;
delete cu_list;
delete cu_bond_distance;
delete cu_angle_distance;
}
/* ---------------------------------------------------------------------- */
int FixShakeCuda::setmask()
{
int mask = 0;
mask |= PRE_NEIGHBOR_CUDA;
mask |= POST_FORCE_CUDA;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ----------------------------------------------------------------------
set bond and angle distances
this init must happen after force->bond and force->angle inits
------------------------------------------------------------------------- */
void FixShakeCuda::init()
{
int i,m,flag,flag_all,type1,type2,bond1_type,bond2_type;
double rsq,angle;
// error if more than one shake fix
int count = 0;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"shake") == 0) count++;
- if (count > 1) error->all("More than one fix shake");
+ if (count > 1) error->all(FLERR,"More than one fix shake");
// cannot use with minimization since SHAKE turns off bonds
// that should contribute to potential energy
if (update->whichflag == 2)
- error->all("Fix shake cannot be used with minimization");
+ error->all(FLERR,"Fix shake cannot be used with minimization");
// error if npt,nph fix comes before shake fix
for (i = 0; i < modify->nfix; i++) {
if (strcmp(modify->fix[i]->style,"npt") == 0) break;
if (strcmp(modify->fix[i]->style,"nph") == 0) break;
}
if (i < modify->nfix) {
for (int j = i; j < modify->nfix; j++)
if (strcmp(modify->fix[j]->style,"shake") == 0)
- error->all("Shake fix must come before NPT/NPH fix");
+ error->all(FLERR,"Shake fix must come before NPT/NPH fix");
}
// if rRESPA, find associated fix that must exist
// could have changed locations in fix list since created
// set ptrs to rRESPA variables
if (strstr(update->integrate_style,"respa")) {
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"RESPA") == 0) ifix_respa = i;
nlevels_respa = ((Respa *) update->integrate)->nlevels;
loop_respa = ((Respa *) update->integrate)->loop;
step_respa = ((Respa *) update->integrate)->step;
}
// set equilibrium bond distances
if (force->bond == NULL)
- error->all("Bond potential must be defined for SHAKE");
+ error->all(FLERR,"Bond potential must be defined for SHAKE");
for (i = 1; i <= atom->nbondtypes; i++)
bond_distance[i] = force->bond->equilibrium_distance(i);
// set equilibrium angle distances
int nlocal = atom->nlocal;
for (i = 1; i <= atom->nangletypes; i++) {
if (angle_flag[i] == 0) continue;
if (force->angle == NULL)
- error->all("Angle potential must be defined for SHAKE");
+ error->all(FLERR,"Angle potential must be defined for SHAKE");
// scan all atoms for a SHAKE angle cluster
// extract bond types for the 2 bonds in the cluster
// bond types must be same in all clusters of this angle type,
// else set error flag
flag = 0;
bond1_type = bond2_type = 0;
for (m = 0; m < nlocal; m++) {
if (shake_flag[m] != 1) continue;
if (shake_type[m][2] != i) continue;
type1 = MIN(shake_type[m][0],shake_type[m][1]);
type2 = MAX(shake_type[m][0],shake_type[m][1]);
if (bond1_type > 0) {
if (type1 != bond1_type || type2 != bond2_type) {
flag = 1;
break;
}
}
bond1_type = type1;
bond2_type = type2;
}
// error check for any bond types that are not the same
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_MAX,world);
- if (flag_all) error->all("Shake angles have different bond types");
+ if (flag_all) error->all(FLERR,"Shake angles have different bond types");
// insure all procs have bond types
MPI_Allreduce(&bond1_type,&flag_all,1,MPI_INT,MPI_MAX,world);
bond1_type = flag_all;
MPI_Allreduce(&bond2_type,&flag_all,1,MPI_INT,MPI_MAX,world);
bond2_type = flag_all;
// if bond types are 0, no SHAKE angles of this type exist
// just skip this angle
if (bond1_type == 0) {
angle_distance[i] = 0.0;
continue;
}
// compute the angle distance as a function of 2 bond distances
angle = force->angle->equilibrium_angle(i);
rsq = 2.0*bond_distance[bond1_type]*bond_distance[bond2_type] *
(1.0-cos(angle));
angle_distance[i] = sqrt(rsq);
}
}
/* ----------------------------------------------------------------------
SHAKE as pre-integrator constraint
------------------------------------------------------------------------- */
void FixShakeCuda::setup(int vflag)
{
pre_neighbor();
if (output_every) stats();
// setup SHAKE output
int ntimestep = update->ntimestep;
next_output = ntimestep + output_every;
if (output_every == 0) next_output = update->laststep + 1;
if (output_every && ntimestep % output_every != 0)
next_output = (ntimestep/output_every)*output_every + output_every;
// half timestep constraint on pre-step, full timestep thereafter
if (strstr(update->integrate_style,"verlet")) {
dtv = update->dt;
dtfsq = 0.5 * update->dt * update->dt * force->ftm2v;
post_force(vflag);
dtfsq = update->dt * update->dt * force->ftm2v;
} else {
dtv = step_respa[0];
dtf_innerhalf = 0.5 * step_respa[0] * force->ftm2v;
dtf_inner = dtf_innerhalf;
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
dtf_inner = step_respa[0] * force->ftm2v;
}
Cuda_FixShakeCuda_Init(&cuda->shared_data,dtv, dtfsq,
cu_shake_flag->dev_data(),cu_shake_atom->dev_data(),cu_shake_type->dev_data(), cu_xshake->dev_data(),
cu_bond_distance->dev_data(),cu_angle_distance->dev_data(),cu_virial->dev_data(),
max_iter,tolerance);
}
/* ----------------------------------------------------------------------
build list of SHAKE clusters to constrain
if one or more atoms in cluster are on this proc,
this proc lists the cluster exactly once
------------------------------------------------------------------------- */
void FixShakeCuda::pre_neighbor()
{
int atom1,atom2,atom3,atom4;
// local copies of atom quantities
// used by SHAKE until next re-neighboring
x = atom->x;
v = atom->v;
f = atom->f;
mass = atom->mass;
rmass = atom->rmass;
type = atom->type;
nlocal = atom->nlocal;
// extend size of SHAKE list if necessary
if (nlocal > maxlist) {
maxlist = nlocal;
memory->destroy(list);
memory->create(list,maxlist,"shake:list");
delete cu_list; cu_list = new cCudaData<int , int , xx >(list,maxlist);
}
// build list of SHAKE clusters I compute
nlist = 0;
int count2=0,count3=0,count4=0,count3a=0;
for (int i = 0; i < nlocal; i++)
if (shake_flag[i]) {
if(shake_flag[i] == 2) count2++;
if(shake_flag[i] == 3) count3++;
if(shake_flag[i] == 4) count4++;
if(shake_flag[i] == 1) count3a++;
if (shake_flag[i] == 2) {
atom1 = atom->map(shake_atom[i][0]);
atom2 = atom->map(shake_atom[i][1]);
if (atom1 == -1 || atom2 == -1) {
char str[128];
sprintf(str,
"Shake atoms %d %d missing on proc %d at step " BIGINT_FORMAT,
shake_atom[i][0],shake_atom[i][1],me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (i <= atom1 && i <= atom2) list[nlist++] = i;
} else if (shake_flag[i] % 2 == 1) {
atom1 = atom->map(shake_atom[i][0]);
atom2 = atom->map(shake_atom[i][1]);
atom3 = atom->map(shake_atom[i][2]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1) {
char str[128];
sprintf(str,
"Shake atoms %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
shake_atom[i][0],shake_atom[i][1],shake_atom[i][2],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (i <= atom1 && i <= atom2 && i <= atom3) list[nlist++] = i;
} else {
atom1 = atom->map(shake_atom[i][0]);
atom2 = atom->map(shake_atom[i][1]);
atom3 = atom->map(shake_atom[i][2]);
atom4 = atom->map(shake_atom[i][3]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) {
char str[128];
sprintf(str,
"Shake atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
shake_atom[i][0],shake_atom[i][1],
shake_atom[i][2],shake_atom[i][3],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (i <= atom1 && i <= atom2 && i <= atom3 && i <= atom4)
list[nlist++] = i;
}
}
count2/=2;
count3/=3;
count4/=4;
count3a/=3;
count3+=count2;
count4+=count3;
count3a+=count4;
for(int k = 0,l = count2; k < count2; k++)
{
if(shake_flag[list[k]]!=2)
{
while(shake_flag[list[l]]!=2 && l<nlist-1) l++;
if(shake_flag[list[l]]!=2) {printf("FixShakeCuda: Error in List SortA %i %i\n",k,l);return;}
int tmp = list[k]; list[k]=list[l]; list[l]=tmp;
}
}
for(int k = count2,l = count3; k < count3; k++)
{
if(shake_flag[list[k]]!=3)
{
while(shake_flag[list[l]]!=3 && l<nlist-1) l++;
if(shake_flag[list[l]]!=3) {printf("FixShakeCuda: Error in List SortB %i %i\n",k,l);return;}
int tmp = list[k]; list[k]=list[l]; list[l]=tmp;
}
}
for(int k = count3,l = count4; k < count4; k++)
{
if(shake_flag[list[k]]!=4)
{
while(shake_flag[list[l]]!=4 && l<nlist-1) l++;
if(shake_flag[list[l]]!=4) {printf("FixShakeCuda: Error in List SortC %i %i\n",k,l);return;}
int tmp = list[k]; list[k]=list[l]; list[l]=tmp;
}
}
cu_list->upload();
cu_bond_distance->upload();
cu_angle_distance->upload();
cu_shake_flag->upload();
cu_shake_atom->upload();
cu_shake_type->upload();
neighbor_step=true;
}
/* ----------------------------------------------------------------------
compute the force adjustment for SHAKE constraint
------------------------------------------------------------------------- */
void FixShakeCuda::post_force(int vflag)
{
timespec starttime;
timespec endtime;
if(cuda->finished_setup && neighbor_step)
{
Cuda_FixShakeCuda_Init(&cuda->shared_data,dtv, dtfsq,
cu_shake_flag->dev_data(),cu_shake_atom->dev_data(),cu_shake_type->dev_data(), cu_xshake->dev_data(),
cu_bond_distance->dev_data(),cu_angle_distance->dev_data(),cu_virial->dev_data(),
max_iter,tolerance);
}
if(not cuda->finished_setup)
cuda->downloadAll();
if (update->ntimestep == next_output)
{
if(cuda->finished_setup)
cuda->cu_x->download();
stats();
}
// xshake = unconstrained move with current v,f
unconstrained_update();
// communicate results if necessary
//if(cuda->finished_setup) cu_xshake->download();
if (nprocs > 1)
{
//if(cuda->finished_setup)
//cu_xshake->download();
comm->forward_comm_fix(this);
//if(cuda->finished_setup)
//cu_xshake->upload();
}
// virial setup
if (vflag) v_setup(vflag);
else evflag = 0;
// loop over clusters
clock_gettime(CLOCK_REALTIME,&starttime);
if(cuda->finished_setup)
{
cu_virial->upload();
if(vflag_atom) cuda->cu_vatom->upload();
Cuda_FixShakeCuda_Shake(&cuda->shared_data,vflag,vflag_atom,(int*)cu_list->dev_data(),nlist);
cu_virial->download();
if(vflag_atom) cuda->cu_vatom->download();
}
else
for (int i = 0; i < nlist; i++) {
int m = list[i];
if (shake_flag[m] == 2) shake2(m);
else if (shake_flag[m] == 3) shake3(m);
else if (shake_flag[m] == 4) shake4(m);
else shake3angle(m);
}
if((not cuda->finished_setup)) cuda->cu_f->upload();
clock_gettime(CLOCK_REALTIME,&endtime);
if(cuda->finished_setup)
time_postforce+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
else
time_postforce=0.0;
//printf("Postforce time: %lf\n",time_postforce);
}
/* ----------------------------------------------------------------------
count # of degrees-of-freedom removed by SHAKE for atoms in igroup
------------------------------------------------------------------------- */
int FixShakeCuda::dof(int igroup)
{
int groupbit = group->bitmask[igroup];
int *mask = atom->mask;
int *tag = atom->tag;
int nlocal = atom->nlocal;
// count dof in a cluster if and only if
// the central atom is in group and atom i is the central atom
int n = 0;
for (int i = 0; i < nlocal; i++) {
if (!(mask[i] & groupbit)) continue;
if (shake_flag[i] == 0) continue;
if (shake_atom[i][0] != tag[i]) continue;
if (shake_flag[i] == 1) n += 3;
else if (shake_flag[i] == 2) n += 1;
else if (shake_flag[i] == 3) n += 2;
else if (shake_flag[i] == 4) n += 3;
}
int nall;
MPI_Allreduce(&n,&nall,1,MPI_INT,MPI_SUM,world);
return nall;
}
/* ----------------------------------------------------------------------
identify whether each atom is in a SHAKE cluster
only include atoms in fix group and those bonds/angles specified in input
test whether all clusters are valid
set shake_flag, shake_atom, shake_type values
set bond,angle types negative so will be ignored in neighbor lists
------------------------------------------------------------------------- */
void FixShakeCuda::find_clusters()
{
int i,j,m,n;
int flag,flag_all,messtag,loop,nbuf,nbufmax,size;
double massone;
int *buf,*bufcopy;
MPI_Request request;
MPI_Status status;
if (me == 0 && screen) fprintf(screen,"Finding SHAKE clusters ...\n");
// local copies of atom ptrs
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
double *mass = atom->mass;
double *rmass = atom->rmass;
int **bond_type = atom->bond_type;
int **angle_type = atom->angle_type;
int **nspecial = atom->nspecial;
int **special = atom->special;
int nlocal = atom->nlocal;
// setup ring of procs
int next = me + 1;
int prev = me -1;
if (next == nprocs) next = 0;
if (prev < 0) prev = nprocs - 1;
// -----------------------------------------------------
// allocate arrays for self (1d) and bond partners (2d)
// max = max # of bond partners for owned atoms = 2nd dim of partner arrays
// npartner[i] = # of bonds attached to atom i
// nshake[i] = # of SHAKE bonds attached to atom i
// partner_tag[i][] = global IDs of each partner
// partner_mask[i][] = mask of each partner
// partner_type[i][] = type of each partner
// partner_massflag[i][] = 1 if partner meets mass criterion, 0 if not
// partner_bondtype[i][] = type of bond attached to each partner
// partner_shake[i][] = 1 if SHAKE bonded to partner, 0 if not
// partner_nshake[i][] = nshake value for each partner
// -----------------------------------------------------
int max = 0;
for (i = 0; i < nlocal; i++) max = MAX(max,nspecial[i][0]);
int *npartner,*nshake;
memory->create(npartner,nlocal,"shake:npartner");
memory->create(nshake,nlocal,"shake:nshake");
int **partner_tag,**partner_mask,**partner_type,**partner_massflag;
int ** partner_bondtype,**partner_shake,**partner_nshake;
memory->create(partner_tag,nlocal,max,"shake:partner_tag");
memory->create(partner_mask,nlocal,max,"shake:partner_mask");
memory->create(partner_type,nlocal,max,"shake:partner_type");
memory->create(partner_massflag,nlocal,max,"shake:partner_massflag");
memory->create(partner_bondtype,nlocal,max,"shake:partner_bondtype");
memory->create(partner_shake,nlocal,max,"shake:partner_shake");
memory->create(partner_nshake,nlocal,max,"shake:partner_nshake");
// -----------------------------------------------------
// set npartner and partner_tag from special arrays
// -----------------------------------------------------
for (i = 0; i < nlocal; i++) {
npartner[i] = nspecial[i][0];
for (j = 0; j < npartner[i]; j++) partner_tag[i][j] = special[i][j];
}
// -----------------------------------------------------
// set partner_mask, partner_type, partner_massflag, partner_bondtype
// for bonded partners
// requires communication for off-proc partners
// -----------------------------------------------------
// fill in mask, type, massflag, bondtype if own bond partner
// info to store in buf for each off-proc bond = nper = 6
// 2 atoms IDs in bond, space for mask, type, massflag, bondtype
// nbufmax = largest buffer needed to hold info from any proc
int nper = 6;
nbuf = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
partner_mask[i][j] = 0;
partner_type[i][j] = 0;
partner_massflag[i][j] = 0;
partner_bondtype[i][j] = 0;
m = atom->map(partner_tag[i][j]);
if (m >= 0 && m < nlocal) {
partner_mask[i][j] = mask[m];
partner_type[i][j] = type[m];
if (nmass) {
if (rmass) massone = rmass[m];
else massone = mass[type[m]];
partner_massflag[i][j] = masscheck(massone);
}
n = bondfind(i,tag[i],partner_tag[i][j]);
if (n >= 0) partner_bondtype[i][j] = bond_type[i][n];
else {
n = bondfind(m,tag[i],partner_tag[i][j]);
if (n >= 0) partner_bondtype[i][j] = bond_type[m][n];
}
} else nbuf += nper;
}
}
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with info
size = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
m = atom->map(partner_tag[i][j]);
if (m < 0 || m >= nlocal) {
buf[size] = tag[i];
buf[size+1] = partner_tag[i][j];
buf[size+2] = 0;
buf[size+3] = 0;
buf[size+4] = 0;
n = bondfind(i,tag[i],partner_tag[i][j]);
if (n >= 0) buf[size+5] = bond_type[i][n];
else buf[size+5] = 0;
size += nper;
}
}
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan bond partner IDs for atoms I own
// if I own partner:
// fill in mask and type and massflag
// search for bond with 1st atom and fill in bondtype
messtag = 1;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
m = atom->map(buf[i+1]);
if (m >= 0 && m < nlocal) {
buf[i+2] = mask[m];
buf[i+3] = type[m];
if (nmass) {
if (rmass) massone = rmass[m];
else massone = mass[type[m]];
buf[i+4] = masscheck(massone);
}
if (buf[i+5] == 0) {
n = bondfind(m,buf[i],buf[i+1]);
if (n >= 0) buf[i+5] = bond_type[m][n];
}
}
i += nper;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// store partner info returned to me
m = 0;
while (m < size) {
i = atom->map(buf[m]);
for (j = 0; j < npartner[i]; j++)
if (buf[m+1] == partner_tag[i][j]) break;
partner_mask[i][j] = buf[m+2];
partner_type[i][j] = buf[m+3];
partner_massflag[i][j] = buf[m+4];
partner_bondtype[i][j] = buf[m+5];
m += nper;
}
delete [] buf;
delete [] bufcopy;
// error check for unfilled partner info
// if partner_type not set, is an error
// partner_bondtype may not be set if special list is not consistent
// with bondatom (e.g. due to delete_bonds command)
// this is OK if one or both atoms are not in fix group, since
// bond won't be SHAKEn anyway
// else it's an error
flag = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < npartner[i]; j++) {
if (partner_type[i][j] == 0) flag = 1;
if (!(mask[i] & groupbit)) continue;
if (!(partner_mask[i][j] & groupbit)) continue;
if (partner_bondtype[i][j] == 0) flag = 1;
}
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Did not find fix shake partner info");
+ if (flag_all) error->all(FLERR,"Did not find fix shake partner info");
// -----------------------------------------------------
// identify SHAKEable bonds
// set nshake[i] = # of SHAKE bonds attached to atom i
// set partner_shake[i][] = 1 if SHAKE bonded to partner, 0 if not
// both atoms must be in group, bondtype must be > 0
// check if bondtype is in input bond_flag
// check if type of either atom is in input type_flag
// check if mass of either atom is in input mass_list
// -----------------------------------------------------
int np;
for (i = 0; i < nlocal; i++) {
nshake[i] = 0;
np = npartner[i];
for (j = 0; j < np; j++) {
partner_shake[i][j] = 0;
if (!(mask[i] & groupbit)) continue;
if (!(partner_mask[i][j] & groupbit)) continue;
if (partner_bondtype[i][j] <= 0) continue;
if (bond_flag[partner_bondtype[i][j]]) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
}
if (type_flag[type[i]] || type_flag[partner_type[i][j]]) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
}
if (nmass) {
if (partner_massflag[i][j]) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
} else {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
if (masscheck(massone)) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
}
}
}
}
}
// -----------------------------------------------------
// set partner_nshake for bonded partners
// requires communication for off-proc partners
// -----------------------------------------------------
// fill in partner_nshake if own bond partner
// info to store in buf for each off-proc bond =
// 2 atoms IDs in bond, space for nshake value
// nbufmax = largest buffer needed to hold info from any proc
nbuf = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
m = atom->map(partner_tag[i][j]);
if (m >= 0 && m < nlocal) partner_nshake[i][j] = nshake[m];
else nbuf += 3;
}
}
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with info
size = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
m = atom->map(partner_tag[i][j]);
if (m < 0 || m >= nlocal) {
buf[size] = tag[i];
buf[size+1] = partner_tag[i][j];
size += 3;
}
}
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan bond partner IDs for atoms I own
// if I own partner, fill in nshake value
messtag = 2;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
m = atom->map(buf[i+1]);
if (m >= 0 && m < nlocal) buf[i+2] = nshake[m];
i += 3;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// store partner info returned to me
m = 0;
while (m < size) {
i = atom->map(buf[m]);
for (j = 0; j < npartner[i]; j++)
if (buf[m+1] == partner_tag[i][j]) break;
partner_nshake[i][j] = buf[m+2];
m += 3;
}
delete [] buf;
delete [] bufcopy;
// -----------------------------------------------------
// error checks
// no atom with nshake > 3
// no connected atoms which both have nshake > 1
// -----------------------------------------------------
flag = 0;
for (i = 0; i < nlocal; i++) if (nshake[i] > 3) flag = 1;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Shake cluster of more than 4 atoms");
+ if (flag_all) error->all(FLERR,"Shake cluster of more than 4 atoms");
flag = 0;
for (i = 0; i < nlocal; i++) {
if (nshake[i] <= 1) continue;
for (j = 0; j < npartner[i]; j++)
if (partner_shake[i][j] && partner_nshake[i][j] > 1) flag = 1;
}
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Shake clusters are connected");
+ if (flag_all) error->all(FLERR,"Shake clusters are connected");
// -----------------------------------------------------
// set SHAKE arrays that are stored with atoms & add angle constraints
// zero shake arrays for all owned atoms
// if I am central atom set shake_flag & shake_atom & shake_type
// for 2-atom clusters, I am central atom if my atom ID < partner ID
// for 3-atom clusters, test for angle constraint
// angle will be stored by this atom if it exists
// if angle type matches angle_flag, then it is angle-constrained
// shake_flag[] = 0 if atom not in SHAKE cluster
// 2,3,4 = size of bond-only cluster
// 1 = 3-atom angle cluster
// shake_atom[][] = global IDs of 2,3,4 atoms in cluster
// central atom is 1st
// for 2-atom cluster, lowest ID is 1st
// shake_type[][] = bondtype of each bond in cluster
// for 3-atom angle cluster, 3rd value is angletype
// -----------------------------------------------------
for (i = 0; i < nlocal; i++) {
shake_flag[i] = 0;
shake_atom[i][0] = 0;
shake_atom[i][1] = 0;
shake_atom[i][2] = 0;
shake_atom[i][3] = 0;
shake_type[i][0] = 0;
shake_type[i][1] = 0;
shake_type[i][2] = 0;
if (nshake[i] == 1) {
for (j = 0; j < npartner[i]; j++)
if (partner_shake[i][j]) break;
if (partner_nshake[i][j] == 1 && tag[i] < partner_tag[i][j]) {
shake_flag[i] = 2;
shake_atom[i][0] = tag[i];
shake_atom[i][1] = partner_tag[i][j];
shake_type[i][0] = partner_bondtype[i][j];
}
}
if (nshake[i] > 1) {
shake_flag[i] = 1;
shake_atom[i][0] = tag[i];
for (j = 0; j < npartner[i]; j++)
if (partner_shake[i][j]) {
m = shake_flag[i];
shake_atom[i][m] = partner_tag[i][j];
shake_type[i][m-1] = partner_bondtype[i][j];
shake_flag[i]++;
}
}
if (nshake[i] == 2) {
n = anglefind(i,shake_atom[i][1],shake_atom[i][2]);
if (n < 0) continue;
if (angle_type[i][n] < 0) continue;
if (angle_flag[angle_type[i][n]]) {
shake_flag[i] = 1;
shake_type[i][2] = angle_type[i][n];
}
}
}
// -----------------------------------------------------
// set shake_flag,shake_atom,shake_type for non-central atoms
// requires communication for off-proc atoms
// -----------------------------------------------------
// fill in shake arrays for each bond partner I own
// info to store in buf for each off-proc bond =
// all values from shake_flag, shake_atom, shake_type
// nbufmax = largest buffer needed to hold info from any proc
nbuf = 0;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
for (j = 0; j < npartner[i]; j++) {
if (partner_shake[i][j] == 0) continue;
m = atom->map(partner_tag[i][j]);
if (m >= 0 && m < nlocal) {
shake_flag[m] = shake_flag[i];
shake_atom[m][0] = shake_atom[i][0];
shake_atom[m][1] = shake_atom[i][1];
shake_atom[m][2] = shake_atom[i][2];
shake_atom[m][3] = shake_atom[i][3];
shake_type[m][0] = shake_type[i][0];
shake_type[m][1] = shake_type[i][1];
shake_type[m][2] = shake_type[i][2];
} else nbuf += 9;
}
}
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with info
size = 0;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
for (j = 0; j < npartner[i]; j++) {
if (partner_shake[i][j] == 0) continue;
m = atom->map(partner_tag[i][j]);
if (m < 0 || m >= nlocal) {
buf[size] = partner_tag[i][j];
buf[size+1] = shake_flag[i];
buf[size+2] = shake_atom[i][0];
buf[size+3] = shake_atom[i][1];
buf[size+4] = shake_atom[i][2];
buf[size+5] = shake_atom[i][3];
buf[size+6] = shake_type[i][0];
buf[size+7] = shake_type[i][1];
buf[size+8] = shake_type[i][2];
size += 9;
}
}
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan for ID that I own
// if I own ID, fill in shake array values
messtag = 3;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
m = atom->map(buf[i]);
if (m >= 0 && m < nlocal) {
shake_flag[m] = buf[i+1];
shake_atom[m][0] = buf[i+2];
shake_atom[m][1] = buf[i+3];
shake_atom[m][2] = buf[i+4];
shake_atom[m][3] = buf[i+5];
shake_type[m][0] = buf[i+6];
shake_type[m][1] = buf[i+7];
shake_type[m][2] = buf[i+8];
}
i += 9;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
delete [] buf;
delete [] bufcopy;
// -----------------------------------------------------
// free local memory
// -----------------------------------------------------
memory->destroy(npartner);
memory->destroy(nshake);
memory->destroy(partner_tag);
memory->destroy(partner_mask);
memory->destroy(partner_type);
memory->destroy(partner_massflag);
memory->destroy(partner_bondtype);
memory->destroy(partner_shake);
memory->destroy(partner_nshake);
// -----------------------------------------------------
// set bond_type and angle_type negative for SHAKE clusters
// must set for all SHAKE bonds and angles stored by each atom
// -----------------------------------------------------
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
else if (shake_flag[i] == 1) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = anglefind(i,shake_atom[i][1],shake_atom[i][2]);
if (n >= 0) angle_type[i][n] = -angle_type[i][n];
} else if (shake_flag[i] == 2) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 3) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 4) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][3]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
}
}
// -----------------------------------------------------
// print info on SHAKE clusters
// -----------------------------------------------------
int count1,count2,count3,count4;
count1 = count2 = count3 = count4 = 0;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 1) count1++;
else if (shake_flag[i] == 2) count2++;
else if (shake_flag[i] == 3) count3++;
else if (shake_flag[i] == 4) count4++;
}
for(int i=0;i<nlocal;i++)
{
}
int tmp;
tmp = count1;
MPI_Allreduce(&tmp,&count1,1,MPI_INT,MPI_SUM,world);
tmp = count2;
MPI_Allreduce(&tmp,&count2,1,MPI_INT,MPI_SUM,world);
tmp = count3;
MPI_Allreduce(&tmp,&count3,1,MPI_INT,MPI_SUM,world);
tmp = count4;
MPI_Allreduce(&tmp,&count4,1,MPI_INT,MPI_SUM,world);
if (me == 0) {
if (screen) {
fprintf(screen," %d = # of size 2 clusters\n",count2/2);
fprintf(screen," %d = # of size 3 clusters\n",count3/3);
fprintf(screen," %d = # of size 4 clusters\n",count4/4);
fprintf(screen," %d = # of frozen angles\n",count1/3);
}
if (logfile) {
fprintf(logfile," %d = # of size 2 clusters\n",count2/2);
fprintf(logfile," %d = # of size 3 clusters\n",count3/3);
fprintf(logfile," %d = # of size 4 clusters\n",count4/4);
fprintf(logfile," %d = # of frozen angles\n",count1/3);
}
}
cu_shake_flag->upload();
cu_shake_atom->upload();
cu_shake_type->upload();
Cuda_FixShakeCuda_Init(&cuda->shared_data,dtv, dtfsq,
cu_shake_flag->dev_data(),cu_shake_atom->dev_data(),cu_shake_type->dev_data(), cu_xshake->dev_data(),
cu_bond_distance->dev_data(),cu_angle_distance->dev_data(),cu_virial->dev_data(),
max_iter,tolerance);
}
void FixShakeCuda::swap_clusters(int i, int j)
{
int tmp;
tmp = shake_flag[i]; shake_flag[i] = shake_flag[j]; shake_flag[j] = tmp;
tmp = shake_atom[i][0]; shake_atom[i][0] = shake_atom[j][0]; shake_atom[j][0] = tmp;
tmp = shake_atom[i][1]; shake_atom[i][1] = shake_atom[j][1]; shake_atom[j][1] = tmp;
tmp = shake_atom[i][2]; shake_atom[i][2] = shake_atom[j][2]; shake_atom[j][2] = tmp;
tmp = shake_atom[i][3]; shake_atom[i][3] = shake_atom[j][3]; shake_atom[j][3] = tmp;
tmp = shake_type[i][0]; shake_type[i][0] = shake_type[j][0]; shake_type[j][0] = tmp;
tmp = shake_type[i][1]; shake_type[i][1] = shake_type[j][1]; shake_type[j][1] = tmp;
tmp = shake_type[i][2]; shake_type[i][2] = shake_type[j][2]; shake_type[j][2] = tmp;
}
/* ----------------------------------------------------------------------
check if massone is within MASSDELTA of any mass in mass_list
return 1 if yes, 0 if not
------------------------------------------------------------------------- */
int FixShakeCuda::masscheck(double massone)
{
for (int i = 0; i < nmass; i++)
if (fabs(mass_list[i]-massone) <= MASSDELTA) return 1;
return 0;
}
/* ----------------------------------------------------------------------
update the unconstrained position of each atom
only for SHAKE clusters, else set to 0.0
assumes NVE update, seems to be accurate enough for NVT,NPT,NPH as well
------------------------------------------------------------------------- */
void FixShakeCuda::unconstrained_update()
{
if(cuda->finished_setup)
{
Cuda_FixShakeCuda_UnconstrainedUpdate(&cuda->shared_data);
return;
}
double dtfmsq;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
dtfmsq = dtfsq / rmass[i];
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
} else {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
dtfmsq = dtfsq / mass[type[i]];
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
}
cu_xshake->upload();
}
/* ---------------------------------------------------------------------- */
void FixShakeCuda::shake2(int m)
{
int nlist,list[2];
double v[6];
double invmass0,invmass1;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
double bond1 = bond_distance[shake_type[m][0]];
// r01 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
// s01 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
// a,b,c = coeffs in quadratic equation for lamda
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
}
double a = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double b = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double c = s01sq - bond1*bond1;
// error check
double determ = b*b - 4.0*a*c;
if (determ < 0.0) {
- error->warning("Shake determinant < 0.0");
+ error->warning(FLERR,"Shake determinant < 0.0");
determ = 0.0;
}
// exact quadratic solution for lamda
double lamda,lamda1,lamda2;
lamda1 = (-b+sqrt(determ)) / (2.0*a);
lamda2 = (-b-sqrt(determ)) / (2.0*a);
if (fabs(lamda1) <= fabs(lamda2)) lamda = lamda1;
else lamda = lamda2;
// update forces if atom is owned by this processor
lamda /= dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda*r01[0];
f[i0][1] += lamda*r01[1];
f[i0][2] += lamda*r01[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda*r01[0];
f[i1][1] -= lamda*r01[1];
f[i1][2] -= lamda*r01[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
v[0] = lamda*r01[0]*r01[0];
v[1] = lamda*r01[1]*r01[1];
v[2] = lamda*r01[2]*r01[2];
v[3] = lamda*r01[0]*r01[1];
v[4] = lamda*r01[0]*r01[2];
v[5] = lamda*r01[1]*r01[2];
v_tally(nlist,list,2.0,v);
}
}
/* ---------------------------------------------------------------------- */
void FixShakeCuda::shake3(int m)
{
int nlist,list[3];
double v[6];
double invmass0,invmass1,invmass2;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
int i2 = atom->map(shake_atom[m][2]);
double bond1 = bond_distance[shake_type[m][0]];
double bond2 = bond_distance[shake_type[m][1]];
// r01,r02 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
double r02[3];
r02[0] = x[i0][0] - x[i2][0];
r02[1] = x[i0][1] - x[i2][1];
r02[2] = x[i0][2] - x[i2][2];
domain->minimum_image(r02);
// s01,s02 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
double s02[3];
s02[0] = xshake[i0][0] - xshake[i2][0];
s02[1] = xshake[i0][1] - xshake[i2][1];
s02[2] = xshake[i0][2] - xshake[i2][2];
domain->minimum_image(s02);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double r02sq = r02[0]*r02[0] + r02[1]*r02[1] + r02[2]*r02[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
double s02sq = s02[0]*s02[0] + s02[1]*s02[1] + s02[2]*s02[2];
// matrix coeffs and rhs for lamda equations
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
invmass2 = 1.0/rmass[i2];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
invmass2 = 1.0/mass[type[i2]];
}
double a11 = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double a12 = 2.0 * invmass0 *
(s01[0]*r02[0] + s01[1]*r02[1] + s01[2]*r02[2]);
double a21 = 2.0 * invmass0 *
(s02[0]*r01[0] + s02[1]*r01[1] + s02[2]*r01[2]);
double a22 = 2.0 * (invmass0+invmass2) *
(s02[0]*r02[0] + s02[1]*r02[1] + s02[2]*r02[2]);
// inverse of matrix
double determ = a11*a22 - a12*a21;
- if (determ == 0.0) error->one("Shake determinant = 0.0");
+ if (determ == 0.0) error->one(FLERR,"Shake determinant = 0.0");
double determinv = 1.0/determ;
double a11inv = a22*determinv;
double a12inv = -a12*determinv;
double a21inv = -a21*determinv;
double a22inv = a11*determinv;
// quadratic correction coeffs
double r0102 = (r01[0]*r02[0] + r01[1]*r02[1] + r01[2]*r02[2]);
double quad1_0101 = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double quad1_0202 = invmass0*invmass0 * r02sq;
double quad1_0102 = 2.0 * (invmass0+invmass1)*invmass0 * r0102;
double quad2_0202 = (invmass0+invmass2)*(invmass0+invmass2) * r02sq;
double quad2_0101 = invmass0*invmass0 * r01sq;
double quad2_0102 = 2.0 * (invmass0+invmass2)*invmass0 * r0102;
// iterate until converged
double lamda01 = 0.0;
double lamda02 = 0.0;
int niter = 0;
int done = 0;
double quad1,quad2,b1,b2,lamda01_new,lamda02_new;
while (!done && niter < max_iter) {
quad1 = quad1_0101 * lamda01*lamda01 + quad1_0202 * lamda02*lamda02 +
quad1_0102 * lamda01*lamda02;
quad2 = quad2_0101 * lamda01*lamda01 + quad2_0202 * lamda02*lamda02 +
quad2_0102 * lamda01*lamda02;
b1 = bond1*bond1 - s01sq - quad1;
b2 = bond2*bond2 - s02sq - quad2;
lamda01_new = a11inv*b1 + a12inv*b2;
lamda02_new = a21inv*b1 + a22inv*b2;
done = 1;
if (fabs(lamda01_new-lamda01) > tolerance) done = 0;
if (fabs(lamda02_new-lamda02) > tolerance) done = 0;
lamda01 = lamda01_new;
lamda02 = lamda02_new;
niter++;
}
// update forces if atom is owned by this processor
lamda01 = lamda01/dtfsq;
lamda02 = lamda02/dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda01*r01[0] + lamda02*r02[0];
f[i0][1] += lamda01*r01[1] + lamda02*r02[1];
f[i0][2] += lamda01*r01[2] + lamda02*r02[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda01*r01[0];
f[i1][1] -= lamda01*r01[1];
f[i1][2] -= lamda01*r01[2];
}
if (i2 < nlocal) {
f[i2][0] -= lamda02*r02[0];
f[i2][1] -= lamda02*r02[1];
f[i2][2] -= lamda02*r02[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
if (i2 < nlocal) list[nlist++] = i2;
v[0] = lamda01*r01[0]*r01[0] + lamda02*r02[0]*r02[0];
v[1] = lamda01*r01[1]*r01[1] + lamda02*r02[1]*r02[1];
v[2] = lamda01*r01[2]*r01[2] + lamda02*r02[2]*r02[2];
v[3] = lamda01*r01[0]*r01[1] + lamda02*r02[0]*r02[1];
v[4] = lamda01*r01[0]*r01[2] + lamda02*r02[0]*r02[2];
v[5] = lamda01*r01[1]*r01[2] + lamda02*r02[1]*r02[2];
v_tally(nlist,list,3.0,v);
}
}
/* ---------------------------------------------------------------------- */
void FixShakeCuda::shake4(int m)
{
int nlist,list[4];
double v[6];
double invmass0,invmass1,invmass2,invmass3;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
int i2 = atom->map(shake_atom[m][2]);
int i3 = atom->map(shake_atom[m][3]);
double bond1 = bond_distance[shake_type[m][0]];
double bond2 = bond_distance[shake_type[m][1]];
double bond3 = bond_distance[shake_type[m][2]];
// r01,r02,r03 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
double r02[3];
r02[0] = x[i0][0] - x[i2][0];
r02[1] = x[i0][1] - x[i2][1];
r02[2] = x[i0][2] - x[i2][2];
domain->minimum_image(r02);
double r03[3];
r03[0] = x[i0][0] - x[i3][0];
r03[1] = x[i0][1] - x[i3][1];
r03[2] = x[i0][2] - x[i3][2];
domain->minimum_image(r03);
// s01,s02,s03 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
double s02[3];
s02[0] = xshake[i0][0] - xshake[i2][0];
s02[1] = xshake[i0][1] - xshake[i2][1];
s02[2] = xshake[i0][2] - xshake[i2][2];
domain->minimum_image(s02);
double s03[3];
s03[0] = xshake[i0][0] - xshake[i3][0];
s03[1] = xshake[i0][1] - xshake[i3][1];
s03[2] = xshake[i0][2] - xshake[i3][2];
domain->minimum_image(s03);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double r02sq = r02[0]*r02[0] + r02[1]*r02[1] + r02[2]*r02[2];
double r03sq = r03[0]*r03[0] + r03[1]*r03[1] + r03[2]*r03[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
double s02sq = s02[0]*s02[0] + s02[1]*s02[1] + s02[2]*s02[2];
double s03sq = s03[0]*s03[0] + s03[1]*s03[1] + s03[2]*s03[2];
// matrix coeffs and rhs for lamda equations
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
invmass2 = 1.0/rmass[i2];
invmass3 = 1.0/rmass[i3];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
invmass2 = 1.0/mass[type[i2]];
invmass3 = 1.0/mass[type[i3]];
}
double a11 = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double a12 = 2.0 * invmass0 *
(s01[0]*r02[0] + s01[1]*r02[1] + s01[2]*r02[2]);
double a13 = 2.0 * invmass0 *
(s01[0]*r03[0] + s01[1]*r03[1] + s01[2]*r03[2]);
double a21 = 2.0 * invmass0 *
(s02[0]*r01[0] + s02[1]*r01[1] + s02[2]*r01[2]);
double a22 = 2.0 * (invmass0+invmass2) *
(s02[0]*r02[0] + s02[1]*r02[1] + s02[2]*r02[2]);
double a23 = 2.0 * invmass0 *
(s02[0]*r03[0] + s02[1]*r03[1] + s02[2]*r03[2]);
double a31 = 2.0 * invmass0 *
(s03[0]*r01[0] + s03[1]*r01[1] + s03[2]*r01[2]);
double a32 = 2.0 * invmass0 *
(s03[0]*r02[0] + s03[1]*r02[1] + s03[2]*r02[2]);
double a33 = 2.0 * (invmass0+invmass3) *
(s03[0]*r03[0] + s03[1]*r03[1] + s03[2]*r03[2]);
// inverse of matrix;
double determ = a11*a22*a33 + a12*a23*a31 + a13*a21*a32 -
a11*a23*a32 - a12*a21*a33 - a13*a22*a31;
- if (determ == 0.0) error->one("Shake determinant = 0.0");
+ if (determ == 0.0) error->one(FLERR,"Shake determinant = 0.0");
double determinv = 1.0/determ;
double a11inv = determinv * (a22*a33 - a23*a32);
double a12inv = -determinv * (a12*a33 - a13*a32);
double a13inv = determinv * (a12*a23 - a13*a22);
double a21inv = -determinv * (a21*a33 - a23*a31);
double a22inv = determinv * (a11*a33 - a13*a31);
double a23inv = -determinv * (a11*a23 - a13*a21);
double a31inv = determinv * (a21*a32 - a22*a31);
double a32inv = -determinv * (a11*a32 - a12*a31);
double a33inv = determinv * (a11*a22 - a12*a21);
// quadratic correction coeffs
double r0102 = (r01[0]*r02[0] + r01[1]*r02[1] + r01[2]*r02[2]);
double r0103 = (r01[0]*r03[0] + r01[1]*r03[1] + r01[2]*r03[2]);
double r0203 = (r02[0]*r03[0] + r02[1]*r03[1] + r02[2]*r03[2]);
double quad1_0101 = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double quad1_0202 = invmass0*invmass0 * r02sq;
double quad1_0303 = invmass0*invmass0 * r03sq;
double quad1_0102 = 2.0 * (invmass0+invmass1)*invmass0 * r0102;
double quad1_0103 = 2.0 * (invmass0+invmass1)*invmass0 * r0103;
double quad1_0203 = 2.0 * invmass0*invmass0 * r0203;
double quad2_0101 = invmass0*invmass0 * r01sq;
double quad2_0202 = (invmass0+invmass2)*(invmass0+invmass2) * r02sq;
double quad2_0303 = invmass0*invmass0 * r03sq;
double quad2_0102 = 2.0 * (invmass0+invmass2)*invmass0 * r0102;
double quad2_0103 = 2.0 * invmass0*invmass0 * r0103;
double quad2_0203 = 2.0 * (invmass0+invmass2)*invmass0 * r0203;
double quad3_0101 = invmass0*invmass0 * r01sq;
double quad3_0202 = invmass0*invmass0 * r02sq;
double quad3_0303 = (invmass0+invmass3)*(invmass0+invmass3) * r03sq;
double quad3_0102 = 2.0 * invmass0*invmass0 * r0102;
double quad3_0103 = 2.0 * (invmass0+invmass3)*invmass0 * r0103;
double quad3_0203 = 2.0 * (invmass0+invmass3)*invmass0 * r0203;
// iterate until converged
double lamda01 = 0.0;
double lamda02 = 0.0;
double lamda03 = 0.0;
int niter = 0;
int done = 0;
double quad1,quad2,quad3,b1,b2,b3,lamda01_new,lamda02_new,lamda03_new;
while (!done && niter < max_iter) {
quad1 = quad1_0101 * lamda01*lamda01 +
quad1_0202 * lamda02*lamda02 +
quad1_0303 * lamda03*lamda03 +
quad1_0102 * lamda01*lamda02 +
quad1_0103 * lamda01*lamda03 +
quad1_0203 * lamda02*lamda03;
quad2 = quad2_0101 * lamda01*lamda01 +
quad2_0202 * lamda02*lamda02 +
quad2_0303 * lamda03*lamda03 +
quad2_0102 * lamda01*lamda02 +
quad2_0103 * lamda01*lamda03 +
quad2_0203 * lamda02*lamda03;
quad3 = quad3_0101 * lamda01*lamda01 +
quad3_0202 * lamda02*lamda02 +
quad3_0303 * lamda03*lamda03 +
quad3_0102 * lamda01*lamda02 +
quad3_0103 * lamda01*lamda03 +
quad3_0203 * lamda02*lamda03;
b1 = bond1*bond1 - s01sq - quad1;
b2 = bond2*bond2 - s02sq - quad2;
b3 = bond3*bond3 - s03sq - quad3;
lamda01_new = a11inv*b1 + a12inv*b2 + a13inv*b3;
lamda02_new = a21inv*b1 + a22inv*b2 + a23inv*b3;
lamda03_new = a31inv*b1 + a32inv*b2 + a33inv*b3;
done = 1;
if (fabs(lamda01_new-lamda01) > tolerance) done = 0;
if (fabs(lamda02_new-lamda02) > tolerance) done = 0;
if (fabs(lamda03_new-lamda03) > tolerance) done = 0;
lamda01 = lamda01_new;
lamda02 = lamda02_new;
lamda03 = lamda03_new;
niter++;
}
// update forces if atom is owned by this processor
lamda01 = lamda01/dtfsq;
lamda02 = lamda02/dtfsq;
lamda03 = lamda03/dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda01*r01[0] + lamda02*r02[0] + lamda03*r03[0];
f[i0][1] += lamda01*r01[1] + lamda02*r02[1] + lamda03*r03[1];
f[i0][2] += lamda01*r01[2] + lamda02*r02[2] + lamda03*r03[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda01*r01[0];
f[i1][1] -= lamda01*r01[1];
f[i1][2] -= lamda01*r01[2];
}
if (i2 < nlocal) {
f[i2][0] -= lamda02*r02[0];
f[i2][1] -= lamda02*r02[1];
f[i2][2] -= lamda02*r02[2];
}
if (i3 < nlocal) {
f[i3][0] -= lamda03*r03[0];
f[i3][1] -= lamda03*r03[1];
f[i3][2] -= lamda03*r03[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
if (i2 < nlocal) list[nlist++] = i2;
if (i3 < nlocal) list[nlist++] = i3;
v[0] = lamda01*r01[0]*r01[0]+lamda02*r02[0]*r02[0]+lamda03*r03[0]*r03[0];
v[1] = lamda01*r01[1]*r01[1]+lamda02*r02[1]*r02[1]+lamda03*r03[1]*r03[1];
v[2] = lamda01*r01[2]*r01[2]+lamda02*r02[2]*r02[2]+lamda03*r03[2]*r03[2];
v[3] = lamda01*r01[0]*r01[1]+lamda02*r02[0]*r02[1]+lamda03*r03[0]*r03[1];
v[4] = lamda01*r01[0]*r01[2]+lamda02*r02[0]*r02[2]+lamda03*r03[0]*r03[2];
v[5] = lamda01*r01[1]*r01[2]+lamda02*r02[1]*r02[2]+lamda03*r03[1]*r03[2];
//if(i0==7271) printf("%lf %lf %lf %lf %lf %lf\n",v[0],v[1],v[2],v[3],v[4],v[5]);
v_tally(nlist,list,4.0,v);
}
}
/* ---------------------------------------------------------------------- */
void FixShakeCuda::shake3angle(int m)
{
int nlist,list[3];
double v[6];
double invmass0,invmass1,invmass2;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
int i2 = atom->map(shake_atom[m][2]);
double bond1 = bond_distance[shake_type[m][0]];
double bond2 = bond_distance[shake_type[m][1]];
double bond12 = angle_distance[shake_type[m][2]];
// r01,r02,r12 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
double r02[3];
r02[0] = x[i0][0] - x[i2][0];
r02[1] = x[i0][1] - x[i2][1];
r02[2] = x[i0][2] - x[i2][2];
domain->minimum_image(r02);
double r12[3];
r12[0] = x[i1][0] - x[i2][0];
r12[1] = x[i1][1] - x[i2][1];
r12[2] = x[i1][2] - x[i2][2];
domain->minimum_image(r12);
// s01,s02,s12 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
double s02[3];
s02[0] = xshake[i0][0] - xshake[i2][0];
s02[1] = xshake[i0][1] - xshake[i2][1];
s02[2] = xshake[i0][2] - xshake[i2][2];
domain->minimum_image(s02);
double s12[3];
s12[0] = xshake[i1][0] - xshake[i2][0];
s12[1] = xshake[i1][1] - xshake[i2][1];
s12[2] = xshake[i1][2] - xshake[i2][2];
domain->minimum_image(s12);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double r02sq = r02[0]*r02[0] + r02[1]*r02[1] + r02[2]*r02[2];
double r12sq = r12[0]*r12[0] + r12[1]*r12[1] + r12[2]*r12[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
double s02sq = s02[0]*s02[0] + s02[1]*s02[1] + s02[2]*s02[2];
double s12sq = s12[0]*s12[0] + s12[1]*s12[1] + s12[2]*s12[2];
// matrix coeffs and rhs for lamda equations
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
invmass2 = 1.0/rmass[i2];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
invmass2 = 1.0/mass[type[i2]];
}
double a11 = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double a12 = 2.0 * invmass0 *
(s01[0]*r02[0] + s01[1]*r02[1] + s01[2]*r02[2]);
double a13 = - 2.0 * invmass1 *
(s01[0]*r12[0] + s01[1]*r12[1] + s01[2]*r12[2]);
double a21 = 2.0 * invmass0 *
(s02[0]*r01[0] + s02[1]*r01[1] + s02[2]*r01[2]);
double a22 = 2.0 * (invmass0+invmass2) *
(s02[0]*r02[0] + s02[1]*r02[1] + s02[2]*r02[2]);
double a23 = 2.0 * invmass2 *
(s02[0]*r12[0] + s02[1]*r12[1] + s02[2]*r12[2]);
double a31 = - 2.0 * invmass1 *
(s12[0]*r01[0] + s12[1]*r01[1] + s12[2]*r01[2]);
double a32 = 2.0 * invmass2 *
(s12[0]*r02[0] + s12[1]*r02[1] + s12[2]*r02[2]);
double a33 = 2.0 * (invmass1+invmass2) *
(s12[0]*r12[0] + s12[1]*r12[1] + s12[2]*r12[2]);
// inverse of matrix
double determ = a11*a22*a33 + a12*a23*a31 + a13*a21*a32 -
a11*a23*a32 - a12*a21*a33 - a13*a22*a31;
- if (determ == 0.0) error->one("Shake determinant = 0.0");
+ if (determ == 0.0) error->one(FLERR,"Shake determinant = 0.0");
double determinv = 1.0/determ;
double a11inv = determinv * (a22*a33 - a23*a32);
double a12inv = -determinv * (a12*a33 - a13*a32);
double a13inv = determinv * (a12*a23 - a13*a22);
double a21inv = -determinv * (a21*a33 - a23*a31);
double a22inv = determinv * (a11*a33 - a13*a31);
double a23inv = -determinv * (a11*a23 - a13*a21);
double a31inv = determinv * (a21*a32 - a22*a31);
double a32inv = -determinv * (a11*a32 - a12*a31);
double a33inv = determinv * (a11*a22 - a12*a21);
// quadratic correction coeffs
double r0102 = (r01[0]*r02[0] + r01[1]*r02[1] + r01[2]*r02[2]);
double r0112 = (r01[0]*r12[0] + r01[1]*r12[1] + r01[2]*r12[2]);
double r0212 = (r02[0]*r12[0] + r02[1]*r12[1] + r02[2]*r12[2]);
double quad1_0101 = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double quad1_0202 = invmass0*invmass0 * r02sq;
double quad1_1212 = invmass1*invmass1 * r12sq;
double quad1_0102 = 2.0 * (invmass0+invmass1)*invmass0 * r0102;
double quad1_0112 = - 2.0 * (invmass0+invmass1)*invmass1 * r0112;
double quad1_0212 = - 2.0 * invmass0*invmass1 * r0212;
double quad2_0101 = invmass0*invmass0 * r01sq;
double quad2_0202 = (invmass0+invmass2)*(invmass0+invmass2) * r02sq;
double quad2_1212 = invmass2*invmass2 * r12sq;
double quad2_0102 = 2.0 * (invmass0+invmass2)*invmass0 * r0102;
double quad2_0112 = 2.0 * invmass0*invmass2 * r0112;
double quad2_0212 = 2.0 * (invmass0+invmass2)*invmass2 * r0212;
double quad3_0101 = invmass1*invmass1 * r01sq;
double quad3_0202 = invmass2*invmass2 * r02sq;
double quad3_1212 = (invmass1+invmass2)*(invmass1+invmass2) * r12sq;
double quad3_0102 = - 2.0 * invmass1*invmass2 * r0102;
double quad3_0112 = - 2.0 * (invmass1+invmass2)*invmass1 * r0112;
double quad3_0212 = 2.0 * (invmass1+invmass2)*invmass2 * r0212;
// iterate until converged
double lamda01 = 0.0;
double lamda02 = 0.0;
double lamda12 = 0.0;
int niter = 0;
int done = 0;
double quad1,quad2,quad3,b1,b2,b3,lamda01_new,lamda02_new,lamda12_new;
while (!done && niter < max_iter) {
quad1 = quad1_0101 * lamda01*lamda01 +
quad1_0202 * lamda02*lamda02 +
quad1_1212 * lamda12*lamda12 +
quad1_0102 * lamda01*lamda02 +
quad1_0112 * lamda01*lamda12 +
quad1_0212 * lamda02*lamda12;
quad2 = quad2_0101 * lamda01*lamda01 +
quad2_0202 * lamda02*lamda02 +
quad2_1212 * lamda12*lamda12 +
quad2_0102 * lamda01*lamda02 +
quad2_0112 * lamda01*lamda12 +
quad2_0212 * lamda02*lamda12;
quad3 = quad3_0101 * lamda01*lamda01 +
quad3_0202 * lamda02*lamda02 +
quad3_1212 * lamda12*lamda12 +
quad3_0102 * lamda01*lamda02 +
quad3_0112 * lamda01*lamda12 +
quad3_0212 * lamda02*lamda12;
b1 = bond1*bond1 - s01sq - quad1;
b2 = bond2*bond2 - s02sq - quad2;
b3 = bond12*bond12 - s12sq - quad3;
lamda01_new = a11inv*b1 + a12inv*b2 + a13inv*b3;
lamda02_new = a21inv*b1 + a22inv*b2 + a23inv*b3;
lamda12_new = a31inv*b1 + a32inv*b2 + a33inv*b3;
done = 1;
if (fabs(lamda01_new-lamda01) > tolerance) done = 0;
if (fabs(lamda02_new-lamda02) > tolerance) done = 0;
if (fabs(lamda12_new-lamda12) > tolerance) done = 0;
lamda01 = lamda01_new;
lamda02 = lamda02_new;
lamda12 = lamda12_new;
niter++;
}
// update forces if atom is owned by this processor
lamda01 = lamda01/dtfsq;
lamda02 = lamda02/dtfsq;
lamda12 = lamda12/dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda01*r01[0] + lamda02*r02[0];
f[i0][1] += lamda01*r01[1] + lamda02*r02[1];
f[i0][2] += lamda01*r01[2] + lamda02*r02[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda01*r01[0] - lamda12*r12[0];
f[i1][1] -= lamda01*r01[1] - lamda12*r12[1];
f[i1][2] -= lamda01*r01[2] - lamda12*r12[2];
}
if (i2 < nlocal) {
f[i2][0] -= lamda02*r02[0] + lamda12*r12[0];
f[i2][1] -= lamda02*r02[1] + lamda12*r12[1];
f[i2][2] -= lamda02*r02[2] + lamda12*r12[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
if (i2 < nlocal) list[nlist++] = i2;
v[0] = lamda01*r01[0]*r01[0]+lamda02*r02[0]*r02[0]+lamda12*r12[0]*r12[0];
v[1] = lamda01*r01[1]*r01[1]+lamda02*r02[1]*r02[1]+lamda12*r12[1]*r12[1];
v[2] = lamda01*r01[2]*r01[2]+lamda02*r02[2]*r02[2]+lamda12*r12[2]*r12[2];
v[3] = lamda01*r01[0]*r01[1]+lamda02*r02[0]*r02[1]+lamda12*r12[0]*r12[1];
v[4] = lamda01*r01[0]*r01[2]+lamda02*r02[0]*r02[2]+lamda12*r12[0]*r12[2];
v[5] = lamda01*r01[1]*r01[2]+lamda02*r02[1]*r02[2]+lamda12*r12[1]*r12[2];
v_tally(nlist,list,3.0,v);
}
}
/* ----------------------------------------------------------------------
print-out bond & angle statistics
------------------------------------------------------------------------- */
void FixShakeCuda::stats()
{
int i,j,m,n,iatom,jatom,katom;
double delx,dely,delz;
double r,r1,r2,r3,angle;
// zero out accumulators
int nb = atom->nbondtypes + 1;
int na = atom->nangletypes + 1;
for (i = 0; i < nb; i++) {
b_count[i] = 0;
b_ave[i] = b_max[i] = 0.0;
b_min[i] = BIG;
}
for (i = 0; i < na; i++) {
a_count[i] = 0;
a_ave[i] = a_max[i] = 0.0;
a_min[i] = BIG;
}
// log stats for each bond & angle
// OK to double count since are just averaging
double **x = atom->x;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
// bond stats
n = shake_flag[i];
if (n == 1) n = 3;
iatom = atom->map(shake_atom[i][0]);
for (j = 1; j < n; j++) {
jatom = atom->map(shake_atom[i][j]);
delx = x[iatom][0] - x[jatom][0];
dely = x[iatom][1] - x[jatom][1];
delz = x[iatom][2] - x[jatom][2];
domain->minimum_image(delx,dely,delz);
r = sqrt(delx*delx + dely*dely + delz*delz);
m = shake_type[i][j-1];
b_count[m]++;
b_ave[m] += r;
b_max[m] = MAX(b_max[m],r);
b_min[m] = MIN(b_min[m],r);
}
// angle stats
if (shake_flag[i] == 1) {
iatom = atom->map(shake_atom[i][0]);
jatom = atom->map(shake_atom[i][1]);
katom = atom->map(shake_atom[i][2]);
delx = x[iatom][0] - x[jatom][0];
dely = x[iatom][1] - x[jatom][1];
delz = x[iatom][2] - x[jatom][2];
domain->minimum_image(delx,dely,delz);
r1 = sqrt(delx*delx + dely*dely + delz*delz);
delx = x[iatom][0] - x[katom][0];
dely = x[iatom][1] - x[katom][1];
delz = x[iatom][2] - x[katom][2];
domain->minimum_image(delx,dely,delz);
r2 = sqrt(delx*delx + dely*dely + delz*delz);
delx = x[jatom][0] - x[katom][0];
dely = x[jatom][1] - x[katom][1];
delz = x[jatom][2] - x[katom][2];
domain->minimum_image(delx,dely,delz);
r3 = sqrt(delx*delx + dely*dely + delz*delz);
angle = acos((r1*r1 + r2*r2 - r3*r3) / (2.0*r1*r2));
angle *= 180.0/PI;
m = shake_type[i][2];
a_count[m]++;
a_ave[m] += angle;
a_max[m] = MAX(a_max[m],angle);
a_min[m] = MIN(a_min[m],angle);
}
}
// sum across all procs
MPI_Allreduce(b_count,b_count_all,nb,MPI_INT,MPI_SUM,world);
MPI_Allreduce(b_ave,b_ave_all,nb,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(b_max,b_max_all,nb,MPI_DOUBLE,MPI_MAX,world);
MPI_Allreduce(b_min,b_min_all,nb,MPI_DOUBLE,MPI_MIN,world);
MPI_Allreduce(a_count,a_count_all,na,MPI_INT,MPI_SUM,world);
MPI_Allreduce(a_ave,a_ave_all,na,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(a_max,a_max_all,na,MPI_DOUBLE,MPI_MAX,world);
MPI_Allreduce(a_min,a_min_all,na,MPI_DOUBLE,MPI_MIN,world);
// print stats only for non-zero counts
if (me == 0) {
if (screen) {
fprintf(screen,
"SHAKE stats (type/ave/delta) on step " BIGINT_FORMAT "\n",
update->ntimestep);
for (i = 1; i < nb; i++)
if (b_count_all[i])
fprintf(screen," %d %g %g\n",i,
b_ave_all[i]/b_count_all[i],b_max_all[i]-b_min_all[i]);
for (i = 1; i < na; i++)
if (a_count_all[i])
fprintf(screen," %d %g %g\n",i,
a_ave_all[i]/a_count_all[i],a_max_all[i]-a_min_all[i]);
}
if (logfile) {
fprintf(logfile,
"SHAKE stats (type/ave/delta) on step " BIGINT_FORMAT "\n",
update->ntimestep);
for (i = 0; i < nb; i++)
if (b_count_all[i])
fprintf(logfile," %d %g %g\n",i,
b_ave_all[i]/b_count_all[i],b_max_all[i]-b_min_all[i]);
for (i = 0; i < na; i++)
if (a_count_all[i])
fprintf(logfile," %d %g %g\n",i,
a_ave_all[i]/a_count_all[i],a_max_all[i]-a_min_all[i]);
}
}
// next timestep for stats
next_output += output_every;
}
/* ----------------------------------------------------------------------
find a bond between global tags n1 and n2 stored with local atom i
return -1 if don't find it
return bond index if do find it
------------------------------------------------------------------------- */
int FixShakeCuda::bondfind(int i, int n1, int n2)
{
int *tag = atom->tag;
int **bond_atom = atom->bond_atom;
int nbonds = atom->num_bond[i];
int m;
for (m = 0; m < nbonds; m++) {
if (n1 == tag[i] && n2 == bond_atom[i][m]) break;
if (n1 == bond_atom[i][m] && n2 == tag[i]) break;
}
if (m < nbonds) return m;
return -1;
}
/* ----------------------------------------------------------------------
find an angle with global end atoms n1 and n2 stored with local atom i
return -1 if don't find it
return angle index if do find it
------------------------------------------------------------------------- */
int FixShakeCuda::anglefind(int i, int n1, int n2)
{
int **angle_atom1 = atom->angle_atom1;
int **angle_atom3 = atom->angle_atom3;
int nangles = atom->num_angle[i];
int m;
for (m = 0; m < nangles; m++) {
if (n1 == angle_atom1[i][m] && n2 == angle_atom3[i][m]) break;
if (n1 == angle_atom3[i][m] && n2 == angle_atom1[i][m]) break;
}
if (m < nangles) return m;
return -1;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixShakeCuda::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int);
bytes += nmax*4 * sizeof(int);
bytes += nmax*3 * sizeof(int);
bytes += nmax*3 * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixShakeCuda::grow_arrays(int nmax)
{
memory->grow(shake_flag,nmax,"shake:shake_flag");
memory->grow(shake_atom,nmax,4,"shake:shake_atom");
memory->grow(shake_type,nmax,3,"shake:shake_type");
memory->destroy(xshake);
memory->create(xshake,nmax,3,"shake:xshake");
delete cu_shake_flag; cu_shake_flag = new cCudaData<int, int, xx > (shake_flag, nmax );
delete cu_shake_atom; cu_shake_atom = new cCudaData<int, int, yx> ((int*)shake_atom, nmax, 4);
delete cu_shake_type; cu_shake_type = new cCudaData<int, int, yx> ((int*)shake_type, nmax, 3);
delete cu_xshake; cu_xshake = new cCudaData<double, X_FLOAT, xy> ((double*)xshake, nmax, 3);
cu_shake_flag->upload();
cu_shake_atom->upload();
cu_shake_type->upload();
if(cu_bond_distance)
Cuda_FixShakeCuda_Init(&cuda->shared_data,dtv, dtfsq,
cu_shake_flag->dev_data(),cu_shake_atom->dev_data(),cu_shake_type->dev_data(), cu_xshake->dev_data(),
cu_bond_distance->dev_data(),cu_angle_distance->dev_data(),cu_virial->dev_data(),
max_iter,tolerance);
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixShakeCuda::copy_arrays(int i, int j)
{
int flag = shake_flag[j] = shake_flag[i];
if (flag == 1) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_atom[j][2] = shake_atom[i][2];
shake_type[j][0] = shake_type[i][0];
shake_type[j][1] = shake_type[i][1];
shake_type[j][2] = shake_type[i][2];
} else if (flag == 2) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_type[j][0] = shake_type[i][0];
} else if (flag == 3) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_atom[j][2] = shake_atom[i][2];
shake_type[j][0] = shake_type[i][0];
shake_type[j][1] = shake_type[i][1];
} else if (flag == 4) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_atom[j][2] = shake_atom[i][2];
shake_atom[j][3] = shake_atom[i][3];
shake_type[j][0] = shake_type[i][0];
shake_type[j][1] = shake_type[i][1];
shake_type[j][2] = shake_type[i][2];
}
}
/* ----------------------------------------------------------------------
initialize one atom's array values, called when atom is created
------------------------------------------------------------------------- */
void FixShakeCuda::set_arrays(int i)
{
shake_flag[i] = 0;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixShakeCuda::pack_exchange(int i, double *buf)
{
int m = 0;
buf[m++] = shake_flag[i];
int flag = shake_flag[i];
if (flag == 1) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_atom[i][2];
buf[m++] = shake_type[i][0];
buf[m++] = shake_type[i][1];
buf[m++] = shake_type[i][2];
} else if (flag == 2) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_type[i][0];
} else if (flag == 3) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_atom[i][2];
buf[m++] = shake_type[i][0];
buf[m++] = shake_type[i][1];
} else if (flag == 4) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_atom[i][2];
buf[m++] = shake_atom[i][3];
buf[m++] = shake_type[i][0];
buf[m++] = shake_type[i][1];
buf[m++] = shake_type[i][2];
}
return m;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixShakeCuda::unpack_exchange(int nlocal, double *buf)
{
int m = 0;
int flag = shake_flag[nlocal] = static_cast<int> (buf[m++]);
if (flag == 1) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_atom[nlocal][2] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
shake_type[nlocal][1] = static_cast<int> (buf[m++]);
shake_type[nlocal][2] = static_cast<int> (buf[m++]);
} else if (flag == 2) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
} else if (flag == 3) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_atom[nlocal][2] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
shake_type[nlocal][1] = static_cast<int> (buf[m++]);
} else if (flag == 4) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_atom[nlocal][2] = static_cast<int> (buf[m++]);
shake_atom[nlocal][3] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
shake_type[nlocal][1] = static_cast<int> (buf[m++]);
shake_type[nlocal][2] = static_cast<int> (buf[m++]);
}
return m;
}
/* ----------------------------------------------------------------------
enforce SHAKE constraints from rRESPA
prediction portion is different than Verlet
rRESPA updating of atom coords is done with full v, but only portions of f
------------------------------------------------------------------------- */
/*
void FixShakeCuda::post_force_respa(int vflag, int ilevel, int iloop)
{
// call stats only on outermost level
if (ilevel == nlevels_respa-1 && update->ntimestep == next_output) stats();
// perform SHAKE on every loop iteration of every rRESPA level
// except last loop iteration of inner levels
if (ilevel < nlevels_respa-1 && iloop == loop_respa[ilevel]-1) return;
// xshake = atom coords after next x update in innermost loop
// depends on rRESPA level
// for levels > 0 this includes more than one velocity update
// xshake = predicted position from call to this routine at level N =
// x + dt0 (v + dtN/m fN + 1/2 dt(N-1)/m f(N-1) + ... + 1/2 dt0/m f0)
double ***f_level = ((FixRespa *) modify->fix[ifix_respa])->f_level;
dtfsq = dtf_inner * step_respa[ilevel];
double invmass,dtfmsq;
int jlevel;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
invmass = 1.0 / rmass[i];
dtfmsq = dtfsq * invmass;
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
for (jlevel = 0; jlevel < ilevel; jlevel++) {
dtfmsq = dtf_innerhalf * step_respa[jlevel] * invmass;
xshake[i][0] += dtfmsq*f_level[i][jlevel][0];
xshake[i][1] += dtfmsq*f_level[i][jlevel][1];
xshake[i][2] += dtfmsq*f_level[i][jlevel][2];
}
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
} else {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
invmass = 1.0 / mass[type[i]];
dtfmsq = dtfsq * invmass;
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
for (jlevel = 0; jlevel < ilevel; jlevel++) {
dtfmsq = dtf_innerhalf * step_respa[jlevel] * invmass;
xshake[i][0] += dtfmsq*f_level[i][jlevel][0];
xshake[i][1] += dtfmsq*f_level[i][jlevel][1];
xshake[i][2] += dtfmsq*f_level[i][jlevel][2];
}
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
}
// communicate results if necessary
if (nprocs > 1) comm->forward_comm_fix(this);
// virial setup
if (vflag) v_setup(vflag);
else evflag = 0;
// loop over clusters
int m;
for (int i = 0; i < nlist; i++) {
m = list[i];
if (shake_flag[m] == 2) shake2(m);
else if (shake_flag[m] == 3) shake3(m);
else if (shake_flag[m] == 4) shake4(m);
else shake3angle(m);
}
}
/* ---------------------------------------------------------------------- */
int FixShakeCuda::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
if(cuda->finished_setup)
{
int iswap=*list;
if(iswap<0)
{
iswap=-iswap-1;
int first= ((int*) buf)[0];
Cuda_FixShakeCuda_PackComm_Self(&cuda->shared_data,n,iswap,first,pbc,pbc_flag);
}
else
Cuda_FixShakeCuda_PackComm(&cuda->shared_data,n,iswap,(void*) buf,pbc,pbc_flag);
return 3;
}
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = xshake[j][0];
buf[m++] = xshake[j][1];
buf[m++] = xshake[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = xshake[j][0] + dx;
buf[m++] = xshake[j][1] + dy;
buf[m++] = xshake[j][2] + dz;
}
}
return 3;
}
/* ---------------------------------------------------------------------- */
void FixShakeCuda::unpack_comm(int n, int first, double *buf)
{
if(cuda->finished_setup)
{
Cuda_FixShakeCuda_UnpackComm(&cuda->shared_data,n,first,(void*)buf);
return;
}
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
xshake[i][0] = buf[m++];
xshake[i][1] = buf[m++];
xshake[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void FixShakeCuda::reset_dt()
{
if (strstr(update->integrate_style,"verlet")) {
dtv = update->dt;
dtfsq = update->dt * update->dt * force->ftm2v;
} else {
dtv = step_respa[0];
dtf_innerhalf = 0.5 * step_respa[0] * force->ftm2v;
dtf_inner = step_respa[0] * force->ftm2v;
}
if(cu_shake_atom)
Cuda_FixShakeCuda_Init(&cuda->shared_data,dtv, dtfsq,
cu_shake_flag->dev_data(),cu_shake_atom->dev_data(),cu_shake_type->dev_data(), cu_xshake->dev_data(),
cu_bond_distance->dev_data(),cu_angle_distance->dev_data(),cu_virial->dev_data(),
max_iter,tolerance);
}
diff --git a/src/USER-CUDA/fix_temp_berendsen_cuda.cpp b/src/USER-CUDA/fix_temp_berendsen_cuda.cpp
index 5fe9b0544..697ddbefd 100644
--- a/src/USER-CUDA/fix_temp_berendsen_cuda.cpp
+++ b/src/USER-CUDA/fix_temp_berendsen_cuda.cpp
@@ -1,220 +1,220 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstring>
#include <cstdlib>
#include <cmath>
#include "fix_temp_berendsen_cuda.h"
#include "fix_temp_berendsen_cuda_cu.h"
#include "atom.h"
#include "force.h"
#include "group.h"
#include "update.h"
#include "comm.h"
#include "modify.h"
#include "compute.h"
#include "error.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
enum{NOBIAS,BIAS};
/* ---------------------------------------------------------------------- */
FixTempBerendsenCuda::FixTempBerendsenCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg != 6) error->all("Illegal fix temp/berendsen/cuda command");
+ if (narg != 6) error->all(FLERR,"Illegal fix temp/berendsen/cuda command");
// Berendsen thermostat should be applied every step
nevery = 1;
t_start = atof(arg[3]);
t_stop = atof(arg[4]);
t_period = atof(arg[5]);
// error checks
- if (t_period <= 0.0) error->all("Fix temp/berendsen/cuda period must be > 0.0");
+ if (t_period <= 0.0) error->all(FLERR,"Fix temp/berendsen/cuda period must be > 0.0");
// create a new compute temp style
// id = fix-ID + temp, compute group = fix group
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/cuda";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
/* ---------------------------------------------------------------------- */
FixTempBerendsenCuda::~FixTempBerendsenCuda()
{
// delete temperature if fix created it
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
}
/* ---------------------------------------------------------------------- */
int FixTempBerendsenCuda::setmask()
{
int mask = 0;
mask |= END_OF_STEP_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTempBerendsenCuda::init()
{
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix temp/berendsen/cuda does not exist");
+ error->all(FLERR,"Temperature ID for fix temp/berendsen/cuda does not exist");
temperature = modify->compute[icompute];
if(not temperature->cudable)
- error->warning("Fix temp/berendsen/cuda uses non cudable temperature compute");
+ error->warning(FLERR,"Fix temp/berendsen/cuda uses non cudable temperature compute");
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
//temperature->init(); //not in original berendsen possible error?
}
/* ---------------------------------------------------------------------- */
void FixTempBerendsenCuda::end_of_step()
{
double t_current;
if(not temperature->cudable) {cuda->cu_x->download();cuda->cu_v->download();}
t_current = temperature->compute_scalar();
if (t_current == 0.0)
- error->all("Computed temperature for fix temp/berendsen/cuda cannot be 0.0");
+ error->all(FLERR,"Computed temperature for fix temp/berendsen/cuda cannot be 0.0");
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
t_target = t_start + delta * (t_stop-t_start);
// rescale velocities by lamda
double lamda = sqrt(1.0 + update->dt/t_period*(t_target/t_current - 1.0));
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (which == NOBIAS) {
Cuda_FixTempBerendsenCuda_EndOfStep(&cuda->shared_data, groupbit,lamda);
} else {
if(not temperature->cudable)
{
cuda->cu_x->download();cuda->cu_v->download();
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= lamda;
v[i][1] *= lamda;
v[i][2] *= lamda;
temperature->restore_bias(i,v[i]);
}
}
cuda->cu_v->upload();
}
else
{
temperature->remove_bias_all();
Cuda_FixTempBerendsenCuda_EndOfStep(&cuda->shared_data, groupbit,lamda);
temperature->restore_bias_all();
}
}
}
/* ---------------------------------------------------------------------- */
int FixTempBerendsenCuda::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void FixTempBerendsenCuda::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
diff --git a/src/USER-CUDA/fix_temp_rescale_cuda.cpp b/src/USER-CUDA/fix_temp_rescale_cuda.cpp
index a633bdc86..df23ef36a 100644
--- a/src/USER-CUDA/fix_temp_rescale_cuda.cpp
+++ b/src/USER-CUDA/fix_temp_rescale_cuda.cpp
@@ -1,222 +1,222 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cstring>
#include <cstdlib>
#include <cmath>
#include "fix_temp_rescale_cuda.h"
#include "fix_temp_rescale_cuda_cu.h"
#include "atom.h"
#include "force.h"
#include "group.h"
#include "update.h"
#include "domain.h"
#include "region.h"
#include "comm.h"
#include "modify.h"
#include "compute.h"
#include "error.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
enum{NOBIAS,BIAS};
/* ---------------------------------------------------------------------- */
FixTempRescaleCuda::FixTempRescaleCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg < 8) error->all("Illegal fix temp/rescale/cuda command");
+ if (narg < 8) error->all(FLERR,"Illegal fix temp/rescale/cuda command");
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix temp/rescale/cuda command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix temp/rescale/cuda command");
scalar_flag = 1;
global_freq = nevery;
extscalar = 1;
t_start = atof(arg[4]);
t_stop = atof(arg[5]);
t_window = atof(arg[6]);
fraction = atof(arg[7]);
// create a new compute temp
// id = fix-ID + temp, compute group = fix group
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[6];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/cuda";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
energy = 0.0;
}
/* ---------------------------------------------------------------------- */
FixTempRescaleCuda::~FixTempRescaleCuda()
{
// delete temperature if fix created it
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
}
/* ---------------------------------------------------------------------- */
int FixTempRescaleCuda::setmask()
{
int mask = 0;
mask |= END_OF_STEP_CUDA;
mask |= THERMO_ENERGY_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleCuda::init()
{
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix temp/rescale/cuda does not exist");
+ error->all(FLERR,"Temperature ID for fix temp/rescale/cuda does not exist");
temperature = modify->compute[icompute];
if(not temperature->cudable)
- error->warning("Fix temp/rescale/cuda uses non cudable temperature compute");
+ error->warning(FLERR,"Fix temp/rescale/cuda uses non cudable temperature compute");
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleCuda::end_of_step()
{
double t_current;
if(not temperature->cudable) {cuda->cu_x->download();cuda->cu_v->download();}
t_current = temperature->compute_scalar();
if (t_current == 0.0)
- error->all("Computed temperature for fix temp/rescale/cuda cannot be 0.0");
+ error->all(FLERR,"Computed temperature for fix temp/rescale/cuda cannot be 0.0");
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
// rescale velocity of appropriate atoms if outside window
if (fabs(t_current-t_target) > t_window) {
t_target = t_current - fraction*(t_current-t_target);
double factor = sqrt(t_target/t_current);
double efactor = 0.5 * force->boltz * temperature->dof;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (which == NOBIAS) {
energy += (t_current-t_target) * efactor;
Cuda_FixTempRescaleCuda_EndOfStep(&cuda->shared_data, groupbit,factor);
} else if (which == BIAS) {
energy += (t_current-t_target) * efactor;
if(not temperature->cudable)
{
cuda->cu_x->download();cuda->cu_v->download();
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= factor;
v[i][1] *= factor;
v[i][2] *= factor;
temperature->restore_bias(i,v[i]);
}
}
cuda->cu_v->upload();
}
else
{
temperature->remove_bias_all();
Cuda_FixTempRescaleCuda_EndOfStep(&cuda->shared_data, groupbit,factor);
temperature->restore_bias_all();
}
}
}
}
/* ---------------------------------------------------------------------- */
int FixTempRescaleCuda::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
if(not temperature->cudable)
- error->warning("Fix temp/rescale/cuda uses non cudable temperature compute");
+ error->warning(FLERR,"Fix temp/rescale/cuda uses non cudable temperature compute");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleCuda::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
double FixTempRescaleCuda::compute_scalar()
{
return energy;
}
diff --git a/src/USER-CUDA/fix_temp_rescale_limit_cuda.cpp b/src/USER-CUDA/fix_temp_rescale_limit_cuda.cpp
index be2d6a1f2..875cb391a 100644
--- a/src/USER-CUDA/fix_temp_rescale_limit_cuda.cpp
+++ b/src/USER-CUDA/fix_temp_rescale_limit_cuda.cpp
@@ -1,237 +1,235 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cstring>
#include <cstdlib>
#include <cmath>
#include "fix_temp_rescale_limit_cuda.h"
#include "fix_temp_rescale_limit_cuda_cu.h"
#include "atom.h"
#include "force.h"
#include "group.h"
#include "update.h"
#include "domain.h"
#include "region.h"
#include "comm.h"
#include "modify.h"
#include "compute.h"
#include "error.h"
#include "cuda.h"
#include "cuda_modify_flags.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
enum{NOBIAS,BIAS};
/* ---------------------------------------------------------------------- */
FixTempRescaleLimitCuda::FixTempRescaleLimitCuda(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if (narg < 9) error->all("Illegal fix temp/rescale/limit/cuda command");
+ if (narg < 9) error->all(FLERR,"Illegal fix temp/rescale/limit/cuda command");
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix temp/rescale/limit/cuda command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix temp/rescale/limit/cuda command");
scalar_flag = 1;
global_freq = nevery;
extscalar = 1;
t_start = atof(arg[4]);
t_stop = atof(arg[5]);
t_window = atof(arg[6]);
fraction = atof(arg[7]);
limit = atof(arg[8]);
- if (limit <= 1.0) error->all("Illegal fix temp/rescale/limit/cuda command (limit must be > 1.0)");
+ if (limit <= 1.0) error->all(FLERR,"Illegal fix temp/rescale/limit/cuda command (limit must be > 1.0)");
// create a new compute temp
// id = fix-ID + temp, compute group = fix group
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[6];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/cuda";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
energy = 0.0;
}
/* ---------------------------------------------------------------------- */
FixTempRescaleLimitCuda::~FixTempRescaleLimitCuda()
{
// delete temperature if fix created it
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
}
/* ---------------------------------------------------------------------- */
int FixTempRescaleLimitCuda::setmask()
{
int mask = 0;
mask |= END_OF_STEP_CUDA;
mask |= THERMO_ENERGY_CUDA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleLimitCuda::init()
{
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix temp/rescale/limit/cuda does not exist");
+ error->all(FLERR,"Temperature ID for fix temp/rescale/limit/cuda does not exist");
temperature = modify->compute[icompute];
if(not temperature->cudable)
- error->warning("Fix temp/rescale/limit/cuda uses non cudable temperature compute");
+ error->warning(FLERR,"Fix temp/rescale/limit/cuda uses non cudable temperature compute");
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleLimitCuda::end_of_step()
{
double t_current;
if(not temperature->cudable) {cuda->cu_x->download();cuda->cu_v->download();}
t_current = temperature->compute_scalar();
if (t_current == 0.0)
- error->all("Computed temperature for fix temp/rescale/limit/cuda cannot be 0.0");
+ error->all(FLERR,"Computed temperature for fix temp/rescale/limit/cuda cannot be 0.0");
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
// rescale velocity of appropriate atoms if outside window
if (fabs(t_current-t_target) > t_window) {
t_target = t_current - fraction*(t_current-t_target);
double factor = sqrt(t_target/t_current);
double efactor = 0.5 * force->boltz * temperature->dof;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone;
if(atom->rmass) massone = atom->rmass[0];
else massone = atom->mass[0];
double current_limit=sqrt(limit*force->boltz*t_target*temperature->dof/massone/force->mvv2e);
if (which == NOBIAS) {
energy += (t_current-t_target) * efactor;
Cuda_FixTempRescaleLimitCuda_EndOfStep(&cuda->shared_data, groupbit,factor,current_limit);
} else if (which == BIAS) {
energy += (t_current-t_target) * efactor;
if(not temperature->cudable)
{
cuda->cu_x->download();cuda->cu_v->download();
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
double vx = v[i][0] * factor;
double vy = v[i][1] * factor;
double vz = v[i][2] * factor;
v[i][0]=vx>0?MIN(vx,current_limit):MAX(vx,-current_limit);
v[i][1]=vy>0?MIN(vy,current_limit):MAX(vy,-current_limit);
v[i][2]=vz>0?MIN(vz,current_limit):MAX(vz,-current_limit);
temperature->restore_bias(i,v[i]);
}
}
cuda->cu_v->upload();
}
else
{
temperature->remove_bias_all();
Cuda_FixTempRescaleLimitCuda_EndOfStep(&cuda->shared_data, groupbit,factor,current_limit);
temperature->restore_bias_all();
}
}
}
}
/* ---------------------------------------------------------------------- */
int FixTempRescaleLimitCuda::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
if(not temperature->cudable)
- error->warning("Fix temp/rescale/limit/cuda uses non cudable temperature compute");
+ error->warning(FLERR,"Fix temp/rescale/limit/cuda uses non cudable temperature compute");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleLimitCuda::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
double FixTempRescaleLimitCuda::compute_scalar()
{
return energy;
}
diff --git a/src/USER-CUDA/fix_viscous_cuda.cpp b/src/USER-CUDA/fix_viscous_cuda.cpp
index 37509dcb3..e0f32e7b6 100644
--- a/src/USER-CUDA/fix_viscous_cuda.cpp
+++ b/src/USER-CUDA/fix_viscous_cuda.cpp
@@ -1,103 +1,103 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdlib>
#include <cstring>
#include "fix_viscous_cuda.h"
#include "fix_viscous_cuda_cu.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "cuda_modify_flags.h"
#include "cuda.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixViscousCuda::FixViscousCuda(LAMMPS *lmp, int narg, char **arg) :
FixViscous(lmp, narg, arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
cu_gamma=NULL;
}
/* ---------------------------------------------------------------------- */
FixViscousCuda::~FixViscousCuda()
{
delete cu_gamma;
}
/* ---------------------------------------------------------------------- */
int FixViscousCuda::setmask()
{
int mask = 0;
mask |= POST_FORCE_CUDA;
// mask |= POST_FORCE_RESPA;
// mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixViscousCuda::setup(int vflag)
{
if(not cu_gamma)
cu_gamma = new cCudaData<double, F_FLOAT, x> (gamma,atom->ntypes+1);
Cuda_FixViscousCuda_Init(&cuda->shared_data);
cu_gamma->upload();
// if (strcmp(update->integrate_style,"verlet/cuda") == 0)
post_force(vflag);
/* else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}*/
}
/* ---------------------------------------------------------------------- */
void FixViscousCuda::min_setup(int vflag)
{
Cuda_FixViscousCuda_Init(&cuda->shared_data);
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixViscousCuda::post_force(int vflag)
{
// apply drag force to atoms in group
// direction is opposed to velocity vector
// magnitude depends on atom type
Cuda_FixViscousCuda_PostForce(&cuda->shared_data, groupbit,cu_gamma->dev_data());
}
diff --git a/src/USER-CUDA/modify_cuda.cpp b/src/USER-CUDA/modify_cuda.cpp
index 6eb832803..9fd043589 100644
--- a/src/USER-CUDA/modify_cuda.cpp
+++ b/src/USER-CUDA/modify_cuda.cpp
@@ -1,443 +1,440 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include <cstdio>
#include <cstring>
#include "modify_cuda.h"
#include "style_compute.h"
#include "style_fix.h"
#include "atom.h"
#include "comm.h"
#include "fix.h"
#include "compute.h"
#include "group.h"
#include "update.h"
#include "domain.h"
#include "cuda.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 4
// mask settings - same as in fix.cpp
#define INITIAL_INTEGRATE 1
#define POST_INTEGRATE 2
#define PRE_EXCHANGE 4
#define PRE_NEIGHBOR 8
#define PRE_FORCE 16
#define POST_FORCE 32
#define FINAL_INTEGRATE 64
#define END_OF_STEP 128
#define THERMO_ENERGY 256
#define INITIAL_INTEGRATE_RESPA 512
#define POST_INTEGRATE_RESPA 1024
#define PRE_FORCE_RESPA 2048
#define POST_FORCE_RESPA 4096
#define FINAL_INTEGRATE_RESPA 8192
#define MIN_PRE_EXCHANGE 16384
#define MIN_POST_FORCE 32768
#define MIN_ENERGY 65536
#include "cuda_modify_flags.h"
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
ModifyCuda::ModifyCuda(LAMMPS *lmp) : Modify(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
n_initial_integrate_cuda = 0;
n_post_integrate_cuda = 0;
n_pre_exchange = 0;
n_pre_neighbor_cuda = 0;
n_pre_force_cuda = 0;
n_post_force_cuda = 0;
n_final_integrate_cuda = 0;
n_end_of_step_cuda = 0;
n_thermo_energy_cuda = 0;
n_initial_integrate_host = 0;
n_post_integrate_host = 0;
n_pre_exchange = 0;
n_pre_neighbor_host = 0;
n_pre_force_host = 0;
n_post_force_host = 0;
n_final_integrate_host = 0;
n_end_of_step_host = 0;
n_thermo_energy_host = 0;
list_initial_integrate_cuda = NULL;
list_post_integrate_cuda = NULL;
list_pre_exchange_cuda = NULL;
list_pre_neighbor_cuda = NULL;
list_pre_force_cuda = NULL;
list_post_force_cuda = NULL;
list_final_integrate_cuda = NULL;
list_end_of_step_cuda = NULL;
list_thermo_energy_cuda = NULL;
end_of_step_every_cuda = NULL;
}
/* ---------------------------------------------------------------------- */
ModifyCuda::~ModifyCuda()
{
delete [] list_initial_integrate_cuda;
delete [] list_post_integrate_cuda;
delete [] list_pre_exchange_cuda;
delete [] list_pre_neighbor_cuda;
delete [] list_pre_force_cuda;
delete [] list_post_force_cuda;
delete [] list_final_integrate_cuda;
delete [] list_end_of_step_cuda;
delete [] list_thermo_energy_cuda;
delete [] end_of_step_every_cuda;
}
/* ----------------------------------------------------------------------
initialize all fixes and computes
------------------------------------------------------------------------- */
void ModifyCuda::init()
{
int i,j;
// delete storage of restart info since it is not valid after 1st run
restart_deallocate();
// create lists of fixes to call at each stage of run
list_init(INITIAL_INTEGRATE,n_initial_integrate,list_initial_integrate);
list_init(POST_INTEGRATE,n_post_integrate,list_post_integrate);
list_init(PRE_EXCHANGE,n_pre_exchange,list_pre_exchange);
list_init(PRE_NEIGHBOR,n_pre_neighbor,list_pre_neighbor);
list_init(PRE_FORCE,n_pre_force,list_pre_force);
list_init(POST_FORCE,n_post_force,list_post_force);
list_init(FINAL_INTEGRATE,n_final_integrate,list_final_integrate);
list_init_end_of_step(END_OF_STEP,n_end_of_step,list_end_of_step);
list_init_thermo_energy(THERMO_ENERGY,n_thermo_energy,list_thermo_energy);
list_init(INITIAL_INTEGRATE_CUDA, n_initial_integrate_cuda, list_initial_integrate_cuda);
list_init(POST_INTEGRATE_CUDA, n_post_integrate_cuda, list_post_integrate_cuda);
list_init(PRE_EXCHANGE_CUDA, n_pre_exchange_cuda, list_pre_exchange_cuda);
list_init(PRE_NEIGHBOR_CUDA, n_pre_neighbor_cuda, list_pre_neighbor_cuda);
list_init(PRE_FORCE_CUDA, n_pre_force_cuda, list_pre_force_cuda);
list_init(POST_FORCE_CUDA, n_post_force_cuda, list_post_force_cuda);
list_init(FINAL_INTEGRATE_CUDA, n_final_integrate_cuda, list_final_integrate_cuda);
list_init_end_of_step_cuda(END_OF_STEP_CUDA, n_end_of_step_cuda, list_end_of_step_cuda);
list_init_thermo_energy(THERMO_ENERGY_CUDA, n_thermo_energy_cuda, list_thermo_energy_cuda);
n_initial_integrate_host = n_initial_integrate;
n_post_integrate_host = n_post_integrate;
n_pre_exchange_host = n_pre_exchange;
n_pre_neighbor_host = n_pre_neighbor;
n_pre_force_host = n_pre_force;
n_post_force_host = n_post_force;
n_final_integrate_host = n_final_integrate;
n_end_of_step_host = n_end_of_step;
n_thermo_energy_host = n_thermo_energy;
n_initial_integrate = n_initial_integrate_cuda+n_initial_integrate_host;
n_post_integrate = n_post_integrate_cuda+n_post_integrate_host;
n_pre_exchange = n_pre_exchange_cuda+n_pre_exchange_host;
n_pre_neighbor = n_pre_neighbor_cuda+n_pre_neighbor_host;
n_pre_force = n_pre_force_cuda+n_pre_force_host;
n_post_force = n_post_force_cuda+n_post_force_host;
n_final_integrate = n_final_integrate_cuda+n_final_integrate_host;
n_end_of_step = n_end_of_step_cuda+n_end_of_step_host;
n_thermo_energy = n_thermo_energy_cuda+n_thermo_energy_host;
list_init(INITIAL_INTEGRATE_RESPA,
n_initial_integrate_respa,list_initial_integrate_respa);
list_init(POST_INTEGRATE_RESPA,
n_post_integrate_respa,list_post_integrate_respa);
list_init(POST_FORCE_RESPA,
n_post_force_respa,list_post_force_respa);
list_init(PRE_FORCE_RESPA,
n_pre_force_respa,list_pre_force_respa);
list_init(FINAL_INTEGRATE_RESPA,
n_final_integrate_respa,list_final_integrate_respa);
list_init(MIN_PRE_EXCHANGE,n_min_pre_exchange,list_min_pre_exchange);
list_init(MIN_POST_FORCE,n_min_post_force,list_min_post_force);
list_init(MIN_ENERGY,n_min_energy,list_min_energy);
// init each fix
// needs to come before compute init
// this is b/c some computes call fix->dof()
// FixRigid::dof() depends on its own init having been called
for (i = 0; i < nfix; i++) fix[i]->init();
// set global flag if any fix has its restart_pbc flag set
restart_pbc_any = 0;
for (i = 0; i < nfix; i++)
if (fix[i]->restart_pbc) restart_pbc_any = 1;
// create list of computes that store invocation times
list_init_compute();
// init each compute
// set invoked_scalar,vector,etc to -1 to force new run to re-compute them
// add initial timestep to all computes that store invocation times
// since any of them may be invoked by initial thermo
// do not clear out invocation times stored within a compute,
// b/c some may be holdovers from previous run, like for ave fixes
for (i = 0; i < ncompute; i++) {
compute[i]->init();
compute[i]->invoked_scalar = -1;
compute[i]->invoked_vector = -1;
compute[i]->invoked_array = -1;
compute[i]->invoked_peratom = -1;
compute[i]->invoked_local = -1;
}
addstep_compute_all(update->ntimestep);
// warn if any particle is time integrated more than once
int nlocal = atom->nlocal;
int *mask = atom->mask;
int *flag = new int[nlocal];
for (i = 0; i < nlocal; i++) flag[i] = 0;
int groupbit;
for (i = 0; i < nfix; i++) {
if (fix[i]->time_integrate == 0) continue;
groupbit = fix[i]->groupbit;
for (j = 0; j < nlocal; j++)
if (mask[j] & groupbit) flag[j]++;
}
int check = 0;
for (i = 0; i < nlocal; i++)
if (flag[i] > 1) check = 1;
delete [] flag;
int checkall;
MPI_Allreduce(&check,&checkall,1,MPI_INT,MPI_SUM,world);
if (comm->me == 0 && checkall)
- error->warning("One or more atoms are time integrated more than once");
+ error->warning(FLERR,"One or more atoms are time integrated more than once");
}
/* ----------------------------------------------------------------------
1st half of integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyCuda::initial_integrate(int vflag)
{
for(int i = 0; i < n_initial_integrate_cuda; i++)
fix[list_initial_integrate_cuda[i]]->initial_integrate(vflag);
if(n_initial_integrate_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_initial_integrate_host; i++)
fix[list_initial_integrate[i]]->initial_integrate(vflag);
cuda->uploadAll(); cuda->oncpu = false;
}
}
/* ----------------------------------------------------------------------
post_integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyCuda::post_integrate()
{
for(int i = 0; i < n_post_integrate_cuda; i++)
fix[list_post_integrate_cuda[i]]->post_integrate();
if(n_post_integrate_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_post_integrate_host; i++)
fix[list_post_integrate[i]]->post_integrate();
cuda->uploadAll(); cuda->oncpu = false;
}
}
/* ----------------------------------------------------------------------
pre_exchange call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyCuda::pre_exchange()
{
for(int i = 0; i < n_pre_exchange_cuda; i++)
fix[list_pre_exchange_cuda[i]]->pre_exchange();
if(n_pre_exchange_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_pre_exchange_host; i++)
fix[list_pre_exchange[i]]->pre_exchange();
cuda->uploadAll(); cuda->oncpu = false;
}
}
/* ----------------------------------------------------------------------
pre_neighbor call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyCuda::pre_neighbor()
{
for(int i = 0; i < n_pre_neighbor_cuda; i++)
fix[list_pre_neighbor_cuda[i]]->pre_neighbor();
if(n_pre_neighbor_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_pre_neighbor_host; i++)
fix[list_pre_neighbor[i]]->pre_neighbor();
cuda->uploadAll(); cuda->oncpu = false;
}
}
/* ----------------------------------------------------------------------
pre_force call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyCuda::pre_force(int vflag)
{
for(int i = 0; i < n_pre_force_cuda; i++)
fix[list_pre_force_cuda[i]]->pre_force(vflag);
if(n_pre_force_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_pre_force_host; i++)
fix[list_pre_force[i]]->pre_force(vflag);
cuda->uploadAll(); cuda->oncpu = false;
}
}
/* ----------------------------------------------------------------------
post_force call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyCuda::post_force(int vflag)
{
for(int i = 0; i < n_post_force_cuda; i++)
fix[list_post_force_cuda[i]]->post_force(vflag);
if(n_post_force_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_post_force_host; i++)
fix[list_post_force[i]]->post_force(vflag);
cuda->uploadAll(); cuda->oncpu = false;
}
}
/* ----------------------------------------------------------------------
2nd half of integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void ModifyCuda::final_integrate()
{
for (int i = 0; i < n_final_integrate_cuda; i++)
fix[list_final_integrate_cuda[i]]->final_integrate();
if(n_final_integrate_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_final_integrate_host; i++)
fix[list_final_integrate[i]]->final_integrate();
cuda->uploadAll(); cuda->oncpu = false;
}
}
/* ----------------------------------------------------------------------
end-of-timestep call, only for relevant fixes
only call fix->end_of_step() on timesteps that are multiples of nevery
------------------------------------------------------------------------- */
void ModifyCuda::end_of_step()
{
for (int i = 0; i < n_end_of_step_cuda; i++)
if (update->ntimestep % end_of_step_every_cuda[i] == 0)
fix[list_end_of_step_cuda[i]]->end_of_step();
if(n_end_of_step_host != 0)
{
int do_thisstep=0;
for (int i = 0; i < n_end_of_step_host; i++)
if (update->ntimestep % end_of_step_every[i] == 0) do_thisstep=1;
if(do_thisstep)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_end_of_step_host; i++)
if (update->ntimestep % end_of_step_every[i] == 0)
fix[list_end_of_step[i]]->end_of_step();
cuda->uploadAll(); cuda->oncpu = false;
}
}
}
/* ----------------------------------------------------------------------
thermo energy call, only for relevant fixes
called by Thermo class
compute_scalar() is fix call to return energy
------------------------------------------------------------------------- */
double ModifyCuda::thermo_energy()
{
double energy = 0.0;
for (int i = 0; i < n_thermo_energy_cuda; i++)
energy += fix[list_thermo_energy_cuda[i]]->compute_scalar();
if(n_thermo_energy_host != 0)
{
cuda->downloadAll(); cuda->oncpu = true;
for (int i = 0; i < n_thermo_energy_host; i++)
energy += fix[list_thermo_energy[i]]->compute_scalar();
cuda->uploadAll(); cuda->oncpu = false;
}
return energy;
}
void ModifyCuda::list_init_end_of_step_cuda(int mask, int &n, int *&list)
{
delete [] list;
delete [] end_of_step_every_cuda;
n = 0;
for (int i = 0; i < nfix; i++) if (fmask[i] & mask) n++;
list = new int[n];
end_of_step_every_cuda = new int[n];
n = 0;
for (int i = 0; i < nfix; i++)
if (fmask[i] & mask) {
list[n] = i;
end_of_step_every_cuda[n++] = fix[i]->nevery;
}
}
diff --git a/src/USER-CUDA/neigh_full_cuda.cpp b/src/USER-CUDA/neigh_full_cuda.cpp
index 197b62a0a..61c9897f4 100644
--- a/src/USER-CUDA/neigh_full_cuda.cpp
+++ b/src/USER-CUDA/neigh_full_cuda.cpp
@@ -1,315 +1,315 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include "neighbor_cuda.h"
#include "neigh_list.h"
#include "atom.h"
#include "domain.h"
#include "group.h"
#include "error.h"
#include "cuda_neigh_list.h"
#include "cuda.h"
#include "neighbor_cu.h"
#include <cmath>
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
N^2 search for all neighbors
every neighbor pair appears in list of both atoms i and j
------------------------------------------------------------------------- */
void NeighborCuda::full_bin_cuda(NeighList *list)
{
MYDBG(printf(" # CUDA::NeighFullBinCuda ... start\n");)
- if(includegroup) error->warning("Warning using inlcudegroup neighborbuild. This is not yet supported by CUDA neighborbuild styles.\n");
+ if(includegroup) error->warning(FLERR,"Warning using inlcudegroup neighborbuild. This is not yet supported by CUDA neighborbuild styles.\n");
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if(nlocal==0) return;
CudaNeighList* clist=list->cuda_list;
cuda_shared_neighlist* slist=&clist->sneighlist;
if(not clist) cuda->registerNeighborList(list);
clist->build_cuda=true;
if(slist->bin_extraspace<0.09)
{
for(int i=1;i<=atom->ntypes;i++)
for(int j=1;j<=atom->ntypes;j++)
{
if(slist->maxcut<cutneighsq[i][j]) slist->maxcut=cutneighsq[i][j];
}
slist->maxcut=sqrt(slist->maxcut);
}
int bin_dim_tmp[3];
int bin_nmax_tmp;
//printf("Hallo\n");
timespec starttime,endtime;
do
{
do
{
bin_dim_tmp[0]=static_cast <int> ((domain->subhi[0]-domain->sublo[0])/slist->maxcut);
bin_dim_tmp[1]=static_cast <int> ((domain->subhi[1]-domain->sublo[1])/slist->maxcut);
bin_dim_tmp[2]=static_cast <int> ((domain->subhi[2]-domain->sublo[2])/slist->maxcut);
if(bin_dim_tmp[0]==0) bin_dim_tmp[0]+=1;
if(bin_dim_tmp[1]==0) bin_dim_tmp[1]+=1;
if(bin_dim_tmp[2]==0) bin_dim_tmp[2]+=1;
bin_nmax_tmp=static_cast <int> ((1.0+slist->bin_extraspace)*nlocal/(bin_dim_tmp[0]*bin_dim_tmp[1]*bin_dim_tmp[2]));
bin_dim_tmp[0]+=4;
bin_dim_tmp[1]+=4;
bin_dim_tmp[2]+=4;
if(bin_nmax_tmp<32) slist->maxcut*=1.2;
// printf("slist->maxcut: %lf\n", slist->maxcut);
} while(bin_nmax_tmp<32);
if((slist->bin_dim[0]!=bin_dim_tmp[0])||(slist->bin_dim[1]!=bin_dim_tmp[1])||(slist->bin_dim[2]!=bin_dim_tmp[2])||(slist->bin_nmax!=bin_nmax_tmp))
{
if(slist->binned_id!=NULL)
CudaWrapper_FreeCudaData(slist->binned_id,slist->bin_dim[0]*slist->bin_dim[1]*slist->bin_dim[2]*slist->bin_nmax*sizeof(int));
slist->bin_dim[0] = bin_dim_tmp[0];
slist->bin_dim[1] = bin_dim_tmp[1];
slist->bin_dim[2] = bin_dim_tmp[2];
slist->bin_nmax = bin_nmax_tmp;
slist->binned_id=(int*) CudaWrapper_AllocCudaData(slist->bin_dim[0]*slist->bin_dim[1]*slist->bin_dim[2]*slist->bin_nmax*sizeof(int));
//printf("slist->bin: %i %i %i %i \n", bin_dim_tmp[0],bin_dim_tmp[1],bin_dim_tmp[2],bin_nmax_tmp);
}
- //if(list->cuda_list->sneighlist.bin_nmax>512) error->all("To many atoms per bin. Likely cause is very long pair cutoff. This needs major rewrite of code and is not yet scheduled to be done.\n");
+ //if(list->cuda_list->sneighlist.bin_nmax>512) error->all(FLERR,"To many atoms per bin. Likely cause is very long pair cutoff. This needs major rewrite of code and is not yet scheduled to be done.\n");
}while(Cuda_BinAtoms(&cuda->shared_data, &list->cuda_list->sneighlist));
// cuda->cu_debugdata->memset_device(0);
int maxneighbors=slist->maxneighbors;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
if((nex_type!=slist->nex_type)||
(nex_group!=slist->nex_group)||
(nex_mol!=slist->nex_mol))
{
slist->nex_type=nex_type;
slist->nex_group=nex_group;
slist->nex_mol=nex_mol;
//printf("%i %i %i\n",nex_type,nex_group,nex_mol);
if(nex_type)
{
delete clist->cu_ex_type;
clist->cu_ex_type=new cCudaData<int , int , x> (&ex_type[0][0] , & slist->ex_type , (atom->ntypes+1)*(atom->ntypes+1) );
clist->cu_ex_type->upload();
}
//printf("AA %i %i %i\n",nex_type,nex_group,nex_mol);
if(nex_group)
{
delete clist->cu_ex1_bit;
clist->cu_ex1_bit=new cCudaData<int , int , x> (ex1_bit , & slist->ex1_bit , nex_group );
clist->cu_ex1_bit->upload();
//printf("A %i %i %i\n",nex_type,nex_group,nex_mol);
delete clist->cu_ex2_bit;
clist->cu_ex2_bit=new cCudaData<int , int , x> (ex2_bit , & slist->ex2_bit , nex_group );
clist->cu_ex2_bit->upload();
}
//printf("B %i %i %i\n",nex_type,nex_group,nex_mol);
if(nex_mol)
{
delete clist->cu_ex_mol_bit;
clist->cu_ex_mol_bit=new cCudaData<int , int , x> (ex_mol_bit , & slist->ex_mol_bit , nex_mol );
clist->cu_ex_mol_bit->upload();
}
//printf("C %i %i %i\n",nex_type,nex_group,nex_mol);
}
int overflow = 0;
int inum = 0;
int npnt = 0;
do
{
npnt=0;
inum=0;
overflow=0;
clist->grow_device();
slist->cutneighsq=cutneighsq;
slist->maxneighbors=maxneighbors;
slist->inum = list->inum = nlocal;
//list->cuda_list->grow_device();
if(cuda->shared_data.overlap_comm)
{
list->cuda_list->inum_border=0;
list->cuda_list->cu_inum_border->upload();
}
cuda->shared_data.atom.nall=nall;
//Cuda_NeighborReBuildFirstneigh(&cuda->shared_data, &list->cuda_list->sneighlist);
overflow= Cuda_NeighborBuildFullBin(&cuda->shared_data, &list->cuda_list->sneighlist);
/*cuda->cu_debugdata->download();
printf("Debugdata: %i ",cuda->debugdata[0]);
for(int i=0;i<cuda->debugdata[0];i+=3) printf("// %i %i %i",cuda->debugdata[i+1],cuda->debugdata[i+2],cuda->debugdata[i+3]);
printf("\n");*/
//printf("maxneighborsA: %i %i %i %i\n",maxneighbors,pgsize,oneatom,atom->nmax);
if(overflow<0)
{
maxneighbors+=32;
if(-overflow>maxneighbors) maxneighbors=((-overflow+37)/32)*32;
delete list->cuda_list->cu_neighbors;
delete [] list->cuda_list->neighbors;
list->cuda_list->neighbors= new int[slist->maxlocal*maxneighbors];
list->cuda_list->sneighlist.maxneighbors=maxneighbors;
//printf("maxneighborsA1: %i %i %i %i %i\n",maxneighbors,pgsize,oneatom,atom->nmax,slist->maxlocal);
list->cuda_list->cu_neighbors= new cCudaData<int, int, x> (list->cuda_list->neighbors , & list->cuda_list->sneighlist.neighbors, slist->maxlocal*maxneighbors );
//printf("maxneighborsA2: %i %i %i %i\n",maxneighbors,pgsize,oneatom,atom->nmax);
if(cuda->shared_data.overlap_comm)
{
list->cuda_list->sneighlist.maxneighbors=maxneighbors;
list->cuda_list->dev_free();
list->cuda_list->dev_alloc();
}
//printf("maxneighborsA3: %i %i %i %i\n",maxneighbors,pgsize,oneatom,atom->nmax);
}
//printf("maxneighborsB: %i %i %i %i\n",maxneighbors,pgsize,oneatom,atom->nmax);
if(cuda->shared_data.overlap_comm)
{
list->cuda_list->cu_inum_border->download();
list->cuda_list->sneighlist.inum_border2=list->cuda_list->inum_border;
}
}
while(overflow<0);
//cuda->cu_debugdata->download();
// printf("Differences in: %i\n",cuda->debugdata[0]);
// for(int i=0;i<20;i++) printf("%i %i %i %i// ",cuda->debugdata[4*i+1],cuda->debugdata[4*i+2],cuda->debugdata[4*i+3],cuda->debugdata[4*i+4]);
// printf("\n");
/*for(int i=0;i<10;i++)
{
printf("%i %i // ",i,numneigh[i]);
for(int j=0;j<numneigh[i];j++)
printf("%i ",list->cuda_list->neighbors[i+j*nlocal]);
printf("\n");
}*/
/* int count=0;
if(cuda->shared_data.overlap_comm)
{
list->cuda_list->cu_inum_border->download();
list->cuda_list->cu_ilist_border->download();
list->cuda_list->cu_numneigh_border->download();
list->cuda_list->cu_numneigh_inner->download();
list->cuda_list->cu_neighbors->download();
list->cuda_list->cu_neighbors_inner->download();
list->cuda_list->cu_neighbors_border->download();
//list->cuda_list->cu_firstneigh->download();
// list->cuda_list->nl_download();
list->cuda_list->cu_numneigh->download();
int diff=0;
//for(int i=0;i<nlocal;i++)*/
/* int i=123;
{
int k=-1;
//printf("inum_border: %i\n",list->cuda_list->inum_border);
//for(int j=0;j<list->numneigh[i];j++) printf("%i ",list->firstneigh[i][j]);printf("\n");
for(int j=0;j<list->cuda_list->inum_border;j++)
if(list->cuda_list->ilist_border[j]==i) k=j;
int d=numneigh[i]-list->cuda_list->numneigh_inner[i];
if(k>-1) d-=list->cuda_list->numneigh_border[k];
if(d!=0) {printf("Error at %i %i %i %i %i\n",i,k,d,numneigh[i],list->cuda_list->numneigh_inner[i]); diff++;}
if(k>-1 && count<10)
{
printf("Numneighs: %i %i %i Border_i: %i %i\n",numneigh[i],list->cuda_list->numneigh_inner[i],list->cuda_list->numneigh_border[k],k,(int)list->cuda_list->cu_ilist_border->dev_data());
cuda->shared_data.me=k;
for(int j=0;j<numneigh[i];j++)
printf("%i ",list->cuda_list->neighbors[i+j*nlocal]);
printf("\n");
for(int j=0;j<list->cuda_list->numneigh_inner[i];j++)
printf("%i ",list->cuda_list->neighbors_inner[i+j*nlocal]);
printf(" // ");
for(int j=0;j<list->cuda_list->numneigh_border[k];j++)
printf("%i ",list->cuda_list->neighbors_border[k+j*nlocal]);
printf("\n");
count++;
}
}
printf("%i\n",diff);
}*/
list->cuda_list->cu_numneigh->download();
list->cuda_list->cu_ilist->download();
//printf("Done\n");
MYDBG(printf(" # CUDA::NeighFullBinCuda ... end\n");)
}
void NeighborCuda::full_nsq_cuda(NeighList *list)
{
printf("Full_Nsq cuda neighbor list build is not implemented anymore.\n");
return;
/*
MYDBG(printf(" # CUDA::NeighFullNSQCuda ... start\n");)
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if(cuda->cu_xhold) cuda->cu_xhold->upload();
if(not list->cuda_list) cuda->registerNeighborList(list);
list->cuda_list->build_cuda=true;
int maxneighbors=list->cuda_list->sneighlist.maxneighbors;
int neigh_lists_per_page=pgsize/maxneighbors;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int overflow = 0;
int inum = 0;
int npage = 0;
int npnt = 0;
do
{
npage=0;
npnt=0;
inum=0;
overflow=0;
neigh_lists_per_page=pgsize/maxneighbors;
npage=(2*nlocal*maxneighbors-1)/pgsize;
while(npage>list->maxpage) list->add_pages();
pages = list->pages;
npage=0;
list->cuda_list->sneighlist.neigh_lists_per_page=pgsize/maxneighbors;
list->cuda_list->grow_device();
list->cuda_list->sneighlist.cutneighsq=cutneighsq;
list->cuda_list->sneighlist.maxneighbors=maxneighbors;
list->cuda_list->sneighlist.inum = list->inum = nlocal;
cuda->shared_data.atom.nall=nall;
Cuda_NeighborReBuildFirstneigh(&cuda->shared_data, &list->cuda_list->sneighlist);
overflow= not Cuda_NeighborBuildFullNsq(&cuda->shared_data, &list->cuda_list->sneighlist);
if(overflow) maxneighbors+=32;
}
while(overflow);
if(not cudable) list->cuda_list->nl_download();
MYDBG(printf(" # CUDA::NeighFullNSQCuda ... end\n");)
*/
}
diff --git a/src/USER-CUDA/neighbor_cuda.cpp b/src/USER-CUDA/neighbor_cuda.cpp
index e8f317afd..99bf2dce3 100644
--- a/src/USER-CUDA/neighbor_cuda.cpp
+++ b/src/USER-CUDA/neighbor_cuda.cpp
@@ -1,223 +1,220 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "neighbor_cuda.h"
#include "cuda.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
enum{NSQ,BIN,MULTI}; // also in neigh_list.cpp
/* ---------------------------------------------------------------------- */
NeighborCuda::NeighborCuda(LAMMPS *lmp) : Neighbor(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
}
/* ---------------------------------------------------------------------- */
void NeighborCuda::init()
{
cuda->set_neighinit(dist_check,0.25*skin*skin);
cudable = 1;
Neighbor::init();
}
/* ----------------------------------------------------------------------
overwrite either full_nsq or full_bin with CUDA-equivalent methods
any other neighbor build method is unchanged
------------------------------------------------------------------------- */
void NeighborCuda::choose_build(int index, NeighRequest *rq)
{
Neighbor::choose_build(index,rq);
if (rq->full && style == NSQ && rq->ghost == 0 && rq->cudable)
pair_build[index] = (Neighbor::PairPtr) &NeighborCuda::full_nsq_cuda;
else if (rq->full && style == BIN && rq->ghost == 0 && rq->cudable)
pair_build[index] = (Neighbor::PairPtr) &NeighborCuda::full_bin_cuda;
}
/* ---------------------------------------------------------------------- */
int NeighborCuda::check_distance()
{
double delx,dely,delz,rsq;
double delta,deltasq,delta1,delta2;
if (boxcheck) {
if (triclinic == 0) {
delx = bboxlo[0] - boxlo_hold[0];
dely = bboxlo[1] - boxlo_hold[1];
delz = bboxlo[2] - boxlo_hold[2];
delta1 = sqrt(delx*delx + dely*dely + delz*delz);
delx = bboxhi[0] - boxhi_hold[0];
dely = bboxhi[1] - boxhi_hold[1];
delz = bboxhi[2] - boxhi_hold[2];
delta2 = sqrt(delx*delx + dely*dely + delz*delz);
delta = 0.5 * (skin - (delta1+delta2));
deltasq = delta*delta;
} else {
domain->box_corners();
delta1 = delta2 = 0.0;
for (int i = 0; i < 8; i++) {
delx = corners[i][0] - corners_hold[i][0];
dely = corners[i][1] - corners_hold[i][1];
delz = corners[i][2] - corners_hold[i][2];
delta = sqrt(delx*delx + dely*dely + delz*delz);
if (delta > delta1) delta1 = delta;
else if (delta > delta2) delta2 = delta;
}
delta = 0.5 * (skin - (delta1+delta2));
deltasq = delta*delta;
}
} else deltasq = triggersq;
double **x = atom->x;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int flag = 0;
if (not cuda->neighbor_decide_by_integrator) {
cuda->cu_x_download();
for (int i = 0; i < nlocal; i++) {
delx = x[i][0] - xhold[i][0];
dely = x[i][1] - xhold[i][1];
delz = x[i][2] - xhold[i][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq > deltasq) flag = 1;
}
}
else flag = cuda->shared_data.atom.reneigh_flag;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_MAX,world);
if (flagall && ago == MAX(every,delay)) ndanger++;
return flagall;
}
/* ---------------------------------------------------------------------- */
void NeighborCuda::build()
{
int i;
ago = 0;
ncalls++;
// store current atom positions and box size if needed
if (dist_check) {
if (cuda->decide_by_integrator())
cuda->update_xhold(maxhold, &xhold[0][0]);
else {
if (cuda->finished_setup) cuda->cu_x_download();
double **x = atom->x;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
if (nlocal > maxhold) {
maxhold = atom->nmax;
memory->destroy(xhold);
memory->create(xhold,maxhold,3,"neigh:xhold");
}
for (i = 0; i < nlocal; i++) {
xhold[i][0] = x[i][0];
xhold[i][1] = x[i][1];
xhold[i][2] = x[i][2];
}
if (boxcheck) {
if (triclinic == 0) {
boxlo_hold[0] = bboxlo[0];
boxlo_hold[1] = bboxlo[1];
boxlo_hold[2] = bboxlo[2];
boxhi_hold[0] = bboxhi[0];
boxhi_hold[1] = bboxhi[1];
boxhi_hold[2] = bboxhi[2];
} else {
domain->box_corners();
corners = domain->corners;
for (i = 0; i < 8; i++) {
corners_hold[i][0] = corners[i][0];
corners_hold[i][1] = corners[i][1];
corners_hold[i][2] = corners[i][2];
}
}
}
}
}
if (not cudable && cuda->finished_setup && atom->avec->cudable)
cuda->downloadAll();
if (cudable && (not cuda->finished_setup)) {
cuda->checkResize();
cuda->uploadAll();
}
// if any lists store neighbors of ghosts:
// invoke grow() if nlocal+nghost exceeds previous list size
// else only invoke grow() if nlocal exceeds previous list size
// only done for lists with growflag set and which are perpetual
if (anyghostlist && atom->nlocal+atom->nghost > maxatom) {
maxatom = atom->nmax;
for (i = 0; i < nglist; i++) lists[glist[i]]->grow(maxatom);
} else if (atom->nlocal > maxatom) {
maxatom = atom->nmax;
for (i = 0; i < nglist; i++) lists[glist[i]]->grow(maxatom);
}
// extend atom bin list if necessary
if (style != NSQ && atom->nmax > maxbin) {
maxbin = atom->nmax;
memory->destroy(bins);
memory->create(bins,maxbin,"bins");
}
// check that neighbor list with special bond flags will not overflow
if (atom->nlocal+atom->nghost > NEIGHMASK)
- error->one("Too many local+ghost atoms for neighbor list");
+ error->one(FLERR,"Too many local+ghost atoms for neighbor list");
// invoke building of pair and molecular neighbor lists
// only for pairwise lists with buildflag set
for (i = 0; i < nblist; i++)
(this->*pair_build[blist[i]])(lists[blist[i]]);
if (atom->molecular) {
if (force->bond) (this->*bond_build)();
if (force->angle) (this->*angle_build)();
if (force->dihedral) (this->*dihedral_build)();
if (force->improper) (this->*improper_build)();
}
}
diff --git a/src/USER-CUDA/pair_born_coul_long_cuda.cpp b/src/USER-CUDA/pair_born_coul_long_cuda.cpp
index 1d8c65631..f5aaff51f 100644
--- a/src/USER-CUDA/pair_born_coul_long_cuda.cpp
+++ b/src/USER-CUDA/pair_born_coul_long_cuda.cpp
@@ -1,186 +1,183 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_born_coul_long_cuda.h"
#include "pair_born_coul_long_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairBornCoulLongCuda::PairBornCoulLongCuda(LAMMPS *lmp) : PairBornCoulLong(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairBornCoulLongCuda::allocate()
{
if(! allocated) PairBornCoulLong::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.coeff1 = rhoinv;
cuda->shared_data.pair.coeff2 = sigma;
cuda->shared_data.pair.coeff3 = a;
cuda->shared_data.pair.coeff4 = c;
cuda->shared_data.pair.coeff5 = d;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairBornCoulLongCuda::compute(int eflag, int vflag)
{
MYDBG( printf("PairBornCoulLongCuda compute start\n"); fflush(stdout);)
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
#ifdef CUDA_USE_BINNING
Cuda_PairBornCoulLongCuda(& cuda->shared_data, eflag, vflag);
#else
Cuda_PairBornCoulLongCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
#endif
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
MYDBG( printf("PairBornCoulLongCuda compute end\n"); fflush(stdout);)
}
/* ---------------------------------------------------------------------- */
void PairBornCoulLongCuda::settings(int narg, char **arg)
{
PairBornCoulLong::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
}
/* ---------------------------------------------------------------------- */
void PairBornCoulLongCuda::coeff(int narg, char **arg)
{
PairBornCoulLong::coeff(narg, arg);
allocate();
}
void PairBornCoulLongCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style born/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style born/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
- if (strstr(update->integrate_style,"respa")) error->all("Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
+ if (strstr(update->integrate_style,"respa")) error->all(FLERR,"Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
cuda->shared_data.pair.g_ewald=g_ewald;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
- if(ncoultablebits) error->warning("# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
+ if(ncoultablebits) error->warning(FLERR,"# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
}
void PairBornCoulLongCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairBornCoulLongCuda::init_list\n");)
PairBornCoulLong::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairBornCoulLongCuda::init_list end\n");)
}
void PairBornCoulLongCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairBornCoulLong::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_buck_coul_cut_cuda.cpp b/src/USER-CUDA/pair_buck_coul_cut_cuda.cpp
index 4416a3d19..bc0854618 100644
--- a/src/USER-CUDA/pair_buck_coul_cut_cuda.cpp
+++ b/src/USER-CUDA/pair_buck_coul_cut_cuda.cpp
@@ -1,173 +1,170 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_buck_coul_cut_cuda.h"
#include "pair_buck_coul_cut_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairBuckCoulCutCuda::PairBuckCoulCutCuda(LAMMPS *lmp) : PairBuckCoulCut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairBuckCoulCutCuda::allocate()
{
if(! allocated) PairBuckCoulCut::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut_coul = cut_coul;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.coeff1 = rhoinv;
cuda->shared_data.pair.coeff2 = buck1;
cuda->shared_data.pair.coeff3 = buck2;
cuda->shared_data.pair.coeff4 = a;
cuda->shared_data.pair.coeff5 = c;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulCutCuda::compute(int eflag, int vflag)
{
MYDBG( printf("PairBuckCoulCutCuda compute start\n"); fflush(stdout);)
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairBuckCoulCutCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
MYDBG( printf("PairBuckCoulCutCuda compute end\n"); fflush(stdout);)
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulCutCuda::settings(int narg, char **arg)
{
PairBuckCoulCut::settings(narg, arg);
cuda->shared_data.pair.cut_coul_global = (F_FLOAT) cut_coul_global;
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulCutCuda::coeff(int narg, char **arg)
{
PairBuckCoulCut::coeff(narg, arg);
allocate();
}
void PairBuckCoulCutCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style buck/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style buck/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
- if (strstr(update->integrate_style,"respa")) error->all("Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
+ if (strstr(update->integrate_style,"respa")) error->all(FLERR,"Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
cuda->shared_data.pair.cut_coulsq_global=cut_coul_global * cut_coul_global;
- if(ncoultablebits) error->warning("# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
+ if(ncoultablebits) error->warning(FLERR,"# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
}
void PairBuckCoulCutCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairBuckCoulCutCuda::init_list\n");)
PairBuckCoulCut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairBuckCoulCutCuda::init_list end\n");)
}
void PairBuckCoulCutCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairBuckCoulCut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_buck_coul_long_cuda.cpp b/src/USER-CUDA/pair_buck_coul_long_cuda.cpp
index 9044d2128..4cbd304e0 100644
--- a/src/USER-CUDA/pair_buck_coul_long_cuda.cpp
+++ b/src/USER-CUDA/pair_buck_coul_long_cuda.cpp
@@ -1,184 +1,181 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_buck_coul_long_cuda.h"
#include "pair_buck_coul_long_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairBuckCoulLongCuda::PairBuckCoulLongCuda(LAMMPS *lmp) : PairBuckCoulLong(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairBuckCoulLongCuda::allocate()
{
if(! allocated) PairBuckCoulLong::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.coeff1 = rhoinv;
cuda->shared_data.pair.coeff2 = buck1;
cuda->shared_data.pair.coeff3 = buck2;
cuda->shared_data.pair.coeff4 = a;
cuda->shared_data.pair.coeff5 = c;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulLongCuda::compute(int eflag, int vflag)
{
MYDBG( printf("PairBuckCoulLongCuda compute start\n"); fflush(stdout);)
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairBuckCoulLongCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
MYDBG( printf("PairBuckCoulLongCuda compute end\n"); fflush(stdout);)
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulLongCuda::settings(int narg, char **arg)
{
PairBuckCoulLong::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulLongCuda::coeff(int narg, char **arg)
{
PairBuckCoulLong::coeff(narg, arg);
allocate();
}
void PairBuckCoulLongCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style buck/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style buck/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
- if (strstr(update->integrate_style,"respa")) error->all("Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
+ if (strstr(update->integrate_style,"respa")) error->all(FLERR,"Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
cuda->shared_data.pair.g_ewald=g_ewald;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
- if(ncoultablebits) error->warning("# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
+ if(ncoultablebits) error->warning(FLERR,"# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
}
void PairBuckCoulLongCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairBuckCoulLongCuda::init_list\n");)
PairBuckCoulLong::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairBuckCoulLongCuda::init_list end\n");)
}
void PairBuckCoulLongCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairBuckCoulLong::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_buck_cuda.cpp b/src/USER-CUDA/pair_buck_cuda.cpp
index e90678339..a537e600e 100644
--- a/src/USER-CUDA/pair_buck_cuda.cpp
+++ b/src/USER-CUDA/pair_buck_cuda.cpp
@@ -1,169 +1,166 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_buck_cuda.h"
#include "pair_buck_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairBuckCuda::PairBuckCuda(LAMMPS *lmp) : PairBuck(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairBuckCuda::allocate()
{
if(! allocated) PairBuck::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.coeff1 = rhoinv;
cuda->shared_data.pair.coeff2 = buck1;
cuda->shared_data.pair.coeff3 = buck2;
cuda->shared_data.pair.coeff4 = a;
cuda->shared_data.pair.coeff5 = c;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
}
}
/* ---------------------------------------------------------------------- */
void PairBuckCuda::compute(int eflag, int vflag)
{
MYDBG( printf("PairBuckCuda compute start\n"); fflush(stdout);)
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairBuckCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
MYDBG( printf("PairBuckCuda compute end\n"); fflush(stdout);)
}
/* ---------------------------------------------------------------------- */
void PairBuckCuda::settings(int narg, char **arg)
{
PairBuck::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
}
/* ---------------------------------------------------------------------- */
void PairBuckCuda::coeff(int narg, char **arg)
{
PairBuck::coeff(narg, arg);
allocate();
}
void PairBuckCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style buck/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style buck/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
- if (strstr(update->integrate_style,"respa")) error->all("Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
+ if (strstr(update->integrate_style,"respa")) error->all(FLERR,"Integrate Style Respa is not supported by pair style buck/coul/long/cuda");
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
- if(ncoultablebits) error->warning("# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
+ if(ncoultablebits) error->warning(FLERR,"# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
}
void PairBuckCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairBuckCuda::init_list\n");)
PairBuck::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairBuckCuda::init_list end\n");)
}
void PairBuckCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairBuck::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_cg_cmm_coul_cut_cuda.cpp b/src/USER-CUDA/pair_cg_cmm_coul_cut_cuda.cpp
index 1c82a8d79..5334e91f9 100644
--- a/src/USER-CUDA/pair_cg_cmm_coul_cut_cuda.cpp
+++ b/src/USER-CUDA/pair_cg_cmm_coul_cut_cuda.cpp
@@ -1,204 +1,201 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_cg_cmm_coul_cut_cuda.h"
#include "pair_cg_cmm_coul_cut_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairCGCMMCoulCutCuda::PairCGCMMCoulCutCuda(LAMMPS *lmp) : PairCGCMMCoulCut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cg_type_double = NULL;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairCGCMMCoulCutCuda::allocate()
{
if(! allocated) PairCGCMMCoulCut::allocate();
int n = atom->ntypes;
if(! allocated2)
{
allocated2 = true;
memory->create(cg_type_double,n+1,n+1,"paircg:cgtypedouble");
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.cut_coul= cut_coul;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = cg_type_double;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
cg_type_double[i][j] = cg_type[i][j];
cg_type_double[j][i] = cg_type[i][j];
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCutCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairCGCMMCoulCutCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCutCuda::settings(int narg, char **arg)
{
PairCGCMMCoulCut::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
cuda->shared_data.pair.cut_coul_global = (F_FLOAT) cut_coul_global;
cuda->shared_data.pair.kappa = (F_FLOAT) kappa;
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulCutCuda::coeff(int narg, char **arg)
{
PairCGCMMCoulCut::coeff(narg, arg);
allocate();
}
void PairCGCMMCoulCutCuda::init_style()
{
MYDBG(printf("# CUDA PairCGCMMCoulCutCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
cut_respa=NULL;
- if (force->newton) error->warning("Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
+ if (force->newton) error->warning(FLERR,"Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
MYDBG(printf("# CUDA PairCGCMMCoulCutCuda::init_style end\n"); )
}
void PairCGCMMCoulCutCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairCGCMMCoulCutCuda::init_list\n");)
PairCGCMMCoulCut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairCGCMMCoulCutCuda::init_list end\n");)
}
void PairCGCMMCoulCutCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairCGCMMCoulCut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_cg_cmm_coul_debye_cuda.cpp b/src/USER-CUDA/pair_cg_cmm_coul_debye_cuda.cpp
index 280ec2638..862d8e56b 100644
--- a/src/USER-CUDA/pair_cg_cmm_coul_debye_cuda.cpp
+++ b/src/USER-CUDA/pair_cg_cmm_coul_debye_cuda.cpp
@@ -1,204 +1,201 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_cg_cmm_coul_debye_cuda.h"
#include "pair_cg_cmm_coul_debye_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairCGCMMCoulDebyeCuda::PairCGCMMCoulDebyeCuda(LAMMPS *lmp) : PairCGCMMCoulCut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cg_type_double = NULL;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairCGCMMCoulDebyeCuda::allocate()
{
if(! allocated) PairCGCMMCoulCut::allocate();
int n = atom->ntypes;
if(! allocated2)
{
allocated2 = true;
memory->create(cg_type_double,n+1,n+1,"paircg:cgtypedouble");
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.cut_coul= cut_coul;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = cg_type_double;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
cg_type_double[i][j] = cg_type[i][j];
cg_type_double[j][i] = cg_type[i][j];
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulDebyeCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairCGCMMCoulDebyeCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulDebyeCuda::settings(int narg, char **arg)
{
PairCGCMMCoulCut::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
cuda->shared_data.pair.cut_coul_global = (F_FLOAT) cut_coul_global;
cuda->shared_data.pair.kappa = (F_FLOAT) kappa;
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulDebyeCuda::coeff(int narg, char **arg)
{
PairCGCMMCoulCut::coeff(narg, arg);
allocate();
}
void PairCGCMMCoulDebyeCuda::init_style()
{
MYDBG(printf("# CUDA PairCGCMMCoulDebyeCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
cut_respa=NULL;
- if (force->newton) error->warning("Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
+ if (force->newton) error->warning(FLERR,"Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
MYDBG(printf("# CUDA PairCGCMMCoulDebyeCuda::init_style end\n"); )
}
void PairCGCMMCoulDebyeCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairCGCMMCoulDebyeCuda::init_list\n");)
PairCGCMMCoulCut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairCGCMMCoulDebyeCuda::init_list end\n");)
}
void PairCGCMMCoulDebyeCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairCGCMMCoulCut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_cg_cmm_coul_long_cuda.cpp b/src/USER-CUDA/pair_cg_cmm_coul_long_cuda.cpp
index 359769169..c2d4ede4b 100644
--- a/src/USER-CUDA/pair_cg_cmm_coul_long_cuda.cpp
+++ b/src/USER-CUDA/pair_cg_cmm_coul_long_cuda.cpp
@@ -1,206 +1,203 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_cg_cmm_coul_long_cuda.h"
#include "pair_cg_cmm_coul_long_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairCGCMMCoulLongCuda::PairCGCMMCoulLongCuda(LAMMPS *lmp) : PairCGCMMCoulLong(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cg_type_double = NULL;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairCGCMMCoulLongCuda::allocate()
{
if(! allocated) PairCGCMMCoulLong::allocate();
int n = atom->ntypes;
if(! allocated2)
{
allocated2 = true;
memory->create(cg_type_double,n+1,n+1,"paircg:cgtypedouble");
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.cut_coul= cut_coul;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = cg_type_double;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
cg_type_double[i][j] = cg_type[i][j];
cg_type_double[j][i] = cg_type[i][j];
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLongCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairCGCMMCoulLongCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLongCuda::settings(int narg, char **arg)
{
PairCGCMMCoulLong::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
cuda->shared_data.pair.cut_coul_global = (F_FLOAT) cut_coul_global;
cuda->shared_data.pair.kappa = (F_FLOAT) kappa;
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCoulLongCuda::coeff(int narg, char **arg)
{
PairCGCMMCoulLong::coeff(narg, arg);
allocate();
}
void PairCGCMMCoulLongCuda::init_style()
{
MYDBG(printf("# CUDA PairCGCMMCoulLongCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
g_ewald = force->kspace->g_ewald;
cuda->shared_data.pair.g_ewald=g_ewald;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
cut_respa=NULL;
- if (force->newton) error->warning("Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
+ if (force->newton) error->warning(FLERR,"Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
MYDBG(printf("# CUDA PairCGCMMCoulLongCuda::init_style end\n"); )
}
void PairCGCMMCoulLongCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairCGCMMCoulLongCuda::init_list\n");)
PairCGCMMCoulLong::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairCGCMMCoulLongCuda::init_list end\n");)
}
void PairCGCMMCoulLongCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairCGCMMCoulLong::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_cg_cmm_cuda.cpp b/src/USER-CUDA/pair_cg_cmm_cuda.cpp
index 5471d95f2..cc3e5e585 100644
--- a/src/USER-CUDA/pair_cg_cmm_cuda.cpp
+++ b/src/USER-CUDA/pair_cg_cmm_cuda.cpp
@@ -1,201 +1,198 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_cg_cmm_cuda.h"
#include "pair_cg_cmm_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairCGCMMCuda::PairCGCMMCuda(LAMMPS *lmp) : PairCGCMM(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cg_type_double = NULL;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairCGCMMCuda::allocate()
{
if(! allocated) PairCGCMM::allocate();
int n = atom->ntypes;
if(! allocated2)
{
allocated2 = true;
memory->create(cg_type_double,n+1,n+1,"paircg:cgtypedouble");
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = cg_type_double;
/*cu_lj1_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj1, &cuda->shared_data.pair.coeff1_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj2_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj2, &cuda->shared_data.pair.coeff2_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj3_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj3, &cuda->shared_data.pair.coeff3_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj4_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj4, &cuda->shared_data.pair.coeff4_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_cg_type_double_gm = new cCudaData<double, F_FLOAT, x> ((double*)cg_type_double, &cuda->shared_data.pair.coeff5_gm, (atom->ntypes+1)*(atom->ntypes+1));*/
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
}
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
cg_type_double[i][j] = cg_type[i][j];
cg_type_double[j][i] = cg_type[i][j];
}
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairCGCMMCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCuda::settings(int narg, char **arg)
{
PairCGCMM::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
}
/* ---------------------------------------------------------------------- */
void PairCGCMMCuda::coeff(int narg, char **arg)
{
PairCGCMM::coeff(narg, arg);
allocate();
}
void PairCGCMMCuda::init_style()
{
MYDBG(printf("# CUDA PairCGCMMCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
cut_respa=NULL;
MYDBG(printf("# CUDA PairCGCMMCuda::init_style end\n"); )
}
void PairCGCMMCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairCGCMMCuda::init_list\n");)
PairCGCMM::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairCGCMMCuda::init_list end\n");)
}
void PairCGCMMCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairCGCMM::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_eam_alloy_cuda.cpp b/src/USER-CUDA/pair_eam_alloy_cuda.cpp
index eb70fcc12..fd78c5713 100644
--- a/src/USER-CUDA/pair_eam_alloy_cuda.cpp
+++ b/src/USER-CUDA/pair_eam_alloy_cuda.cpp
@@ -1,326 +1,326 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Stephen Foiles (SNL), Murray Daw (SNL)
------------------------------------------------------------------------- */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_eam_alloy_cuda.h"
#include "atom.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairEAMAlloyCuda::PairEAMAlloyCuda(LAMMPS *lmp) : PairEAMCuda(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
one_coeff = 1;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
read DYNAMO setfl file
------------------------------------------------------------------------- */
void PairEAMAlloyCuda::coeff(int narg, char **arg)
{
int i,j;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read EAM setfl file
if (setfl) {
for (i = 0; i < setfl->nelements; i++) delete [] setfl->elements[i];
delete [] setfl->elements;
delete [] setfl->mass;
memory->destroy(setfl->frho);
memory->destroy(setfl->rhor);
memory->destroy(setfl->z2r);
delete setfl;
}
setfl = new Setfl();
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
for (i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
continue;
}
for (j = 0; j < setfl->nelements; j++)
if (strcmp(arg[i],setfl->elements[j]) == 0) break;
if (j < setfl->nelements) map[i-2] = j;
- else error->all("No matching element in EAM potential file");
+ else error->all(FLERR,"No matching element in EAM potential file");
}
// clear setflag since coeff() called once with I,J = * *
int n = atom->ntypes;
for (i = 1; i <= n; i++)
for (j = i; j <= n; j++)
setflag[i][j] = 0;
// set setflag i,j for type pairs where both are mapped to elements
// set mass of atom type if i = j
int count = 0;
for (i = 1; i <= n; i++) {
for (j = i; j <= n; j++) {
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
if (i == j) atom->set_mass(i,setfl->mass[map[i]]);
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
read a multi-element DYNAMO setfl file
------------------------------------------------------------------------- */
void PairEAMAlloyCuda::read_file(char *filename)
{
Setfl *file = setfl;
// open potential file
int me = comm->me;
FILE *fptr;
char line[MAXLINE];
if (me == 0) {
fptr = fopen(filename,"r");
if (fptr == NULL) {
char str[128];
sprintf(str,"Cannot open EAM potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read and broadcast header
// extract element names from nelements line
int n;
if (me == 0) {
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
n = strlen(line) + 1;
}
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
sscanf(line,"%d",&file->nelements);
int nwords = atom->count_words(line);
if (nwords != file->nelements + 1)
- error->all("Incorrect element names in EAM potential file");
+ error->all(FLERR,"Incorrect element names in EAM potential file");
char **words = new char*[file->nelements+1];
nwords = 0;
char *first = strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
file->elements = new char*[file->nelements];
for (int i = 0; i < file->nelements; i++) {
n = strlen(words[i]) + 1;
file->elements[i] = new char[n];
strcpy(file->elements[i],words[i]);
}
delete [] words;
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg %d %lg %lg",
&file->nrho,&file->drho,&file->nr,&file->dr,&file->cut);
}
MPI_Bcast(&file->nrho,1,MPI_INT,0,world);
MPI_Bcast(&file->drho,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->nr,1,MPI_INT,0,world);
MPI_Bcast(&file->dr,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->cut,1,MPI_DOUBLE,0,world);
file->mass = new double[file->nelements];
memory->create(file->frho,file->nelements,file->nrho+1,"pair:frho");
memory->create(file->rhor,file->nelements,file->nr+1,"pair:rhor");
memory->create(file->z2r,file->nelements,file->nelements,file->nr+1,
"pair:z2r");
int i,j,tmp;
for (i = 0; i < file->nelements; i++) {
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg",&tmp,&file->mass[i]);
}
MPI_Bcast(&file->mass[i],1,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nrho,&file->frho[i][1]);
MPI_Bcast(&file->frho[i][1],file->nrho,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nr,&file->rhor[i][1]);
MPI_Bcast(&file->rhor[i][1],file->nr,MPI_DOUBLE,0,world);
}
for (i = 0; i < file->nelements; i++)
for (j = 0; j <= i; j++) {
if (me == 0) grab(fptr,file->nr,&file->z2r[i][j][1]);
MPI_Bcast(&file->z2r[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
// close the potential file
if (me == 0) fclose(fptr);
}
/* ----------------------------------------------------------------------
copy read-in setfl potential to standard array format
------------------------------------------------------------------------- */
void PairEAMAlloyCuda::file2array()
{
int i,j,m,n;
int ntypes = atom->ntypes;
// set function params directly from setfl file
nrho = setfl->nrho;
nr = setfl->nr;
drho = setfl->drho;
dr = setfl->dr;
// ------------------------------------------------------------------
// setup frho arrays
// ------------------------------------------------------------------
// allocate frho arrays
// nfrho = # of setfl elements + 1 for zero array
nfrho = setfl->nelements + 1;
memory->destroy(frho);
memory->create(frho,nfrho,nrho+1,"pair:frho");
// copy each element's frho to global frho
for (i = 0; i < setfl->nelements; i++)
for (m = 1; m <= nrho; m++) frho[i][m] = setfl->frho[i][m];
// add extra frho of zeroes for non-EAM types to point to (pair hybrid)
// this is necessary b/c fp is still computed for non-EAM atoms
for (m = 1; m <= nrho; m++) frho[nfrho-1][m] = 0.0;
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
// if atom type doesn't point to element (non-EAM atom in pair hybrid)
// then map it to last frho array of zeroes
for (i = 1; i <= ntypes; i++)
if (map[i] >= 0) type2frho[i] = map[i];
else type2frho[i] = nfrho-1;
// ------------------------------------------------------------------
// setup rhor arrays
// ------------------------------------------------------------------
// allocate rhor arrays
// nrhor = # of setfl elements
nrhor = setfl->nelements;
memory->destroy(rhor);
memory->create(rhor,nrhor,nr+1,"pair:rhor");
// copy each element's rhor to global rhor
for (i = 0; i < setfl->nelements; i++)
for (m = 1; m <= nr; m++) rhor[i][m] = setfl->rhor[i][m];
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
// for setfl files, I,J mapping only depends on I
// OK if map = -1 (non-EAM atom in pair hybrid) b/c type2rhor not used
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++)
type2rhor[i][j] = map[i];
// ------------------------------------------------------------------
// setup z2r arrays
// ------------------------------------------------------------------
// allocate z2r arrays
// nz2r = N*(N+1)/2 where N = # of setfl elements
nz2r = setfl->nelements * (setfl->nelements+1) / 2;
memory->destroy(z2r);
memory->create(z2r,nz2r,nr+1,"pair:z2r");
// copy each element pair z2r to global z2r, only for I >= J
n = 0;
for (i = 0; i < setfl->nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) z2r[n][m] = setfl->z2r[i][j][m];
n++;
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// if map = -1 (non-EAM atom in pair hybrid):
// type2z2r is not used by non-opt
// but set type2z2r to 0 since accessed by opt
int irow,icol;
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2z2r[i][j] = 0;
continue;
}
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2z2r[i][j] = n;
}
}
}
diff --git a/src/USER-CUDA/pair_eam_cuda.cpp b/src/USER-CUDA/pair_eam_cuda.cpp
index 6d012a80a..1c9c710a9 100644
--- a/src/USER-CUDA/pair_eam_cuda.cpp
+++ b/src/USER-CUDA/pair_eam_cuda.cpp
@@ -1,251 +1,248 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_eam_cuda.h"
#include "pair_eam_cuda_cu.h"
#include "pair_virial_compute_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairEAMCuda::PairEAMCuda(LAMMPS *lmp) : PairEAM(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.override_block_per_atom = 0;
cuda->setSystemParams();
cu_rho=NULL;
cu_fp=NULL;
cu_frho_spline = NULL;
cu_z2r_spline = NULL;
cu_rhor_spline = NULL;
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairEAMCuda::allocate()
{
if(! allocated) PairEAM::allocate();
cuda->shared_data.pair.cutsq = cutsq;
cuda->shared_data.pair.cut_global = (F_FLOAT) cutforcesq;
}
/* ---------------------------------------------------------------------- */
void PairEAMCuda::compute(int eflag, int vflag)
{
cuda->shared_data.pair.cut_global = (F_FLOAT) cutforcesq;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->shared_data.pair.collect_forces_later = 0;
if (atom->nmax > nmax) {
memory->destroy(rho);
memory->destroy(fp);
nmax = atom->nmax;
memory->create(rho,nmax,"pair:rho");
memory->create(fp,nmax,"pair:fp");
delete cu_rho;
delete cu_fp;
cu_rho = new cCudaData<double, F_FLOAT, x> (rho, atom->nmax);
cu_fp = new cCudaData<double, F_FLOAT, x> (fp, atom->nmax);
Cuda_PairEAMCuda_Init(&cuda->shared_data,rdr,rdrho,nfrho,nrhor,nr,nrho,nz2r,
cu_frho_spline->dev_data(),cu_rhor_spline->dev_data(),cu_z2r_spline->dev_data(),
cu_rho->dev_data(),cu_fp->dev_data(),type2frho,type2z2r,type2rhor);
}
if(eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairEAM1Cuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag,eflag_atom,vflag_atom);
comm->forward_comm_pair(this);
Cuda_PairEAM2Cuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag,eflag_atom,vflag_atom);
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
/* ---------------------------------------------------------------------- */
void PairEAMCuda::settings(int narg, char **arg)
{
PairEAM::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cutforcesq;
}
/* ---------------------------------------------------------------------- */
void PairEAMCuda::coeff(int narg, char **arg)
{
PairEAM::coeff(narg, arg);
allocate();
}
void PairEAMCuda::init_style()
{
MYDBG(printf("# CUDA PairEAMCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
file2array();
array2spline();
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
delete cu_rhor_spline;
delete cu_z2r_spline;
delete cu_frho_spline;
cu_rhor_spline = new cCudaData<double, F_FLOAT, xyz>((double*)rhor_spline,nrhor,nr+1,EAM_COEFF_LENGTH);
cu_z2r_spline = new cCudaData<double, F_FLOAT, xyz>((double*)z2r_spline,nz2r,nr+1,EAM_COEFF_LENGTH);
cu_frho_spline = new cCudaData<double, F_FLOAT, xyz>((double*)frho_spline,nfrho,nrho+1,EAM_COEFF_LENGTH);
cu_rhor_spline->upload();
cu_z2r_spline->upload();
cu_frho_spline->upload();
MYDBG(printf("# CUDA PairEAMCuda::init_style end\n"); )
}
void PairEAMCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairEAMCuda::init_list\n");)
PairEAM::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairEAMCuda::init_list end\n");)
}
void PairEAMCuda::array2spline()
{
rdr = 1.0/dr;
rdrho = 1.0/drho;
memory->destroy(frho_spline);
memory->destroy(rhor_spline);
memory->destroy(z2r_spline);
memory->create(frho_spline,nfrho,nrho+1,7,"pair:frho");
memory->create(rhor_spline,nrhor,nr+1,7,"pair:rhor");
memory->create(z2r_spline,nz2r,nr+1,7,"pair:z2r");
for (int i = 0; i < nfrho; i++){
interpolate(nrho,drho,frho[i],frho_spline[i]);
for(int j=0;j<nrho+1;j++)
frho_spline[i][j][7]=frho_spline[i][j][3];
}
for (int i = 0; i < nrhor; i++){
interpolate(nr,dr,rhor[i],rhor_spline[i]);
for(int j=0;j<nr+1;j++)
rhor_spline[i][j][7]=rhor_spline[i][j][3];
}
for (int i = 0; i < nz2r; i++){
interpolate(nr,dr,z2r[i],z2r_spline[i]);
for(int j=0;j<nr+1;j++)
z2r_spline[i][j][7]=z2r_spline[i][j][3];
}
}
/* ---------------------------------------------------------------------- */
int PairEAMCuda::pack_comm(int n, int *iswap, double *buf, int pbc_flag, int *pbc)
{
Cuda_PairEAMCuda_PackComm(&cuda->shared_data,n,*iswap,buf);
if(sizeof(F_FLOAT)<sizeof(double)) return 1;
else return 1;
}
/* ---------------------------------------------------------------------- */
void PairEAMCuda::unpack_comm(int n, int first, double *buf)
{
Cuda_PairEAMCuda_UnpackComm(&cuda->shared_data,n,first,buf,cu_fp->dev_data());
}
void PairEAMCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairEAM::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_eam_fs_cuda.cpp b/src/USER-CUDA/pair_eam_fs_cuda.cpp
index c7dd6e4ee..13efb5a4f 100644
--- a/src/USER-CUDA/pair_eam_fs_cuda.cpp
+++ b/src/USER-CUDA/pair_eam_fs_cuda.cpp
@@ -1,335 +1,335 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Tim Lau (MIT)
------------------------------------------------------------------------- */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_eam_fs_cuda.h"
#include "atom.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairEAMFSCuda::PairEAMFSCuda(LAMMPS *lmp) : PairEAMCuda(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
one_coeff = 1;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
read EAM Finnis-Sinclair file
------------------------------------------------------------------------- */
void PairEAMFSCuda::coeff(int narg, char **arg)
{
int i,j;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read EAM Finnis-Sinclair file
if (fs) {
for (i = 0; i < fs->nelements; i++) delete [] fs->elements[i];
delete [] fs->elements;
delete [] fs->mass;
memory->destroy(fs->frho);
memory->destroy(fs->rhor);
memory->destroy(fs->z2r);
delete fs;
}
fs = new Fs();
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
for (i = 3; i < narg; i++) {
if (strcmp(arg[i],"NULL") == 0) {
map[i-2] = -1;
continue;
}
for (j = 0; j < fs->nelements; j++)
if (strcmp(arg[i],fs->elements[j]) == 0) break;
if (j < fs->nelements) map[i-2] = j;
- else error->all("No matching element in EAM potential file");
+ else error->all(FLERR,"No matching element in EAM potential file");
}
// clear setflag since coeff() called once with I,J = * *
int n = atom->ntypes;
for (i = 1; i <= n; i++)
for (j = i; j <= n; j++)
setflag[i][j] = 0;
// set setflag i,j for type pairs where both are mapped to elements
// set mass of atom type if i = j
int count = 0;
for (i = 1; i <= n; i++) {
for (j = i; j <= n; j++) {
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
if (i == j) atom->set_mass(i,fs->mass[map[i]]);
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
read a multi-element DYNAMO setfl file
------------------------------------------------------------------------- */
void PairEAMFSCuda::read_file(char *filename)
{
Fs *file = fs;
// open potential file
int me = comm->me;
FILE *fptr;
char line[MAXLINE];
if (me == 0) {
fptr = fopen(filename,"r");
if (fptr == NULL) {
char str[128];
sprintf(str,"Cannot open EAM potential file %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read and broadcast header
// extract element names from nelements line
int n;
if (me == 0) {
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
fgets(line,MAXLINE,fptr);
n = strlen(line) + 1;
}
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
sscanf(line,"%d",&file->nelements);
int nwords = atom->count_words(line);
if (nwords != file->nelements + 1)
- error->all("Incorrect element names in EAM potential file");
+ error->all(FLERR,"Incorrect element names in EAM potential file");
char **words = new char*[file->nelements+1];
nwords = 0;
char *first = strtok(line," \t\n\r\f");
while (words[nwords++] = strtok(NULL," \t\n\r\f")) continue;
file->elements = new char*[file->nelements];
for (int i = 0; i < file->nelements; i++) {
n = strlen(words[i]) + 1;
file->elements[i] = new char[n];
strcpy(file->elements[i],words[i]);
}
delete [] words;
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg %d %lg %lg",
&file->nrho,&file->drho,&file->nr,&file->dr,&file->cut);
}
MPI_Bcast(&file->nrho,1,MPI_INT,0,world);
MPI_Bcast(&file->drho,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->nr,1,MPI_INT,0,world);
MPI_Bcast(&file->dr,1,MPI_DOUBLE,0,world);
MPI_Bcast(&file->cut,1,MPI_DOUBLE,0,world);
file->mass = new double[file->nelements];
memory->create(file->frho,file->nelements,file->nrho+1,
"pair:frho");
memory->create(file->rhor,file->nelements,file->nelements,
file->nr+1,"pair:rhor");
memory->create(file->z2r,file->nelements,file->nelements,
file->nr+1,"pair:z2r");
int i,j,tmp;
for (i = 0; i < file->nelements; i++) {
if (me == 0) {
fgets(line,MAXLINE,fptr);
sscanf(line,"%d %lg",&tmp,&file->mass[i]);
}
MPI_Bcast(&file->mass[i],1,MPI_DOUBLE,0,world);
if (me == 0) grab(fptr,file->nrho,&file->frho[i][1]);
MPI_Bcast(&file->frho[i][1],file->nrho,MPI_DOUBLE,0,world);
for (j = 0; j < file->nelements; j++) {
if (me == 0) grab(fptr,file->nr,&file->rhor[i][j][1]);
MPI_Bcast(&file->rhor[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
}
for (i = 0; i < file->nelements; i++)
for (j = 0; j <= i; j++) {
if (me == 0) grab(fptr,file->nr,&file->z2r[i][j][1]);
MPI_Bcast(&file->z2r[i][j][1],file->nr,MPI_DOUBLE,0,world);
}
// close the potential file
if (me == 0) fclose(fptr);
}
/* ----------------------------------------------------------------------
copy read-in setfl potential to standard array format
------------------------------------------------------------------------- */
void PairEAMFSCuda::file2array()
{
int i,j,m,n;
int ntypes = atom->ntypes;
// set function params directly from fs file
nrho = fs->nrho;
nr = fs->nr;
drho = fs->drho;
dr = fs->dr;
// ------------------------------------------------------------------
// setup frho arrays
// ------------------------------------------------------------------
// allocate frho arrays
// nfrho = # of fs elements + 1 for zero array
nfrho = fs->nelements + 1;
memory->destroy(frho);
memory->create(frho,nfrho,nrho+1,"pair:frho");
// copy each element's frho to global frho
for (i = 0; i < fs->nelements; i++)
for (m = 1; m <= nrho; m++) frho[i][m] = fs->frho[i][m];
// add extra frho of zeroes for non-EAM types to point to (pair hybrid)
// this is necessary b/c fp is still computed for non-EAM atoms
for (m = 1; m <= nrho; m++) frho[nfrho-1][m] = 0.0;
// type2frho[i] = which frho array (0 to nfrho-1) each atom type maps to
// if atom type doesn't point to element (non-EAM atom in pair hybrid)
// then map it to last frho array of zeroes
for (i = 1; i <= ntypes; i++)
if (map[i] >= 0) type2frho[i] = map[i];
else type2frho[i] = nfrho-1;
// ------------------------------------------------------------------
// setup rhor arrays
// ------------------------------------------------------------------
// allocate rhor arrays
// nrhor = square of # of fs elements
nrhor = fs->nelements * fs->nelements;
memory->destroy(rhor);
memory->create(rhor,nrhor,nr+1,"pair:rhor");
// copy each element pair rhor to global rhor
n = 0;
for (i = 0; i < fs->nelements; i++)
for (j = 0; j < fs->nelements; j++) {
for (m = 1; m <= nr; m++) rhor[n][m] = fs->rhor[i][j][m];
n++;
}
// type2rhor[i][j] = which rhor array (0 to nrhor-1) each type pair maps to
// for fs files, there is a full NxN set of rhor arrays
// OK if map = -1 (non-EAM atom in pair hybrid) b/c type2rhor not used
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++)
type2rhor[i][j] = map[i] * fs->nelements + map[j];
// ------------------------------------------------------------------
// setup z2r arrays
// ------------------------------------------------------------------
// allocate z2r arrays
// nz2r = N*(N+1)/2 where N = # of fs elements
nz2r = fs->nelements * (fs->nelements+1) / 2;
memory->destroy(z2r);
memory->create(z2r,nz2r,nr+1,"pair:z2r");
// copy each element pair z2r to global z2r, only for I >= J
n = 0;
for (i = 0; i < fs->nelements; i++)
for (j = 0; j <= i; j++) {
for (m = 1; m <= nr; m++) z2r[n][m] = fs->z2r[i][j][m];
n++;
}
// type2z2r[i][j] = which z2r array (0 to nz2r-1) each type pair maps to
// set of z2r arrays only fill lower triangular Nelement matrix
// value = n = sum over rows of lower-triangular matrix until reach irow,icol
// swap indices when irow < icol to stay lower triangular
// if map = -1 (non-EAM atom in pair hybrid):
// type2z2r is not used by non-opt
// but set type2z2r to 0 since accessed by opt
int irow,icol;
for (i = 1; i <= ntypes; i++) {
for (j = 1; j <= ntypes; j++) {
irow = map[i];
icol = map[j];
if (irow == -1 || icol == -1) {
type2z2r[i][j] = 0;
continue;
}
if (irow < icol) {
irow = map[j];
icol = map[i];
}
n = 0;
for (m = 0; m < irow; m++) n += m + 1;
n += icol;
type2z2r[i][j] = n;
}
}
}
diff --git a/src/USER-CUDA/pair_gran_hooke_cuda.cpp b/src/USER-CUDA/pair_gran_hooke_cuda.cpp
index 6d3dd7324..74a3dbca8 100644
--- a/src/USER-CUDA/pair_gran_hooke_cuda.cpp
+++ b/src/USER-CUDA/pair_gran_hooke_cuda.cpp
@@ -1,247 +1,244 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_gran_hooke_cuda.h"
#include "pair_gran_hooke_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "modify.h"
#include "fix_pour.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairGranHookeCuda::PairGranHookeCuda(LAMMPS *lmp) : PairGranHooke(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairGranHookeCuda::allocate()
{
if(! allocated) PairGranHooke::allocate();
if(! allocated2)
{
allocated2 = true;
int n = atom->ntypes;
cuda->shared_data.pair.cutsq = cutsq;
memory->create(cuda->shared_data.pair.coeff1,n+1,n+1,
"pair:cuda_coeff1");
memory->create(cuda->shared_data.pair.coeff2,
n+1,n+1,"pair:cuda_coeff2");
cuda->shared_data.pair.coeff1[0][0]=kn;
cuda->shared_data.pair.coeff1[0][1]=kt;
cuda->shared_data.pair.coeff1[1][0]=gamman;
cuda->shared_data.pair.coeff1[1][1]=gammat;
cuda->shared_data.pair.coeff2[0][0]=xmu;
cuda->shared_data.pair.coeff2[0][1]=dampflag;
}
}
/* ---------------------------------------------------------------------- */
void PairGranHookeCuda::compute(int eflag, int vflag)
{
cuda->shared_data.pair.use_block_per_atom = 0;
//cuda->cu_debugdata->memset_device(0);
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairGranHookeCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
//cuda->cu_debugdata->download();
//printf("%lf %lf %lf %lf %lf %lf\n",1.0e-6*cuda->debugdata[0],1.0e-6*cuda->debugdata[1],1.0e-6*cuda->debugdata[2],1.0e-6*cuda->debugdata[3],1.0e-6*cuda->debugdata[4],1.0e-6*cuda->debugdata[5]);
}
/* ---------------------------------------------------------------------- */
void PairGranHookeCuda::settings(int narg, char **arg)
{
PairGranHooke::settings(narg, arg);
}
/* ---------------------------------------------------------------------- */
void PairGranHookeCuda::coeff(int narg, char **arg)
{
PairGranHooke::coeff(narg, arg);
allocate();
}
void PairGranHookeCuda::init_style()
{
int i;
MYDBG(printf("# CUDA PairGranHookeCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->gran = 1;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
if (!atom->radius_flag || !atom->omega_flag || !atom->torque_flag)
- error->all("Pair granular requires atom attributes radius, omega, torque");
+ error->all(FLERR,"Pair granular requires atom attributes radius, omega, torque");
if (comm->ghost_velocity == 0)
- error->all("Pair granular requires ghost atoms store velocity");
+ error->all(FLERR,"Pair granular requires ghost atoms store velocity");
// need a half neigh list and optionally a granular history neigh list
dt = update->dt;
// check for Fix freeze and set freeze_group_bit
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"freeze") == 0) break;
if (i < modify->nfix) freeze_group_bit = modify->fix[i]->groupbit;
else freeze_group_bit = 0;
cuda->shared_data.pair.freeze_group_bit=freeze_group_bit;
// check for Fix pour and set pour_type and pour_maxdiam
int pour_type = 0;
double pour_maxrad = 0.0;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"pour") == 0) break;
if (i < modify->nfix) {
pour_type = ((FixPour *) modify->fix[i])->ntype;
pour_maxrad = ((FixPour *) modify->fix[i])->radius_hi;
}
// set maxrad_dynamic and maxrad_frozen for each type
// include future Fix pour particles as dynamic
for (i = 1; i <= atom->ntypes; i++)
onerad_dynamic[i] = onerad_frozen[i] = 0.0;
if (pour_type) onerad_dynamic[pour_type] = pour_maxrad;
double *radius = atom->radius;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++){
if (mask[i] & freeze_group_bit)
onerad_frozen[type[i]] = MAX(onerad_frozen[type[i]],radius[i]);
else
onerad_dynamic[type[i]] = MAX(onerad_dynamic[type[i]],radius[i]);
}
MPI_Allreduce(&onerad_dynamic[1],&maxrad_dynamic[1],atom->ntypes,
MPI_DOUBLE,MPI_MAX,world);
MPI_Allreduce(&onerad_frozen[1],&maxrad_frozen[1],atom->ntypes,
MPI_DOUBLE,MPI_MAX,world);
MYDBG(printf("# CUDA PairGranHookeCuda::init_style end\n"); )
}
void PairGranHookeCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairGranHookeCuda::init_list\n");)
PairGranHooke::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairGranHookeCuda::init_list end\n");)
}
void PairGranHookeCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairGranHooke::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.eatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj96_cut_cuda.cpp b/src/USER-CUDA/pair_lj96_cut_cuda.cpp
index f60c61bf2..408665d85 100644
--- a/src/USER-CUDA/pair_lj96_cut_cuda.cpp
+++ b/src/USER-CUDA/pair_lj96_cut_cuda.cpp
@@ -1,184 +1,181 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj96_cut_cuda.h"
#include "pair_lj96_cut_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJ96CutCuda::PairLJ96CutCuda(LAMMPS *lmp) : PairLJ96Cut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJ96CutCuda::allocate()
{
if(! allocated) PairLJ96Cut::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJ96CutCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJ96CutCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJ96CutCuda::settings(int narg, char **arg)
{
PairLJ96Cut::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
}
/* ---------------------------------------------------------------------- */
void PairLJ96CutCuda::coeff(int narg, char **arg)
{
PairLJ96Cut::coeff(narg, arg);
allocate();
}
void PairLJ96CutCuda::init_style()
{
MYDBG(printf("# CUDA PairLJ96CutCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
cut_respa = NULL;
MYDBG(printf("# CUDA PairLJ96CutCuda::init_style end\n"); )
}
void PairLJ96CutCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJ96CutCuda::init_list\n");)
PairLJ96Cut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJ96CutCuda::init_list end\n");)
}
void PairLJ96CutCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJ96Cut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_charmm_coul_charmm_cuda.cpp b/src/USER-CUDA/pair_lj_charmm_coul_charmm_cuda.cpp
index a5a08046a..bcd356909 100644
--- a/src/USER-CUDA/pair_lj_charmm_coul_charmm_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_charmm_coul_charmm_cuda.cpp
@@ -1,194 +1,191 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_charmm_coul_charmm_cuda.h"
#include "pair_lj_charmm_coul_charmm_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulCharmmCuda::PairLJCharmmCoulCharmmCuda(LAMMPS *lmp) : PairLJCharmmCoulCharmm(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmCuda::allocate()
{
if(! allocated) PairLJCharmmCoulCharmm::allocate();
if(! allocated2)
{
cuda->accelerator(0,NULL);
allocated2 = true;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
cu_lj1_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj1, &cuda->shared_data.pair.coeff1_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj2_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj2, &cuda->shared_data.pair.coeff2_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj3_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj3, &cuda->shared_data.pair.coeff3_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj4_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj4, &cuda->shared_data.pair.coeff4_gm, (atom->ntypes+1)*(atom->ntypes+1));
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
}
Cuda_PairLJCharmmCoulCharmmCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom,denom_lj,cut_coul_innersq,denom_coul);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmCuda::settings(int narg, char **arg)
{
PairLJCharmmCoulCharmm::settings(narg, arg);
cuda->shared_data.pair.cut_global = (X_FLOAT) cut_lj;
cuda->shared_data.pair.cut_coulsq_global = (X_FLOAT) cut_coulsq;
cuda->shared_data.pair.cut_inner_global = (F_FLOAT) cut_lj_inner;
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmCuda::coeff(int narg, char **arg)
{
PairLJCharmmCoulCharmm::coeff(narg, arg);
allocate();
}
void PairLJCharmmCoulCharmmCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/charmm/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/charmm/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
if(atom->molecular)
{
cuda->shared_data.pair.collect_forces_later = 1;
}
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
if (cut_lj_inner >= cut_lj || cut_coul_inner >= cut_coul)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coul_innersq = cut_coul_inner * cut_coul_inner;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) *
(cut_ljsq-cut_lj_innersq);
denom_coul = (cut_coulsq-cut_coul_innersq) * (cut_coulsq-cut_coul_innersq) *
(cut_coulsq-cut_coul_innersq);
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
}
void PairLJCharmmCoulCharmmCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCharmmCoulCharmmCuda::init_list\n");)
PairLJCharmmCoulCharmm::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCharmmCoulCharmmCuda::init_list end\n");)
}
void PairLJCharmmCoulCharmmCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCharmmCoulCharmm::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_charmm_coul_charmm_implicit_cuda.cpp b/src/USER-CUDA/pair_lj_charmm_coul_charmm_implicit_cuda.cpp
index f127d9e31..10696094c 100644
--- a/src/USER-CUDA/pair_lj_charmm_coul_charmm_implicit_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_charmm_coul_charmm_implicit_cuda.cpp
@@ -1,189 +1,186 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_charmm_coul_charmm_implicit_cuda.h"
#include "pair_lj_charmm_coul_charmm_implicit_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulCharmmImplicitCuda::PairLJCharmmCoulCharmmImplicitCuda(LAMMPS *lmp) : PairLJCharmmCoulCharmmImplicit(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.collect_forces_later = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmImplicitCuda::allocate()
{
if(! allocated) PairLJCharmmCoulCharmmImplicit::allocate();
if(! allocated2)
{
cuda->accelerator(0,NULL);
allocated2 = true;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
cu_lj1_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj1, &cuda->shared_data.pair.coeff1_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj2_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj2, &cuda->shared_data.pair.coeff2_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj3_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj3, &cuda->shared_data.pair.coeff3_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj4_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj4, &cuda->shared_data.pair.coeff4_gm, (atom->ntypes+1)*(atom->ntypes+1));
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmImplicitCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
}
Cuda_PairLJCharmmCoulCharmmImplicitCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom,denom_lj,cut_coul_innersq,denom_coul);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmImplicitCuda::settings(int narg, char **arg)
{
PairLJCharmmCoulCharmmImplicit::settings(narg, arg);
cuda->shared_data.pair.cut_global = (X_FLOAT) cut_lj;
cuda->shared_data.pair.cut_coulsq_global = (X_FLOAT) cut_coulsq;
cuda->shared_data.pair.cut_inner_global = (F_FLOAT) cut_lj_inner;
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulCharmmImplicitCuda::coeff(int narg, char **arg)
{
PairLJCharmmCoulCharmmImplicit::coeff(narg, arg);
allocate();
}
void PairLJCharmmCoulCharmmImplicitCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/charmm/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/charmm/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
if (cut_lj_inner >= cut_lj || cut_coul_inner >= cut_coul)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coul_innersq = cut_coul_inner * cut_coul_inner;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) *
(cut_ljsq-cut_lj_innersq);
denom_coul = (cut_coulsq-cut_coul_innersq) * (cut_coulsq-cut_coul_innersq) *
(cut_coulsq-cut_coul_innersq);
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
}
void PairLJCharmmCoulCharmmImplicitCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCharmmCoulCharmmImplicitCuda::init_list\n");)
PairLJCharmmCoulCharmmImplicit::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCharmmCoulCharmmImplicitCuda::init_list end\n");)
}
void PairLJCharmmCoulCharmmImplicitCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCharmmCoulCharmmImplicit::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_charmm_coul_long_cuda.cpp b/src/USER-CUDA/pair_lj_charmm_coul_long_cuda.cpp
index 434f098f3..29629f1ed 100644
--- a/src/USER-CUDA/pair_lj_charmm_coul_long_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_charmm_coul_long_cuda.cpp
@@ -1,202 +1,199 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_charmm_coul_long_cuda.h"
#include "pair_lj_charmm_coul_long_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJCharmmCoulLongCuda::PairLJCharmmCoulLongCuda(LAMMPS *lmp) : PairLJCharmmCoulLong(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.collect_forces_later = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCharmmCoulLongCuda::allocate()
{
if(! allocated) PairLJCharmmCoulLong::allocate();
if(! allocated2)
{
cuda->accelerator(0,NULL);
allocated2 = true;
//cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
cu_lj1_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj1, &cuda->shared_data.pair.coeff1_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj2_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj2, &cuda->shared_data.pair.coeff2_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj3_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj3, &cuda->shared_data.pair.coeff3_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj4_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj4, &cuda->shared_data.pair.coeff4_gm, (atom->ntypes+1)*(atom->ntypes+1));
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLongCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
}
Cuda_PairLJCharmmCoulLongCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom,denom_lj);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLongCuda::settings(int narg, char **arg)
{
PairLJCharmmCoulLong::settings(narg, arg);
cuda->shared_data.pair.cut_global = (X_FLOAT) cut_lj;
cuda->shared_data.pair.cut_coulsq_global = (X_FLOAT) cut_coulsq;
cuda->shared_data.pair.cut_inner_global = (F_FLOAT) cut_lj_inner;
}
/* ---------------------------------------------------------------------- */
void PairLJCharmmCoulLongCuda::coeff(int narg, char **arg)
{
PairLJCharmmCoulLong::coeff(narg, arg);
allocate();
}
void PairLJCharmmCoulLongCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/charmm/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/charmm/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
if (cut_lj_inner >= cut_lj)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
denom_lj = (cut_ljsq-cut_lj_innersq) * (cut_ljsq-cut_lj_innersq) *
(cut_ljsq-cut_lj_innersq);
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
cuda->shared_data.pair.g_ewald=g_ewald;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
- if(ncoultablebits) error->warning("# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
+ if(ncoultablebits) error->warning(FLERR,"# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
}
void PairLJCharmmCoulLongCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCharmmCoulLongCuda::init_list\n");)
PairLJCharmmCoulLong::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCharmmCoulLongCuda::init_list end\n");)
}
void PairLJCharmmCoulLongCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCharmmCoulLong::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_class2_coul_cut_cuda.cpp b/src/USER-CUDA/pair_lj_class2_coul_cut_cuda.cpp
index a75a70ba0..702f2089c 100644
--- a/src/USER-CUDA/pair_lj_class2_coul_cut_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_class2_coul_cut_cuda.cpp
@@ -1,167 +1,164 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_class2_coul_cut_cuda.h"
#include "pair_lj_class2_coul_cut_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJClass2CoulCutCuda::PairLJClass2CoulCutCuda(LAMMPS *lmp) : PairLJClass2CoulCut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJClass2CoulCutCuda::allocate()
{
if(! allocated) PairLJClass2CoulCut::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.cut_coul= cut_coul;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulCutCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJClass2CoulCutCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulCutCuda::settings(int narg, char **arg)
{
PairLJClass2CoulCut::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
cuda->shared_data.pair.cut_coul_global = (F_FLOAT) cut_coul_global;
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulCutCuda::coeff(int narg, char **arg)
{
PairLJClass2CoulCut::coeff(narg, arg);
allocate();
}
void PairLJClass2CoulCutCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/cut/cuda requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/cut/cuda requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
}
void PairLJClass2CoulCutCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJClass2CoulCutCuda::init_list\n");)
PairLJClass2CoulCut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJClass2CoulCutCuda::init_list end\n");)
}
void PairLJClass2CoulCutCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJClass2CoulCut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_class2_coul_long_cuda.cpp b/src/USER-CUDA/pair_lj_class2_coul_long_cuda.cpp
index 5c1d3a6ff..44f0fb3f2 100644
--- a/src/USER-CUDA/pair_lj_class2_coul_long_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_class2_coul_long_cuda.cpp
@@ -1,180 +1,177 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_class2_coul_long_cuda.h"
#include "pair_lj_class2_coul_long_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJClass2CoulLongCuda::PairLJClass2CoulLongCuda(LAMMPS *lmp) : PairLJClass2CoulLong(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJClass2CoulLongCuda::allocate()
{
if(! allocated) PairLJClass2CoulLong::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulLongCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJClass2CoulLongCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulLongCuda::settings(int narg, char **arg)
{
PairLJClass2CoulLong::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
}
/* ---------------------------------------------------------------------- */
void PairLJClass2CoulLongCuda::coeff(int narg, char **arg)
{
PairLJClass2CoulLong::coeff(narg, arg);
allocate();
}
void PairLJClass2CoulLongCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coul_global=cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
// set rRESPA cutoffs
- if (force->newton) error->warning("Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
+ if (force->newton) error->warning(FLERR,"Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
cuda->shared_data.pair.g_ewald=g_ewald;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
- if(ncoultablebits) error->warning("# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
+ if(ncoultablebits) error->warning(FLERR,"# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
}
void PairLJClass2CoulLongCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJClass2CoulLongCuda::init_list\n");)
PairLJClass2CoulLong::init_list(id, ptr);
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
MYDBG(printf("# CUDA PairLJClass2CoulLongCuda::init_list end\n");)
}
void PairLJClass2CoulLongCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJClass2CoulLong::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_class2_cuda.cpp b/src/USER-CUDA/pair_lj_class2_cuda.cpp
index 98d8d8746..a218dc9cc 100644
--- a/src/USER-CUDA/pair_lj_class2_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_class2_cuda.cpp
@@ -1,172 +1,169 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_class2_cuda.h"
#include "pair_lj_class2_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJClass2Cuda::PairLJClass2Cuda(LAMMPS *lmp) : PairLJClass2(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJClass2Cuda::allocate()
{
if(! allocated) PairLJClass2::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2Cuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJClass2Cuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJClass2Cuda::settings(int narg, char **arg)
{
PairLJClass2::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
}
/* ---------------------------------------------------------------------- */
void PairLJClass2Cuda::coeff(int narg, char **arg)
{
PairLJClass2::coeff(narg, arg);
allocate();
}
void PairLJClass2Cuda::init_style()
{
MYDBG(printf("# CUDA PairLJClass2Cuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
MYDBG(printf("# CUDA PairLJClass2Cuda::init_style end\n"); )
}
void PairLJClass2Cuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJClass2Cuda::init_list\n");)
PairLJClass2::init_list(id, ptr);
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
MYDBG(printf("# CUDA PairLJClass2Cuda::init_list end\n");)
}
void PairLJClass2Cuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJClass2::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_cut_coul_cut_cuda.cpp b/src/USER-CUDA/pair_lj_cut_coul_cut_cuda.cpp
index ce2c36bc2..ac80ff521 100644
--- a/src/USER-CUDA/pair_lj_cut_coul_cut_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_cut_coul_cut_cuda.cpp
@@ -1,167 +1,164 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_cut_coul_cut_cuda.h"
#include "pair_lj_cut_coul_cut_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCutCoulCutCuda::PairLJCutCoulCutCuda(LAMMPS *lmp) : PairLJCutCoulCut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCutCoulCutCuda::allocate()
{
if(! allocated) PairLJCutCoulCut::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.cut_coul= cut_coul;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulCutCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJCutCoulCutCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulCutCuda::settings(int narg, char **arg)
{
PairLJCutCoulCut::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
cuda->shared_data.pair.cut_coul_global = (F_FLOAT) cut_coul_global;
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulCutCuda::coeff(int narg, char **arg)
{
PairLJCutCoulCut::coeff(narg, arg);
allocate();
}
void PairLJCutCoulCutCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/cut/cuda requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/cut/cuda requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
}
void PairLJCutCoulCutCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCutCoulCutCuda::init_list\n");)
PairLJCutCoulCut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCutCoulCutCuda::init_list end\n");)
}
void PairLJCutCoulCutCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCutCoulCut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_cut_coul_debye_cuda.cpp b/src/USER-CUDA/pair_lj_cut_coul_debye_cuda.cpp
index a1e553d78..bc9a6f33b 100644
--- a/src/USER-CUDA/pair_lj_cut_coul_debye_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_cut_coul_debye_cuda.cpp
@@ -1,168 +1,165 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_cut_coul_debye_cuda.h"
#include "pair_lj_cut_coul_debye_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCutCoulDebyeCuda::PairLJCutCoulDebyeCuda(LAMMPS *lmp) : PairLJCutCoulDebye(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCutCoulDebyeCuda::allocate()
{
if(! allocated) PairLJCutCoulDebye::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.cut_coul= cut_coul;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulDebyeCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJCutCoulDebyeCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulDebyeCuda::settings(int narg, char **arg)
{
PairLJCutCoulDebye::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
cuda->shared_data.pair.cut_coul_global = (F_FLOAT) cut_coul_global;
cuda->shared_data.pair.kappa = (F_FLOAT) kappa;
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulDebyeCuda::coeff(int narg, char **arg)
{
PairLJCutCoulDebye::coeff(narg, arg);
allocate();
}
void PairLJCutCoulDebyeCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/debye/cuda requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/debye/cuda requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
}
void PairLJCutCoulDebyeCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCutCoulDebyeCuda::init_list\n");)
PairLJCutCoulDebye::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCutCoulDebyeCuda::init_list end\n");)
}
void PairLJCutCoulDebyeCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCutCoulDebye::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_cut_coul_long_cuda.cpp b/src/USER-CUDA/pair_lj_cut_coul_long_cuda.cpp
index 80d0f7de3..12ea4b6d1 100644
--- a/src/USER-CUDA/pair_lj_cut_coul_long_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_cut_coul_long_cuda.cpp
@@ -1,221 +1,218 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_cut_coul_long_cuda.h"
#include "pair_lj_cut_coul_long_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJCutCoulLongCuda::PairLJCutCoulLongCuda(LAMMPS *lmp) : PairLJCutCoulLong(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCutCoulLongCuda::allocate()
{
if(! allocated) PairLJCutCoulLong::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut_lj;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLongCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJCutCoulLongCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLongCuda::settings(int narg, char **arg)
{
PairLJCutCoulLong::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_lj_global;
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulLongCuda::coeff(int narg, char **arg)
{
PairLJCutCoulLong::coeff(narg, arg);
allocate();
}
void PairLJCutCoulLongCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/long requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/long requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
}
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coul_global=cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
- if (force->newton) error->warning("Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
+ if (force->newton) error->warning(FLERR,"Pair style uses does not use \"newton\" setting. You might test if \"newton off\" makes the simulation run faster.");
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
cuda->shared_data.pair.g_ewald=g_ewald;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
- if(ncoultablebits) error->warning("# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
+ if(ncoultablebits) error->warning(FLERR,"# CUDA: You asked for the useage of Coulomb Tables. This is not supported in CUDA Pair forces. Setting is ignored.\n");
}
void PairLJCutCoulLongCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCutCoulLongCuda::init_list\n");)
PairLJCutCoulLong::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCutCoulLongCuda::init_list end\n");)
}
void PairLJCutCoulLongCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCutCoulLong::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_cut_cuda.cpp b/src/USER-CUDA/pair_lj_cut_cuda.cpp
index 29dfbb814..c865f2136 100644
--- a/src/USER-CUDA/pair_lj_cut_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_cut_cuda.cpp
@@ -1,184 +1,181 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_cut_cuda.h"
#include "pair_lj_cut_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCutCuda::PairLJCutCuda(LAMMPS *lmp) : PairLJCut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCutCuda::allocate()
{
if(! allocated) PairLJCut::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJCutCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCuda::settings(int narg, char **arg)
{
PairLJCut::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
}
/* ---------------------------------------------------------------------- */
void PairLJCutCuda::coeff(int narg, char **arg)
{
PairLJCut::coeff(narg, arg);
allocate();
}
void PairLJCutCuda::init_style()
{
MYDBG(printf("# CUDA PairLJCutCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
cut_respa = NULL;
MYDBG(printf("# CUDA PairLJCutCuda::init_style end\n"); )
}
void PairLJCutCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCutCuda::init_list\n");)
PairLJCut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCutCuda::init_list end\n");)
}
void PairLJCutCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_cut_experimental_cuda.cpp b/src/USER-CUDA/pair_lj_cut_experimental_cuda.cpp
index a8700008d..50dfaa5fa 100644
--- a/src/USER-CUDA/pair_lj_cut_experimental_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_cut_experimental_cuda.cpp
@@ -1,183 +1,180 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_cut_experimental_cuda.h"
#include "pair_lj_cut_experimental_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCutExperimentalCuda::PairLJCutExperimentalCuda(LAMMPS *lmp) : PairLJCut(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJCutExperimentalCuda::allocate()
{
if(! allocated) PairLJCut::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutExperimentalCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJCutExperimentalCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
CudaWrapper_Sync();
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutExperimentalCuda::settings(int narg, char **arg)
{
PairLJCut::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
}
/* ---------------------------------------------------------------------- */
void PairLJCutExperimentalCuda::coeff(int narg, char **arg)
{
PairLJCut::coeff(narg, arg);
allocate();
}
void PairLJCutExperimentalCuda::init_style()
{
MYDBG(printf("# CUDA PairLJCutExperimentalCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
cut_respa = NULL;
MYDBG(printf("# CUDA PairLJCutExperimentalCuda::init_style end\n"); )
}
void PairLJCutExperimentalCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJCutExperimentalCuda::init_list\n");)
PairLJCut::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJCutExperimentalCuda::init_list end\n");)
}
void PairLJCutExperimentalCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJCut::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_expand_cuda.cpp b/src/USER-CUDA/pair_lj_expand_cuda.cpp
index f06f227af..79f5f77c8 100644
--- a/src/USER-CUDA/pair_lj_expand_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_expand_cuda.cpp
@@ -1,185 +1,182 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_expand_cuda.h"
#include "pair_lj_expand_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJExpandCuda::PairLJExpandCuda(LAMMPS *lmp) : PairLJExpand(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJExpandCuda::allocate()
{
if(! allocated) PairLJExpand::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.cutsq = cutsq;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = shift;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
}
}
/* ---------------------------------------------------------------------- */
void PairLJExpandCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairLJExpandCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJExpandCuda::settings(int narg, char **arg)
{
PairLJExpand::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
}
/* ---------------------------------------------------------------------- */
void PairLJExpandCuda::coeff(int narg, char **arg)
{
PairLJExpand::coeff(narg, arg);
allocate();
}
void PairLJExpandCuda::init_style()
{
MYDBG(printf("# CUDA PairLJExpandCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
MYDBG(printf("# CUDA PairLJExpandCuda::init_style end\n"); )
}
void PairLJExpandCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJExpandCuda::init_list\n");)
PairLJExpand::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJExpandCuda::init_list end\n");)
}
void PairLJExpandCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJExpand::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_gromacs_coul_gromacs_cuda.cpp b/src/USER-CUDA/pair_lj_gromacs_coul_gromacs_cuda.cpp
index 8e05acc4f..862d180e9 100644
--- a/src/USER-CUDA/pair_lj_gromacs_coul_gromacs_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_gromacs_coul_gromacs_cuda.cpp
@@ -1,200 +1,197 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_gromacs_coul_gromacs_cuda.h"
#include "pair_lj_gromacs_coul_gromacs_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJGromacsCoulGromacsCuda::PairLJGromacsCoulGromacsCuda(LAMMPS *lmp) : PairLJGromacsCoulGromacs(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacsCuda::allocate()
{
if(! allocated) PairLJGromacsCoulGromacs::allocate();
if(! allocated2)
{
cuda->accelerator(0,NULL);
allocated2 = true;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = ljsw1;
cuda->shared_data.pair.coeff6 = ljsw2;
cuda->shared_data.pair.coeff7 = ljsw3;
cuda->shared_data.pair.coeff8 = ljsw4;
cuda->shared_data.pair.coeff9 = ljsw5;
cuda->shared_data.pair.special_lj = force->special_lj;
cuda->shared_data.pair.special_coul = force->special_coul;
cu_lj1_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj1, &cuda->shared_data.pair.coeff1_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj2_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj2, &cuda->shared_data.pair.coeff2_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj3_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj3, &cuda->shared_data.pair.coeff3_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj4_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj4, &cuda->shared_data.pair.coeff4_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw1_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw1, &cuda->shared_data.pair.coeff5_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw2_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw2, &cuda->shared_data.pair.coeff6_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw3_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw3, &cuda->shared_data.pair.coeff7_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw4_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw4, &cuda->shared_data.pair.coeff8_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw5_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw5, &cuda->shared_data.pair.coeff9_gm, (atom->ntypes+1)*(atom->ntypes+1));
}
}
/* ---------------------------------------------------------------------- */
void PairLJGromacsCoulGromacsCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
}
Cuda_PairLJGromacsCoulGromacsCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom,cut_coul_inner,coulsw1,coulsw2,coulsw5);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJGromacsCoulGromacsCuda::settings(int narg, char **arg)
{
PairLJGromacsCoulGromacs::settings(narg, arg);
cuda->shared_data.pair.cut_global = (X_FLOAT) cut_lj;
cuda->shared_data.pair.cut_coulsq_global = (X_FLOAT) cut_coulsq;
cuda->shared_data.pair.cut_inner_global = (F_FLOAT) cut_lj_inner;
}
/* ---------------------------------------------------------------------- */
void PairLJGromacsCoulGromacsCuda::coeff(int narg, char **arg)
{
PairLJGromacsCoulGromacs::coeff(narg, arg);
allocate();
}
void PairLJGromacsCoulGromacsCuda::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/gromacs/coul/gromacs requires atom attribute q");
+ error->all(FLERR,"Pair style lj/gromacs/coul/gromacs requires atom attribute q");
// request regular or rRESPA neighbor lists
if(atom->molecular)
{
cuda->shared_data.pair.collect_forces_later = 1;
}
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
if (cut_lj_inner >= cut_lj || cut_coul_inner >= cut_coul)
- error->all("Pair inner cutoff >= Pair outer cutoff");
+ error->all(FLERR,"Pair inner cutoff >= Pair outer cutoff");
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coul_innersq = cut_coul_inner * cut_coul_inner;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
cut_coulsq = cut_coul * cut_coul;
cuda->shared_data.pair.cut_coulsq_global=cut_coulsq;
cuda->shared_data.pppm.qqrd2e=force->qqrd2e;
}
void PairLJGromacsCoulGromacsCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJGromacsCoulGromacsCuda::init_list\n");)
PairLJGromacsCoulGromacs::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJGromacsCoulGromacsCuda::init_list end\n");)
}
void PairLJGromacsCoulGromacsCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJGromacsCoulGromacs::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_gromacs_cuda.cpp b/src/USER-CUDA/pair_lj_gromacs_cuda.cpp
index 97bf05aac..518ab5632 100644
--- a/src/USER-CUDA/pair_lj_gromacs_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_gromacs_cuda.cpp
@@ -1,183 +1,180 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_gromacs_cuda.h"
#include "pair_lj_gromacs_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJGromacsCuda::PairLJGromacsCuda(LAMMPS *lmp) : PairLJGromacs(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJGromacsCuda::allocate()
{
if(! allocated) PairLJGromacs::allocate();
if(! allocated2)
{
cuda->accelerator(0,NULL);
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.cut_inner = cut_inner;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = ljsw1;
cuda->shared_data.pair.coeff6 = ljsw2;
cuda->shared_data.pair.coeff7 = ljsw3;
cuda->shared_data.pair.coeff8 = ljsw4;
cuda->shared_data.pair.coeff9 = ljsw5;
cuda->shared_data.pair.special_lj = force->special_lj;
cu_lj1_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj1, &cuda->shared_data.pair.coeff1_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj2_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj2, &cuda->shared_data.pair.coeff2_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj3_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj3, &cuda->shared_data.pair.coeff3_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj4_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj4, &cuda->shared_data.pair.coeff4_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw1_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw1, &cuda->shared_data.pair.coeff5_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw2_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw2, &cuda->shared_data.pair.coeff6_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw3_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw3, &cuda->shared_data.pair.coeff7_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw4_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw4, &cuda->shared_data.pair.coeff8_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw5_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw5, &cuda->shared_data.pair.coeff9_gm, (atom->ntypes+1)*(atom->ntypes+1));
}
}
/* ---------------------------------------------------------------------- */
void PairLJGromacsCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
}
Cuda_PairLJGromacsCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJGromacsCuda::settings(int narg, char **arg)
{
PairLJGromacs::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
cuda->shared_data.pair.cut_inner_global = (F_FLOAT) cut_inner_global;
}
/* ---------------------------------------------------------------------- */
void PairLJGromacsCuda::coeff(int narg, char **arg)
{
PairLJGromacs::coeff(narg, arg);
allocate();
}
void PairLJGromacsCuda::init_style()
{
// request regular or rRESPA neighbor lists
if(atom->molecular)
{
cuda->shared_data.pair.collect_forces_later = 1;
}
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
}
void PairLJGromacsCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJGromacsCuda::init_list\n");)
PairLJGromacs::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJGromacsCuda::init_list end\n");)
}
void PairLJGromacsCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJGromacs::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_lj_smooth_cuda.cpp b/src/USER-CUDA/pair_lj_smooth_cuda.cpp
index 25f2c5059..84a4d9086 100644
--- a/src/USER-CUDA/pair_lj_smooth_cuda.cpp
+++ b/src/USER-CUDA/pair_lj_smooth_cuda.cpp
@@ -1,183 +1,180 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
Contributing author: Paul Crozier (SNL)
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_lj_smooth_cuda.h"
#include "pair_lj_smooth_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJSmoothCuda::PairLJSmoothCuda(LAMMPS *lmp) : PairLJSmooth(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->shared_data.pair.use_block_per_atom = 0;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairLJSmoothCuda::allocate()
{
if(! allocated) PairLJSmooth::allocate();
if(! allocated2)
{
cuda->accelerator(0,NULL);
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.cut_inner = cut_inner;
cuda->shared_data.pair.coeff1 = lj1;
cuda->shared_data.pair.coeff2 = lj2;
cuda->shared_data.pair.coeff3 = lj3;
cuda->shared_data.pair.coeff4 = lj4;
cuda->shared_data.pair.coeff5 = ljsw1;
cuda->shared_data.pair.coeff6 = ljsw2;
cuda->shared_data.pair.coeff7 = ljsw3;
cuda->shared_data.pair.coeff8 = ljsw4;
cuda->shared_data.pair.coeff9 = ljsw0;
cuda->shared_data.pair.special_lj = force->special_lj;
cu_lj1_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj1, &cuda->shared_data.pair.coeff1_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj2_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj2, &cuda->shared_data.pair.coeff2_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj3_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj3, &cuda->shared_data.pair.coeff3_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_lj4_gm = new cCudaData<double, F_FLOAT, x> ((double*)lj4, &cuda->shared_data.pair.coeff4_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw0_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw0, &cuda->shared_data.pair.coeff9_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw1_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw1, &cuda->shared_data.pair.coeff5_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw2_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw2, &cuda->shared_data.pair.coeff6_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw3_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw3, &cuda->shared_data.pair.coeff7_gm, (atom->ntypes+1)*(atom->ntypes+1));
cu_ljsw4_gm = new cCudaData<double, F_FLOAT, x> ((double*)ljsw4, &cuda->shared_data.pair.coeff8_gm, (atom->ntypes+1)*(atom->ntypes+1));
}
}
/* ---------------------------------------------------------------------- */
void PairLJSmoothCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
}
Cuda_PairLJSmoothCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairLJSmoothCuda::settings(int narg, char **arg)
{
PairLJSmooth::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
cuda->shared_data.pair.cut_inner_global = (F_FLOAT) cut_inner_global;
}
/* ---------------------------------------------------------------------- */
void PairLJSmoothCuda::coeff(int narg, char **arg)
{
PairLJSmooth::coeff(narg, arg);
allocate();
}
void PairLJSmoothCuda::init_style()
{
// request regular or rRESPA neighbor lists
if(atom->molecular)
{
cuda->shared_data.pair.collect_forces_later = 1;
}
int irequest;
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
}
void PairLJSmoothCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairLJSmoothCuda::init_list\n");)
PairLJSmooth::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairLJSmoothCuda::init_list end\n");)
}
void PairLJSmoothCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairLJSmooth::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pair_morse_cuda.cpp b/src/USER-CUDA/pair_morse_cuda.cpp
index befacd341..ec2375fb9 100644
--- a/src/USER-CUDA/pair_morse_cuda.cpp
+++ b/src/USER-CUDA/pair_morse_cuda.cpp
@@ -1,182 +1,179 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "pair_morse_cuda.h"
#include "pair_morse_cuda_cu.h"
#include "cuda_data.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "cuda_neigh_list.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "cuda.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairMorseCuda::PairMorseCuda(LAMMPS *lmp) : PairMorse(lmp)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
allocated2 = false;
cuda->shared_data.pair.cudable_force = 1;
cuda->setSystemParams();
}
/* ----------------------------------------------------------------------
remember pointer to arrays in cuda shared data
------------------------------------------------------------------------- */
void PairMorseCuda::allocate()
{
if(! allocated) PairMorse::allocate();
if(! allocated2)
{
allocated2 = true;
cuda->shared_data.pair.cut = cut;
cuda->shared_data.pair.coeff1 = r0;
cuda->shared_data.pair.coeff2 = alpha;
cuda->shared_data.pair.coeff3 = morse1;
cuda->shared_data.pair.coeff4 = d0;
cuda->shared_data.pair.offset = offset;
cuda->shared_data.pair.special_lj = force->special_lj;
}
}
/* ---------------------------------------------------------------------- */
void PairMorseCuda::compute(int eflag, int vflag)
{
if (eflag || vflag) ev_setup(eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_PairMorseCuda(& cuda->shared_data, & cuda_neigh_list->sneighlist, eflag, vflag, eflag_atom, vflag_atom);
if(not cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->download();
if(vflag) cuda->cu_virial->download();
}
}
/* ---------------------------------------------------------------------- */
void PairMorseCuda::settings(int narg, char **arg)
{
PairMorse::settings(narg, arg);
cuda->shared_data.pair.cut_global = (F_FLOAT) cut_global;
}
/* ---------------------------------------------------------------------- */
void PairMorseCuda::coeff(int narg, char **arg)
{
PairMorse::coeff(narg, arg);
allocate();
}
void PairMorseCuda::init_style()
{
MYDBG(printf("# CUDA PairMorseCuda::init_style start\n"); )
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
}
else
{
irequest = neighbor->request(this);
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->cudable = 1;
//neighbor->style=0; //0=NSQ neighboring
}
MYDBG(printf("# CUDA PairMorseCuda::init_style end\n"); )
}
void PairMorseCuda::init_list(int id, NeighList *ptr)
{
MYDBG(printf("# CUDA PairMorseCuda::init_list\n");)
PairMorse::init_list(id, ptr);
#ifndef CUDA_USE_BINNING
// right now we can only handle verlet (id 0), not respa
if(id == 0) cuda_neigh_list = cuda->registerNeighborList(ptr);
// see Neighbor::init() for details on lammps lists' logic
#endif
MYDBG(printf("# CUDA PairMorseCuda::init_list end\n");)
}
void PairMorseCuda::ev_setup(int eflag, int vflag)
{
int maxeatomold=maxeatom;
PairMorse::ev_setup(eflag,vflag);
if (eflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_eatom; cuda->cu_eatom = new cCudaData<double, ENERGY_FLOAT, x > ((double*)eatom, & cuda->shared_data.atom.eatom , atom->nmax );}
if (vflag_atom && atom->nmax > maxeatomold)
{delete cuda->cu_vatom; cuda->cu_vatom = new cCudaData<double, ENERGY_FLOAT, yx > ((double*)vatom, & cuda->shared_data.atom.vatom , atom->nmax, 6 );}
}
diff --git a/src/USER-CUDA/pppm_cuda.cpp b/src/USER-CUDA/pppm_cuda.cpp
index ffa5d1797..8167eb1d7 100644
--- a/src/USER-CUDA/pppm_cuda.cpp
+++ b/src/USER-CUDA/pppm_cuda.cpp
@@ -1,1741 +1,1738 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Roy Pollock (LLNL), Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include "pppm_cuda.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "domain.h"
#include "fft3d_wrap_cuda.h"
#include "remap_wrap.h"
#include "memory.h"
#include "error.h"
#include <ctime> //crmadd
#include "cuda_wrapper_cu.h"
#include "pppm_cuda_cu.h"
#include "cuda.h"
using namespace LAMMPS_NS;
#define MAXORDER 7
#define OFFSET 4096
#define SMALL 0.00001
#define LARGE 10000.0
#define EPS_HOC 1.0e-7
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
void printArray(double* data,int nx, int ny, int nz)
{
for(int i=0;i<nz;i++)
for(int j=0;j<ny;j++)
{
printf("%i %i\n",i,j);
for(int k=0;k<nx;k++)
printf("%e ",data[2*(i*ny*nx+j*nx+k)]);
printf("\n\n");
}
}
void printArray(double*** data,int nx, int ny, int nz)
{
for(int i=0;i<nx;i++)
for(int j=0;j<ny;j++)
{
printf("%i %i\n",i,j);
for(int k=0;k<nz;k++)
printf("%e ",data[i][j][k]);
printf("\n\n");
}
}
/* ---------------------------------------------------------------------- */
PPPMCuda::PPPMCuda(LAMMPS *lmp, int narg, char **arg) : PPPM(lmp, (narg==2?1:narg), arg)
{
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
- if ((narg > 3)||(narg<1)) error->all("Illegal kspace_style pppm/cuda command");
+ if ((narg > 3)||(narg<1)) error->all(FLERR,"Illegal kspace_style pppm/cuda command");
#ifndef FFT_CUFFT
- error->all("Using kspace_style pppm/cuda without cufft is not possible. Compile with cufft=1 to include cufft. Aborting.");
+ error->all(FLERR,"Using kspace_style pppm/cuda without cufft is not possible. Compile with cufft=1 to include cufft. Aborting.");
#endif
precision = atof(arg[0]);
if(narg>1)
precisionmodify=arg[1][0];
else precisionmodify='=';
PI = 4.0*atan(1.0);
nfactors = 3;
factors = new int[nfactors];
factors[0] = 2;
factors[1] = 3;
factors[2] = 5;
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
density_brick = vdx_brick = vdy_brick = vdz_brick = vdx_brick_tmp = NULL;
density_fft = NULL;
greensfn = NULL;
work1 = work2 = NULL;
vg = NULL;
fkx = fky = fkz = NULL;
buf1 = buf2 = NULL;
gf_b = NULL;
rho1d = rho_coeff = NULL;
fft1c = fft2c = NULL;
remap = NULL;
density_brick_int=NULL;
density_intScale=1000000;
cu_vdx_brick = cu_vdy_brick = cu_vdz_brick = NULL;
cu_density_brick = NULL;
cu_density_brick_int = NULL;
cu_density_fft = NULL;
cu_energy=NULL;
cu_greensfn = NULL;
cu_work1 = cu_work2 = cu_work3 = NULL;
cu_vg = NULL;
cu_fkx = cu_fky = cu_fkz = NULL;
cu_flag = NULL;
cu_debugdata = NULL;
cu_rho_coeff = NULL;
cu_virial = NULL;
cu_gf_b = NULL;
cu_slabbuf = NULL;
slabbuf = NULL;
nmax = 0;
part2grid = NULL;
cu_part2grid = NULL;
adev_data_array=NULL;
poissontime=0;
old_nmax=0;
cu_pppm_grid_n=NULL;
cu_pppm_grid_ids=NULL;
pppm_grid_nmax=0;
pppm2partgrid=new int[3];
pppm_grid=new int[3];
firstpass=true;
scale = 1.0;
}
/* ----------------------------------------------------------------------
free all memory
------------------------------------------------------------------------- */
PPPMCuda::~PPPMCuda()
{
delete [] slabbuf;
delete cu_slabbuf;
delete [] factors;
factors=NULL;
deallocate();
delete cu_part2grid;
cu_part2grid=NULL;
memory->destroy(part2grid);
part2grid = NULL;
}
/* ----------------------------------------------------------------------
called once before run
------------------------------------------------------------------------- */
void PPPMCuda::init()
{
cuda->shared_data.pppm.cudable_force=1;
//if(cuda->finished_run) {PPPM::init(); return;}
if (me == 0) {
if (screen) fprintf(screen,"PPPMCuda initialization ...\n");
if (logfile) fprintf(logfile,"PPPMCuda initialization ...\n");
}
// error check
if (domain->triclinic)
- error->all("Cannot (yet) use PPPMCuda with triclinic box");
- if (domain->dimension == 2) error->all("Cannot use PPPMCuda with 2d simulation");
+ error->all(FLERR,"Cannot (yet) use PPPMCuda with triclinic box");
+ if (domain->dimension == 2) error->all(FLERR,"Cannot use PPPMCuda with 2d simulation");
- if (!atom->q_flag) error->all("Kspace style requires atom attribute q");
+ if (!atom->q_flag) error->all(FLERR,"Kspace style requires atom attribute q");
if (slabflag == 0 && domain->nonperiodic > 0)
- error->all("Cannot use nonperiodic boundaries with PPPMCuda");
+ error->all(FLERR,"Cannot use nonperiodic boundaries with PPPMCuda");
if (slabflag == 1) {
if (domain->xperiodic != 1 || domain->yperiodic != 1 ||
domain->boundary[2][0] != 1 || domain->boundary[2][1] != 1)
- error->all("Incorrect boundaries with slab PPPMCuda");
+ error->all(FLERR,"Incorrect boundaries with slab PPPMCuda");
}
if (order > MAXORDER) {
char str[128];
sprintf(str,"PPPMCuda order cannot be greater than %d",MAXORDER);
- error->all(str);
+ error->all(FLERR,str);
}
// free all arrays previously allocated
deallocate();
// extract short-range Coulombic cutoff from pair style
qqrd2e = force->qqrd2e;
if (force->pair == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
int itmp=0;
double *p_cutoff = (double *) force->pair->extract("cut_coul",itmp);
if (p_cutoff == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
cutoff = *p_cutoff;
// if kspace is TIP4P, extract TIP4P params from pair style
qdist = 0.0;
if (strcmp(force->kspace_style,"pppm/tip4p") == 0) {
if (force->pair == NULL)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
double *p_qdist = (double *) force->pair->extract("qdist",itmp);
int *p_typeO = (int *) force->pair->extract("typeO",itmp);
int *p_typeH = (int *) force->pair->extract("typeH",itmp);
int *p_typeA = (int *) force->pair->extract("typeA",itmp);
int *p_typeB = (int *) force->pair->extract("typeB",itmp);
if (!p_qdist || !p_typeO || !p_typeH || !p_typeA || !p_typeB)
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
qdist = *p_qdist;
typeO = *p_typeO;
typeH = *p_typeH;
int typeA = *p_typeA;
int typeB = *p_typeB;
if (force->angle == NULL || force->bond == NULL)
- error->all("Bond and angle potentials must be defined for TIP4P");
+ error->all(FLERR,"Bond and angle potentials must be defined for TIP4P");
double theta = force->angle->equilibrium_angle(typeA);
double blen = force->bond->equilibrium_distance(typeB);
alpha = qdist / (2.0 * cos(0.5*theta) * blen);
}
// compute qsum & qsqsum and warn if not charge-neutral
qsum = qsqsum = 0.0;
for (int i = 0; i < atom->nlocal; i++) {
qsum += atom->q[i];
qsqsum += atom->q[i]*atom->q[i];
}
double tmp;
MPI_Allreduce(&qsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
qsum = tmp;
MPI_Allreduce(&qsqsum,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
qsqsum = tmp;
if (qsqsum == 0.0)
- error->all("Cannot use kspace solver on system with no charge");
+ error->all(FLERR,"Cannot use kspace solver on system with no charge");
if (fabs(qsum) > SMALL && me == 0) {
char str[128];
sprintf(str,"System is not charge neutral, net charge = %g",qsum);
- error->warning(str);
+ error->warning(FLERR,str);
}
// setup FFT grid resolution and g_ewald
// normally one iteration thru while loop is all that is required
// if grid stencil extends beyond neighbor proc, reduce order and try again
int iteration = 0;
while (order > 0) {
if (iteration && me == 0)
- error->warning("Reducing PPPMCuda order b/c stencil extends "
+ error->warning(FLERR,"Reducing PPPMCuda order b/c stencil extends "
"beyond neighbor processor");
iteration++;
set_grid();
if (nx_pppm >= OFFSET || ny_pppm >= OFFSET || nz_pppm >= OFFSET)
- error->all("PPPMCuda grid is too large");
+ error->all(FLERR,"PPPMCuda grid is too large");
// global indices of PPPMCuda grid range from 0 to N-1
// nlo_in,nhi_in = lower/upper limits of the 3d sub-brick of
// global PPPMCuda grid that I own without ghost cells
// for slab PPPMCuda, assign z grid as if it were not extended
nxlo_in = comm->myloc[0]*nx_pppm / comm->procgrid[0];
nxhi_in = (comm->myloc[0]+1)*nx_pppm / comm->procgrid[0] - 1;
nylo_in = comm->myloc[1]*ny_pppm / comm->procgrid[1];
nyhi_in = (comm->myloc[1]+1)*ny_pppm / comm->procgrid[1] - 1;
nzlo_in = comm->myloc[2] *
(static_cast<int> (nz_pppm/slab_volfactor)) / comm->procgrid[2];
nzhi_in = (comm->myloc[2]+1) *
(static_cast<int> (nz_pppm/slab_volfactor)) / comm->procgrid[2] - 1;
// nlower,nupper = stencil size for mapping particles to PPPMCuda grid
nlower = -(order-1)/2;
nupper = order/2;
// shift values for particle <-> grid mapping
// add/subtract OFFSET to avoid int(-0.75) = 0 when want it to be -1
if (order % 2) shift = OFFSET + 0.5;
else shift = OFFSET;
if (order % 2) shiftone = 0.0;
else shiftone = 0.5;
// nlo_out,nhi_out = lower/upper limits of the 3d sub-brick of
// global PPPMCuda grid that my particles can contribute charge to
// effectively nlo_in,nhi_in + ghost cells
// nlo,nhi = global coords of grid pt to "lower left" of smallest/largest
// position a particle in my box can be at
// dist[3] = particle position bound = subbox + skin/2.0 + qdist
// qdist = offset due to TIP4P fictitious charge
// convert to triclinic if necessary
// nlo_out,nhi_out = nlo,nhi + stencil size for particle mapping
// for slab PPPMCuda, assign z grid as if it were not extended
triclinic = domain->triclinic;
double *prd,*sublo,*subhi;
if (triclinic == 0) {
prd = domain->prd;
boxlo = domain->boxlo;
sublo = domain->sublo;
subhi = domain->subhi;
} else {
prd = domain->prd_lamda;
boxlo = domain->boxlo_lamda;
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
double xprd = prd[0];
double yprd = prd[1];
double zprd = prd[2];
double zprd_slab = zprd*slab_volfactor;
double dist[3];
double cuthalf = 0.5*neighbor->skin + qdist;
if (triclinic == 0) dist[0] = dist[1] = dist[2] = cuthalf;
else {
dist[0] = cuthalf/domain->prd[0];
dist[1] = cuthalf/domain->prd[1];
dist[2] = cuthalf/domain->prd[2];
}
int nlo,nhi;
nlo = static_cast<int> ((sublo[0]-dist[0]-boxlo[0]) *
nx_pppm/xprd + shift) - OFFSET;
nhi = static_cast<int> ((subhi[0]+dist[0]-boxlo[0]) *
nx_pppm/xprd + shift) - OFFSET;
nxlo_out = nlo + nlower;
nxhi_out = nhi + nupper;
nlo = static_cast<int> ((sublo[1]-dist[1]-boxlo[1]) *
ny_pppm/yprd + shift) - OFFSET;
nhi = static_cast<int> ((subhi[1]+dist[1]-boxlo[1]) *
ny_pppm/yprd + shift) - OFFSET;
nylo_out = nlo + nlower;
nyhi_out = nhi + nupper;
nlo = static_cast<int> ((sublo[2]-dist[2]-boxlo[2]) *
nz_pppm/zprd_slab + shift) - OFFSET;
nhi = static_cast<int> ((subhi[2]+dist[2]-boxlo[2]) *
nz_pppm/zprd_slab + shift) - OFFSET;
nzlo_out = nlo + nlower;
nzhi_out = nhi + nupper;
// for slab PPPMCuda, change the grid boundary for processors at +z end
// to include the empty volume between periodically repeating slabs
// for slab PPPMCuda, want charge data communicated from -z proc to +z proc,
// but not vice versa, also want field data communicated from +z proc to
// -z proc, but not vice versa
// this is accomplished by nzhi_in = nzhi_out on +z end (no ghost cells)
if (slabflag && ((comm->myloc[2]+1) == (comm->procgrid[2]))) {
nzhi_in = nz_pppm - 1;
nzhi_out = nz_pppm - 1;
}
// nlo_ghost,nhi_ghost = # of planes I will recv from 6 directions
// that overlay domain I own
// proc in that direction tells me via sendrecv()
// if no neighbor proc, value is from self since I have ghosts regardless
int nplanes;
MPI_Status status;
nplanes = nxlo_in - nxlo_out;
if (comm->procneigh[0][0] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[0][0],0,
&nxhi_ghost,1,MPI_INT,comm->procneigh[0][1],0,
world,&status);
else nxhi_ghost = nplanes;
nplanes = nxhi_out - nxhi_in;
if (comm->procneigh[0][1] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[0][1],0,
&nxlo_ghost,1,MPI_INT,comm->procneigh[0][0],
0,world,&status);
else nxlo_ghost = nplanes;
nplanes = nylo_in - nylo_out;
if (comm->procneigh[1][0] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[1][0],0,
&nyhi_ghost,1,MPI_INT,comm->procneigh[1][1],0,
world,&status);
else nyhi_ghost = nplanes;
nplanes = nyhi_out - nyhi_in;
if (comm->procneigh[1][1] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[1][1],0,
&nylo_ghost,1,MPI_INT,comm->procneigh[1][0],0,
world,&status);
else nylo_ghost = nplanes;
nplanes = nzlo_in - nzlo_out;
if (comm->procneigh[2][0] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[2][0],0,
&nzhi_ghost,1,MPI_INT,comm->procneigh[2][1],0,
world,&status);
else nzhi_ghost = nplanes;
nplanes = nzhi_out - nzhi_in;
if (comm->procneigh[2][1] != me)
MPI_Sendrecv(&nplanes,1,MPI_INT,comm->procneigh[2][1],0,
&nzlo_ghost,1,MPI_INT,comm->procneigh[2][0],0,
world,&status);
else nzlo_ghost = nplanes;
// test that ghost overlap is not bigger than my sub-domain
int flag = 0;
if (nxlo_ghost > nxhi_in-nxlo_in+1) flag = 1;
if (nxhi_ghost > nxhi_in-nxlo_in+1) flag = 1;
if (nylo_ghost > nyhi_in-nylo_in+1) flag = 1;
if (nyhi_ghost > nyhi_in-nylo_in+1) flag = 1;
if (nzlo_ghost > nzhi_in-nzlo_in+1) flag = 1;
if (nzhi_ghost > nzhi_in-nzlo_in+1) flag = 1;
int flag_all;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
if (flag_all == 0) break;
order--;
}
- if (order == 0) error->all("PPPMCuda order has been reduced to 0");
+ if (order == 0) error->all(FLERR,"PPPMCuda order has been reduced to 0");
//printf("PPPMCuda: order is %i\n");
// decomposition of FFT mesh
// global indices range from 0 to N-1
// proc owns entire x-dimension, clump of columns in y,z dimensions
// npey_fft,npez_fft = # of procs in y,z dims
// if nprocs is small enough, proc can own 1 or more entire xy planes,
// else proc owns 2d sub-blocks of yz plane
// me_y,me_z = which proc (0-npe_fft-1) I am in y,z dimensions
// nlo_fft,nhi_fft = lower/upper limit of the section
// of the global FFT mesh that I own
int npey_fft,npez_fft;
if (nz_pppm >= nprocs) {
npey_fft = 1;
npez_fft = nprocs;
} else procs2grid2d(nprocs,ny_pppm,nz_pppm,&npey_fft,&npez_fft);
int me_y = me % npey_fft;
int me_z = me / npey_fft;
nxlo_fft = 0;
nxhi_fft = nx_pppm - 1;
nylo_fft = me_y*ny_pppm/npey_fft;
nyhi_fft = (me_y+1)*ny_pppm/npey_fft - 1;
nzlo_fft = me_z*nz_pppm/npez_fft;
nzhi_fft = (me_z+1)*nz_pppm/npez_fft - 1;
// PPPMCuda grid for this proc, including ghosts
ngrid = (nxhi_out-nxlo_out+1) * (nyhi_out-nylo_out+1) *
(nzhi_out-nzlo_out+1);
// FFT arrays on this proc, without ghosts
// nfft = FFT points in FFT decomposition on this proc
// nfft_brick = FFT points in 3d brick-decomposition on this proc
// nfft_both = greater of 2 values
nfft = (nxhi_fft-nxlo_fft+1) * (nyhi_fft-nylo_fft+1) *
(nzhi_fft-nzlo_fft+1);
int nfft_brick = (nxhi_in-nxlo_in+1) * (nyhi_in-nylo_in+1) *
(nzhi_in-nzlo_in+1);
nfft_both = MAX(nfft,nfft_brick);
// buffer space for use in brick2fft and fillbrick
// idel = max # of ghost planes to send or recv in +/- dir of each dim
// nx,ny,nz = owned planes (including ghosts) in each dim
// nxx,nyy,nzz = max # of grid cells to send in each dim
// nbuf = max in any dim, augment by 3x for components of vd_xyz in fillbrick
int idelx,idely,idelz,nx,ny,nz,nxx,nyy,nzz;
idelx = MAX(nxlo_ghost,nxhi_ghost);
idelx = MAX(idelx,nxhi_out-nxhi_in);
idelx = MAX(idelx,nxlo_in-nxlo_out);
idely = MAX(nylo_ghost,nyhi_ghost);
idely = MAX(idely,nyhi_out-nyhi_in);
idely = MAX(idely,nylo_in-nylo_out);
idelz = MAX(nzlo_ghost,nzhi_ghost);
idelz = MAX(idelz,nzhi_out-nzhi_in);
idelz = MAX(idelz,nzlo_in-nzlo_out);
nx = nxhi_out - nxlo_out + 1;
ny = nyhi_out - nylo_out + 1;
nz = nzhi_out - nzlo_out + 1;
nxx = idelx * ny * nz;
nyy = idely * nx * nz;
nzz = idelz * nx * ny;
nbuf = MAX(nxx,nyy);
nbuf = MAX(nbuf,nzz);
nbuf *= 3;
// print stats
int ngrid_max,nfft_both_max,nbuf_max;
MPI_Allreduce(&ngrid,&ngrid_max,1,MPI_INT,MPI_MAX,world);
MPI_Allreduce(&nfft_both,&nfft_both_max,1,MPI_INT,MPI_MAX,world);
MPI_Allreduce(&nbuf,&nbuf_max,1,MPI_INT,MPI_MAX,world);
if (me == 0) {
if (screen) fprintf(screen," brick FFT buffer size/proc = %d %d %d\n",
ngrid_max,nfft_both_max,nbuf_max);
if (logfile) fprintf(logfile," brick FFT buffer size/proc = %d %d %d\n",
ngrid_max,nfft_both_max,nbuf_max);
}
cuda_shared_pppm* ap=&(cuda->shared_data.pppm);
ap->density_intScale=density_intScale;
ap->nxlo_in=nxlo_in;
ap->nxhi_in=nxhi_in;
ap->nxlo_out=nxlo_out;
ap->nxhi_out=nxhi_out;
ap->nylo_in=nylo_in;
ap->nyhi_in=nyhi_in;
ap->nylo_out=nylo_out;
ap->nyhi_out=nyhi_out;
ap->nzlo_in=nzlo_in;
ap->nzhi_in=nzhi_in;
ap->nzlo_out=nzlo_out;
ap->nzhi_out=nzhi_out;
ap->nxlo_in=nxlo_fft;
ap->nxhi_in=nxhi_fft;
ap->nylo_in=nylo_fft;
ap->nyhi_in=nyhi_fft;
ap->nzlo_in=nzlo_fft;
ap->nzhi_in=nzhi_fft;
ap->nx_pppm=nx_pppm;
ap->ny_pppm=ny_pppm;
ap->nz_pppm=nz_pppm;
ap->qqrd2e=qqrd2e;
ap->order=order;
ap->nmax=nmax;
ap->nlocal=atom->nlocal;
ap->delxinv=delxinv;
ap->delyinv=delyinv;
ap->delzinv=delzinv;
ap->nlower=nlower;
ap->nupper=nupper;
ap->shiftone=shiftone;
// allocate K-space dependent memory
allocate();
// pre-compute Green's function denomiator expansion
// pre-compute 1d charge distribution coefficients
compute_gf_denom();
compute_rho_coeff();
}
/* ----------------------------------------------------------------------
adjust PPPMCuda coeffs, called initially and whenever volume has changed
------------------------------------------------------------------------- */
void PPPMCuda::setup()
{
int i,j,k,l,m,n;
double *prd;
cu_gf_b->upload();
// volume-dependent factors
// adjust z dimension for 2d slab PPPMCuda
// z dimension for 3d PPPMCuda is zprd since slab_volfactor = 1.0
if (triclinic == 0) prd = domain->prd;
else prd = domain->prd_lamda;
double xprd = prd[0];
double yprd = prd[1];
double zprd = prd[2];
double zprd_slab = zprd*slab_volfactor;
volume = xprd * yprd * zprd_slab;
delxinv = nx_pppm/xprd;
delyinv = ny_pppm/yprd;
delzinv = nz_pppm/zprd_slab;
delvolinv = delxinv*delyinv*delzinv;
double unitkx = (2.0*PI/xprd);
double unitky = (2.0*PI/yprd);
double unitkz = (2.0*PI/zprd_slab);
// fkx,fky,fkz for my FFT grid pts
Cuda_PPPM_Setup_fkxyz_vg(nx_pppm, ny_pppm,nz_pppm,unitkx,unitky,unitkz,g_ewald);
/* cu_vg->download();
int offset=8100-2;//10*(nxhi_fft-nxlo_fft+1)*(nyhi_fft-nylo_fft+1)+10*(nyhi_fft-nylo_fft+1);
for (int i=nxlo_fft; i <= nxhi_fft+1;i++) printf("%e ",vg[i-nxlo_fft+offset][0]);
printf("\n\n");
double per;
#ifndef FFT_CUFFT
for (i = nxlo_fft; i <= nxhi_fft; i++) {
per = i - nx_pppm*(2*i/nx_pppm);
fkx[i] = unitkx*per;
}
for (i = nylo_fft; i <= nyhi_fft; i++) {
per = i - ny_pppm*(2*i/ny_pppm);
fky[i] = unitky*per;
}
for (i = nzlo_fft; i <= nzhi_fft; i++) {
per = i - nz_pppm*(2*i/nz_pppm);
fkz[i] = unitkz*per;
}
#endif
#ifdef FFT_CUFFT
for (i = 0; i < nx_pppm; i++) {
per = i - nx_pppm*(2*i/nx_pppm);
fkx[i] = unitkx*per;
}
for (i = 0; i < ny_pppm; i++) {
per = i - ny_pppm*(2*i/ny_pppm);
fky[i] = unitky*per;
}
for (i = 0; i < nz_pppm; i++) {
per = i - nz_pppm*(2*i/nz_pppm);
fkz[i] = unitkz*per;
}
#endif
// virial coefficients
double sqk,vterm;
int save_n=0;
int s_i,s_j,s_k;
double max=0.0;
n = 0;
for (k = nzlo_fft; k <= nzhi_fft; k++) {
for (j = nylo_fft; j <= nyhi_fft; j++) {
for (i = nxlo_fft; i <= nxhi_fft; i++) {
sqk = fkx[i]*fkx[i] + fky[j]*fky[j] + fkz[k]*fkz[k];
if(n==8100) printf("%lf\n",sqk);
if (sqk == 0.0) {
vg[n][0] = 0.0;
vg[n][1] = 0.0;
vg[n][2] = 0.0;
vg[n][3] = 0.0;
vg[n][4] = 0.0;
vg[n][5] = 0.0;
} else {
vterm = -2.0 * (1.0/sqk + 0.25/(g_ewald*g_ewald));
double tmp=vg[n][0];
vg[n][0] = 1.0 + vterm*fkx[i]*fkx[i];
if(((vg[n][0]-tmp)*(vg[n][0]-tmp)>1e-6)&&(save_n==0)) {save_n=n;s_k=k;s_j=j;s_i=i;}
vg[n][1] = 1.0 + vterm*fky[j]*fky[j];
vg[n][2] = 1.0 + vterm*fkz[k]*fkz[k];
vg[n][3] = vterm*fkx[i]*fky[j];
vg[n][4] = vterm*fkx[i]*fkz[k];
vg[n][5] = vterm*fky[j]*fkz[k];
//if(vg[n][0]>max) {max=vg[n][0]; save_n=n;}
}
n++;
}
}
}
printf("%lf %i %i %i %i\n",max,save_n,s_k,s_j,s_i);
for (int i=nxlo_fft; i <= nxhi_fft;i++) printf("%e ",vg[i-nxlo_fft+offset][0]);
printf("\n\n");
//cu_fkx->upload();
//cu_fky->upload();
// cu_fkz->upload();
//cu_vg->upload(); */
// modified (Hockney-Eastwood) Coulomb Green's function
double sqk;
int nx,ny,nz,kper,lper,mper;
double snx,sny,snz,snx2,sny2,snz2;
double argx,argy,argz,wx,wy,wz,sx,sy,sz,qx,qy,qz;
double sum1,dot1,dot2;
double numerator,denominator;
int nbx = static_cast<int> ((g_ewald*xprd/(PI*nx_pppm)) *
pow(-log(EPS_HOC),0.25));
int nby = static_cast<int> ((g_ewald*yprd/(PI*ny_pppm)) *
pow(-log(EPS_HOC),0.25));
int nbz = static_cast<int> ((g_ewald*zprd_slab/(PI*nz_pppm)) *
pow(-log(EPS_HOC),0.25));
Cuda_PPPM_setup_greensfn(nx_pppm,ny_pppm,nz_pppm,unitkx,unitky,unitkz,g_ewald,
nbx,nby,nbz,xprd,yprd,zprd_slab);
/*
double form = 1.0;
n = 0;
#ifndef FFT_CUFFT
for (m = nzlo_fft; m <= nzhi_fft; m++) {
#endif
#ifdef FFT_CUFFT
for (m = 0; m < nz_pppm; m++) {
#endif
mper = m - nz_pppm*(2*m/nz_pppm);
snz = sin(0.5*unitkz*mper*zprd_slab/nz_pppm);
snz2 = snz*snz;
#ifndef FFT_CUFFT
for (l = nylo_fft; l <= nyhi_fft; l++) {
#endif
#ifdef FFT_CUFFT
for (l = 0; l < ny_pppm; l++) {
#endif
lper = l - ny_pppm*(2*l/ny_pppm);
sny = sin(0.5*unitky*lper*yprd/ny_pppm);
sny2 = sny*sny;
#ifndef FFT_CUFFT
for (k = nxlo_fft; k <= nxhi_fft; k++) {
#endif
#ifdef FFT_CUFFT
for (k = 0; k < nx_pppm; k++) {
#endif
kper = k - nx_pppm*(2*k/nx_pppm);
snx = sin(0.5*unitkx*kper*xprd/nx_pppm);
snx2 = snx*snx;
sqk = pow(unitkx*kper,2.0) + pow(unitky*lper,2.0) +
pow(unitkz*mper,2.0);
if (sqk != 0.0) {
numerator = form*12.5663706/sqk;
denominator = gf_denom(snx2,sny2,snz2);
sum1 = 0.0;
for (nx = -nbx; nx <= nbx; nx++) {
qx = unitkx*(kper+nx_pppm*nx);
sx = exp(-.25*pow(qx/g_ewald,2.0));
wx = 1.0;
argx = 0.5*qx*xprd/nx_pppm;
if (argx != 0.0) wx = pow(sin(argx)/argx,order);
for (ny = -nby; ny <= nby; ny++) {
qy = unitky*(lper+ny_pppm*ny);
sy = exp(-.25*pow(qy/g_ewald,2.0));
wy = 1.0;
argy = 0.5*qy*yprd/ny_pppm;
if (argy != 0.0) wy = pow(sin(argy)/argy,order);
for (nz = -nbz; nz <= nbz; nz++) {
qz = unitkz*(mper+nz_pppm*nz);
sz = exp(-.25*pow(qz/g_ewald,2.0));
wz = 1.0;
argz = 0.5*qz*zprd_slab/nz_pppm;
if (argz != 0.0) wz = pow(sin(argz)/argz,order);
dot1 = unitkx*kper*qx + unitky*lper*qy + unitkz*mper*qz;
dot2 = qx*qx+qy*qy+qz*qz;
sum1 += (dot1/dot2) * sx*sy*sz * pow(wx*wy*wz,2.0);
}
}
}
greensfn[n++] = numerator*sum1/denominator;
} else greensfn[n++] = 0.0;
}
}
}*/
#ifdef FFT_CUFFT
//cu_greensfn->upload();
//cu_fkx->upload();
//cu_fky->upload();
//cu_fkz->upload();
//cu_vg->upload();
cu_vdx_brick->upload();
cu_vdy_brick->upload();
cu_vdz_brick->upload();
#endif
cu_rho_coeff->upload();
cu_density_brick->memset_device(0);
pppm_device_init_setup(&cuda->shared_data,shiftone,delxinv,delyinv,delzinv,nlower,nupper);
}
/* ----------------------------------------------------------------------
compute the PPPMCuda long-range force, energy, virial
------------------------------------------------------------------------- */
void PPPMCuda::compute(int eflag, int vflag)
{
// printf("PPPMCuda::compute START\n");
cuda_shared_atom* cu_atom = & cuda->shared_data.atom;
int i;
timespec starttime;
timespec endtime;
timespec starttotal;
timespec endtotal;
// convert atoms from box to lamda coords
if (triclinic == 0) boxlo = domain->boxlo;
else {
boxlo = domain->boxlo_lamda;
domain->x2lamda(atom->nlocal);
}
// extend size of per-atom arrays if necessary
if ((cu_atom->update_nmax)||(old_nmax==0)) {
memory->destroy(part2grid);
nmax = atom->nmax;
memory->create(part2grid,nmax,3,"pppm:part2grid");
delete cu_part2grid;
delete [] adev_data_array;
adev_data_array=new dev_array[1];
cu_part2grid = new cCudaData<int , int , yx > ((int*)part2grid,adev_data_array, nmax,3);
pppm_device_update(&cuda->shared_data,cu_part2grid->dev_data(),atom->nlocal,atom->nmax);
old_nmax=nmax;
}
if(cu_atom->update_nlocal) {pppm_update_nlocal(cu_atom->nlocal);}
energy = 0.0;
if (vflag)
{
for (i = 0; i < 6; i++) virial[i] = 0.0;
cu_virial->memset_device(0);
}
if(eflag) cu_energy->memset_device(0);
clock_gettime(CLOCK_REALTIME,&starttotal);
// find grid points for all my particles
// map my particle charge onto my local 3d density grid
clock_gettime(CLOCK_REALTIME,&starttime);
particle_map();
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.pppm_particle_map+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
//cu_part2grid->download();
clock_gettime(CLOCK_REALTIME,&starttime);
make_rho();
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.pppm_make_rho+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
// all procs communicate density values from their ghost cells
// to fully sum contribution in their 3d bricks
// remap from 3d decomposition to FFT decomposition
int nprocs=comm->nprocs;
clock_gettime(CLOCK_REALTIME,&starttime);
if(nprocs>1)
{
cu_density_brick->download();
brick2fft();
}
else
{
#ifdef FFT_CUFFT
pppm_initfftdata(&cuda->shared_data,(PPPM_FLOAT*)cu_density_brick->dev_data(),(FFT_FLOAT*)cu_work2->dev_data());
#endif
}
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.pppm_brick2fft+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
// compute potential gradient on my FFT grid and
// portion of e_long on this proc's FFT grid
// return gradients (electric fields) in 3d brick decomposition
clock_gettime(CLOCK_REALTIME,&starttime);
poisson(eflag,vflag);
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.pppm_poisson+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
// all procs communicate E-field values to fill ghost cells
// surrounding their 3d bricks
// not necessary since all the calculations are done on one proc
// calculate the force on my particles
//cu_vdx_brick->download();
//cu_vdy_brick->download();
//cu_vdz_brick->download();
clock_gettime(CLOCK_REALTIME,&starttime);
fieldforce();
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.pppm_fieldforce+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
// sum energy across procs and add in volume-dependent term
clock_gettime(CLOCK_REALTIME,&endtotal);
cuda->shared_data.cuda_timings.pppm_compute+=(endtotal.tv_sec-starttotal.tv_sec+1.0*(endtotal.tv_nsec-starttotal.tv_nsec)/1000000000);
if (eflag) {
double energy_all;
MPI_Allreduce(&energy,&energy_all,1,MPI_DOUBLE,MPI_SUM,world);
energy = energy_all;
energy *= 0.5*volume;
energy -= g_ewald*qsqsum/1.772453851 +
0.5*PI*qsum*qsum / (g_ewald*g_ewald*volume);
energy *= qqrd2e;
}
// sum virial across procs
if (vflag) {
double virial_all[6];
MPI_Allreduce(virial,virial_all,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) virial[i] = 0.5*qqrd2e*volume*virial_all[i];
}
// 2d slab correction
if (slabflag) slabcorr(eflag);
// convert atoms back from lamda to box coords
if (triclinic) domain->lamda2x(atom->nlocal);
if(firstpass) firstpass=false;
}
/* ----------------------------------------------------------------------
allocate memory that depends on # of K-vectors and order
------------------------------------------------------------------------- */
void PPPMCuda::allocate()
{
//printf("PPPMCuda::allocate START Mem: %i\n",CudaWrapper_CheckMemUseage());
/*if(sizeof(CUDA_FLOAT)==sizeof(float)) printf("PPPMCuda: Using single precision\n");
#ifdef PPPM_PRECISION
if(sizeof(PPPM_FLOAT)==sizeof(float)) printf("PPPMCuda: Using single precision for pppm core\n");
if(sizeof(PPPM_FLOAT)==sizeof(double)) printf("PPPMCuda: Using double precision for pppm core\n");
#endif
#ifdef ENERGY_PRECISION
if(sizeof(ENERGY_FLOAT)==sizeof(float)) printf("PPPMCuda: Using single precision for energy\n");
if(sizeof(ENERGY_FLOAT)==sizeof(double)) printf("PPPMCuda: Using double precision for energy\n");
#endif
#ifdef ENERGY_PRECISION
if(sizeof(FFT_FLOAT)==sizeof(float)) printf("PPPMCuda: Using single precision for fft\n");
if(sizeof(FFT_FLOAT)==sizeof(double)) printf("PPPMCuda: Using double precision for fft\n");
#endif
#ifdef X_PRECISION
if(sizeof(X_FLOAT)==sizeof(float)) printf("PPPMCuda: Using single precision for positions\n");
if(sizeof(X_FLOAT)==sizeof(double)) printf("PPPMCuda: Using double precision for positions\n");
#endif
#ifdef F_PRECISION
if(sizeof(F_FLOAT)==sizeof(float)) printf("PPPMCuda: Using single precision for forces\n");
if(sizeof(F_FLOAT)==sizeof(double)) printf("PPPMCuda: Using double precision for forces\n");
#endif*/
//if(sizeof(PPPM_FLOAT)==sizeof(float)) printf("PPPMCuda: Using single precision\n");
struct dev_array* dev_tmp=new struct dev_array[20];
int n_cudata=0;
memory->create3d_offset(density_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:density_brick");
memory->create3d_offset(density_brick_int,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:density_brick_int");
cu_density_brick = new cCudaData<double, PPPM_FLOAT, x> ((double*) &(density_brick[nzlo_out][nylo_out][nxlo_out]), & (dev_tmp[n_cudata++]),
(nzhi_out-nzlo_out+1)*(nyhi_out-nylo_out+1)*(nxhi_out-nxlo_out+1));
cu_density_brick_int = new cCudaData<int, int, x> ((int*) &(density_brick_int[nzlo_out][nylo_out][nxlo_out]), & (dev_tmp[n_cudata++]),
(nzhi_out-nzlo_out+1)*(nyhi_out-nylo_out+1)*(nxhi_out-nxlo_out+1));
memory->create3d_offset(vdx_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vdx_brick");
memory->create3d_offset(vdx_brick_tmp,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vdx_brick_tmp");
cu_vdx_brick = new cCudaData<double, PPPM_FLOAT, x> ((double*) &(vdx_brick[nzlo_out][nylo_out][nxlo_out]), & (dev_tmp[n_cudata++]),
(nzhi_out-nzlo_out+1)*(nyhi_out-nylo_out+1)*(nxhi_out-nxlo_out+1));
memory->create3d_offset(vdy_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vdy_brick");
cu_vdy_brick = new cCudaData<double, PPPM_FLOAT, x> ((double*) &(vdy_brick[nzlo_out][nylo_out][nxlo_out]), & (dev_tmp[n_cudata++]),
(nzhi_out-nzlo_out+1)*(nyhi_out-nylo_out+1)*(nxhi_out-nxlo_out+1));
memory->create3d_offset(vdz_brick,nzlo_out,nzhi_out,nylo_out,nyhi_out,
nxlo_out,nxhi_out,"pppm:vdz_brick");
cu_vdz_brick = new cCudaData<double, PPPM_FLOAT, x> ((double*) &(vdz_brick[nzlo_out][nylo_out][nxlo_out]), & (dev_tmp[n_cudata++]),
(nzhi_out-nzlo_out+1)*(nyhi_out-nylo_out+1)*(nxhi_out-nxlo_out+1));
memory->create(density_fft,nfft_both,"pppm:density_fft");
cu_density_fft = new cCudaData<double, PPPM_FLOAT, x> (density_fft, & (dev_tmp[n_cudata++]),nfft_both);
cu_energy = new cCudaData<double, ENERGY_FLOAT, x> (NULL, &(dev_tmp[n_cudata++]),ny_pppm*nz_pppm);
cu_virial = new cCudaData<double, ENERGY_FLOAT, x> (NULL, &(dev_tmp[n_cudata++]),ny_pppm*nz_pppm*6);
memory->create(greensfn,nfft_both,"pppm:greensfn");
cu_greensfn = new cCudaData<double, PPPM_FLOAT, x> (greensfn, & (dev_tmp[n_cudata++]) , nx_pppm*ny_pppm*nz_pppm);
memory->create(work1,2*nx_pppm*ny_pppm*nz_pppm,"pppm:work1");
memory->create(work2,2*nx_pppm*ny_pppm*nz_pppm,"pppm:work2");
memory->create(work3,2*nx_pppm*ny_pppm*nz_pppm,"pppm:work3");
cu_work1 = new cCudaData<double, FFT_FLOAT, x> (work1, & (dev_tmp[n_cudata++]) , 2*nx_pppm*ny_pppm*nz_pppm);
cu_work2 = new cCudaData<double, FFT_FLOAT, x> (work2, & (dev_tmp[n_cudata++]) , 2*nx_pppm*ny_pppm*nz_pppm);
cu_work3 = new cCudaData<double, FFT_FLOAT, x> (work3, & (dev_tmp[n_cudata++]) , 2*nx_pppm*ny_pppm*nz_pppm);
memory->create(fkx,nx_pppm,"pppmcuda:fkx");
cu_fkx = new cCudaData<double, PPPM_FLOAT, x> (fkx, & (dev_tmp[n_cudata++]) , nx_pppm);
memory->create(fky,ny_pppm,"pppmcuda:fky");
cu_fky = new cCudaData<double, PPPM_FLOAT, x> (fky, & (dev_tmp[n_cudata++]) , ny_pppm);
memory->create(fkz,nz_pppm,"pppmcuda:fkz");
cu_fkz = new cCudaData<double, PPPM_FLOAT, x> (fkz, & (dev_tmp[n_cudata++]) , nz_pppm);
memory->create(vg,nfft_both,6,"pppm:vg");
cu_vg = new cCudaData<double, PPPM_FLOAT, xy> ((double*)vg, & (dev_tmp[n_cudata++]) , nfft_both,6);
memory->create(buf1,nbuf,"pppm:buf1");
memory->create(buf2,nbuf,"pppm:buf2");
// summation coeffs
gf_b = new double[order];
cu_gf_b = new cCudaData<double,PPPM_FLOAT,x> (gf_b, &(dev_tmp[n_cudata++]) , order);
memory->create2d_offset(rho1d,3,-order/2,order/2,"pppm:rho1d");
memory->create2d_offset(rho_coeff,order,(1-order)/2,order/2,"pppm:rho_coeff");
cu_rho_coeff = new cCudaData<double, PPPM_FLOAT, x> ((double*) &(rho_coeff[0][(1-order)/2]), & (dev_tmp[n_cudata++]) , order*(order/2-(1-order)/2+1));
debugdata=new PPPM_FLOAT[100];
cu_debugdata = new cCudaData<PPPM_FLOAT, PPPM_FLOAT, x> (debugdata,& (dev_tmp[n_cudata++]),100);
cu_flag = new cCudaData<int, int, x> (&global_flag,& (dev_tmp[n_cudata++]),3);
// create 2 FFTs and a Remap
// 1st FFT keeps data in FFT decompostion
// 2nd FFT returns data in 3d brick decomposition
// remap takes data from 3d brick to FFT decomposition
int tmp;
fft1c = new FFT3dCuda(lmp,world,nx_pppm,ny_pppm,nz_pppm,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
0,0,&tmp,true);
fft2c = new FFT3dCuda(lmp,world,nx_pppm,ny_pppm,nz_pppm,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in,
0,0,&tmp,false);
#ifdef FFT_CUFFT
fft1c->set_cudata(cu_work2->dev_data(),cu_work1->dev_data());
fft2c->set_cudata(cu_work2->dev_data(),cu_work3->dev_data());
#endif
remap = new Remap(lmp,world,
nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in,
nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,
1,0,0,2);
pppm_device_init(cu_density_brick->dev_data(), cu_vdx_brick->dev_data(), cu_vdy_brick->dev_data(), cu_vdz_brick->dev_data(), cu_density_fft->dev_data(),cu_energy->dev_data(),cu_virial->dev_data()
, cu_work1->dev_data(), cu_work2->dev_data(), cu_work3->dev_data(), cu_greensfn->dev_data(), cu_fkx->dev_data(), cu_fky->dev_data(), cu_fkz->dev_data(), cu_vg->dev_data()
,nxlo_in,nxhi_in,nylo_in,nyhi_in,nzlo_in,nzhi_in,nxlo_out,nxhi_out,nylo_out,nyhi_out,nzlo_out,nzhi_out,nx_pppm,ny_pppm,nz_pppm
,nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,cu_gf_b->dev_data()
,qqrd2e,order,cu_rho_coeff->dev_data(),cu_debugdata->dev_data(),cu_density_brick_int->dev_data(),slabflag
);
}
/* ----------------------------------------------------------------------
deallocate memory that depends on # of K-vectors and order
---------------------------------------------------------------------- */
void PPPMCuda::deallocate()
{
memory->destroy3d_offset(density_brick,nzlo_out,nylo_out,nxlo_out);
memory->destroy3d_offset(vdx_brick,nzlo_out,nylo_out,nxlo_out);
memory->destroy3d_offset(vdy_brick,nzlo_out,nylo_out,nxlo_out);
memory->destroy3d_offset(vdz_brick,nzlo_out,nylo_out,nxlo_out);
density_brick = vdx_brick = vdy_brick = vdz_brick = NULL;
memory->destroy(density_fft);
memory->destroy(greensfn);
memory->destroy(work1);
memory->destroy(work2);
memory->destroy(vg);
density_fft = NULL;
greensfn = NULL;
work1 = NULL;
work2 = NULL;
vg = NULL;
memory->destroy(fkx);
memory->destroy(fky);
memory->destroy(fkz);
fkx = NULL;
fky = NULL;
fkz = NULL;
delete cu_density_brick;
delete cu_density_brick_int;
delete cu_vdx_brick;
delete cu_vdy_brick;
delete cu_vdz_brick;
delete cu_density_fft;
delete cu_energy;
delete cu_virial;
#ifdef FFT_CUFFT
delete cu_greensfn;
delete cu_gf_b;
delete cu_vg;
delete cu_work1;
delete cu_work2;
delete cu_work3;
delete cu_fkx;
delete cu_fky;
delete cu_fkz;
#endif
delete cu_flag;
delete cu_debugdata;
delete cu_rho_coeff;
cu_vdx_brick = cu_vdy_brick = cu_vdz_brick = NULL;
cu_density_brick = NULL;
cu_density_brick_int = NULL;
cu_density_fft = NULL;
cu_energy=NULL;
cu_virial=NULL;
#ifdef FFT_CUFFT
cu_greensfn = NULL;
cu_gf_b = NULL;
cu_work1 = cu_work2 = cu_work3 = NULL;
cu_vg = NULL;
cu_fkx = cu_fky = cu_fkz = NULL;
#endif
cu_flag = NULL;
cu_debugdata = NULL;
cu_rho_coeff = NULL;
cu_part2grid = NULL;
memory->destroy(buf1);
memory->destroy(buf2);
delete [] gf_b;
gf_b = NULL;
memory->destroy2d_offset(rho1d,-order/2); rho1d = NULL;
memory->destroy2d_offset(rho_coeff,(1-order)/2); rho_coeff = NULL;
delete fft1c;
fft1c = NULL;
double end=CudaWrapper_CheckMemUseage()/1024/1024;
delete fft2c;
fft2c = NULL;
delete remap;
remap = NULL;
buf1 = NULL;
buf2 = NULL;
}
/* ----------------------------------------------------------------------
set size of FFT grid (nx,ny,nz_pppm) and g_ewald
-------------------------------------------------------------------------*/
void PPPMCuda::set_grid()
{
// see JCP 109, pg 7698 for derivation of coefficients
// higher order coefficients may be computed if needed
double **acons;
memory->create(acons,8,7,"pppm:acons");
acons[1][0] = 2.0 / 3.0;
acons[2][0] = 1.0 / 50.0;
acons[2][1] = 5.0 / 294.0;
acons[3][0] = 1.0 / 588.0;
acons[3][1] = 7.0 / 1440.0;
acons[3][2] = 21.0 / 3872.0;
acons[4][0] = 1.0 / 4320.0;
acons[4][1] = 3.0 / 1936.0;
acons[4][2] = 7601.0 / 2271360.0;
acons[4][3] = 143.0 / 28800.0;
acons[5][0] = 1.0 / 23232.0;
acons[5][1] = 7601.0 / 13628160.0;
acons[5][2] = 143.0 / 69120.0;
acons[5][3] = 517231.0 / 106536960.0;
acons[5][4] = 106640677.0 / 11737571328.0;
acons[6][0] = 691.0 / 68140800.0;
acons[6][1] = 13.0 / 57600.0;
acons[6][2] = 47021.0 / 35512320.0;
acons[6][3] = 9694607.0 / 2095994880.0;
acons[6][4] = 733191589.0 / 59609088000.0;
acons[6][5] = 326190917.0 / 11700633600.0;
acons[7][0] = 1.0 / 345600.0;
acons[7][1] = 3617.0 / 35512320.0;
acons[7][2] = 745739.0 / 838397952.0;
acons[7][3] = 56399353.0 / 12773376000.0;
acons[7][4] = 25091609.0 / 1560084480.0;
acons[7][5] = 1755948832039.0 / 36229939200000.0;
acons[7][6] = 4887769399.0 / 37838389248.0;
double q2 = qsqsum / force->dielectric;
bigint natoms = atom->natoms;
// use xprd,yprd,zprd even if triclinic so grid size is the same
// adjust z dimension for 2d slab PPPMCuda
// 3d PPPMCuda just uses zprd since slab_volfactor = 1.0
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double zprd_slab = zprd*slab_volfactor;
// make initial g_ewald estimate
// based on desired error and real space cutoff
// fluid-occupied volume used to estimate real-space error
// zprd used rather than zprd_slab
double h_x,h_y,h_z;
if (!gewaldflag)
g_ewald = sqrt(-log(precision*sqrt(natoms*cutoff*xprd*yprd*zprd) /
(2.0*q2))) / cutoff;
// set optimal nx_pppm,ny_pppm,nz_pppm based on order and precision
// nz_pppm uses extended zprd_slab instead of zprd
// h = 1/g_ewald is upper bound on h such that h*g_ewald <= 1
// reduce it until precision target is met
if (!gridflag) {
double err;
h_x = h_y = h_z = 1/g_ewald;
nx_pppm = static_cast<int> (xprd/h_x + 1);
ny_pppm = static_cast<int> (yprd/h_y + 1);
nz_pppm = static_cast<int> (zprd_slab/h_z + 1);
err = rms(h_x,xprd,natoms,q2,acons);
while (err > precision) {
err = rms(h_x,xprd,natoms,q2,acons);
nx_pppm++;
h_x = xprd/nx_pppm;
}
err = rms(h_y,yprd,natoms,q2,acons);
while (err > precision) {
err = rms(h_y,yprd,natoms,q2,acons);
ny_pppm++;
h_y = yprd/ny_pppm;
}
err = rms(h_z,zprd_slab,natoms,q2,acons);
while (err > precision) {
err = rms(h_z,zprd_slab,natoms,q2,acons);
nz_pppm++;
h_z = zprd_slab/nz_pppm;
}
}
// boost grid size until it is factorable
while (!factorable(nx_pppm)) nx_pppm++;
while (!factorable(ny_pppm)) ny_pppm++;
while (!factorable(nz_pppm)) nz_pppm++;
// if allowed try to change grid size until it is a power of a single prime factor
if(precisionmodify!='=')
{
if (me == 0) {
if (screen) {
fprintf(screen,"Initial grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
}
if (logfile) {
fprintf(logfile,"Initial grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
}
}
make_power_of_prime(&nx_pppm);
make_power_of_prime(&ny_pppm);
make_power_of_prime(&nz_pppm);
if (me == 0) {
if (screen) {
fprintf(screen,"Modified grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
}
if (logfile) {
fprintf(logfile,"Modified grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
}
}
}
// adjust g_ewald for new grid size
h_x = xprd/nx_pppm;
h_y = yprd/ny_pppm;
h_z = zprd_slab/nz_pppm;
if (!gewaldflag) {
double gew1,gew2,dgew,f,fmid,hmin,rtb;
int ncount;
gew1 = 0.0;
g_ewald = gew1;
f = diffpr(h_x,h_y,h_z,q2,acons);
hmin = MIN(h_x,MIN(h_y,h_z));
gew2 = 10/hmin;
g_ewald = gew2;
fmid = diffpr(h_x,h_y,h_z,q2,acons);
- if (f*fmid >= 0.0) error->all("Cannot compute PPPMCuda G");
+ if (f*fmid >= 0.0) error->all(FLERR,"Cannot compute PPPMCuda G");
rtb = f < 0.0 ? (dgew=gew2-gew1,gew1) : (dgew=gew1-gew2,gew2);
ncount = 0;
while (fabs(dgew) > SMALL && fmid != 0.0) {
dgew *= 0.5;
g_ewald = rtb + dgew;
fmid = diffpr(h_x,h_y,h_z,q2,acons);
if (fmid <= 0.0) rtb = g_ewald;
ncount++;
- if (ncount > LARGE) error->all("Cannot compute PPPMCuda G");
+ if (ncount > LARGE) error->all(FLERR,"Cannot compute PPPMCuda G");
}
}
// final RMS precision
double lprx = rms(h_x,xprd,natoms,q2,acons);
double lpry = rms(h_y,yprd,natoms,q2,acons);
double lprz = rms(h_z,zprd_slab,natoms,q2,acons);
double lpr = sqrt(lprx*lprx + lpry*lpry + lprz*lprz) / sqrt(3.0);
double spr = 2.0*q2 * exp(-g_ewald*g_ewald*cutoff*cutoff) /
sqrt(natoms*cutoff*xprd*yprd*zprd_slab);
// free local memory
memory->destroy(acons);
// print info
if (me == 0) {
if (screen) {
fprintf(screen," G vector = %g\n",g_ewald);
fprintf(screen," grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
fprintf(screen," stencil order = %d\n",order);
fprintf(screen," RMS precision = %g\n",MAX(lpr,spr));
}
if (logfile) {
fprintf(logfile," G vector = %g\n",g_ewald);
fprintf(logfile," grid = %d %d %d\n",nx_pppm,ny_pppm,nz_pppm);
fprintf(logfile," stencil order = %d\n",order);
fprintf(logfile," RMS precision = %g\n",MAX(lpr,spr));
}
}
}
/* ----------------------------------------------------------------------
check if all factors of n are prime
return 1 if yes, 0 if no
-------------------------------------------------------------------------*/
void PPPMCuda::make_power_of_prime(int* n)
{
if((precisionmodify!='+')&&(precisionmodify!='-')&&(precisionmodify!='c'))
- {error->all("Unknown Option for PPPMCuda, assumeing '='");return;}
+ {error->all(FLERR,"Unknown Option for PPPMCuda, assumeing '='");return;}
int oldn=*n;
int* primelist=new int[1000];
int count=0;
int prime=1;
while(prime<2000) primelist[count++]=prime*=2;
prime=1;
while(prime<2000) primelist[count++]=prime*=3;
prime=1;
while(prime<2000) primelist[count++]=prime*=5;
prime=1;
while(prime<2000) primelist[count++]=prime*=7;
for(int i=0;i<count-1;i++)
for(int j=0;j<count-i-1;j++)
{
if(primelist[j]>primelist[j+1])
{
int a=primelist[j+1];
primelist[j+1]=primelist[j];
primelist[j]=a;
}
}
int nextsmaller=0;
while((primelist[nextsmaller+1]<*n)&&(nextsmaller+1<count)) nextsmaller++;
int nextlarger=count-1;
while((primelist[nextlarger-1]>*n)&&(nextlarger>0)) nextlarger--;
if(precisionmodify=='-')
*n=primelist[nextsmaller];
if((precisionmodify=='+')&&
(primelist[nextlarger]*primelist[nextlarger]*primelist[nextlarger]<2*(*n)*(*n)*(*n)))
*n=primelist[nextlarger];
if(precisionmodify=='c')
{
double factorsmaller=1.0*(*n)*(*n)*(*n)/(primelist[nextsmaller]*primelist[nextsmaller]*primelist[nextsmaller]);
double factorlarger=1.0*(primelist[nextlarger]*primelist[nextlarger]*primelist[nextlarger])/((*n)*(*n)*(*n));
if((factorlarger<factorsmaller)&&(factorlarger<2)) *n=primelist[nextlarger];
else *n=primelist[nextsmaller];
}
delete [] primelist;
primelist = NULL;
if(*n<0.75*oldn)
if (me == 0) {
if (screen) {
fprintf(screen,"\n\npppm/cuda WARNING: \t\tSignificantly lower gridsize than requested.\n\t\t\t\t\tYou should most likely use '=' or '+' as precision modify option\n");
}
if (logfile) {
fprintf(logfile,"\n\npppm/cuda WARNING: \t\tSignificantly lower gridsize than requested.\n\t\t\t\t\tYou should most likely use '=' or '+' as precision modify option\n.");
}
}
}
/* ----------------------------------------------------------------------
find center grid pt for each of my particles
check that full stencil for the particle will fit in my 3d brick
store central grid pt indices in part2grid array
------------------------------------------------------------------------- */
void PPPMCuda::particle_map()
{
MYDBG(printf("# CUDA PPPMCuda::particle_map() ... start\n");)
int flag = 0;
cu_flag->memset_device(0);
flag=cuda_particle_map(&cuda->shared_data,cu_flag->dev_data());
if(flag)
{
cu_debugdata->download();
printf("Out of range atom: ");
printf("ID: %i ",atom->tag[int(debugdata[0])]);
printf("x: %e ",debugdata[7]);
printf("y: %e ",debugdata[8]);
printf("z: %e ",debugdata[9]);
printf("nx: %e ",debugdata[4]);
printf("ny: %e ",debugdata[5]);
printf("\n");
//printf("debugdata: cpu: %e %e %e %i\n",boxlo[0],boxlo[1],boxlo[2],atom->nlocal);
cuda->cu_x->download();
int nx,ny,nz;
double **x = atom->x;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
nx = static_cast<int> ((x[i][0]-boxlo[0])*delxinv+shift) - OFFSET;
ny = static_cast<int> ((x[i][1]-boxlo[1])*delyinv+shift) - OFFSET;
nz = static_cast<int> ((x[i][2]-boxlo[2])*delzinv+shift) - OFFSET;
if(i==1203)printf("Outside Atom: %i %e %e %e (%i %i %i)\n",i,x[i][0],x[i][1],x[i][2],nx,ny,nz);
if (nx+nlower < nxlo_out || nx+nupper > nxhi_out ||
ny+nlower < nylo_out || ny+nupper > nyhi_out ||
nz+nlower < nzlo_out || nz+nupper > nzhi_out || i==1203) {printf("Outside Atom: %i %e %e %e (%i %i %i)\n",i,x[i][0],x[i][1],x[i][2],nx,ny,nz); }
}
}
int flag_all;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Out of range atoms - cannot compute PPPMCuda!");
+ if (flag_all) error->all(FLERR,"Out of range atoms - cannot compute PPPMCuda!");
}
/* ----------------------------------------------------------------------
create discretized "density" on section of global grid due to my particles
density(x,y,z) = charge "density" at grid points of my 3d brick
(nxlo:nxhi,nylo:nyhi,nzlo:nzhi) is extent of my brick (including ghosts)
in global grid
------------------------------------------------------------------------- */
void PPPMCuda::make_rho()
{
cuda_make_rho(&cuda->shared_data,cu_flag->dev_data(),&density_intScale,nxhi_out,nxlo_out,nyhi_out,nylo_out,nzhi_out,nzlo_out,cu_density_brick->dev_data(),cu_density_brick_int->dev_data());
}
/* ----------------------------------------------------------------------
FFT-based Poisson solver
------------------------------------------------------------------------- */
void PPPMCuda::poisson(int eflag, int vflag)
{
#ifndef FFT_CUFFT
PPPM::poisson(eflag,vflag);
return;
#endif
#ifdef FFT_CUFFT
timespec starttime,starttime2;
timespec endtime,endtime2;
int nprocs=comm->nprocs;
clock_gettime(CLOCK_REALTIME,&starttime);
fft1c->compute(density_fft,work1,1);
clock_gettime(CLOCK_REALTIME,&endtime);
poissontime+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
if (eflag || vflag) {
poisson_energy(nxlo_fft,nxhi_fft,nylo_fft,nyhi_fft,nzlo_fft,nzhi_fft,vflag);
ENERGY_FLOAT gpuvirial[6];
energy+=sum_energy(cu_virial->dev_data(),cu_energy->dev_data(),nx_pppm,ny_pppm,nz_pppm,vflag,gpuvirial);
if(vflag)
{
for(int j=0;j<6;j++) virial[j]+=gpuvirial[j];
}
}
// scale by 1/total-grid-pts to get rho(k)
// multiply by Green's function to get V(k)
poisson_scale(nx_pppm,ny_pppm,nz_pppm);
// compute gradients of V(r) in each of 3 dims by transformimg -ik*V(k)
// FFT leaves data in 3d brick decomposition
// copy it into inner portion of vdx,vdy,vdz arrays
// x direction gradient
poisson_xgrad(nx_pppm,ny_pppm,nz_pppm);
clock_gettime(CLOCK_REALTIME,&starttime);
fft2c->compute(work2,work2,-1);
clock_gettime(CLOCK_REALTIME,&endtime);
poissontime+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
poisson_vdx_brick(nxhi_out,nxlo_out,nyhi_out,nylo_out,nzhi_out,nzlo_out,nx_pppm,ny_pppm,nz_pppm);
// y direction gradient
poisson_ygrad(nx_pppm,ny_pppm,nz_pppm);
clock_gettime(CLOCK_REALTIME,&starttime);
fft2c->compute(work2,work2,-1);
clock_gettime(CLOCK_REALTIME,&endtime);
poissontime+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
poisson_vdy_brick(nxhi_out,nxlo_out,nyhi_out,nylo_out,nzhi_out,nzlo_out,nx_pppm,ny_pppm,nz_pppm);
// z direction gradient
poisson_zgrad(nx_pppm,ny_pppm,nz_pppm);
clock_gettime(CLOCK_REALTIME,&starttime);
fft2c->compute(work2,work2,-1);
clock_gettime(CLOCK_REALTIME,&endtime);
poissontime+=(endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000);
poisson_vdz_brick(nxhi_out,nxlo_out,nyhi_out,nylo_out,nzhi_out,nzlo_out,nx_pppm,ny_pppm,nz_pppm);
#endif
}
/*----------------------------------------------------------------------
interpolate from grid to get electric field & force on my particles
-------------------------------------------------------------------------*/
void PPPMCuda::fieldforce()
{
cuda_fieldforce(& cuda->shared_data,cu_flag);
return;
}
/* ----------------------------------------------------------------------
perform and time the 4 FFTs required for N timesteps
------------------------------------------------------------------------- */
void PPPMCuda::timing(int n, double &time3d, double &time1d)
{
double time1,time2;
for (int i = 0; i < 2*nfft_both; i++) work1[i] = 0.0;
MPI_Barrier(world);
time1 = MPI_Wtime();
for (int i = 0; i < n; i++) {
fft1c->compute(work1,work1,1);
fft2c->compute(work1,work1,-1);
fft2c->compute(work1,work1,-1);
fft2c->compute(work1,work1,-1);
}
MPI_Barrier(world);
time2 = MPI_Wtime();
time3d = time2 - time1;
MPI_Barrier(world);
/*time1 = MPI_Wtime();
for (int i = 0; i < n; i++) {
fft1c->timing1d(work1,nfft_both,1);
fft2c->timing1d(work1,nfft_both,-1);
fft2c->timing1d(work1,nfft_both,-1);
fft2c->timing1d(work1,nfft_both,-1);
}
MPI_Barrier(world);
time2 = MPI_Wtime();
time1d = time2 - time1;*/
}
void PPPMCuda::slabcorr(int eflag)
{
// compute local contribution to global dipole moment
if(slabbuf==NULL)
{
slabbuf=new ENERGY_FLOAT[(atom->nmax+31)/32];
cu_slabbuf = new cCudaData<ENERGY_FLOAT,ENERGY_FLOAT, x> (slabbuf, (atom->nmax+31)/32);
}
if((atom->nlocal+31)/32*sizeof(ENERGY_FLOAT)>=cu_slabbuf->dev_size())
{
delete [] slabbuf;
delete cu_slabbuf;
slabbuf=new ENERGY_FLOAT[(atom->nmax+31)/32];
cu_slabbuf = new cCudaData<ENERGY_FLOAT,ENERGY_FLOAT, x> (slabbuf, (atom->nmax+31)/32);
}
double dipole = cuda_slabcorr_energy(&cuda->shared_data,slabbuf,(ENERGY_FLOAT*) cu_slabbuf->dev_data());
double dipole_all;
MPI_Allreduce(&dipole,&dipole_all,1,MPI_DOUBLE,MPI_SUM,world);
// compute corrections
double e_slabcorr = 2.0*PI*dipole_all*dipole_all/volume;
if (eflag) energy += qqrd2e*scale * e_slabcorr;
double ffact = -4.0*PI*dipole_all/volume;
cuda_slabcorr_force(&cuda->shared_data,ffact);
}
diff --git a/src/USER-CUDA/verlet_cuda.cpp b/src/USER-CUDA/verlet_cuda.cpp
index 1a75e55de..0c3f675fa 100644
--- a/src/USER-CUDA/verlet_cuda.cpp
+++ b/src/USER-CUDA/verlet_cuda.cpp
@@ -1,1103 +1,1100 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
Original Version:
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
See the README file in the top-level LAMMPS directory.
-----------------------------------------------------------------------
USER-CUDA Package and associated modifications:
https://sourceforge.net/projects/lammpscuda/
Christian Trott, christian.trott@tu-ilmenau.de
Lars Winterfeld, lars.winterfeld@tu-ilmenau.de
Theoretical Physics II, University of Technology Ilmenau, Germany
See the README file in the USER-CUDA directory.
This software is distributed under the GNU General Public License.
------------------------------------------------------------------------- */
-
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "verlet_cuda.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "atom.h"
#include "atom_vec.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "output.h"
#include "update.h"
#include "modify_cuda.h"
#include "compute.h"
#include "fix.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
#include "cuda_wrapper_cu.h"
#include "thermo.h"
#include "cuda_pair_cu.h"
#include "cuda.h"
#include <ctime>
#include <cmath>
using namespace LAMMPS_NS;
-#define MAX(a, b) ((a)>(b) ? (a) : (b))
#define MAKETIMEING
-
VerletCuda::VerletCuda(LAMMPS *lmp, int narg, char **arg) : Verlet(lmp, narg, arg) {
cuda = lmp->cuda;
if(cuda == NULL)
- error->all("You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
+ error->all(FLERR,"You cannot use a /cuda class, without activating 'cuda' acceleration. Provide '-c on' as command-line argument to LAMMPS..");
modify_cuda=(ModifyCuda*) modify;
}
/* ----------------------------------------------------------------------
setup before run
------------------------------------------------------------------------- */
void VerletCuda::setup()
{
//debug related variables
cuda->debugdata[0]=0;
cuda->cu_debugdata->upload();
dotestatom=cuda->dotestatom;
int testatom=cuda->testatom;//48267;
MYDBG(printf("# CUDA VerletCuda::setup start\n"); )
cuda->oncpu = true;
cuda->begin_setup = true;
cuda->finished_run = false;
time_pair=0;
time_kspace=0;
time_comm=0;
time_modify=0;
time_fulliterate=0;
atom->setup();
cuda_shared_atom* cu_atom = & cuda->shared_data.atom;
cuda_shared_domain* cu_domain = & cuda->shared_data.domain;
cuda_shared_pair* cu_pair = & cuda->shared_data.pair;
cu_atom->update_nlocal=1;
cu_atom->update_nmax=1;
if(atom->molecular||(force->kspace&&(not cuda->shared_data.pppm.cudable_force))) cuda->shared_data.pair.collect_forces_later = true;
cuda->setDomainParams();
if(cuda->shared_data.me==0)
printf("# CUDA: VerletCuda::setup: Allocate memory on device for maximum of %i atoms...\n", atom->nmax);
if(cuda->shared_data.me==0)
printf("# CUDA: Using precision: Global: %u X: %u V: %u F: %u PPPM: %u \n", CUDA_PRECISION==1?4:8,sizeof(X_FLOAT),sizeof(V_FLOAT),sizeof(F_FLOAT),sizeof(PPPM_FLOAT));
cuda->allocate();
if (comm->me == 0 && screen) fprintf(screen,"Setting up run ...\n");
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
if (atom->sortfreq > 0) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
cuda->setSystemParams();
cuda->checkResize();
if(cuda->shared_data.me==0)
printf("# CUDA: VerletCuda::setup: Upload data...\n");
cuda->uploadAll();
neighbor->build();
neighbor->ncalls = 0;
cuda->uploadAllNeighborLists();
if(atom->mass)
cuda->cu_mass->upload();
if(cuda->cu_map_array)
cuda->cu_map_array->upload();
// compute all forces
ev_set(update->ntimestep);
if(elist_atom) cuda->shared_data.atom.need_eatom = 1;
if(vlist_atom) cuda->shared_data.atom.need_vatom = 1;
if(elist_atom||vlist_atom) cuda->checkResize();
int test_BpA_vs_TpA = true;
timespec starttime;
timespec endtime;
#ifdef NO_PREC_TIMING
double startsec,endsec;
#endif
//if(atom->molecular||(force->kspace&&(not cuda->shared_data.pppm.cudable_force))) cuda->shared_data.pair.collect_forces_later = false;
if(test_BpA_vs_TpA && cuda->shared_data.pair.cudable_force && force->pair &&(cuda->shared_data.pair.override_block_per_atom<0))
{
int StyleLoops=10;
if(cuda->shared_data.me==0)
printf("Test TpA\n");
cuda->shared_data.pair.use_block_per_atom = 0;
neighbor->build();
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
force->pair->compute(eflag,vflag);
CudaWrapper_Sync();
#ifdef NO_PREC_TIMING
startsec = 1.0*clock()/CLOCKS_PER_SEC;
#endif
clock_gettime(CLOCK_REALTIME,&starttime);
for(int i=0;i<StyleLoops;i++)
{
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
force->pair->compute(eflag,vflag);
CudaWrapper_Sync();
}
clock_gettime(CLOCK_REALTIME,&endtime);
double TpAtime=endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
#ifdef NO_PREC_TIMING
endsec = 1.0*clock()/CLOCKS_PER_SEC;
TpAtime = endsec - startsec;
#endif
if(cuda->shared_data.me==0)
printf("Test BpA\n");
cuda->shared_data.pair.use_block_per_atom = 1;
neighbor->build();
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
force->pair->compute(eflag,vflag);
CudaWrapper_Sync();
clock_gettime(CLOCK_REALTIME,&starttime);
#ifdef NO_PREC_TIMING
startsec = 1.0*clock()/CLOCKS_PER_SEC;
#endif
for(int i=0;i<StyleLoops;i++)
{
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
force->pair->compute(eflag,vflag);
CudaWrapper_Sync();
}
clock_gettime(CLOCK_REALTIME,&endtime);
double BpAtime=endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
#ifdef NO_PREC_TIMING
endsec = 1.0*clock()/CLOCKS_PER_SEC;
BpAtime = endsec - startsec;
#endif
if(cuda->shared_data.me==0)
printf("\n# CUDA: Timing of parallelisation layout with %i loops:\n",StyleLoops);
if(cuda->shared_data.me==0)
printf("# CUDA: BpA TpA\n %lf %lf\n",BpAtime,TpAtime);
if(BpAtime>TpAtime) cuda->shared_data.pair.use_block_per_atom = 0;
}
else
cuda->shared_data.pair.use_block_per_atom = cuda->shared_data.pair.override_block_per_atom;
//cuda->shared_data.pair.use_block_per_atom = 0;
if(atom->molecular||(force->kspace&&(not cuda->shared_data.pppm.cudable_force))) cuda->shared_data.pair.collect_forces_later = true;
neighbor->build();
neighbor->ncalls = 0;
force_clear();
cuda->cu_f->download();
if(cuda->cu_torque)
cuda->cu_torque->download();
//printf("# Verlet::setup: g f[0] = (%f, %f, %f)\n", atom->f[0][0], atom->f[0][1], atom->f[0][2]);
MYDBG( printf("# CUDA: VerletCuda::setup: initial force compute\n"); )
test_atom(testatom,"pre pair force");
if(cuda->shared_data.pair.cudable_force)
{
cuda->uploadAll();
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
}
if (force->pair) force->pair->compute(eflag,vflag);
if(cuda->shared_data.pair.cudable_force)
{
if(cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_Pair_CollectForces(&cuda->shared_data,eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
cuda->downloadAll();
}
test_atom(testatom,"post pair force");
MYDBG( printf("# CUDA: VerletCuda::setup: initial force compute done\n"); )
//printf("# Verlet::setup: h f[0] = (%f, %f, %f)\n", atom->f[0][0], atom->f[0][1], atom->f[0][2]);
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if(cuda->shared_data.pppm.cudable_force)
{
cuda->cu_tag ->upload();
cuda->cu_type->upload();
cuda->cu_x ->upload();
cuda->cu_v ->upload();
cuda->cu_f ->upload();
if(cu_atom->q_flag) cuda->cu_q->upload();
}
if (force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if(cuda->shared_data.pppm.cudable_force)
{
cuda->cu_f ->download();
}
test_atom(testatom,"post kspace");
cuda->uploadAll();
if (force->newton) comm->reverse_comm();
cuda->downloadAll();
test_atom(testatom,"post reverse comm");
if(cuda->shared_data.me==0)
printf("# CUDA: Total Device Memory useage post setup: %lf MB\n",1.0*CudaWrapper_CheckMemUseage()/1024/1024);
MYDBG( printf("# CUDA: VerletCuda::setup: call modify setup\n"); )
modify->setup(vflag);
MYDBG( printf("# CUDA: VerletCuda::setup: call modify setup done\n"); )
output->setup(1);
test_atom(testatom,"post setup");
MYDBG( printf("# CUDA: VerletCuda::setup: done\n"); )
cuda->finished_setup = true;
cuda->oncpu = false;
}
//this routine is in a messy state
void VerletCuda::setup_minimal(int flag)
{
dotestatom=0;
int testatom=104;
cuda->oncpu = true;
cuda->begin_setup = true;
cuda->finished_run = false;
MYDBG(printf("# CUDA VerletCuda::setup start\n"); )
time_pair=0;
time_kspace=0;
time_comm=0;
time_modify=0;
time_fulliterate=0;
//cuda->allocate();
cuda_shared_atom* cu_atom = & cuda->shared_data.atom;
cuda_shared_domain* cu_domain = & cuda->shared_data.domain;
cuda_shared_pair* cu_pair = & cuda->shared_data.pair;
cu_atom->update_nlocal=1;
cu_atom->update_nmax=1;
if(atom->molecular) cuda->shared_data.pair.collect_forces_later = true;
cuda->setDomainParams();
if(cuda->shared_data.me==0)
printf("# CUDA: VerletCuda::setup: Allocate memory on device for maximum of %i atoms...\n", atom->nmax);
cuda->allocate();
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
if (flag) {
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
cuda->setSystemParams();
cuda->checkResize();
neighbor->build();
neighbor->ncalls = 0;
}
if(cuda->shared_data.me==0)
printf("# CUDA: VerletCuda::setup: Upload data...\n");
cuda->uploadAll();
cuda->uploadAllNeighborLists();
if(atom->mass)
cuda->cu_mass->upload();
if(cuda->cu_map_array)
cuda->cu_map_array->upload();
// compute all forces
ev_set(update->ntimestep);
if(elist_atom) cuda->shared_data.atom.need_eatom = 1;
if(vlist_atom) cuda->shared_data.atom.need_vatom = 1;
if(elist_atom||vlist_atom) cuda->checkResize();
force_clear();
cuda->cu_f->download();
//printf("# Verlet::setup: g f[0] = (%f, %f, %f)\n", atom->f[0][0], atom->f[0][1], atom->f[0][2]);
cuda->cu_mass->upload();
MYDBG( printf("# CUDA: VerletCuda::setup: initial force compute\n"); )
test_atom(testatom,"pre pair force");
if(cuda->shared_data.pair.cudable_force)
{
cuda->uploadAll();
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
}
if (force->pair) force->pair->compute(eflag,vflag);
if(cuda->shared_data.pair.cudable_force)
{
if(cuda->shared_data.pair.collect_forces_later)
{
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_Pair_CollectForces(&cuda->shared_data,eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
}
cuda->downloadAll();
}
test_atom(testatom,"post pair force");
MYDBG( printf("# CUDA: VerletCuda::setup: initial force compute done\n"); )
//printf("# Verlet::setup: h f[0] = (%f, %f, %f)\n", atom->f[0][0], atom->f[0][1], atom->f[0][2]);
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if(cuda->shared_data.pppm.cudable_force)
{
cuda->cu_tag ->upload();
cuda->cu_type->upload();
cuda->cu_x ->upload();
cuda->cu_v ->upload();
cuda->cu_f ->upload();
if(cu_atom->q_flag) cuda->cu_q->upload();
}
if (force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if(cuda->shared_data.pppm.cudable_force)
{
cuda->cu_f ->download();
}
test_atom(testatom,"post kspace");
cuda->uploadAll();
if (force->newton) comm->reverse_comm();
cuda->downloadAll();
test_atom(testatom,"post reverse comm");
if(cuda->shared_data.me==0)
printf("# CUDA: Total Device Memory useage post setup: %lf MB\n",1.0*CudaWrapper_CheckMemUseage()/1024/1024);
MYDBG( printf("# CUDA: VerletCuda::setup: call modify setup\n"); )
modify->setup(vflag);
MYDBG( printf("# CUDA: VerletCuda::setup: done\n"); )
cuda->finished_setup=true;
cuda->oncpu=false;
}
//#define TESTATOM
/* ----------------------------------------------------------------------
iterate for n steps
------------------------------------------------------------------------- */
void VerletCuda::run(int n)
{
dotestatom=cuda->dotestatom;
int testatom=cuda->testatom;//48267;
timespec starttime;
timespec endtime;
timespec starttotal;
timespec endtotal;
cuda->setTimingsZero();
static double testtime=0.0;
// clock_gettime(CLOCK_REALTIME,&starttime);
// clock_gettime(CLOCK_REALTIME,&endtime);
// testtime+=endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
// printf("Time: %lf\n",testtime);*/
cuda_shared_domain* cu_domain = & cuda->shared_data.domain;
int nflag,ntimestep,sortflag;
int n_initial_integrate = modify_cuda->n_initial_integrate;
int n_post_integrate = modify_cuda->n_post_integrate;
int n_final_integrate = modify_cuda->n_final_integrate;
int n_pre_exchange = modify_cuda->n_pre_exchange;
int n_pre_neighbor = modify_cuda->n_pre_neighbor;
int n_pre_force = modify_cuda->n_pre_force;
int n_post_force = modify_cuda->n_post_force;
int n_end_of_step = modify_cuda->n_end_of_step;
MYDBG(printf("# CUDA: Fixes: i_int: %i p_int: %i f_int: %i pr_exc: %i pr_neigh: %i pr_f: %i p_f: %i eos: %i\n",
n_initial_integrate,n_post_integrate,n_final_integrate,n_pre_exchange,n_pre_neighbor,n_pre_force,n_post_force,n_end_of_step);)
if (atom->sortfreq > 0) sortflag = 1;
else sortflag = 0;
if(cuda->shared_data.me==0)
{
if((not cuda->shared_data.pair.cudable_force)&&(force->pair))
- error->warning("# CUDA: You asked for a Verlet integration using Cuda, "
+ error->warning(FLERR,"# CUDA: You asked for a Verlet integration using Cuda, "
"but selected a pair force which has not yet been ported to Cuda");
if((not cuda->shared_data.pppm.cudable_force)&&(force->kspace))
- error->warning("# CUDA: You asked for a Verlet integration using Cuda, "
+ error->warning(FLERR,"# CUDA: You asked for a Verlet integration using Cuda, "
"but selected a kspace force which has not yet been ported to Cuda");
if(modify_cuda->n_post_integrate_host+modify_cuda->n_pre_exchange_host+modify_cuda->n_pre_neighbor_host+modify_cuda->n_pre_force_host+modify_cuda->n_post_force_host+modify_cuda->n_end_of_step_host+modify_cuda->n_initial_integrate_host+modify_cuda->n_final_integrate_host)
- error->warning("# CUDA: You asked for a Verlet integration using Cuda, "
+ error->warning(FLERR,"# CUDA: You asked for a Verlet integration using Cuda, "
"but several fixes have not yet been ported to Cuda.\n"
"This can cause a severe speed penalty due to frequent data synchronization between host and GPU.");
if(atom->firstgroupname)
- error->warning("Warning: firstgroupname is used, this will cause additional data transfers.");
+ error->warning(FLERR,"Warning: firstgroupname is used, this will cause additional data transfers.");
}
cuda->uploadAll();
if(cuda->neighbor_decide_by_integrator && cuda->cu_xhold)
{
const int n=cuda->shared_data.atom.maxhold;
CudaWrapper_CopyData(cuda->cu_xhold->dev_data(),cuda->cu_x->dev_data(),n*sizeof(X_FLOAT));
CudaWrapper_CopyData((void*) &((X_FLOAT*)cuda->cu_xhold->dev_data())[n],(void*) &((X_FLOAT*)cuda->cu_x->dev_data())[atom->nmax],n*sizeof(X_FLOAT));
CudaWrapper_CopyData((void*) &((X_FLOAT*)cuda->cu_xhold->dev_data())[2*n],(void*) &((X_FLOAT*)cuda->cu_x->dev_data())[2*atom->nmax],n*sizeof(X_FLOAT));
}
cuda->shared_data.atom.reneigh_flag=0;
cuda->shared_data.atom.update_nlocal=1;
cuda->shared_data.atom.update_nmax=1;
cuda->shared_data.domain.update=1;
cuda->shared_data.buffer_new=1;
cuda->uploadtime=0;
cuda->downloadtime=0;
int firstreneigh=1;
for(int i = 0; i < n; i++)
{
ntimestep = ++update->ntimestep;
ev_set(ntimestep);
// initial time integration
test_atom(testatom,"Pre initial");
MYDBG( printf("# CUDA VerletCuda::iterate: before initial_integrate\n"); )
modify->initial_integrate(vflag);
MYDBG( printf("# CUDA VerletCuda::iterate: after initial_integrate\n"); )
if(n_post_integrate) modify->post_integrate();
// regular communication vs neighbor list rebuild
test_atom(testatom,"Pre Exchange");
MYDBG( printf("# CUDA VerletCuda::iterate: before neighbor decide\n"); )
nflag = neighbor->decide();
if(nflag == 0)
{
MYDBG( printf("# CUDA VerletCuda::iterate: communicate\n"); )
timer->stamp();
if((not (eflag||vflag))&&(cuda->shared_data.overlap_comm))
{
//overlap forward communication of ghost atom positions with inner force calculation (interactions between local atoms)
//build communication buffers
// printf("Pre forward_comm(1)\n");
clock_gettime(CLOCK_REALTIME,&starttotal);
cuda->shared_data.atom.reneigh_flag=0;
clock_gettime(CLOCK_REALTIME,&starttime);
timer->stamp();
comm->forward_comm(1);
timer->stamp(TIME_COMM);
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.comm_forward_total+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
//prepare force calculation
// printf("Pre force_clear\n");
force_clear();
// printf("Pre Generate XType\n");
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
//start force calculation asynchronus
cuda->shared_data.comm.comm_phase=1;
// printf("Pre Force Compute\n");
force->pair->compute(eflag, vflag);
timer->stamp(TIME_PAIR);
//CudaWrapper_Sync();
//download comm buffers from GPU, perform MPI communication and upload buffers again
clock_gettime(CLOCK_REALTIME,&starttime);
// printf("Pre forward_comm(2)\n");
comm->forward_comm(2);
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.comm_forward_total+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
timer->stamp(TIME_COMM);
//wait for force calculation
//printf("Pre Synch\n");
CudaWrapper_Sync();
timer->stamp(TIME_PAIR);
//unpack communication buffers
clock_gettime(CLOCK_REALTIME,&starttime);
// printf("Pre forward_comm(3)\n");
comm->forward_comm(3);
clock_gettime(CLOCK_REALTIME,&endtime);
// printf("Post forward_comm(3)\n");
cuda->shared_data.cuda_timings.comm_forward_total+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
timer->stamp(TIME_COMM);
MYDBG( printf("# CUDA VerletCuda::iterate: communicate done\n"); )
cuda->shared_data.cuda_timings.test1+=
endtotal.tv_sec-starttotal.tv_sec+1.0*(endtotal.tv_nsec-starttotal.tv_nsec)/1000000000;
}
else
{
//perform standard forward communication
//printf("Forward_comm\n");
clock_gettime(CLOCK_REALTIME,&starttime);
comm->forward_comm();
clock_gettime(CLOCK_REALTIME,&endtime);
//printf("Forward_comm_done\n");
cuda->shared_data.cuda_timings.comm_forward_total+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
timer->stamp(TIME_COMM);
MYDBG( printf("# CUDA VerletCuda::iterate: communicate done\n"); )
}
}
else
{
int nlocalold=cuda->shared_data.atom.nlocal;
//if(firstreneigh)
{
cuda->shared_data.atom.update_nlocal=1;
cuda->shared_data.atom.update_nmax=1;
firstreneigh=0;
}
cuda->shared_data.buffer_new=1;
MYDBG( printf("# CUDA VerletCuda::iterate: neighbor\n"); )
cuda->setDomainParams();
if(n_pre_exchange) modify->pre_exchange();
if(atom->nlocal!=cuda->shared_data.atom.nlocal) //did someone add atoms during pre_exchange?
{
cuda->checkResize();
cuda->uploadAll();
}
//check domain changes
if(domain->triclinic) domain->x2lamda(atom->nlocal);
MYDBG( printf("# CUDA VerletCuda::iterate: neighbor pbc\n"); )
domain->pbc();
if(domain->box_change)
{
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
}
timer->stamp();
MYDBG( printf("# CUDA VerletCuda::iterate: neighbor exchange\n"); )
//perform exchange of local atoms
clock_gettime(CLOCK_REALTIME,&starttime);
comm->exchange();
clock_gettime(CLOCK_REALTIME,&endtime);
//special and nspecial fields of the atom data are not currently transfered via the GPU buffer might be changed in the future
if(comm->nprocs>1)
{
clock_gettime(CLOCK_REALTIME,&starttime);
if(atom->special)
cuda->cu_special->upload();
if(atom->nspecial)
cuda->cu_nspecial->upload();
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.test1+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
}
cuda->shared_data.cuda_timings.comm_exchange_total+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
if(nlocalold!=cuda->shared_data.atom.nlocal) cuda->shared_data.atom.update_nlocal=2;
//sort atoms
if (sortflag && ntimestep >= atom->nextsort) atom->sort();
MYDBG( printf("# CUDA VerletCuda::iterate: neighbor borders\n"); )
//generate ghost atom lists, and transfer ghost atom data
clock_gettime(CLOCK_REALTIME,&starttime);
comm->borders();
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.comm_border_total+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
clock_gettime(CLOCK_REALTIME,&starttime);
//atom index maps are generated on CPU, and need to be transfered to GPU if they are used
if(cuda->cu_map_array)
cuda->cu_map_array->upload();
if(domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
if(n_pre_neighbor) modify->pre_neighbor();
cuda->shared_data.buffer_new=2;
if(atom->molecular) cuda->cu_molecule->download();
MYDBG( printf("# CUDA VerletCuda::iterate: neighbor build\n"); )
timer->stamp(TIME_COMM);
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.test2+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
//rebuild neighbor list
test_atom(testatom,"Pre Neighbor");
neighbor->build();
timer->stamp(TIME_NEIGHBOR);
MYDBG( printf("# CUDA VerletCuda::iterate: neighbor done\n"); )
//if bonded interactions are used (in this case collect_forces_later is true), transfer data which only changes upon exchange/border routines from GPU to CPU
if(cuda->shared_data.pair.collect_forces_later)
{
if(cuda->cu_molecule) cuda->cu_molecule->download();
cuda->cu_tag->download();
cuda->cu_type->download();
cuda->cu_mask->download();
if(cuda->cu_q) cuda->cu_q->download();
}
cuda->shared_data.comm.comm_phase=3;
}
test_atom(testatom,"Post Exchange");
// force computations
//only do force_clear if it has not been done during overlap of communication with local interactions
if(not((not (eflag||vflag))&&(cuda->shared_data.overlap_comm)&&(cuda->shared_data.comm.comm_phase<3)))
force_clear();
if(n_pre_force) modify->pre_force(vflag);
timer->stamp();
//if overlap of bonded interactions with nonbonded interactions takes place, download forces and positions
/* if(cuda->shared_data.pair.collect_forces_later)
{
cuda->cu_x->downloadAsync(2);
cuda->cu_f->downloadAsync(2);
}*/
if(force->pair)
{
if((not (eflag||vflag))&&(cuda->shared_data.overlap_comm)&&(cuda->shared_data.comm.comm_phase<3)&&cuda->shared_data.pair.cudable_force)
{
//second part of force calculations in case of overlaping it with commuincation. Only interactions between local and ghost atoms are done now
//regenerate data layout for force computations, its actually only needed for the ghost atoms
cuda->shared_data.comm.comm_phase=2;
timespec atime1,atime2;
clock_gettime(CLOCK_REALTIME,&atime1);
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
clock_gettime(CLOCK_REALTIME,&atime2);
cuda->shared_data.cuda_timings.pair_xtype_conversion+=
atime2.tv_sec-atime1.tv_sec+1.0*(atime2.tv_nsec-atime1.tv_nsec)/1000000000;
force->pair->compute(eflag, vflag);
}
else
{
//calculate complete pair interactions
if(not cuda->shared_data.pair.cudable_force) cuda->downloadAll();
else
{
//regenerate data layout for force computations, its actually only needed for the ghost atoms
timespec atime1,atime2;
clock_gettime(CLOCK_REALTIME,&atime1);
Cuda_Pair_GenerateXType(&cuda->shared_data);
if(cuda->cu_v_radius)
Cuda_Pair_GenerateVRadius(&cuda->shared_data);
if(cuda->cu_omega_rmass)
Cuda_Pair_GenerateOmegaRmass(&cuda->shared_data);
clock_gettime(CLOCK_REALTIME,&atime2);
cuda->shared_data.cuda_timings.pair_xtype_conversion+=
atime2.tv_sec-atime1.tv_sec+1.0*(atime2.tv_nsec-atime1.tv_nsec)/1000000000;
}
cuda->shared_data.comm.comm_phase=0;
force->pair->compute(eflag, vflag);
}
if(not cuda->shared_data.pair.cudable_force) cuda->uploadAll();
//wait for force calculation in case of not using overlap with bonded interactions
if(not cuda->shared_data.pair.collect_forces_later)
CudaWrapper_Sync();
timer->stamp(TIME_PAIR);
}
//calculate bonded interactions
if(atom->molecular)
{
cuda->cu_x->downloadAsync(2);
if(n_pre_force==0) Verlet::force_clear();
else cuda->cu_f->downloadAsync(2);
timer->stamp(TIME_PAIR);
test_atom(testatom,"pre bond force");
if(force->bond) force->bond->compute(eflag, vflag);
if(force->angle) force->angle->compute(eflag, vflag);
if(force->dihedral) force->dihedral->compute(eflag, vflag);
if(force->improper) force->improper->compute(eflag, vflag);
timer->stamp(TIME_BOND);
}
//collect forces in case pair force and bonded interactions were overlapped, and either no KSPACE or a GPU KSPACE style is used
if(cuda->shared_data.pair.collect_forces_later&&cuda->shared_data.pair.cudable_force&&(not (force->kspace&&(not cuda->shared_data.pppm.cudable_force))))
{
clock_gettime(CLOCK_REALTIME,&starttime);
cuda->cu_f->uploadAsync(2);
test_atom(testatom,"post molecular force");
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_Pair_CollectForces(&cuda->shared_data,eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
timer->stamp(TIME_PAIR);
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.pair_force_collection+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
}
//compute kspace force
if(force->kspace)
{
if((not cuda->shared_data.pppm.cudable_force) && (not cuda->shared_data.pair.collect_forces_later))
cuda->downloadAll();
if((not cuda->shared_data.pppm.cudable_force) && (cuda->shared_data.pair.collect_forces_later) && (not atom->molecular))
{
cuda->cu_x->downloadAsync(2);
if(n_pre_force==0) Verlet::force_clear();
else cuda->cu_f->downloadAsync(2);
timer->stamp(TIME_PAIR);
}
force->kspace->compute(eflag,vflag);
if((not cuda->shared_data.pppm.cudable_force) && (not cuda->shared_data.pair.collect_forces_later))
cuda->uploadAll();
timer->stamp(TIME_KSPACE);
}
//collect forces in case pair forces and kspace was overlaped
if(cuda->shared_data.pair.collect_forces_later&&cuda->shared_data.pair.cudable_force&&((force->kspace&&(not cuda->shared_data.pppm.cudable_force))))
{
cuda->cu_f->uploadAsync(2);
clock_gettime(CLOCK_REALTIME,&starttime);
if(eflag) cuda->cu_eng_vdwl->upload();
if(eflag) cuda->cu_eng_coul->upload();
if(vflag) cuda->cu_virial->upload();
Cuda_Pair_CollectForces(&cuda->shared_data,eflag,vflag);
if(eflag) cuda->cu_eng_vdwl->download();
if(eflag) cuda->cu_eng_coul->download();
if(vflag) cuda->cu_virial->download();
timer->stamp(TIME_PAIR);
clock_gettime(CLOCK_REALTIME,&endtime);
cuda->shared_data.cuda_timings.pair_force_collection+=
endtime.tv_sec-starttime.tv_sec+1.0*(endtime.tv_nsec-starttime.tv_nsec)/1000000000;
}
//send forces on ghost atoms back to other GPU: THIS SHOULD NEVER HAPPEN
if(force->newton)
{
comm->reverse_comm();
timer->stamp(TIME_COMM);
}
test_atom(testatom,"post force");
// force modifications, final time integration, diagnostics
if(n_post_force) modify->post_force(vflag);
test_atom(testatom,"pre final");
modify->final_integrate();
test_atom(testatom,"post final");
if(n_end_of_step) modify->end_of_step();
// all output
test_atom(testatom,"pre output");
if(ntimestep == output->next)
{
if(not output->thermo->cudable)
cuda->downloadAll();
timer->stamp();
output->write(ntimestep);
timer->stamp(TIME_OUTPUT);
}
test_atom(testatom,"post output");
if(cuda->shared_data.atom.update_nlocal>0)
cuda->shared_data.atom.update_nlocal--;
if(cuda->shared_data.atom.update_nmax>0)
cuda->shared_data.atom.update_nmax--;
if(cuda->shared_data.domain.update>0)
cuda->shared_data.domain.update--;
if(cuda->shared_data.buffer_new>0)
cuda->shared_data.buffer_new--;
cuda->shared_data.atom.reneigh_flag=0;
}
cuda->downloadAll();
cuda->downloadAllNeighborLists();
cuda->shared_data.atom.update_nlocal=1;
cuda->shared_data.atom.update_nmax=1;
cuda->shared_data.buffer_new=1;
cuda->shared_data.domain.update=1;
cuda->oncpu = true;
cuda->finished_run = true;
}
/* ----------------------------------------------------------------------
clear force on own & ghost atoms
setup and clear other arrays as needed
------------------------------------------------------------------------- */
void VerletCuda::force_clear()
{
cuda->cu_f->memset_device(0);
if(cuda->cu_torque) cuda->cu_torque->memset_device(0);
return;
//The rest should not be necessary
int i;
for(i=0;i<atom->nlocal;i++)
{
atom->f[i][0]=0.0;
atom->f[i][1]=0.0;
atom->f[i][2]=0.0;
}
// clear force on all particles
// if either newton flag is set, also include ghosts
if (neighbor->includegroup == 0) {
int nall;
if (force->newton) nall = atom->nlocal + atom->nghost;
else nall = atom->nlocal;
if (torqueflag) {
double **torque = atom->torque;
for (i = 0; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
// neighbor includegroup flag is set
// clear force only on initial nfirst particles
// if either newton flag is set, also include ghosts
} else {
int nall = atom->nfirst;
if (torqueflag) {
double **torque = atom->torque;
for (i = 0; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
if (force->newton) {
nall = atom->nlocal + atom->nghost;
if (torqueflag) {
double **torque = atom->torque;
for (i = atom->nlocal; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
}
}
}
void VerletCuda::test_atom(int aatom, char* string) //printing properties of one atom for test purposes
{
if(not dotestatom) return;
bool check=false;
if(cuda->finished_setup) cuda->downloadAll();
for(int i=0;i<atom->nlocal+atom->nghost;i++)
{
if((atom->tag[i]==aatom)&&(i<atom->nlocal))
{
printf("%i # CUDA %s: %i %i %e %e %e %i ",comm->me,string,update->ntimestep,atom->tag[i],atom->x[i][0],atom->v[i][0],atom->f[i][0],i);
if(atom->molecular && (i<atom->nlocal))
{
printf(" // %i %i %i ",atom->num_bond[i],atom->num_angle[i],atom->num_dihedral[i]);
for(int k=0;k<atom->num_bond[i];k++)
printf("// %i %i ",atom->bond_type[i][k],atom->bond_atom[i][k]);
}
printf("\n");
}
if(i<atom->nlocal)
{
if((atom->v[i][0]<-100||atom->v[i][0]>100)||
(atom->v[i][1]<-100||atom->v[i][1]>100)||
(atom->v[i][2]<-100||atom->v[i][2]>100)||
(atom->v[i][0]!=atom->v[i][0])||
(atom->v[i][1]!=atom->v[i][1])||
(atom->v[i][2]!=atom->v[i][2]))
{printf("%i # CUDA %s velocity: %i %e %e %e %i\n",comm->me,string,atom->tag[i],atom->x[i][0],atom->v[i][0],atom->f[i][0],i); check=true;}
if((atom->f[i][0]<-10000||atom->f[i][0]>10000)||
(atom->f[i][1]<-10000||atom->f[i][1]>10000)||
(atom->f[i][2]<-10000||atom->f[i][2]>10000)||
(atom->f[i][0]!=atom->f[i][0])||
(atom->f[i][1]!=atom->f[i][1])||
(atom->f[i][2]!=atom->f[i][2]))
{printf("%i # CUDA %s force: %i %e %e %e %i\n",comm->me,string,atom->tag[i],atom->x[i][0],atom->v[i][0],atom->f[i][0],i); check=true;}
if(atom->tag[i]<=0)
printf("%i # CUDA %s tag: %i %e %e %e %i\n",comm->me,string,atom->tag[i],atom->x[i][0],atom->v[i][0],atom->f[i][0],i);
}
}
if(check) exit(0);
}
diff --git a/src/USER-EFF/atom_vec_electron.cpp b/src/USER-EFF/atom_vec_electron.cpp
index c7affbc38..006de8601 100644
--- a/src/USER-EFF/atom_vec_electron.cpp
+++ b/src/USER-EFF/atom_vec_electron.cpp
@@ -1,851 +1,851 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero (Caltech)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "atom_vec_electron.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "force.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecElectron::AtomVecElectron(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
comm_x_only = comm_f_only = 0;
mass_type = 1;
molecular = 0;
size_forward = 4;
size_reverse = 4;
size_border = 9;
size_velocity = 3;
size_data_atom = 8;
size_data_vel = 5;
xcol_data = 6;
atom->electron_flag = 1;
atom->q_flag = atom->spin_flag = atom->eradius_flag =
atom->ervel_flag = atom->erforce_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom-electron arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecElectron::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
q = memory->grow(atom->q,nmax,"atom:q");
spin = memory->grow(atom->spin,nmax,"atom:spin");
eradius = memory->grow(atom->eradius,nmax,"atom:eradius");
ervel = memory->grow(atom->ervel,nmax,"atom:ervel");
erforce = memory->grow(atom->erforce,nmax,"atom:erforce");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecElectron::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
q = atom->q;
eradius = atom->eradius; ervel = atom->ervel; erforce = atom->erforce;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecElectron::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
q[j] = q[i];
spin[j] = spin[i];
eradius[j] = eradius[i];
ervel[j] = ervel[i];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = eradius[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = eradius[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = eradius[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = eradius[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = eradius[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_comm_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = eradius[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecElectron::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
eradius[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecElectron::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
eradius[i] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::unpack_comm_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
eradius[i] = buf[m++];
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
buf[m++] = erforce[i];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_reverse_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
buf[m++] = erforce[i];
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecElectron::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
erforce[j] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::unpack_reverse_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
erforce[j] += buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (domain->triclinic == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = q[j];
buf[m++] = spin[j];
buf[m++] = eradius[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecElectron::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
spin[i] = static_cast<int> (buf[m++]);
eradius[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecElectron::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
spin[i] = static_cast<int> (buf[m++]);
eradius[i] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
q[i] = buf[m++];
spin[i] = static_cast<int> (buf[m++]);
eradius[i] = buf[m++];
}
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecElectron::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = q[i];
buf[m++] = spin[i];
buf[m++] = eradius[i];
buf[m++] = ervel[i];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecElectron::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
q[nlocal] = buf[m++];
spin[nlocal] = static_cast<int> (buf[m++]);
eradius[nlocal] = buf[m++];
ervel[nlocal] = buf[m++];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecElectron::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 15 * nlocal; // Associated with pack_restart
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecElectron::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = q[i];
buf[m++] = spin[i];
buf[m++] = eradius[i];
buf[m++] = ervel[i];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecElectron::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
q[nlocal] = buf[m++];
spin[nlocal] = static_cast<int> (buf[m++]);
eradius[nlocal] = buf[m++];
ervel[nlocal] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecElectron::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
q[nlocal] = 0.0;
spin[nlocal] = 1;
eradius[nlocal] = 1.0;
ervel[nlocal] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecElectron::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
q[nlocal] = atof(values[2]);
spin[nlocal] = atoi(values[3]);
eradius[nlocal] = atof(values[4]);
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
ervel[nlocal] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecElectron::data_atom_hybrid(int nlocal, char **values)
{
q[nlocal] = atof(values[0]);
spin[nlocal] = atoi(values[1]);
eradius[nlocal] = atof(values[2]);
if (eradius[nlocal] < 0.0)
- error->one("Invalid eradius in Atoms section of data file");
+ error->one(FLERR,"Invalid eradius in Atoms section of data file");
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
ervel[nlocal] = 0.0;
return 3;
}
/* ----------------------------------------------------------------------
unpack one line from Velocities section of data file
------------------------------------------------------------------------- */
void AtomVecElectron::data_vel(int m, char **values)
{
v[m][0] = atof(values[0]);
v[m][1] = atof(values[1]);
v[m][2] = atof(values[2]);
ervel[m] = atof(values[3]);
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Velocities section of data file
------------------------------------------------------------------------- */
int AtomVecElectron::data_vel_hybrid(int m, char **values)
{
ervel[m] = atof(values[0]);
return 1;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecElectron::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("q")) bytes += memory->usage(q,nmax);
if (atom->memcheck("spin")) bytes += memory->usage(spin,nmax);
if (atom->memcheck("eradius")) bytes += memory->usage(eradius,nmax);
if (atom->memcheck("ervel")) bytes += memory->usage(ervel,nmax);
if (atom->memcheck("erforce")) bytes += memory->usage(erforce,nmax);
return bytes;
}
diff --git a/src/USER-EFF/compute_ke_atom_eff.cpp b/src/USER-EFF/compute_ke_atom_eff.cpp
index 33c900f4b..1b68b60d2 100644
--- a/src/USER-EFF/compute_ke_atom_eff.cpp
+++ b/src/USER-EFF/compute_ke_atom_eff.cpp
@@ -1,113 +1,113 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_ke_atom_eff.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeKEAtomEff::ComputeKEAtomEff(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute ke/atom/eff command");
+ if (narg != 3) error->all(FLERR,"Illegal compute ke/atom/eff command");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
ke = NULL;
// error check
if (!atom->electron_flag)
- error->all("Compute ke/atom/eff requires atom style electron");
+ error->all(FLERR,"Compute ke/atom/eff requires atom style electron");
}
/* ---------------------------------------------------------------------- */
ComputeKEAtomEff::~ComputeKEAtomEff()
{
memory->destroy(ke);
}
/* ---------------------------------------------------------------------- */
void ComputeKEAtomEff::init()
{
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"ke/atom/eff") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute ke/atom/eff");
+ error->warning(FLERR,"More than one compute ke/atom/eff");
}
/* ---------------------------------------------------------------------- */
void ComputeKEAtomEff::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow ke array if necessary
if (atom->nlocal > nmax) {
memory->destroy(ke);
nmax = atom->nmax;
memory->create(ke,nmax,"compute/ke/atom/eff:ke");
vector_atom = ke;
}
// compute kinetic energy for each atom in group
double mvv2e = force->mvv2e;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
if (mass)
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
ke[i] = 0.5 * mvv2e * mass[type[i]] *
(v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
if (fabs(spin[i])==1)
ke[i] += 0.5 * mvv2e * mass[type[i]] * ervel[i]*ervel[i] * 0.75;
} else ke[i] = 0.0;
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeKEAtomEff::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/USER-EFF/compute_ke_eff.cpp b/src/USER-EFF/compute_ke_eff.cpp
index 68aaa2c25..43a2a952f 100644
--- a/src/USER-EFF/compute_ke_eff.cpp
+++ b/src/USER-EFF/compute_ke_eff.cpp
@@ -1,81 +1,81 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "compute_ke_eff.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeKEEff::ComputeKEEff(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute ke/eff command");
+ if (narg != 3) error->all(FLERR,"Illegal compute ke/eff command");
scalar_flag = 1;
extscalar = 1;
// error check
if (!atom->electron_flag)
- error->all("Compute ke/eff requires atom style electron");
+ error->all(FLERR,"Compute ke/eff requires atom style electron");
}
/* ---------------------------------------------------------------------- */
void ComputeKEEff::init()
{
pfactor = 0.5 * force->mvv2e;
}
/* ---------------------------------------------------------------------- */
double ComputeKEEff::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double ke = 0.0;
if (mass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
ke += mass[type[i]]*(v[i][0]*v[i][0] + v[i][1]*v[i][1] +
v[i][2]*v[i][2]);
if (fabs(spin[i])==1) ke += 0.75*mass[type[i]]*ervel[i]*ervel[i];
}
}
MPI_Allreduce(&ke,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
scalar *= pfactor;
return scalar;
}
diff --git a/src/USER-EFF/compute_temp_deform_eff.cpp b/src/USER-EFF/compute_temp_deform_eff.cpp
index 7bb53b908..ccba4d782 100644
--- a/src/USER-EFF/compute_temp_deform_eff.cpp
+++ b/src/USER-EFF/compute_temp_deform_eff.cpp
@@ -1,316 +1,316 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero (Caltech)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "compute_temp_deform_eff.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "modify.h"
#include "fix.h"
#include "fix_deform.h"
#include "group.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp
/* ---------------------------------------------------------------------- */
ComputeTempDeformEff::ComputeTempDeformEff(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute temp/deform/eff command");
+ if (narg != 3) error->all(FLERR,"Illegal compute temp/deform/eff command");
if (!atom->electron_flag)
- error->all("Compute temp/deform/eff requires atom style electron");
+ error->all(FLERR,"Compute temp/deform/eff requires atom style electron");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempDeformEff::~ComputeTempDeformEff()
{
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempDeformEff::init()
{
int i;
fix_dof = 0;
for (i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
// check fix deform remap settings
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
if (((FixDeform *) modify->fix[i])->remapflag == X_REMAP &&
comm->me == 0)
- error->warning("Using compute temp/deform/eff with inconsistent "
+ error->warning(FLERR,"Using compute temp/deform/eff with inconsistent "
"fix deform remap option");
break;
}
if (i == modify->nfix && comm->me == 0)
- error->warning("Using compute temp/deform/eff with no fix deform defined");
+ error->warning(FLERR,"Using compute temp/deform/eff with no fix deform defined");
}
/* ---------------------------------------------------------------------- */
void ComputeTempDeformEff::dof_compute()
{
double natoms = group->count(igroup);
dof = domain->dimension * natoms;
dof -= extra_dof + fix_dof;
// just include nuclear dof
int *spin = atom->spin;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int one = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (fabs(spin[i]) == 1) one++;
}
int nelectrons;
MPI_Allreduce(&one,&nelectrons,1,MPI_INT,MPI_SUM,world);
dof -= domain->dimension * nelectrons;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempDeformEff::compute_scalar()
{
double lamda[3],vstream[3],vthermal[3];
invoked_scalar = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// lamda = 0-1 triclinic lamda coords
// vstream = streaming velocity = Hrate*lamda + Hratelo
// vthermal = thermal velocity = v - vstream
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
double t = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
domain->x2lamda(x[i],lamda);
vstream[0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vstream[1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vstream[2] = h_rate[2]*lamda[2] + h_ratelo[2];
vthermal[0] = v[i][0] - vstream[0];
vthermal[1] = v[i][1] - vstream[1];
vthermal[2] = v[i][2] - vstream[2];
if (mass) {
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2])* mass[type[i]];
if (fabs(spin[i])==1) t += 0.75*mass[type[i]]*ervel[i]*ervel[i];
}
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempDeformEff::compute_vector()
{
double lamda[3],vstream[3],vthermal[3];
invoked_vector = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
double massone,t[6];
for (int i = 0; i < 6; i++) t[i] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
domain->x2lamda(x[i],lamda);
vstream[0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vstream[1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vstream[2] = h_rate[2]*lamda[2] + h_ratelo[2];
vthermal[0] = v[i][0] - vstream[0];
vthermal[1] = v[i][1] - vstream[1];
vthermal[2] = v[i][2] - vstream[2];
massone = mass[type[i]];
t[0] += massone * vthermal[0]*vthermal[0];
t[1] += massone * vthermal[1]*vthermal[1];
t[2] += massone * vthermal[2]*vthermal[2];
t[3] += massone * vthermal[0]*vthermal[1];
t[4] += massone * vthermal[0]*vthermal[2];
t[5] += massone * vthermal[1]*vthermal[2];
if (fabs(spin[i])==1) {
t[0] += 0.75 * massone * ervel[i]*ervel[i];
t[1] += 0.75 * massone * ervel[i]*ervel[i];
t[2] += 0.75 * massone * ervel[i]*ervel[i];
}
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (int i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempDeformEff::remove_bias(int i, double *v)
{
double lamda[3];
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
domain->x2lamda(atom->x[i],lamda);
vbias[0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vbias[1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vbias[2] = h_rate[2]*lamda[2] + h_ratelo[2];
v[0] -= vbias[0];
v[1] -= vbias[1];
v[2] -= vbias[2];
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
NOTE: only removes translational velocity bias from electrons
------------------------------------------------------------------------- */
void ComputeTempDeformEff::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/deform/eff:vbiasall");
}
double lamda[3];
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
domain->x2lamda(atom->x[i],lamda);
vbiasall[i][0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vbiasall[i][1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vbiasall[i][2] = h_rate[2]*lamda[2] + h_ratelo[2];
v[i][0] -= vbiasall[i][0];
v[i][1] -= vbiasall[i][1];
v[i][2] -= vbiasall[i][2];
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempDeformEff::restore_bias(int i, double *v)
{
v[0] += vbias[0];
v[1] += vbias[1];
v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempDeformEff::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] += vbiasall[i][0];
v[i][1] += vbiasall[i][1];
v[i][2] += vbiasall[i][2];
}
}
/* ---------------------------------------------------------------------- */
double ComputeTempDeformEff::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/USER-EFF/compute_temp_eff.cpp b/src/USER-EFF/compute_temp_eff.cpp
index 4f7cc40c1..e2089a0d6 100644
--- a/src/USER-EFF/compute_temp_eff.cpp
+++ b/src/USER-EFF/compute_temp_eff.cpp
@@ -1,164 +1,164 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero (Caltech)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "compute_temp_eff.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeTempEff::ComputeTempEff(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
if (!atom->electron_flag)
- error->all("Compute temp/eff requires atom style electron");
+ error->all(FLERR,"Compute temp/eff requires atom style electron");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
vector = new double[size_vector];
}
/* ---------------------------------------------------------------------- */
ComputeTempEff::~ComputeTempEff()
{
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempEff::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ---------------------------------------------------------------------- */
void ComputeTempEff::dof_compute()
{
double natoms = group->count(igroup);
dof = domain->dimension * natoms;
dof -= extra_dof + fix_dof;
int *spin = atom->spin;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int one = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (fabs(spin[i])==1) one++;
}
int nelectrons;
MPI_Allreduce(&one,&nelectrons,1,MPI_INT,MPI_SUM,world);
// average over nuclear dof only
dof -= domain->dimension * nelectrons;
if (dof > 0.0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempEff::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
if (mass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
mass[type[i]];
if (fabs(spin[i])==1) t += 0.75*mass[type[i]]*ervel[i]*ervel[i];
}
}
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempEff::compute_vector()
{
int i;
invoked_vector = update->ntimestep;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = mass[type[i]];
t[0] += massone * v[i][0]*v[i][0];
t[1] += massone * v[i][1]*v[i][1];
t[2] += massone * v[i][2]*v[i][2];
t[3] += massone * v[i][0]*v[i][1];
t[4] += massone * v[i][0]*v[i][2];
t[5] += massone * v[i][1]*v[i][2];
if (fabs(spin[i])==1) {
t[0] += 0.75*massone*ervel[i]*ervel[i];
t[1] += 0.75*massone*ervel[i]*ervel[i];
t[2] += 0.75*massone*ervel[i]*ervel[i];
}
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
diff --git a/src/USER-EFF/compute_temp_region_eff.cpp b/src/USER-EFF/compute_temp_region_eff.cpp
index 9bcabee2a..f43e92095 100644
--- a/src/USER-EFF/compute_temp_region_eff.cpp
+++ b/src/USER-EFF/compute_temp_region_eff.cpp
@@ -1,276 +1,276 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero (Caltech)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "compute_temp_region_eff.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "modify.h"
#include "domain.h"
#include "region.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeTempRegionEff::ComputeTempRegionEff(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
if (!atom->electron_flag)
- error->all("Compute temp/region/eff requires atom style electron");
+ error->all(FLERR,"Compute temp/region/eff requires atom style electron");
- if (narg != 4) error->all("Illegal compute temp/region/eff command");
+ if (narg != 4) error->all(FLERR,"Illegal compute temp/region/eff command");
iregion = domain->find_region(arg[3]);
if (iregion == -1)
- error->all("Region ID for compute temp/region/eff does not exist");
+ error->all(FLERR,"Region ID for compute temp/region/eff does not exist");
int n = strlen(arg[3]) + 1;
idregion = new char[n];
strcpy(idregion,arg[3]);
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempRegionEff::~ComputeTempRegionEff()
{
delete [] idregion;
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRegionEff::init()
{
// set index and check validity of region
iregion = domain->find_region(idregion);
if (iregion == -1)
- error->all("Region ID for compute temp/region/eff does not exist");
+ error->all(FLERR,"Region ID for compute temp/region/eff does not exist");
dof = 0.0;
}
/* ---------------------------------------------------------------------- */
int ComputeTempRegionEff::dof_remove(int i)
{
double *x = atom->x[i];
if (domain->regions[iregion]->match(x[0],x[1],x[2])) return 0;
return 1;
}
/* ---------------------------------------------------------------------- */
double ComputeTempRegionEff::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
Region *region = domain->regions[iregion];
int count = 0;
double t = 0.0;
if (mass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
count++;
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
mass[type[i]];
if (fabs(spin[i])==1) t += 0.75*mass[type[i]]*ervel[i]*ervel[i];
}
}
double tarray[2],tarray_all[2];
tarray[0] = count;
tarray[1] = t;
MPI_Allreduce(tarray,tarray_all,2,MPI_DOUBLE,MPI_SUM,world);
dof = domain->dimension * tarray_all[0] - extra_dof;
int one = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (fabs(spin[i])==1) one++;
}
int nelectrons_region;
MPI_Allreduce(&one,&nelectrons_region,1,MPI_INT,MPI_SUM,world);
// average over nuclear dof only
dof -= domain->dimension * nelectrons_region ;
if (dof > 0) scalar = force->mvv2e * tarray_all[1] / (dof * force->boltz);
else scalar = 0.0;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRegionEff::compute_vector()
{
int i;
invoked_vector = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
Region *region = domain->regions[iregion];
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
massone = mass[type[i]];
t[0] += massone * v[i][0]*v[i][0];
t[1] += massone * v[i][1]*v[i][1];
t[2] += massone * v[i][2]*v[i][2];
t[3] += massone * v[i][0]*v[i][1];
t[4] += massone * v[i][0]*v[i][2];
t[5] += massone * v[i][1]*v[i][2];
if (fabs(spin[i])==1) {
t[0] += 0.75 * massone * ervel[i]*ervel[i];
t[1] += 0.75 * massone * ervel[i]*ervel[i];
t[2] += 0.75 * massone * ervel[i]*ervel[i];
}
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
NOTE: the following commands do not bias the radial electron velocities
------------------------------------------------------------------------- */
void ComputeTempRegionEff::remove_bias(int i, double *v)
{
double *x = atom->x[i];
if (domain->regions[iregion]->match(x[0],x[1],x[2]))
vbias[0] = vbias[1] = vbias[2] = 0.0;
else {
vbias[0] = v[0];
vbias[1] = v[1];
vbias[2] = v[2];
v[0] = v[1] = v[2] = 0.0;
}
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempRegionEff::remove_bias_all()
{
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/region:vbiasall");
}
Region *region = domain->regions[iregion];
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (region->match(x[i][0],x[i][1],x[i][2]))
vbiasall[i][0] = vbiasall[i][1] = vbiasall[i][2] = 0.0;
else {
vbiasall[i][0] = v[i][0];
vbiasall[i][1] = v[i][1];
vbiasall[i][2] = v[i][2];
v[i][0] = v[i][1] = v[i][2] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempRegionEff::restore_bias(int i, double *v)
{
v[0] += vbias[0];
v[1] += vbias[1];
v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempRegionEff::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] += vbiasall[i][0];
v[i][1] += vbiasall[i][1];
v[i][2] += vbiasall[i][2];
}
}
/* ---------------------------------------------------------------------- */
double ComputeTempRegionEff::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/USER-EFF/fix_nh_eff.cpp b/src/USER-EFF/fix_nh_eff.cpp
index 70f2544c2..e3dde8417 100644
--- a/src/USER-EFF/fix_nh_eff.cpp
+++ b/src/USER-EFF/fix_nh_eff.cpp
@@ -1,110 +1,110 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero (Caltech)
------------------------------------------------------------------------- */
#include "math.h"
#include "fix_nh_eff.h"
#include "atom.h"
#include "atom_vec.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NOBIAS,BIAS};
/* ---------------------------------------------------------------------- */
FixNHEff::FixNHEff(LAMMPS *lmp, int narg, char **arg) : FixNH(lmp, narg, arg)
{
if (!atom->electron_flag)
- error->all("Fix nvt/nph/npt/eff requires atom style electron");
+ error->all(FLERR,"Fix nvt/nph/npt/eff requires atom style electron");
}
/* ----------------------------------------------------------------------
perform half-step update of electron radial velocities
-----------------------------------------------------------------------*/
void FixNHEff::nve_v()
{
// standard nve_v velocity update
FixNH::nve_v();
double *erforce = atom->erforce;
double *ervel = atom->ervel;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
int itype;
double dtfm;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (fabs(spin[i])==1) {
dtfm = dtf / mass[type[i]];
ervel[i] = dtfm * erforce[i] / 0.75;
}
}
}
}
/* ----------------------------------------------------------------------
perform full-step update of electron radii
-----------------------------------------------------------------------*/
void FixNHEff::nve_x()
{
// standard nve_x position update
FixNH::nve_x();
double *eradius = atom->eradius;
double *ervel = atom->ervel;
int *spin = atom->spin;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (fabs(spin[i])==1) eradius[i] += dtv * ervel[i];
}
/* ----------------------------------------------------------------------
perform half-step scaling of electron radial velocities
-----------------------------------------------------------------------*/
void FixNHEff::nh_v_temp()
{
// standard nh_v_temp velocity scaling
FixNH::nh_v_temp();
double *ervel = atom->ervel;
int *spin = atom->spin;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (fabs(spin[i])==1) ervel[i] *= factor_eta;
}
diff --git a/src/USER-EFF/fix_nph_eff.cpp b/src/USER-EFF/fix_nph_eff.cpp
index 98f76c346..7cf5be647 100644
--- a/src/USER-EFF/fix_nph_eff.cpp
+++ b/src/USER-EFF/fix_nph_eff.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_nph_eff.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPHEff::FixNPHEff(LAMMPS *lmp, int narg, char **arg) :
FixNHEff(lmp, narg, arg)
{
if (tstat_flag)
- error->all("Temperature control can not be used with fix nph/eff");
+ error->all(FLERR,"Temperature control can not be used with fix nph/eff");
if (!pstat_flag)
- error->all("Pressure control must be used with fix nph/eff");
+ error->all(FLERR,"Pressure control must be used with fix nph/eff");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp/eff";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/USER-EFF/fix_npt_eff.cpp b/src/USER-EFF/fix_npt_eff.cpp
index d71a25d46..3b27e9b96 100644
--- a/src/USER-EFF/fix_npt_eff.cpp
+++ b/src/USER-EFF/fix_npt_eff.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_npt_eff.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPTEff::FixNPTEff(LAMMPS *lmp, int narg, char **arg) :
FixNHEff(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix npt/eff");
+ error->all(FLERR,"Temperature control must be used with fix npt/eff");
if (!pstat_flag)
- error->all("Pressure control must be used with fix npt/eff");
+ error->all(FLERR,"Pressure control must be used with fix npt/eff");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp/eff";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/USER-EFF/fix_nve_eff.cpp b/src/USER-EFF/fix_nve_eff.cpp
index 392f6b786..1466c777d 100644
--- a/src/USER-EFF/fix_nve_eff.cpp
+++ b/src/USER-EFF/fix_nve_eff.cpp
@@ -1,171 +1,171 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero (Caltech)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "string.h"
#include "fix_nve_eff.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "math.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVEEff::FixNVEEff(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (!atom->electron_flag)
- error->all("Fix nve/eff requires atom style electron");
+ error->all(FLERR,"Fix nve/eff requires atom style electron");
time_integrate = 1;
}
/* ---------------------------------------------------------------------- */
int FixNVEEff::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVEEff::init()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixNVEEff::initial_integrate(int vflag)
{
double dtfm;
// update v,vr and x,radius of atoms in group
double **x = atom->x;
double *eradius = atom->eradius;
double **v = atom->v;
double *ervel = atom->ervel;
double **f = atom->f;
double *erforce = atom->erforce;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// x + dt * [v + 0.5 * dt * (f / m)];
if (mass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
if (fabs(spin[i])==1) {
ervel[i] += dtfm * erforce[i] / 0.75;
eradius[i] += dtv * ervel[i];
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVEEff::final_integrate()
{
double dtfm;
double **v = atom->v;
double *ervel = atom->ervel;
double *erforce = atom->erforce;
double **f = atom->f;
double *mass = atom->mass;
int *spin = atom->spin;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// dyn_v[i] += m * dt * dyn_f[i];
if (mass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
if (fabs(spin[i])==1)
ervel[i] += dtfm * erforce[i] / 0.75;
}
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVEEff::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
// innermost level - NVE update of v and x
// all other levels - NVE update of v
if (ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVEEff::final_integrate_respa(int ilevel, int iloop)
{
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVEEff::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}
diff --git a/src/USER-EFF/fix_nvt_eff.cpp b/src/USER-EFF/fix_nvt_eff.cpp
index b742b66ee..a40cd4aef 100644
--- a/src/USER-EFF/fix_nvt_eff.cpp
+++ b/src/USER-EFF/fix_nvt_eff.cpp
@@ -1,49 +1,49 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "math.h"
#include "fix_nvt_eff.h"
#include "group.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVTEff::FixNVTEff(LAMMPS *lmp, int narg, char **arg) :
FixNHEff(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix nvt/eff");
+ error->all(FLERR,"Temperature control must be used with fix nvt/eff");
if (pstat_flag)
- error->all("Pressure control can not be used with fix nvt/eff");
+ error->all(FLERR,"Pressure control can not be used with fix nvt/eff");
// create a new compute temp style
// id = fix-ID + temp
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/eff";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
diff --git a/src/USER-EFF/fix_nvt_sllod_eff.cpp b/src/USER-EFF/fix_nvt_sllod_eff.cpp
index 435d70c20..0d38c1904 100644
--- a/src/USER-EFF/fix_nvt_sllod_eff.cpp
+++ b/src/USER-EFF/fix_nvt_sllod_eff.cpp
@@ -1,129 +1,129 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "fix_nvt_sllod_eff.h"
#include "math_extra.h"
#include "atom.h"
#include "domain.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "fix_deform.h"
#include "compute.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp
/* ---------------------------------------------------------------------- */
FixNVTSllodEff::FixNVTSllodEff(LAMMPS *lmp, int narg, char **arg) :
FixNHEff(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix nvt/sllod/eff");
+ error->all(FLERR,"Temperature control must be used with fix nvt/sllod/eff");
if (pstat_flag)
- error->all("Pressure control can not be used with fix nvt/sllod/eff");
+ error->all(FLERR,"Pressure control can not be used with fix nvt/sllod/eff");
// default values
if (mtchain_default_flag) mtchain = 1;
// create a new compute temp style
// id = fix-ID + temp
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/deform/eff";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
/* ---------------------------------------------------------------------- */
void FixNVTSllodEff::init()
{
FixNHEff::init();
if (!temperature->tempbias)
- error->all("Temperature for fix nvt/sllod/eff does not have a bias");
+ error->all(FLERR,"Temperature for fix nvt/sllod/eff does not have a bias");
nondeformbias = 0;
if (strcmp(temperature->style,"temp/deform/eff") != 0) nondeformbias = 1;
// check fix deform remap settings
int i;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
if (((FixDeform *) modify->fix[i])->remapflag != V_REMAP)
- error->all("Using fix nvt/sllod/eff with inconsistent fix deform "
+ error->all(FLERR,"Using fix nvt/sllod/eff with inconsistent fix deform "
"remap option");
break;
}
if (i == modify->nfix)
- error->all("Using fix nvt/sllod/eff with no fix deform defined");
+ error->all(FLERR,"Using fix nvt/sllod/eff with no fix deform defined");
}
/* ----------------------------------------------------------------------
perform half-step scaling of velocities
-----------------------------------------------------------------------*/
void FixNVTSllodEff::nh_v_temp()
{
// remove and restore bias = streaming velocity = Hrate*lamda + Hratelo
// thermostat thermal velocity only
// vdelu = SLLOD correction = Hrate*Hinv*vthermal
// for non temp/deform BIAS:
// calculate temperature since some computes require temp
// computed on current nlocal atoms to remove bias
if (nondeformbias) double tmp = temperature->compute_scalar();
double **v = atom->v;
double *ervel = atom->ervel;
int *spin = atom->spin;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
double h_two[6],vdelu[3];
MathExtra::multiply_shape_shape(domain->h_rate,domain->h_inv,h_two);
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
vdelu[0] = h_two[0]*v[i][0] + h_two[5]*v[i][1] + h_two[4]*v[i][2];
vdelu[1] = h_two[1]*v[i][1] + h_two[3]*v[i][2];
vdelu[2] = h_two[2]*v[i][2];
v[i][0] = v[i][0]*factor_eta - dthalf*vdelu[0];
v[i][1] = v[i][1]*factor_eta - dthalf*vdelu[1];
v[i][2] = v[i][2]*factor_eta - dthalf*vdelu[2];
temperature->restore_bias(i,v[i]);
if (fabs(spin[i])==1)
ervel[i] = ervel[i]*factor_eta -
dthalf*sqrt(pow(vdelu[0],2)+pow(vdelu[1],2)+pow(vdelu[2],2));
}
}
}
diff --git a/src/USER-EFF/fix_temp_rescale_eff.cpp b/src/USER-EFF/fix_temp_rescale_eff.cpp
index e5a0d19be..b6f4d585f 100644
--- a/src/USER-EFF/fix_temp_rescale_eff.cpp
+++ b/src/USER-EFF/fix_temp_rescale_eff.cpp
@@ -1,206 +1,206 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_temp_rescale_eff.h"
#include "atom.h"
#include "force.h"
#include "group.h"
#include "update.h"
#include "domain.h"
#include "region.h"
#include "comm.h"
#include "modify.h"
#include "compute.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NOBIAS,BIAS};
/* ---------------------------------------------------------------------- */
FixTempRescaleEff::FixTempRescaleEff(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 8) error->all("Illegal fix temp/rescale/eff command");
+ if (narg < 8) error->all(FLERR,"Illegal fix temp/rescale/eff command");
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix temp/rescale/eff command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix temp/rescale/eff command");
scalar_flag = 1;
global_freq = nevery;
extscalar = 1;
t_start = atof(arg[4]);
t_stop = atof(arg[5]);
t_window = atof(arg[6]);
fraction = atof(arg[7]);
// create a new compute temp/eff
// id = fix-ID + temp, compute group = fix group
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[6];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/eff";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
energy = 0.0;
}
/* ---------------------------------------------------------------------- */
FixTempRescaleEff::~FixTempRescaleEff()
{
// delete temperature if fix created it
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
}
/* ---------------------------------------------------------------------- */
int FixTempRescaleEff::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
mask |= THERMO_ENERGY;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleEff::init()
{
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix temp/rescale/eff does not exist");
+ error->all(FLERR,"Temperature ID for fix temp/rescale/eff does not exist");
temperature = modify->compute[icompute];
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleEff::end_of_step()
{
double t_current = temperature->compute_scalar();
if (t_current == 0.0)
- error->all("Computed temperature for fix temp/rescale/eff cannot be 0.0");
+ error->all(FLERR,"Computed temperature for fix temp/rescale/eff cannot be 0.0");
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
// rescale velocity of appropriate atoms if outside window
// for BIAS:
// temperature is current, so do not need to re-compute
// OK to not test returned v = 0, since factor is multiplied by v
if (fabs(t_current-t_target) > t_window) {
t_target = t_current - fraction*(t_current-t_target);
double factor = sqrt(t_target/t_current);
double efactor = 0.5 * force->boltz * temperature->dof;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int *spin = atom->spin;
double *ervel = atom->ervel;
if (which == NOBIAS) {
energy += (t_current-t_target) * efactor;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] *= factor;
v[i][1] *= factor;
v[i][2] *= factor;
if (abs(spin[i])==1)
ervel[i] *= factor;
}
}
} else {
energy += (t_current-t_target) * efactor;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= factor;
v[i][1] *= factor;
v[i][2] *= factor;
if (abs(spin[i])==1)
ervel[i] *= factor;
temperature->restore_bias(i,v[i]);
}
}
}
}
}
/* ---------------------------------------------------------------------- */
int FixTempRescaleEff::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp/eff") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void FixTempRescaleEff::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
double FixTempRescaleEff::compute_scalar()
{
return energy;
}
diff --git a/src/USER-EFF/pair_eff_cut.cpp b/src/USER-EFF/pair_eff_cut.cpp
index 85d2a1d1a..8f9913423 100644
--- a/src/USER-EFF/pair_eff_cut.cpp
+++ b/src/USER-EFF/pair_eff_cut.cpp
@@ -1,957 +1,954 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Andres Jaramillo-Botero
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_eff_cut.h"
#include "pair_eff_inline.h"
#include "atom.h"
#include "update.h"
#include "min.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairEffCut::PairEffCut(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
nmax = 0;
min_eradius = NULL;
min_erforce = NULL;
nextra = 4;
pvector = new double[nextra];
}
/* ---------------------------------------------------------------------- */
PairEffCut::~PairEffCut()
{
delete [] pvector;
memory->destroy(min_eradius);
memory->destroy(min_erforce);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
}
}
/* ---------------------------------------------------------------------- */
void PairEffCut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,energy;
double eke,ecoul,epauli,errestrain,halfcoul,halfpauli;
double fpair,fx,fy,fz;
double e1rforce,e2rforce,e1rvirial,e2rvirial;
double s_fpair, s_e1rforce, s_e2rforce;
double ecp_epauli, ecp_fpair, ecp_e1rforce, ecp_e2rforce;
double rsq,rc;
int *ilist,*jlist,*numneigh,**firstneigh;
energy = eke = epauli = ecoul = errestrain = 0.0;
// pvector = [KE, Pauli, ecoul, radial_restraint]
for (i=0; i<4; i++) pvector[i] = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
double *erforce = atom->erforce;
double *eradius = atom->eradius;
int *spin = atom->spin;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
// add electron wavefuntion kinetic energy (not pairwise)
if (abs(spin[i])==1 || spin[i]==2) {
// reset energy and force temp variables
eke = epauli = ecoul = 0.0;
fpair = e1rforce = e2rforce = 0.0;
s_fpair = 0.0;
KinElec(eradius[i],&eke,&e1rforce);
// Fixed-core
if (spin[i] == 2) {
// KE(2s)+Coul(1s-1s)+Coul(2s-nuclei)+Pauli(2s)
eke *= 2;
ElecNucElec(q[i],0.0,eradius[i],&ecoul,&fpair,&e1rforce);
ElecNucElec(q[i],0.0,eradius[i],&ecoul,&fpair,&e1rforce);
ElecElecElec(0.0,eradius[i],eradius[i],&ecoul,&fpair,&e1rforce,&e2rforce);
// opposite spin electron interactions
PauliElecElec(0,0.0,eradius[i],eradius[i],
&epauli,&s_fpair,&e1rforce,&e2rforce);
// fix core electron size, i.e. don't contribute to ervirial
e2rforce = e1rforce = 0.0;
}
// apply unit conversion factors
eke *= hhmss2e;
ecoul *= qqrd2e;
fpair *= qqrd2e;
epauli *= hhmss2e;
s_fpair *= hhmss2e;
e1rforce *= hhmss2e;
// Sum up contributions
energy = eke + epauli + ecoul;
fpair = fpair + s_fpair;
erforce[i] += e1rforce;
// Tally energy and compute radial atomic virial contribution
if (evflag) {
ev_tally_eff(i,i,nlocal,newton_pair,energy,0.0);
if (flexible_pressure_flag) // iff flexible pressure flag on
ev_tally_eff(i,i,nlocal,newton_pair,0.0,e1rforce*eradius[i]);
}
if (eflag_global) {
pvector[0] += eke;
pvector[1] += epauli;
pvector[2] += ecoul;
}
}
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
rc = sqrt(rsq);
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
energy = ecoul = epauli = ecp_epauli = 0.0;
fx = fy = fz = fpair = s_fpair = ecp_fpair = 0.0;
double taper = sqrt(cutsq[itype][jtype]);
double dist = rc / taper;
double spline = cutoff(dist);
double dspline = dcutoff(dist) / taper;
// nucleus (i) - nucleus (j) Coul interaction
if (spin[i] == 0 && spin[j] == 0) {
double qxq = q[i]*q[j];
ElecNucNuc(qxq, rc, &ecoul, &fpair);
}
// fixed-core (i) - nucleus (j) nuclear Coul interaction
else if (spin[i] == 2 && spin[j] == 0) {
double qxq = q[i]*q[j];
e1rforce = 0.0;
ElecNucNuc(qxq, rc, &ecoul, &fpair);
ElecNucElec(q[j],rc,eradius[i],&ecoul,&fpair,&e1rforce);
ElecNucElec(q[j],rc,eradius[i],&ecoul,&fpair,&e1rforce);
}
// nucleus (i) - fixed-core (j) nuclear Coul interaction
else if (spin[i] == 0 && spin[j] == 2) {
double qxq = q[i]*q[j];
e1rforce = 0.0;
ElecNucNuc(qxq, rc, &ecoul, &fpair);
ElecNucElec(q[i],rc,eradius[j],&ecoul,&fpair,&e1rforce);
ElecNucElec(q[i],rc,eradius[j],&ecoul,&fpair,&e1rforce);
}
// pseudo-core nucleus (i) - nucleus (j) interaction
else if (spin[i] == 3 && spin[j] == 0) {
double qxq = q[i]*q[j];
ElecCoreNuc(qxq, rc, eradius[i], &ecoul, &fpair);
}
// nucleus (i) - pseudo-core nucleus (j) interaction
else if (spin[i] == 0 && spin[j] == 3) {
double qxq = q[i]*q[j];
ElecCoreNuc(qxq, rc, eradius[j], &ecoul, &fpair);
}
// nucleus (i) - electron (j) Coul interaction
else if (spin[i] == 0 && abs(spin[j]) == 1) {
e1rforce = 0.0;
ElecNucElec(q[i],rc,eradius[j],&ecoul,&fpair,&e1rforce);
e1rforce = spline * qqrd2e * e1rforce;
erforce[j] += e1rforce;
// Radial electron virial, iff flexible pressure flag set
if (evflag && flexible_pressure_flag) {
e1rvirial = eradius[j] * e1rforce;
ev_tally_eff(j,j,nlocal,newton_pair,0.0,e1rvirial);
}
}
// electron (i) - nucleus (j) Coul interaction
else if (abs(spin[i]) == 1 && spin[j] == 0) {
e1rforce = 0.0;
ElecNucElec(q[j],rc,eradius[i],&ecoul,&fpair,&e1rforce);
e1rforce = spline * qqrd2e * e1rforce;
erforce[i] += e1rforce;
// Radial electron virial, iff flexible pressure flag set
if (evflag && flexible_pressure_flag) {
e1rvirial = eradius[i] * e1rforce;
ev_tally_eff(i,i,nlocal,newton_pair,0.0,e1rvirial);
}
}
// electron (i) - electron (j) interactions
else if (abs(spin[i]) == 1 && abs(spin[j]) == 1) {
e1rforce = e2rforce = 0.0;
s_e1rforce = s_e2rforce = 0.0;
ElecElecElec(rc,eradius[i],eradius[j],&ecoul,&fpair,
&e1rforce,&e2rforce);
PauliElecElec(spin[i] == spin[j],rc,eradius[i],eradius[j],
&epauli,&s_fpair,&s_e1rforce,&s_e2rforce);
// Apply conversion factor
epauli *= hhmss2e;
s_fpair *= hhmss2e;
e1rforce = spline * (qqrd2e * e1rforce + hhmss2e * s_e1rforce);
erforce[i] += e1rforce;
e2rforce = spline * (qqrd2e * e2rforce + hhmss2e * s_e2rforce);
erforce[j] += e2rforce;
// Radial electron virial, iff flexible pressure flag set
if (evflag && flexible_pressure_flag) {
e1rvirial = eradius[i] * e1rforce;
e2rvirial = eradius[j] * e2rforce;
ev_tally_eff(i,j,nlocal,newton_pair,0.0,e1rvirial+e2rvirial);
}
}
// fixed-core (i) - electron (j) interactions
else if (spin[i] == 2 && abs(spin[j]) == 1) {
e1rforce = e2rforce = 0.0;
s_e1rforce = s_e2rforce = 0.0;
ElecNucElec(q[i],rc,eradius[j],&ecoul,&fpair,&e2rforce);
ElecElecElec(rc,eradius[i],eradius[j],&ecoul,&fpair,
&e1rforce,&e2rforce);
ElecElecElec(rc,eradius[i],eradius[j],&ecoul,&fpair,
&e1rforce,&e2rforce);
PauliElecElec(0,rc,eradius[i],eradius[j],&epauli,
&s_fpair,&s_e1rforce,&s_e2rforce);
PauliElecElec(1,rc,eradius[i],eradius[j],&epauli,
&s_fpair,&s_e1rforce,&s_e2rforce);
// Apply conversion factor
epauli *= hhmss2e;
s_fpair *= hhmss2e;
// only update virial for j electron
e2rforce = spline * (qqrd2e * e2rforce + hhmss2e * s_e2rforce);
erforce[j] += e2rforce;
// Radial electron virial, iff flexible pressure flag set
if (evflag && flexible_pressure_flag) {
e2rvirial = eradius[j] * e2rforce;
ev_tally_eff(j,j,nlocal,newton_pair,0.0,e2rvirial);
}
}
// electron (i) - fixed-core (j) interactions
else if (abs(spin[i]) == 1 && spin[j] == 2) {
e1rforce = e2rforce = 0.0;
s_e1rforce = s_e2rforce = 0.0;
ElecNucElec(q[j],rc,eradius[i],&ecoul,&fpair,&e2rforce);
ElecElecElec(rc,eradius[j],eradius[i],&ecoul,&fpair,
&e1rforce,&e2rforce);
ElecElecElec(rc,eradius[j],eradius[i],&ecoul,&fpair,
&e1rforce,&e2rforce);
PauliElecElec(0,rc,eradius[j],eradius[i],&epauli,
&s_fpair,&s_e1rforce,&s_e2rforce);
PauliElecElec(1,rc,eradius[j],eradius[i],&epauli,
&s_fpair,&s_e1rforce,&s_e2rforce);
// Apply conversion factor
epauli *= hhmss2e;
s_fpair *= hhmss2e;
// only update virial for i electron
e2rforce = spline * (qqrd2e * e2rforce + hhmss2e * s_e2rforce);
erforce[i] += e2rforce;
// add radial atomic virial, iff flexible pressure flag set
if (evflag && flexible_pressure_flag) {
e2rvirial = eradius[i] * e2rforce;
ev_tally_eff(i,i,nlocal,newton_pair,0.0,e2rvirial);
}
}
// fixed-core (i) - fixed-core (j) interactions
else if (spin[i] == 2 && spin[j] == 2) {
e1rforce = e2rforce = 0.0;
s_e1rforce = s_e2rforce = 0.0;
double qxq = q[i]*q[j];
ElecNucNuc(qxq, rc, &ecoul, &fpair);
ElecNucElec(q[i],rc,eradius[j],&ecoul,&fpair,&e1rforce);
ElecNucElec(q[i],rc,eradius[j],&ecoul,&fpair,&e1rforce);
ElecNucElec(q[j],rc,eradius[i],&ecoul,&fpair,&e1rforce);
ElecNucElec(q[j],rc,eradius[i],&ecoul,&fpair,&e1rforce);
ElecElecElec(rc,eradius[i],eradius[j],&ecoul,&fpair,
&e1rforce,&e2rforce);
ElecElecElec(rc,eradius[i],eradius[j],&ecoul,&fpair,
&e1rforce,&e2rforce);
ElecElecElec(rc,eradius[i],eradius[j],&ecoul,&fpair,
&e1rforce,&e2rforce);
ElecElecElec(rc,eradius[i],eradius[j],&ecoul,&fpair,
&e1rforce,&e2rforce);
PauliElecElec(0,rc,eradius[i],eradius[j],&epauli,
&s_fpair,&s_e1rforce,&s_e2rforce);
PauliElecElec(1,rc,eradius[i],eradius[j],&epauli,
&s_fpair,&s_e1rforce,&s_e2rforce);
epauli *= 2;
s_fpair *= 2;
// Apply conversion factor
epauli *= hhmss2e;
s_fpair *= hhmss2e;
}
// pseudo-core (i) - electron/fixed-core electrons (j) interactions
else if (spin[i] == 3 && (abs(spin[j]) == 1 || spin[j] == 2)) {
e2rforce = ecp_e2rforce = 0.0;
if (abs(spin[j]) == 1) {
ElecCoreElec(q[i],rc,eradius[i],eradius[j],&ecoul,
&fpair,&e2rforce);
PauliCoreElec(rc,eradius[j],&ecp_epauli,&ecp_fpair,
&ecp_e2rforce,PAULI_CORE_A, PAULI_CORE_B,
PAULI_CORE_C);
} else { // add second s electron contribution from fixed-core
double qxq = q[i]*q[j];
ElecCoreNuc(qxq, rc, eradius[j], &ecoul, &fpair);
ElecCoreElec(q[i],rc,eradius[i],eradius[j],&ecoul,
&fpair,&e2rforce);
PauliCoreElec(rc,eradius[j],&ecp_epauli,&ecp_fpair,
&ecp_e2rforce,PAULI_CORE_A, PAULI_CORE_B,
PAULI_CORE_C);
}
// Apply conversion factor from Hartree to kcal/mol
ecp_epauli *= h2e;
ecp_fpair *= h2e;
// only update virial for j electron
e2rforce = spline * (qqrd2e * e2rforce + h2e * ecp_e2rforce);
erforce[j] += e2rforce;
// add radial atomic virial, iff flexible pressure flag set
if (evflag && flexible_pressure_flag) {
e2rvirial = eradius[j] * e2rforce;
ev_tally_eff(j,j,nlocal,newton_pair,0.0,e2rvirial);
}
}
// electron/fixed-core electrons (i) - pseudo-core (j) interactions
else if ((abs(spin[i]) == 1 || spin[i] == 2) && spin[j] == 3) {
e1rforce = ecp_e1rforce = 0.0;
if (abs(spin[j]) == 1) {
ElecCoreElec(q[j],rc,eradius[j],eradius[i],&ecoul,
&fpair,&e1rforce);
PauliCoreElec(rc,eradius[i],&ecp_epauli,&ecp_fpair,
&ecp_e1rforce,PAULI_CORE_A,PAULI_CORE_B,
PAULI_CORE_C);
} else {
double qxq = q[i]*q[j];
ElecCoreNuc(qxq,rc,eradius[i],&ecoul,&fpair);
ElecCoreElec(q[j],rc,eradius[j],eradius[i],&ecoul,
&fpair,&e1rforce);
PauliCoreElec(rc,eradius[i],&ecp_epauli,&ecp_fpair,
&ecp_e1rforce,PAULI_CORE_A, PAULI_CORE_B,
PAULI_CORE_C);
}
// Apply conversion factor from Hartree to kcal/mol
ecp_epauli *= h2e;
ecp_fpair *= h2e;
// only update virial for j electron
e1rforce = spline * (qqrd2e * e1rforce + h2e * ecp_e1rforce);
erforce[i] += e1rforce;
// add radial atomic virial, iff flexible pressure flag set
if (evflag && flexible_pressure_flag) {
e1rvirial = eradius[i] * e1rforce;
ev_tally_eff(i,i,nlocal,newton_pair,0.0,e1rvirial);
}
}
// pseudo-core (i) - pseudo-core (j) interactions
else if (spin[i] == 3 && abs(spin[j]) == 3) {
double qxq = q[i]*q[j];
ElecCoreCore(qxq,rc,eradius[i],eradius[j],&ecoul,&fpair);
}
// Apply Coulomb conversion factor for all cases
ecoul *= qqrd2e;
fpair *= qqrd2e;
// Sum up energy and force contributions
epauli += ecp_epauli;
energy = ecoul + epauli;
fpair = fpair + s_fpair + ecp_fpair;
// Apply cutoff spline
fpair = fpair * spline - energy * dspline;
energy = spline * energy;
// Tally cartesian forces
SmallRForce(delx,dely,delz,rc,fpair,&fx,&fy,&fz);
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
if (newton_pair || j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
}
// Tally energy (in ecoul) and compute normal pressure virials
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,0.0,
energy,fx,fy,fz,delx,dely,delz);
if (eflag_global) {
if (newton_pair) {
pvector[1] += spline * epauli;
pvector[2] += spline * ecoul;
}
else {
halfpauli = 0.5 * spline * epauli;
halfcoul = 0.5 * spline * ecoul;
if (i < nlocal) {
pvector[1] += halfpauli;
pvector[2] += halfcoul;
}
if (j < nlocal) {
pvector[1] += halfpauli;
pvector[2] += halfcoul;
}
}
}
}
}
// limit electron stifness (size) for periodic systems, to max=half-box-size
if (abs(spin[i]) == 1 && limit_size_flag) {
double half_box_length=0, dr, kfactor=hhmss2e*1.0;
e1rforce = errestrain = 0.0;
if (domain->xperiodic == 1 || domain->yperiodic == 1 ||
domain->zperiodic == 1) {
delx = domain->boxhi[0]-domain->boxlo[0];
dely = domain->boxhi[1]-domain->boxlo[1];
delz = domain->boxhi[2]-domain->boxlo[2];
half_box_length = 0.5 * MIN(delx, MIN(dely, delz));
if (eradius[i] > half_box_length) {
dr = eradius[i]-half_box_length;
errestrain=0.5*kfactor*dr*dr;
e1rforce=-kfactor*dr;
if (eflag_global) pvector[3] += errestrain;
erforce[i] += e1rforce;
// Tally radial restrain energy and add radial restrain virial
if (evflag) {
ev_tally_eff(i,i,nlocal,newton_pair,errestrain,0.0);
if (flexible_pressure_flag) // flexible electron pressure
ev_tally_eff(i,i,nlocal,newton_pair,0.0,eradius[i]*e1rforce);
}
}
}
}
}
if (vflag_fdotr) {
virial_fdotr_compute();
if (flexible_pressure_flag) virial_eff_compute();
}
}
/* ----------------------------------------------------------------------
eff-specific contribution to global virial
------------------------------------------------------------------------- */
void PairEffCut::virial_eff_compute()
{
double *eradius = atom->eradius;
double *erforce = atom->erforce;
double e_virial;
int *spin = atom->spin;
// sum over force on all particles including ghosts
if (neighbor->includegroup == 0) {
int nall = atom->nlocal + atom->nghost;
for (int i = 0; i < nall; i++) {
if (spin[i]) {
e_virial = erforce[i]*eradius[i]/3;
virial[0] += e_virial;
virial[1] += e_virial;
virial[2] += e_virial;
}
}
// neighbor includegroup flag is set
// sum over force on initial nfirst particles and ghosts
} else {
int nall = atom->nfirst;
for (int i = 0; i < nall; i++) {
if (spin[i]) {
e_virial = erforce[i]*eradius[i]/3;
virial[0] += e_virial;
virial[1] += e_virial;
virial[2] += e_virial;
}
}
nall = atom->nlocal + atom->nghost;
for (int i = atom->nlocal; i < nall; i++) {
if (spin[i]) {
e_virial = erforce[i]*eradius[i]/3;
virial[0] += e_virial;
virial[1] += e_virial;
virial[2] += e_virial;
}
}
}
}
/* ----------------------------------------------------------------------
tally eng_vdwl and virial into per-atom accumulators
for virial radial electronic contributions
------------------------------------------------------------------------- */
void PairEffCut::ev_tally_eff(int i, int j, int nlocal, int newton_pair,
double energy, double e_virial)
{
double energyhalf;
double partial_evirial = e_virial/3.0;
double half_partial_evirial = partial_evirial/2;
int *spin = atom->spin;
if (eflag_either) {
if (eflag_global) {
if (newton_pair)
eng_coul += energy;
else {
energyhalf = 0.5*energy;
if (i < nlocal)
eng_coul += energyhalf;
if (j < nlocal)
eng_coul += energyhalf;
}
}
if (eflag_atom) {
if (newton_pair || i < nlocal) eatom[i] += 0.5 * energy;
if (newton_pair || j < nlocal) eatom[j] += 0.5 * energy;
}
}
if (vflag_either) {
if (vflag_global) {
if (spin[i] && i < nlocal) {
virial[0] += half_partial_evirial;
virial[1] += half_partial_evirial;
virial[2] += half_partial_evirial;
}
if (spin[j] && j < nlocal) {
virial[0] += half_partial_evirial;
virial[1] += half_partial_evirial;
virial[2] += half_partial_evirial;
}
}
if (vflag_atom) {
if (spin[i]) {
if (newton_pair || i < nlocal) {
vatom[i][0] += half_partial_evirial;
vatom[i][1] += half_partial_evirial;
vatom[i][2] += half_partial_evirial;
}
}
if (spin[j]) {
if (newton_pair || j < nlocal) {
vatom[j][0] += half_partial_evirial;
vatom[j][1] += half_partial_evirial;
vatom[j][2] += half_partial_evirial;
}
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairEffCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
}
/* ---------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairEffCut::settings(int narg, char **arg)
{
if (narg != 1 && narg != 3 && narg != 4 && narg != 7)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
// Defaults ECP parameters for Si
PAULI_CORE_A = 0.320852;
PAULI_CORE_B = 2.283269;
PAULI_CORE_C = 0.814857;
if (narg == 1) {
cut_global = force->numeric(arg[0]);
limit_size_flag = 0;
flexible_pressure_flag = 0;
} else if (narg == 3) {
cut_global = force->numeric(arg[0]);
limit_size_flag = force->inumeric(arg[1]);
flexible_pressure_flag = force->inumeric(arg[2]);
} else if (narg == 4) {
cut_global = force->numeric(arg[0]);
limit_size_flag = 0;
flexible_pressure_flag = 0;
if (strcmp(arg[1],"ecp") != 0)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
else {
PAULI_CORE_A = force->numeric(arg[2]);
PAULI_CORE_B = force->numeric(arg[3]);
PAULI_CORE_C = force->numeric(arg[4]);
}
} else if (narg == 7) {
cut_global = force->numeric(arg[0]);
limit_size_flag = force->inumeric(arg[1]);
flexible_pressure_flag = force->inumeric(arg[2]);
if (strcmp(arg[3],"ecp") != 0)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
else {
PAULI_CORE_A = force->numeric(arg[4]);
PAULI_CORE_B = force->numeric(arg[5]);
PAULI_CORE_C = force->numeric(arg[6]);
}
}
// Need to introduce 2 new constants w/out changing update.cpp
if (force->qqr2e==332.06371) { // i.e. Real units chosen
h2e = 627.509; // hartree->kcal/mol
hhmss2e = 175.72044219620075; // hartree->kcal/mol * (Bohr->Angstrom)^2
} else if (force->qqr2e==1.0) { // electron units
h2e = 1.0;
hhmss2e = 1.0;
- } else error->all("Check your units");
+ } else error->all(FLERR,"Check your units");
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairEffCut::coeff(int narg, char **arg)
{
- if (narg < 2 || narg > 3) error->all("Incorrect args for pair coefficients");
+ if (narg < 2 || narg > 3) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double cut_one = cut_global;
if (narg == 3) cut_one = atof(arg[2]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairEffCut::init_style()
{
// error and warning checks
if (!atom->q_flag || !atom->spin_flag ||
!atom->eradius_flag || !atom->erforce_flag)
- error->all("Pair eff/cut requires atom attributes "
+ error->all(FLERR,"Pair eff/cut requires atom attributes "
"q, spin, eradius, erforce");
// add hook to minimizer for eradius and erforce
if (update->whichflag == 2)
int ignore = update->minimize->request(this,1,0.01);
// make sure to use the appropriate timestep when using real units
if (update->whichflag == 1) {
if (force->qqr2e == 332.06371 && update->dt == 1.0)
- error->all("You must lower the default real units timestep for pEFF ");
+ error->all(FLERR,"You must lower the default real units timestep for pEFF ");
}
// need a half neigh list and optionally a granular history neigh list
int irequest = neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairEffCut::init_one(int i, int j)
{
if (setflag[i][j] == 0)
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairEffCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairEffCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) fread(&cut[i][j],sizeof(double),1,fp);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairEffCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairEffCut::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
returns pointers to the log() of electron radius and corresponding force
minimizer operates on log(radius) so radius never goes negative
these arrays are stored locally by pair style
------------------------------------------------------------------------- */
void PairEffCut::min_xf_pointers(int ignore, double **xextra, double **fextra)
{
// grow arrays if necessary
// need to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(min_eradius);
memory->destroy(min_erforce);
nmax = atom->nmax;
memory->create(min_eradius,nmax,"pair:min_eradius");
memory->create(min_erforce,nmax,"pair:min_erforce");
}
*xextra = min_eradius;
*fextra = min_erforce;
}
/* ----------------------------------------------------------------------
minimizer requests the log() of electron radius and corresponding force
calculate and store in min_eradius and min_erforce
------------------------------------------------------------------------- */
void PairEffCut::min_xf_get(int ignore)
{
double *eradius = atom->eradius;
double *erforce = atom->erforce;
int *spin = atom->spin;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (spin[i]) {
min_eradius[i] = log(eradius[i]);
min_erforce[i] = eradius[i]*erforce[i];
} else min_eradius[i] = min_erforce[i] = 0.0;
}
/* ----------------------------------------------------------------------
minimizer has changed the log() of electron radius
propagate the change back to eradius
------------------------------------------------------------------------- */
void PairEffCut::min_x_set(int ignore)
{
double *eradius = atom->eradius;
int *spin = atom->spin;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (spin[i]) eradius[i] = exp(min_eradius[i]);
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairEffCut::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
bytes += 2 * nmax * sizeof(double);
return bytes;
}
diff --git a/src/USER-EWALDN/ewald_n.cpp b/src/USER-EWALDN/ewald_n.cpp
index d45b90f05..ed05ca504 100644
--- a/src/USER-EWALDN/ewald_n.cpp
+++ b/src/USER-EWALDN/ewald_n.cpp
@@ -1,698 +1,698 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter J. in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "ewald_n.h"
#include "math_vector.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define KSPACE_ILLEGAL "Illegal kspace_style ewald/n command"
#define KSPACE_ORDER "Unsupported order in kspace_style ewald/n for"
#define KSPACE_MIX "Unsupported mixing rule in kspace_style ewald/n for"
enum{GEOMETRIC,ARITHMETIC,SIXTHPOWER}; // same as in pair.cpp
//#define DEBUG
/* ---------------------------------------------------------------------- */
EwaldN::EwaldN(LAMMPS *lmp, int narg, char **arg) : KSpace(lmp, narg, arg)
{
- if (narg!=1) error->all(KSPACE_ILLEGAL);
+ if (narg!=1) error->all(FLERR,KSPACE_ILLEGAL);
precision = fabs(atof(arg[0]));
memset(function, 0, EWALD_NORDER*sizeof(int));
kenergy = kvirial = NULL;
cek_local = cek_global = NULL;
ekr_local = NULL;
hvec = NULL;
kvec = NULL;
B = NULL;
first_output = 0;
}
EwaldN::~EwaldN()
{
deallocate();
delete [] ekr_local;
delete [] B;
}
/* --------------------------------------------------------------------- */
void EwaldN::init()
{
nkvec = nkvec_max = nevec = nevec_max = 0;
nfunctions = nsums = sums = 0;
nbox = -1;
bytes = 0.0;
if (!comm->me) { // output message
if (screen) fprintf(screen,"EwaldN initialization ...\n");
if (logfile) fprintf(logfile,"EwaldN initialization ...\n");
}
if (domain->dimension == 2) // check for errors
- error->all("Cannot use EwaldN with 2d simulation");
+ error->all(FLERR,"Cannot use EwaldN with 2d simulation");
if (slabflag == 0 && domain->nonperiodic > 0)
- error->all("Cannot use nonperiodic boundaries with EwaldN");
+ error->all(FLERR,"Cannot use nonperiodic boundaries with EwaldN");
if (slabflag == 1) {
if (domain->xperiodic != 1 || domain->yperiodic != 1 ||
domain->boundary[2][0] != 1 || domain->boundary[2][1] != 1)
- error->all("Incorrect boundaries with slab EwaldN");
+ error->all(FLERR,"Incorrect boundaries with slab EwaldN");
}
qqrd2e = force->qqrd2e; // check pair_style
scale = 1.0;
//mumurd2e = force->mumurd2e;
//dielectric = force->dielectric;
mumurd2e = dielectric = 1.0;
int tmp;
Pair *pair = force->pair;
int *ptr = pair ? (int *) pair->extract("ewald_order",tmp) : NULL;
double *cutoff = pair ? (double *) pair->extract("cut_coul",tmp) : NULL;
if (!(ptr||cutoff))
- error->all("KSpace style is incompatible with Pair style");
+ error->all(FLERR,"KSpace style is incompatible with Pair style");
int ewald_order = ptr ? *((int *) ptr) : 1<<1;
int ewald_mix = ptr ? *((int *) pair->extract("ewald_mix",tmp)) : GEOMETRIC;
memset(function, 0, EWALD_NFUNCS*sizeof(int));
for (int i=0; i<=EWALD_NORDER; ++i) // transcribe order
if (ewald_order&(1<<i)) { // from pair_style
int n[] = EWALD_NSUMS, k;
char str[128];
switch (i) {
case 1:
k = 0; break;
case 3:
k = 3; break;
case 6:
if (ewald_mix==GEOMETRIC) { k = 1; break; }
else if (ewald_mix==ARITHMETIC) { k = 2; break; }
sprintf(str, "%s pair_style %s", KSPACE_MIX, force->pair_style);
- error->all(str);
+ error->all(FLERR,str);
default:
sprintf(str, "%s pair_style %s", KSPACE_ORDER, force->pair_style);
- error->all(str);
+ error->all(FLERR,str);
}
nfunctions += function[k] = 1;
nsums += n[k];
}
g_ewald = (1.35 - 0.15*log(precision))/ *cutoff; // determine resolution
g2_max = -4.0*g_ewald*g_ewald*log(precision);
if (!comm->me) { // output results
if (screen) fprintf(screen, " G vector = %g\n", g_ewald);
if (logfile) fprintf(logfile, " G vector = %g\n", g_ewald);
}
}
/* ----------------------------------------------------------------------
adjust EwaldN coeffs, called initially and whenever volume has changed
------------------------------------------------------------------------- */
void EwaldN::setup()
{
volume = shape_det(domain->h)*slab_volfactor; // cell volume
memcpy(unit, domain->h_inv, sizeof(shape)); // wave vector units
shape_scalar_mult(unit, 2.0*M_PI);
unit[2] /= slab_volfactor;
//int nbox_old = nbox, nkvec_old = nkvec;
if (precision>=1) nbox = 0;
else {
vector n = {1.0, 1.0, 1.0}; // based on cutoff
vec_scalar_mult(n, g_ewald*sqrt(-log(precision))/M_PI);
shape_vec_dot(n, n, domain->h);
n[2] *= slab_volfactor;
nbox = (int) n[0];
if (nbox<(int) n[1]) nbox = (int) n[1];
if (nbox<(int) n[2]) nbox = (int) n[2];
}
reallocate();
coefficients(); // compute coeffs
init_coeffs();
init_coeff_sums();
init_self();
if (!(first_output||comm->me)) { // output on first
first_output = 1;
if (screen) fprintf(screen,
" vectors: nbox = %d, nkvec = %d\n", nbox, nkvec);
if (logfile) fprintf(logfile,
" vectors: nbox = %d, nkvec = %d\n", nbox, nkvec);
}
}
void EwaldN::reallocate() // allocate memory
{
int ix, iy, iz;
int nkvec_max = nkvec;
vector h;
nkvec = 0; // determine size(kvec)
int kflag[(nbox+1)*(2*nbox+1)*(2*nbox+1)], *flag = kflag;
for (ix=0; ix<=nbox; ++ix)
for (iy=-nbox; iy<=nbox; ++iy)
for (iz=-nbox; iz<=nbox; ++iz)
if (!(ix||iy||iz)) *(flag++) = 0;
else if ((!ix)&&(iy<0)) *(flag++) = 0;
else if ((!(ix||iy))&&(iz<0)) *(flag++) = 0; // use symmetry
else {
h[0] = unit[0]*ix;
h[1] = unit[5]*ix+unit[1]*iy;
h[2] = unit[4]*ix+unit[3]*iy+unit[2]*iz;
if ((*(flag++) = h[0]*h[0]+h[1]*h[1]+h[2]*h[2]<=g2_max)) ++nkvec;
}
if (nkvec>nkvec_max) {
deallocate(); // free memory
hvec = new hvector[nkvec]; // hvec
bytes += (nkvec-nkvec_max)*sizeof(hvector);
kvec = new kvector[nkvec]; // kvec
bytes += (nkvec-nkvec_max)*sizeof(kvector);
kenergy = new double[nkvec*nfunctions]; // kenergy
bytes += (nkvec-nkvec_max)*nfunctions*sizeof(double);
kvirial = new double[6*nkvec*nfunctions]; // kvirial
bytes += 6*(nkvec-nkvec_max)*nfunctions*sizeof(double);
cek_local = new complex[nkvec*nsums]; // cek_local
bytes += (nkvec-nkvec_max)*nsums*sizeof(complex);
cek_global = new complex[nkvec*nsums]; // cek_global
bytes += (nkvec-nkvec_max)*nsums*sizeof(complex);
nkvec_max = nkvec;
}
flag = kflag; // create index and
kvector *k = kvec; // wave vectors
hvector *hi = hvec;
for (ix=0; ix<=nbox; ++ix)
for (iy=-nbox; iy<=nbox; ++iy)
for (iz=-nbox; iz<=nbox; ++iz)
if (*(flag++)) {
hi->x = unit[0]*ix;
hi->y = unit[5]*ix+unit[1]*iy;
(hi++)->z = unit[4]*ix+unit[3]*iy+unit[2]*iz;
k->x = ix+nbox; k->y = iy+nbox; (k++)->z = iz+nbox; }
}
void EwaldN::reallocate_atoms()
{
if ((nevec = atom->nmax*(2*nbox+1))<=nevec_max) return;
delete [] ekr_local;
ekr_local = new cvector[nevec];
bytes += (nevec-nevec_max)*sizeof(cvector);
nevec_max = nevec;
}
void EwaldN::deallocate() // free memory
{
delete [] hvec; hvec = NULL;
delete [] kvec; kvec = NULL;
delete [] kenergy; kenergy = NULL;
delete [] kvirial; kvirial = NULL;
delete [] cek_local; cek_local = NULL;
delete [] cek_global; cek_global = NULL;
}
void EwaldN::coefficients() // set up pre-factors
{
vector h;
hvector *hi = hvec, *nh;
double eta2 = 0.25/(g_ewald*g_ewald);
double b1, b2, expb2, h1, h2, c1, c2;
double *ke = kenergy, *kv = kvirial;
int func0 = function[0], func12 = function[1]||function[2],
func3 = function[3];
for (nh = (hi = hvec)+nkvec; hi<nh; ++hi) { // wave vectors
memcpy(h, hi, sizeof(vector));
expb2 = exp(-(b2 = (h2 = vec_dot(h, h))*eta2));
if (func0) { // qi*qj/r coeffs
*(ke++) = c1 = expb2/h2;
*(kv++) = c1-(c2 = 2.0*c1*(1.0+b2)/h2)*h[0]*h[0];
*(kv++) = c1-c2*h[1]*h[1]; // lammps convention
*(kv++) = c1-c2*h[2]*h[2]; // instead of voigt
*(kv++) = -c2*h[1]*h[0];
*(kv++) = -c2*h[2]*h[0];
*(kv++) = -c2*h[2]*h[1];
}
if (func12) { // -Bij/r^6 coeffs
b1 = sqrt(b2); // minus sign folded
h1 = sqrt(h2); // into constants
*(ke++) = c1 = -h1*h2*((c2=sqrt(M_PI)*erfc(b1))+(0.5/b2-1.0)*expb2/b1);
*(kv++) = c1-(c2 = 3.0*h1*(c2-expb2/b1))*h[0]*h[0];
*(kv++) = c1-c2*h[1]*h[1]; // lammps convention
*(kv++) = c1-c2*h[2]*h[2]; // instead of voigt
*(kv++) = -c2*h[1]*h[0];
*(kv++) = -c2*h[2]*h[0];
*(kv++) = -c2*h[2]*h[1];
}
if (func3) { // dipole coeffs
*(ke++) = c1 = expb2/h2;
*(kv++) = c1-(c2 = 2.0*c1*(1.0+b2)/h2)*h[0]*h[0];
*(kv++) = c1-c2*h[1]*h[1]; // lammps convention
*(kv++) = c1-c2*h[2]*h[2]; // instead of voigt
*(kv++) = -c2*h[1]*h[0];
*(kv++) = -c2*h[2]*h[0];
*(kv++) = -c2*h[2]*h[1];
}
}
}
void EwaldN::init_coeffs() // local pair coeffs
{
int tmp;
int n = atom->ntypes;
if (function[1]) { // geometric 1/r^6
double **b = (double **) force->pair->extract("B",tmp);
delete [] B;
B = new double[n+1];
bytes += (n+1)*sizeof(double);
for (int i=0; i<=n; ++i) B[i] = sqrt(fabs(b[i][i]));
}
if (function[2]) { // arithmetic 1/r^6
double **epsilon = (double **) force->pair->extract("epsilon",tmp);
double **sigma = (double **) force->pair->extract("sigma",tmp);
if (!(epsilon&&sigma))
- error->all("epsilon or sigma reference not set by pair style in ewald/n");
+ error->all(FLERR,"epsilon or sigma reference not set by pair style in ewald/n");
double eps_i, sigma_i, sigma_n, *bi = B = new double[7*n+7];
double c[7] = {
1.0, sqrt(6.0), sqrt(15.0), sqrt(20.0), sqrt(15.0), sqrt(6.0), 1.0};
for (int i=0; i<=n; ++i) {
eps_i = sqrt(epsilon[i][i]);
sigma_i = sigma[i][i];
sigma_n = 1.0;
for (int j=0; j<7; ++j) {
*(bi++) = sigma_n*eps_i*c[j]; sigma_n *= sigma_i;
}
}
}
}
void EwaldN::init_coeff_sums() // sums based on atoms
{
if (sums) return; // calculated only once
sums = 1;
Sum sum_local[EWALD_MAX_NSUMS];
memset(sum_local, 0, EWALD_MAX_NSUMS*sizeof(Sum));
if (function[0]) { // 1/r
double *q = atom->q, *qn = q+atom->nlocal;
for (double *i=q; i<qn; ++i) {
sum_local[0].x += i[0]; sum_local[0].x2 += i[0]*i[0]; }
}
if (function[1]) { // geometric 1/r^6
int *type = atom->type, *ntype = type+atom->nlocal;
for (int *i=type; i<ntype; ++i) {
sum_local[1].x += B[i[0]]; sum_local[1].x2 += B[i[0]]*B[i[0]]; }
}
if (function[2]) { // aritmetic 1/r^6
double *bi;
int *type = atom->type, *ntype = type+atom->nlocal;
for (int *i=type; i<ntype; ++i) {
bi = B+7*i[0];
sum_local[2].x2 += bi[0]*bi[6];
for (int k=2; k<9; ++k) sum_local[k].x += *(bi++);
}
}
if (function[3]) { // dipole
double **mu = atom->mu;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
sum_local[9].x2 += mu[i][3]*mu[i][3];
}
MPI_Allreduce(sum_local, sum, 2*EWALD_MAX_NSUMS, MPI_DOUBLE, MPI_SUM, world);
}
void EwaldN::init_self()
{
double g1 = g_ewald, g2 = g1*g1, g3 = g1*g2;
memset(energy_self, 0, EWALD_NFUNCS*sizeof(double)); // self energy
memset(virial_self, 0, EWALD_NFUNCS*sizeof(double));
if (function[0]) { // 1/r
virial_self[0] = -0.5*M_PI*qqrd2e*scale/(g2*volume)*sum[0].x*sum[0].x;
energy_self[0] = sum[0].x2*qqrd2e*scale*g1/sqrt(M_PI)-virial_self[0];
}
if (function[1]) { // geometric 1/r^6
virial_self[1] = M_PI*sqrt(M_PI)*g3/(6.0*volume)*sum[1].x*sum[1].x;
energy_self[1] = -sum[1].x2*g3*g3/12.0+virial_self[1];
}
if (function[2]) { // arithmetic 1/r^6
virial_self[2] = M_PI*sqrt(M_PI)*g3/(48.0*volume)*(sum[2].x*sum[8].x+
sum[3].x*sum[7].x+sum[4].x*sum[6].x+0.5*sum[5].x*sum[5].x);
energy_self[2] = -sum[2].x2*g3*g3/3.0+virial_self[2];
}
if (function[3]) { // dipole
virial_self[3] = 0; // in surface
energy_self[3] = sum[9].x2*mumurd2e*2.0*g3/3.0/sqrt(M_PI)-virial_self[3];
}
}
/* ----------------------------------------------------------------------
compute the EwaldN long-range force, energy, virial
------------------------------------------------------------------------- */
void EwaldN::compute(int eflag, int vflag)
{
if (!nbox) return;
reallocate_atoms();
compute_ek();
compute_force();
compute_surface();
compute_energy(eflag);
compute_virial(vflag);
}
void EwaldN::compute_ek()
{
cvector *ekr = ekr_local;
int lbytes = (2*nbox+1)*sizeof(cvector);
hvector *h;
kvector *k, *nk = kvec+nkvec;
cvector z1, z[2*nbox+1], *zx, *zy, *zz, *zn = z+2*nbox;
complex *cek, zxyz, zxy, cx;
vector mui;
double *x = atom->x[0], *xn = x+3*atom->nlocal, *q = atom->q, qi, bi, ci[7];
double *mu = atom->mu ? atom->mu[0] : NULL;
int i, kx, ky, n = nkvec*nsums, *type = atom->type, tri = domain->triclinic;
int func[EWALD_NFUNCS];
memcpy(func, function, EWALD_NFUNCS*sizeof(int));
memset(cek_local, 0, n*sizeof(complex)); // reset sums
while (x<xn) {
zx = (zy = (zz = z+nbox)+1)-2;
C_SET(zz->x, 1, 0); C_SET(zz->y, 1, 0); C_SET(zz->z, 1, 0); // z[0]
if (tri) { // triclinic z[1]
C_ANGLE(z1.x, unit[0]*x[0]+unit[5]*x[1]+unit[4]*x[2]);
C_ANGLE(z1.y, unit[1]*x[1]+unit[3]*x[2]);
C_ANGLE(z1.z, x[2]*unit[2]); x += 3;
}
else { // orthogonal z[1]
C_ANGLE(z1.x, *(x++)*unit[0]);
C_ANGLE(z1.y, *(x++)*unit[1]);
C_ANGLE(z1.z, *(x++)*unit[2]);
}
for (; zz<zn; --zx, ++zy, ++zz) { // set up z[k]=e^(ik.r)
C_RMULT(zy->x, zz->x, z1.x); // 3D k-vector
C_RMULT(zy->y, zz->y, z1.y); C_CONJ(zx->y, zy->y);
C_RMULT(zy->z, zz->z, z1.z); C_CONJ(zx->z, zy->z);
}
kx = ky = -1;
cek = cek_local;
if (func[0]) qi = *(q++);
if (func[1]) bi = B[*type];
if (func[2]) memcpy(ci, B+7*type[0], 7*sizeof(double));
if (func[3]) {
memcpy(mui, mu, sizeof(vector)); mu += 3;
vec_scalar_mult(mui, mu[3]);
mu += 4;
h = hvec;
}
for (k=kvec; k<nk; ++k) { // compute rho(k)
if (ky!=k->y) { // based on order in
if (kx!=k->x) cx = z[kx = k->x].x; // reallocate
C_RMULT(zxy, z[ky = k->y].y, cx);
}
C_RMULT(zxyz, z[k->z].z, zxy);
if (func[0]) {
cek->re += zxyz.re*qi; (cek++)->im += zxyz.im*qi;
}
if (func[1]) {
cek->re += zxyz.re*bi; (cek++)->im += zxyz.im*bi;
}
if (func[2]) for (i=0; i<7; ++i) {
cek->re += zxyz.re*ci[i]; (cek++)->im += zxyz.im*ci[i];
}
if (func[3]) {
register double muk = mui[0]*h->x+mui[1]*h->y+mui[2]*h->z; ++h;
cek->re += zxyz.re*muk; (cek++)->im += zxyz.im*muk;
}
}
ekr = (cvector *) ((char *) memcpy(ekr, z, lbytes)+lbytes);
++type;
}
MPI_Allreduce(cek_local, cek_global, 2*n, MPI_DOUBLE, MPI_SUM, world);
}
void EwaldN::compute_force()
{
kvector *k;
hvector *h, *nh;
cvector *z = ekr_local;
vector sum[EWALD_MAX_NSUMS], mui;
complex *cek, zc, zx, zxy;
double *f = atom->f[0], *fn = f+3*atom->nlocal, *q = atom->q, *t = NULL;
double *mu = atom->mu ? atom->mu[0] : NULL;
double *ke, c[EWALD_NFUNCS] = {
8.0*M_PI*qqrd2e*scale/volume, 2.0*M_PI*sqrt(M_PI)/(12.0*volume),
2.0*M_PI*sqrt(M_PI)/(192.0*volume), 8.0*M_PI*mumurd2e/volume};
double kt = 4.0*pow(g_ewald, 3.0)/3.0/sqrt(M_PI)/c[3];
int i, kx, ky, lbytes = (2*nbox+1)*sizeof(cvector), *type = atom->type;
int func[EWALD_NFUNCS];
if (atom->torque) t = atom->torque[0];
memcpy(func, function, EWALD_NFUNCS*sizeof(int));
memset(sum, 0, EWALD_MAX_NSUMS*sizeof(vector)); // fj = -dE/dr =
for (; f<fn; f+=3) { // -i*qj*fac*
k = kvec; // Sum[conj(d)-d]
kx = ky = -1; // d = k*conj(ekj)*ek
ke = kenergy;
cek = cek_global;
memset(sum, 0, EWALD_MAX_NSUMS*sizeof(vector));
if (func[3]) {
register double di = mu[3] * c[3];
mui[0] = di*(mu++)[0]; mui[1] = di*(mu++)[1]; mui[2] = di*(mu++)[2];
mu++;
}
for (nh = (h = hvec)+nkvec; h<nh; ++h, ++k) {
if (ky!=k->y) { // based on order in
if (kx!=k->x) zx = z[kx = k->x].x; // reallocate
C_RMULT(zxy, z[ky = k->y].y, zx);
}
C_CRMULT(zc, z[k->z].z, zxy);
if (func[0]) { // 1/r
register double im = *(ke++)*(zc.im*cek->re+cek->im*zc.re); ++cek;
sum[0][0] += h->x*im; sum[0][1] += h->y*im; sum[0][2] += h->z*im;
}
if (func[1]) { // geometric 1/r^6
register double im = *(ke++)*(zc.im*cek->re+cek->im*zc.re); ++cek;
sum[1][0] += h->x*im; sum[1][1] += h->y*im; sum[1][2] += h->z*im;
}
if (func[2]) { // arithmetic 1/r^6
register double im, c = *(ke++);
for (i=2; i<9; ++i) {
im = c*(zc.im*cek->re+cek->im*zc.re); ++cek;
sum[i][0] += h->x*im; sum[i][1] += h->y*im; sum[i][2] += h->z*im;
}
}
if (func[3]) { // dipole
register double im = *(ke++)*(zc.im*cek->re+
cek->im*zc.re)*(mui[0]*h->x+mui[1]*h->y+mui[2]*h->z); ++cek;
sum[9][0] += h->x*im; sum[9][1] += h->y*im; sum[9][2] += h->z*im;
}
}
if (func[0]) { // 1/r
register double qi = *(q++)*c[0];
f[0] -= sum[0][0]*qi; f[1] -= sum[0][1]*qi; f[2] -= sum[0][2]*qi;
}
if (func[1]) { // geometric 1/r^6
register double bi = B[*type]*c[1];
f[0] -= sum[1][0]*bi; f[1] -= sum[1][1]*bi; f[2] -= sum[1][2]*bi;
}
if (func[2]) { // arithmetic 1/r^6
register double *bi = B+7*type[0]+7;
for (i=2; i<9; ++i) {
register double c2 = (--bi)[0]*c[2];
f[0] -= sum[i][0]*c2; f[1] -= sum[i][1]*c2; f[2] -= sum[i][2]*c2;
}
}
if (func[3]) { // dipole
f[0] -= sum[9][0]; f[1] -= sum[9][1]; f[2] -= sum[9][2];
*(t++) -= mui[1]*sum[0][2]+mui[2]*sum[0][1]-mui[0]*kt; // torque
*(t++) -= mui[2]*sum[0][0]+mui[0]*sum[0][2]-mui[1]*kt;
*(t++) -= mui[0]*sum[0][1]+mui[1]*sum[0][0]-mui[2]*kt;
}
z = (cvector *) ((char *) z+lbytes);
++type;
}
}
void EwaldN::compute_surface()
{
if (!function[3]) return;
vector sum_local = VECTOR_NULL, sum_total;
double **mu = atom->mu;
int nlocal = atom->nlocal;
for (int i=0; i < nlocal; i++) {
register double di = mu[i][3];
sum_local[0] += di*mu[i][0];
sum_local[1] += di*mu[i][1];
sum_local[2] += di*mu[i][2];
}
MPI_Allreduce(sum_local, sum_total, 3, MPI_DOUBLE, MPI_SUM, world);
energy_self[3] += virial_self[3];
virial_self[3] =
mumurd2e*(2.0*M_PI*vec_dot(sum_total,sum_total)/(2.0*dielectric+1)/volume);
energy_self[3] -= virial_self[3];
}
void EwaldN::compute_energy(int eflag)
{
energy = 0.0;
if (!eflag) return;
complex *cek = cek_global;
double *ke = kenergy;
double c[EWALD_NFUNCS] = {
4.0*M_PI*qqrd2e*scale/volume, 2.0*M_PI*sqrt(M_PI)/(24.0*volume),
2.0*M_PI*sqrt(M_PI)/(192.0*volume), 4.0*M_PI*mumurd2e/volume};
double sum[EWALD_NFUNCS];
int func[EWALD_NFUNCS];
memcpy(func, function, EWALD_NFUNCS*sizeof(int));
memset(sum, 0, EWALD_NFUNCS*sizeof(double)); // reset sums
for (int k=0; k<nkvec; ++k) { // sum over k vectors
if (func[0]) { // 1/r
sum[0] += *(ke++)*(cek->re*cek->re+cek->im*cek->im); ++cek; }
if (func[1]) { // geometric 1/r^6
sum[1] += *(ke++)*(cek->re*cek->re+cek->im*cek->im); ++cek; }
if (func[2]) { // arithmetic 1/r^6
register double r =
(cek[0].re*cek[6].re+cek[0].im*cek[6].im)+
(cek[1].re*cek[5].re+cek[1].im*cek[5].im)+
(cek[2].re*cek[4].re+cek[2].im*cek[4].im)+
0.5*(cek[3].re*cek[3].re+cek[3].im*cek[3].im); cek += 7;
sum[2] += *(ke++)*r;
}
if (func[3]) { // dipole
sum[3] += *(ke++)*(cek->re*cek->re+cek->im*cek->im); ++cek; }
}
for (int k=0; k<EWALD_NFUNCS; ++k) energy += c[k]*sum[k]-energy_self[k];
if (slabflag) compute_slabcorr(eflag);
}
#define swap(a, b) { register double t = a; a= b; b = t; }
void EwaldN::compute_virial(int vflag)
{
memset(virial, 0, sizeof(shape));
if (!vflag) return;
complex *cek = cek_global;
double *kv = kvirial;
double c[EWALD_NFUNCS] = {
4.0*M_PI*qqrd2e*scale/volume, 2.0*M_PI*sqrt(M_PI)/(24.0*volume),
2.0*M_PI*sqrt(M_PI)/(192.0*volume), 4.0*M_PI*mumurd2e/volume};
shape sum[EWALD_NFUNCS];
int func[EWALD_NFUNCS];
memcpy(func, function, EWALD_NFUNCS*sizeof(int));
memset(sum, 0, EWALD_NFUNCS*sizeof(shape));
for (int k=0; k<nkvec; ++k) { // sum over k vectors
if (func[0]) { // 1/r
register double r = cek->re*cek->re+cek->im*cek->im; ++cek;
sum[0][0] += *(kv++)*r; sum[0][1] += *(kv++)*r; sum[0][2] += *(kv++)*r;
sum[0][3] += *(kv++)*r; sum[0][4] += *(kv++)*r; sum[0][5] += *(kv++)*r;
}
if (func[1]) { // geometric 1/r^6
register double r = cek->re*cek->re+cek->im*cek->im; ++cek;
sum[1][0] += *(kv++)*r; sum[1][1] += *(kv++)*r; sum[1][2] += *(kv++)*r;
sum[1][3] += *(kv++)*r; sum[1][4] += *(kv++)*r; sum[1][5] += *(kv++)*r;
}
if (func[2]) { // arithmetic 1/r^6
register double r =
(cek[0].re*cek[6].re+cek[0].im*cek[6].im)+
(cek[1].re*cek[5].re+cek[1].im*cek[5].im)+
(cek[2].re*cek[4].re+cek[2].im*cek[4].im)+
0.5*(cek[3].re*cek[3].re+cek[3].im*cek[3].im); cek += 7;
sum[2][0] += *(kv++)*r; sum[2][1] += *(kv++)*r; sum[2][2] += *(kv++)*r;
sum[2][3] += *(kv++)*r; sum[2][4] += *(kv++)*r; sum[2][5] += *(kv++)*r;
}
if (func[3]) {
register double r = cek->re*cek->re+cek->im*cek->im; ++cek;
sum[3][0] += *(kv++)*r; sum[3][1] += *(kv++)*r; sum[3][2] += *(kv++)*r;
sum[3][3] += *(kv++)*r; sum[3][4] += *(kv++)*r; sum[3][5] += *(kv++)*r;
}
}
for (int k=0; k<EWALD_NFUNCS; ++k)
if (func[k]) {
shape self = {virial_self[k], virial_self[k], virial_self[k], 0, 0, 0};
shape_scalar_mult(sum[k], c[k]);
shape_add(virial, sum[k]);
shape_subtr(virial, self);
}
}
/* ----------------------------------------------------------------------
Slab-geometry correction term to dampen inter-slab interactions between
periodically repeating slabs. Yields good approximation to 2-D EwaldN if
adequate empty space is left between repeating slabs (J. Chem. Phys.
111, 3155). Slabs defined here to be parallel to the xy plane.
------------------------------------------------------------------------- */
void EwaldN::compute_slabcorr(int eflag)
{
// compute local contribution to global dipole moment
double *q = atom->q;
double *x = atom->x[0]-1, *xn = x+3*atom->nlocal-1;
double dipole = 0.0, dipole_all;
while ((x+=3)<xn) dipole += *x * *(q++);
MPI_Allreduce(&dipole, &dipole_all, 1, MPI_DOUBLE, MPI_SUM, world);
double ffact = -4.0*M_PI*qqrd2e*scale*dipole_all/volume;
double *f = atom->f[0]-1, *fn = f+3*atom->nlocal-3;
q = atom->q;
while ((f+=3)<fn) *f += ffact* *(q++);
if (eflag) // energy correction
energy += qqrd2e*scale*(2.0*M_PI*dipole_all*dipole_all/volume);
}
diff --git a/src/USER-EWALDN/pair_buck_coul.cpp b/src/USER-EWALDN/pair_buck_coul.cpp
index bb2f4f0ed..74e9e5647 100644
--- a/src/USER-EWALDN/pair_buck_coul.cpp
+++ b/src/USER-EWALDN/pair_buck_coul.cpp
@@ -1,1171 +1,1168 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter J. in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math_vector.h"
#include "pair_buck_coul.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "kspace.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairBuckCoul::PairBuckCoul(LAMMPS *lmp) : Pair(lmp)
{
respa_enable = 1;
ftable = NULL;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
#define PAIR_ILLEGAL "Illegal pair_style buck/coul command"
#define PAIR_CUTOFF "Only one cut-off allowed when requesting all long"
#define PAIR_MISSING "Cut-offs missing in pair_style buck/coul"
#define PAIR_LJ_OFF "LJ6 off not supported in pair_style buck/coul"
#define PAIR_COUL_CUT "Coulombic cut not supported in pair_style buck/coul"
#define PAIR_LARGEST "Using largest cut-off for buck/coul long long"
#define PAIR_MIX "Geometric mixing assumed for 1/r^6 coefficients"
void PairBuckCoul::options(char **arg, int order)
{
char *option[] = {"long", "cut", "off", NULL};
int i;
- if (!*arg) error->all(PAIR_ILLEGAL);
+ if (!*arg) error->all(FLERR,PAIR_ILLEGAL);
for (i=0; option[i]&&strcmp(arg[0], option[i]); ++i);
switch (i) {
- default: error->all(PAIR_ILLEGAL);
+ default: error->all(FLERR,PAIR_ILLEGAL);
case 0: ewald_order |= 1<<order; break; // set kspace r^-order
case 2: ewald_off |= 1<<order; // turn r^-order off
case 1: break;
}
}
void PairBuckCoul::settings(int narg, char **arg)
{
- if (narg != 3 && narg != 4) error->all("Illegal pair_style command");
+ if (narg != 3 && narg != 4) error->all(FLERR,"Illegal pair_style command");
ewald_order = 0;
ewald_off = 0;
options(arg, 6);
options(++arg, 1);
- if (!comm->me && ewald_order&(1<<6)) error->warning(PAIR_MIX);
- if (!comm->me && ewald_order==((1<<1)|(1<<6))) error->warning(PAIR_LARGEST);
- if (!*(++arg)) error->all(PAIR_MISSING);
- if (ewald_off&(1<<6)) error->all(PAIR_LJ_OFF);
- if (!((ewald_order^ewald_off)&(1<<1))) error->all(PAIR_COUL_CUT);
+ if (!comm->me && ewald_order&(1<<6)) error->warning(FLERR,PAIR_MIX);
+ if (!comm->me && ewald_order==((1<<1)|(1<<6))) error->warning(FLERR,PAIR_LARGEST);
+ if (!*(++arg)) error->all(FLERR,PAIR_MISSING);
+ if (ewald_off&(1<<6)) error->all(FLERR,PAIR_LJ_OFF);
+ if (!((ewald_order^ewald_off)&(1<<1))) error->all(FLERR,PAIR_COUL_CUT);
cut_buck_global = force->numeric(*(arg++));
- if (*arg&&(ewald_order&0x42==0x42)) error->all(PAIR_CUTOFF);
+ if (*arg&&(ewald_order&0x42==0x42)) error->all(FLERR,PAIR_CUTOFF);
if (narg == 4) cut_coul = force->numeric(*arg);
else cut_coul = cut_buck_global;
if (allocated) { // reset explicit cuts
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut_buck[i][j] = cut_buck_global;
}
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairBuckCoul::~PairBuckCoul()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_buck_read);
memory->destroy(cut_buck);
memory->destroy(cut_bucksq);
memory->destroy(buck_a_read);
memory->destroy(buck_a);
memory->destroy(buck_c_read);
memory->destroy(buck_c);
memory->destroy(buck_rho_read);
memory->destroy(buck_rho);
memory->destroy(buck1);
memory->destroy(buck2);
memory->destroy(rhoinv);
memory->destroy(offset);
}
if (ftable) free_tables();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairBuckCoul::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_buck_read,n+1,n+1,"pair:cut_buck_read");
memory->create(cut_buck,n+1,n+1,"pair:cut_buck");
memory->create(cut_bucksq,n+1,n+1,"pair:cut_bucksq");
memory->create(buck_a_read,n+1,n+1,"pair:buck_a_read");
memory->create(buck_a,n+1,n+1,"pair:buck_a");
memory->create(buck_c_read,n+1,n+1,"pair:buck_c_read");
memory->create(buck_c,n+1,n+1,"pair:buck_c");
memory->create(buck_rho_read,n+1,n+1,"pair:buck_rho_read");
memory->create(buck_rho,n+1,n+1,"pair:buck_rho");
memory->create(buck1,n+1,n+1,"pair:buck1");
memory->create(buck2,n+1,n+1,"pair:buck2");
memory->create(rhoinv,n+1,n+1,"pair:rhoinv");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
extract protected data from object
------------------------------------------------------------------------- */
void *PairBuckCoul::extract(char *id, int &dim)
{
char *ids[] = {
"B", "ewald_order", "ewald_cut", "ewald_mix", "cut_coul", NULL};
void *ptrs[] = {
buck_c, &ewald_order, &cut_coul, &mix_flag, &cut_coul, NULL};
int i;
for (i=0; ids[i]&&strcmp(ids[i], id); ++i);
if (i == 0) dim = 2;
else dim = 0;
return ptrs[i];
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairBuckCoul::coeff(int narg, char **arg)
{
- if (narg < 5 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(*(arg++),atom->ntypes,ilo,ihi);
force->bounds(*(arg++),atom->ntypes,jlo,jhi);
double buck_a_one = force->numeric(*(arg++));
double buck_rho_one = force->numeric(*(arg++));
double buck_c_one = force->numeric(*(arg++));
double cut_buck_one = cut_buck_global;
if (narg == 6) cut_buck_one = force->numeric(*(arg++));
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
buck_a_read[i][j] = buck_a_one;
buck_c_read[i][j] = buck_c_one;
buck_rho_read[i][j] = buck_rho_one;
cut_buck_read[i][j] = cut_buck_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairBuckCoul::init_style()
{
// require an atom style with charge defined
if (!atom->q_flag && (ewald_order&(1<<1)))
- error->all(
+ error->all(FLERR,
"Invoking coulombic in pair style lj/coul requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
} else irequest = neighbor->request(this);
cut_coulsq = cut_coul * cut_coul;
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
// ensure use of KSpace long-range solver, set g_ewald
if (ewald_order&(1<<1)) { // r^-1 kspace
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
}
if (ewald_order&(1<<6)) { // r^-6 kspace
if (!force->kspace && strcmp(force->kspace_style,"ewald/n"))
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
g_ewald = force->kspace->g_ewald;
}
// setup force tables
if (ncoultablebits) init_tables();
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
regular or rRESPA
------------------------------------------------------------------------- */
void PairBuckCoul::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listinner = ptr;
else if (id == 2) listmiddle = ptr;
else if (id == 3) listouter = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairBuckCoul::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
cut_buck[i][j] = cut_buck_read[i][j];
buck_a[i][j] = buck_a_read[i][j];
buck_c[i][j] = buck_c_read[i][j];
buck_rho[i][j] = buck_rho_read[i][j];
double cut = MAX(cut_buck[i][j],cut_coul);
cutsq[i][j] = cut*cut;
cut_bucksq[i][j] = cut_buck[i][j] * cut_buck[i][j];
buck1[i][j] = buck_a[i][j]/buck_rho[i][j];
buck2[i][j] = 6.0*buck_c[i][j];
rhoinv[i][j] = 1.0/buck_rho[i][j];
// check interior rRESPA cutoff
if (cut_respa && MIN(cut_buck[i][j],cut_coul) < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
if (offset_flag) {
double rexp = exp(-cut_buck[i][j]/buck_rho[i][j]);
offset[i][j] = buck_a[i][j]*rexp - buck_c[i][j]/pow(cut_buck[i][j],6.0);
} else offset[i][j] = 0.0;
cutsq[j][i] = cutsq[i][j];
cut_bucksq[j][i] = cut_bucksq[i][j];
buck_a[j][i] = buck_a[i][j];
buck_c[j][i] = buck_c[i][j];
rhoinv[j][i] = rhoinv[i][j];
buck1[j][i] = buck1[i][j];
buck2[j][i] = buck2[i][j];
offset[j][i] = offset[i][j];
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuckCoul::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&buck_a_read[i][j],sizeof(double),1,fp);
fwrite(&buck_rho_read[i][j],sizeof(double),1,fp);
fwrite(&buck_c_read[i][j],sizeof(double),1,fp);
fwrite(&cut_buck_read[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuckCoul::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&buck_a_read[i][j],sizeof(double),1,fp);
fread(&buck_rho_read[i][j],sizeof(double),1,fp);
fread(&buck_c_read[i][j],sizeof(double),1,fp);
fread(&cut_buck_read[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&buck_a_read[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&buck_rho_read[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&buck_c_read[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_buck_read[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuckCoul::write_restart_settings(FILE *fp)
{
fwrite(&cut_buck_global,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
fwrite(&ewald_order,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuckCoul::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_buck_global,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
fread(&ewald_order,sizeof(int),1,fp);
}
MPI_Bcast(&cut_buck_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
MPI_Bcast(&ewald_order,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
compute pair interactions
------------------------------------------------------------------------- */
void PairBuckCoul::compute(int eflag, int vflag)
{
double evdwl,ecoul,fpair;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x, *x0 = x[0];
double **f = atom->f, *f0 = f[0], *fi = f0;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6);
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni;
double qi, qri, *cutsqi, *cut_bucksqi,
*buck1i, *buck2i, *buckai, *buckci, *rhoinvi, *offseti;
double r, rsq, r2inv, force_coul, force_buck;
double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2;
vector xi, d;
ineighn = (ineigh = list->ilist)+list->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
if (order1) qri = (qi = q[i])*qqrd2e; // initialize constants
offseti = offset[typei = type[i]];
buck1i = buck1[typei]; buck2i = buck2[typei];
buckai = buck_a[typei]; buckci = buck_c[typei], rhoinvi = rhoinv[typei];
cutsqi = cutsq[typei]; cut_bucksqi = cut_bucksq[typei];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
jneighn = (jneigh = list->firstneigh[i])+list->numneigh[i];
for (; jneigh<jneighn; ++jneigh) { // loop over neighbors
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cutsqi[typej = type[j]]) continue;
r2inv = 1.0/rsq;
r = sqrt(rsq);
if (order1 && (rsq < cut_coulsq)) { // coulombic
if (!ncoultablebits || rsq <= tabinnersq) { // series real space
register double x = g_ewald*r;
register double s = qri*q[j], t = 1.0/(1.0+EWALD_P*x);
if (ni == 0) {
s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s;
if (eflag) ecoul = t;
}
else { // special case
register double f = s*(1.0-special_coul[ni])/r;
s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-f;
if (eflag) ecoul = t-f;
}
} // table real space
else {
register union_int_float_t t;
t.f = rsq;
register const int k = (t.i & ncoulmask) >> ncoulshiftbits;
register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j];
if (ni == 0) {
force_coul = qiqj*(ftable[k]+f*dftable[k]);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]);
}
else { // special case
t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]);
force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]-t.f);
}
}
}
else force_coul = ecoul = 0.0;
if (rsq < cut_bucksqi[typej]) { // buckingham
register double rn = r2inv*r2inv*r2inv,
expr = exp(-r*rhoinvi[typej]);
if (order6) { // long-range
register double x2 = g2*rsq, a2 = 1.0/x2;
x2 = a2*exp(-x2)*buckci[typej];
if (ni == 0) {
force_buck =
r*expr*buck1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq;
if (eflag) evdwl = expr*buckai[typej]-g6*((a2+1.0)*a2+0.5)*x2;
}
else { // special case
register double f = special_lj[ni], t = rn*(1.0-f);
force_buck = f*r*expr*buck1i[typej]-
g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*buck2i[typej];
if (eflag) evdwl = f*expr*buckai[typej] -
g6*((a2+1.0)*a2+0.5)*x2+t*buckci[typej];
}
}
else { // cut
if (ni == 0) {
force_buck = r*expr*buck1i[typej]-rn*buck2i[typej];
if (eflag) evdwl = expr*buckai[typej] -
rn*buckci[typej]-offseti[typej];
}
else { // special case
register double f = special_lj[ni];
force_buck = f*(r*expr*buck1i[typej]-rn*buck2i[typej]);
if (eflag)
evdwl = f*(expr*buckai[typej]-rn*buckci[typej]-offseti[typej]);
}
}
}
else force_buck = evdwl = 0.0;
fpair = (force_coul+force_buck)*r2inv;
if (newton_pair || j < nlocal) {
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*fpair; fj[0] -= f;
fi[1] += f = d[1]*fpair; fj[1] -= f;
fi[2] += f = d[2]*fpair; fj[2] -= f;
}
else {
fi[0] += d[0]*fpair;
fi[1] += d[1]*fpair;
fi[2] += d[2]*fpair;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,d[0],d[1],d[2]);
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairBuckCoul::compute_inner()
{
double r, rsq, r2inv, force_coul, force_buck, fpair;
int *type = atom->type;
int nlocal = atom->nlocal;
double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
double cut_out_on = cut_respa[0];
double cut_out_off = cut_respa[1];
double cut_out_diff = cut_out_off - cut_out_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni;
int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1);
double qri, *cut_bucksqi, *buck1i, *buck2i, *rhoinvi;
vector xi, d;
ineighn = (ineigh = listinner->ilist)+listinner->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
qri = qqrd2e*q[i];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
cut_bucksqi = cut_bucksq[typei = type[i]];
buck1i = buck1[typei]; buck2i = buck2[typei]; rhoinvi = rhoinv[typei];
jneighn = (jneigh = listinner->firstneigh[i])+listinner->numneigh[i];
for (; jneigh<jneighn; ++jneigh) { // loop over neighbors
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cut_out_off_sq) continue;
r2inv = 1.0/rsq;
r = sqrt(rsq);
if (order1 && (rsq < cut_coulsq)) // coulombic
force_coul = ni == 0 ?
qri*q[j]/r : qri*q[j]/r*special_coul[ni];
if (rsq < cut_bucksqi[typej = type[j]]) { // buckingham
register double rn = r2inv*r2inv*r2inv,
expr = exp(-r*rhoinvi[typej]);
force_buck = ni == 0 ?
(r*expr*buck1i[typej]-rn*buck2i[typej]) :
(r*expr*buck1i[typej]-rn*buck2i[typej])*special_lj[ni];
}
else force_buck = 0.0;
fpair = (force_coul + force_buck) * r2inv;
if (rsq > cut_out_on_sq) { // switching
register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0);
}
if (newton_pair || j < nlocal) { // force update
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*fpair; fj[0] -= f;
fi[1] += f = d[1]*fpair; fj[1] -= f;
fi[2] += f = d[2]*fpair; fj[2] -= f;
}
else {
fi[0] += d[0]*fpair;
fi[1] += d[1]*fpair;
fi[2] += d[2]*fpair;
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairBuckCoul::compute_middle()
{
double r, rsq, r2inv, force_coul, force_buck, fpair;
int *type = atom->type;
int nlocal = atom->nlocal;
double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
double cut_in_off = cut_respa[0];
double cut_in_on = cut_respa[1];
double cut_out_on = cut_respa[2];
double cut_out_off = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_out_diff = cut_out_off - cut_out_on;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni;
int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1);
double qri, *cut_bucksqi, *buck1i, *buck2i, *rhoinvi;
vector xi, d;
ineighn = (ineigh = listmiddle->ilist)+listmiddle->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
qri = qqrd2e*q[i];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
cut_bucksqi = cut_bucksq[typei = type[i]];
buck1i = buck1[typei]; buck2i = buck2[typei]; rhoinvi = rhoinv[typei];
jneighn = (jneigh = listmiddle->firstneigh[i])+listmiddle->numneigh[i];
for (; jneigh<jneighn; ++jneigh) { // loop over neighbors
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cut_out_off_sq) continue;
if (rsq <= cut_in_off_sq) continue;
r2inv = 1.0/rsq;
r = sqrt(rsq);
if (order1 && (rsq < cut_coulsq)) // coulombic
force_coul = ni == 0 ?
qri*q[j]/r : qri*q[j]/r*special_coul[ni];
if (rsq < cut_bucksqi[typej = type[j]]) { // buckingham
register double rn = r2inv*r2inv*r2inv,
expr = exp(-r*rhoinvi[typej]);
force_buck = ni == 0 ?
(r*expr*buck1i[typej]-rn*buck2i[typej]) :
(r*expr*buck1i[typej]-rn*buck2i[typej])*special_lj[ni];
}
else force_buck = 0.0;
fpair = (force_coul + force_buck) * r2inv;
if (rsq < cut_in_on_sq) { // switching
register double rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
if (rsq > cut_out_on_sq) {
register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0);
}
if (newton_pair || j < nlocal) { // force update
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*fpair; fj[0] -= f;
fi[1] += f = d[1]*fpair; fj[1] -= f;
fi[2] += f = d[2]*fpair; fj[2] -= f;
}
else {
fi[0] += d[0]*fpair;
fi[1] += d[1]*fpair;
fi[2] += d[2]*fpair;
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairBuckCoul::compute_outer(int eflag, int vflag)
{
double evdwl,ecoul,fpair;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x, *x0 = x[0];
double **f = atom->f, *f0 = f[0], *fi = f0;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6);
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni, respa_flag;
double qi, qri, *cutsqi, *cut_bucksqi,
*buck1i, *buck2i, *buckai, *buckci, *rhoinvi, *offseti;
double r, rsq, r2inv, force_coul, force_buck;
double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2;
double respa_buck, respa_coul, frespa;
vector xi, d;
double cut_in_off = cut_respa[2];
double cut_in_on = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
ineighn = (ineigh = listouter->ilist)+listouter->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
if (order1) qri = (qi = q[i])*qqrd2e; // initialize constants
offseti = offset[typei = type[i]];
buck1i = buck1[typei]; buck2i = buck2[typei];
buckai = buck_a[typei]; buckci = buck_c[typei]; rhoinvi = rhoinv[typei];
cutsqi = cutsq[typei]; cut_bucksqi = cut_bucksq[typei];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
jneighn = (jneigh = listouter->firstneigh[i])+listouter->numneigh[i];
for (; jneigh<jneighn; ++jneigh) { // loop over neighbors
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cutsqi[typej = type[j]]) continue;
r2inv = 1.0/rsq;
r = sqrt(rsq);
if ((respa_flag = (rsq>cut_in_off_sq)&&(rsq<cut_in_on_sq))) {
register double rsw = (r-cut_in_off)/cut_in_diff;
frespa = rsw*rsw*(3.0-2.0*rsw);
}
if (order1 && (rsq < cut_coulsq)) { // coulombic
if (!ncoultablebits || rsq <= tabinnersq) { // series real space
register double s = qri*q[j];
if (respa_flag) // correct for respa
respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni];
register double x = g_ewald*r, t = 1.0/(1.0+EWALD_P*x);
if (ni == 0) {
s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s;
if (eflag) ecoul = t;
}
else { // correct for special
r = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r;
if (eflag) ecoul = t-r;
}
} // table real space
else {
if (respa_flag) respa_coul = ni == 0 ? // correct for respa
frespa*qri*q[j]/r :
frespa*qri*q[j]/r*special_coul[ni];
register union_int_float_t t;
t.f = rsq;
register const int k = (t.i & ncoulmask) >> ncoulshiftbits;
register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j];
if (ni == 0) {
force_coul = qiqj*(ftable[k]+f*dftable[k]);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]);
}
else { // correct for special
t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]);
force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]-t.f);
}
}
}
else force_coul = respa_coul = ecoul = 0.0;
if (rsq < cut_bucksqi[typej]) { // buckingham
register double rn = r2inv*r2inv*r2inv,
expr = exp(-r*rhoinvi[typej]);
if (respa_flag) respa_buck = ni == 0 ? // correct for respa
frespa*(r*expr*buck1i[typej]-rn*buck2i[typej]) :
frespa*(r*expr*buck1i[typej]-rn*buck2i[typej])*special_lj[ni];
if (order6) { // long-range form
register double x2 = g2*rsq, a2 = 1.0/x2;
x2 = a2*exp(-x2)*buckci[typej];
if (ni == 0) {
force_buck =
r*expr*buck1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq;
if (eflag) evdwl = expr*buckai[typej]-g6*((a2+1.0)*a2+0.5)*x2;
}
else { // correct for special
register double f = special_lj[ni], t = rn*(1.0-f);
force_buck = f*r*expr*buck1i[typej]-
g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*buck2i[typej];
if (eflag) evdwl = f*expr*buckai[typej] -
g6*((a2+1.0)*a2+0.5)*x2+t*buckci[typej];
}
}
else { // cut form
if (ni == 0) {
force_buck = r*expr*buck1i[typej]-rn*buck2i[typej];
if (eflag)
evdwl = expr*buckai[typej]-rn*buckci[typej]-offseti[typej];
}
else { // correct for special
register double f = special_lj[ni];
force_buck = f*(r*expr*buck1i[typej]-rn*buck2i[typej]);
if (eflag)
evdwl = f*(expr*buckai[typej]-rn*buckci[typej]-offseti[typej]);
}
}
}
else force_buck = respa_buck = evdwl = 0.0;
fpair = (force_coul+force_buck)*r2inv;
frespa = fpair-(respa_coul+respa_buck)*r2inv;
if (newton_pair || j < nlocal) {
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*frespa; fj[0] -= f;
fi[1] += f = d[1]*frespa; fj[1] -= f;
fi[2] += f = d[2]*frespa; fj[2] -= f;
}
else {
fi[0] += d[0]*frespa;
fi[1] += d[1]*frespa;
fi[2] += d[2]*frespa;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,d[0],d[1],d[2]);
}
}
}
/* ----------------------------------------------------------------------
setup force tables used in compute routines
------------------------------------------------------------------------- */
void PairBuckCoul::init_tables()
{
int masklo,maskhi;
double r,grij,expm2,derfc,rsw;
double qqrd2e = force->qqrd2e;
tabinnersq = tabinner*tabinner;
init_bitmap(tabinner,cut_coul,ncoultablebits,
masklo,maskhi,ncoulmask,ncoulshiftbits);
int ntable = 1;
for (int i = 0; i < ncoultablebits; i++) ntable *= 2;
// linear lookup tables of length N = 2^ncoultablebits
// stored value = value at lower edge of bin
// d values = delta from lower edge to upper edge of bin
if (ftable) free_tables();
memory->create(rtable,ntable,"pair:rtable");
memory->create(ftable,ntable,"pair:ftable");
memory->create(ctable,ntable,"pair:ctable");
memory->create(etable,ntable,"pair:etable");
memory->create(drtable,ntable,"pair:drtable");
memory->create(dftable,ntable,"pair:dftable");
memory->create(dctable,ntable,"pair:dctable");
memory->create(detable,ntable,"pair:detable");
if (cut_respa == NULL) {
vtable = ptable = dvtable = dptable = NULL;
} else {
memory->create(vtable,ntable,"pair:vtable");
memory->create(ptable,ntable,"pair:ptable");
memory->create(dvtable,ntable,"pair:dvtable");
memory->create(dptable,ntable,"pair:dptable");
}
union_int_float_t rsq_lookup;
union_int_float_t minrsq_lookup;
int itablemin;
minrsq_lookup.i = 0 << ncoulshiftbits;
minrsq_lookup.i |= maskhi;
for (int i = 0; i < ntable; i++) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tabinnersq) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= maskhi;
}
r = sqrt(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
etable[i] = qqrd2e/r * derfc;
} else {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
ctable[i] = 0.0;
etable[i] = qqrd2e/r * derfc;
ptable[i] = qqrd2e/r;
vtable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
ftable[i] += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
ctable[i] = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
}
}
}
minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f);
}
tabinnersq = minrsq_lookup.f;
int ntablem1 = ntable - 1;
for (int i = 0; i < ntablem1; i++) {
drtable[i] = 1.0/(rtable[i+1] - rtable[i]);
dftable[i] = ftable[i+1] - ftable[i];
dctable[i] = ctable[i+1] - ctable[i];
detable[i] = etable[i+1] - etable[i];
}
if (cut_respa) {
for (int i = 0; i < ntablem1; i++) {
dvtable[i] = vtable[i+1] - vtable[i];
dptable[i] = ptable[i+1] - ptable[i];
}
}
// get the delta values for the last table entries
// tables are connected periodically between 0 and ntablem1
drtable[ntablem1] = 1.0/(rtable[0] - rtable[ntablem1]);
dftable[ntablem1] = ftable[0] - ftable[ntablem1];
dctable[ntablem1] = ctable[0] - ctable[ntablem1];
detable[ntablem1] = etable[0] - etable[ntablem1];
if (cut_respa) {
dvtable[ntablem1] = vtable[0] - vtable[ntablem1];
dptable[ntablem1] = ptable[0] - ptable[ntablem1];
}
// get the correct delta values at itablemax
// smallest r is in bin itablemin
// largest r is in bin itablemax, which is itablemin-1,
// or ntablem1 if itablemin=0
// deltas at itablemax only needed if corresponding rsq < cut*cut
// if so, compute deltas between rsq and cut*cut
double f_tmp,c_tmp,e_tmp,p_tmp,v_tmp;
itablemin = minrsq_lookup.i & ncoulmask;
itablemin >>= ncoulshiftbits;
int itablemax = itablemin - 1;
if (itablemin == 0) itablemax = ntablem1;
rsq_lookup.i = itablemax << ncoulshiftbits;
rsq_lookup.i |= maskhi;
if (rsq_lookup.f < cut_coulsq) {
rsq_lookup.f = cut_coulsq;
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
e_tmp = qqrd2e/r * derfc;
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
c_tmp = 0.0;
e_tmp = qqrd2e/r * derfc;
p_tmp = qqrd2e/r;
v_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
f_tmp += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
c_tmp = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
}
}
}
drtable[itablemax] = 1.0/(rsq_lookup.f - rtable[itablemax]);
dftable[itablemax] = f_tmp - ftable[itablemax];
dctable[itablemax] = c_tmp - ctable[itablemax];
detable[itablemax] = e_tmp - etable[itablemax];
if (cut_respa) {
dvtable[itablemax] = v_tmp - vtable[itablemax];
dptable[itablemax] = p_tmp - ptable[itablemax];
}
}
}
/* ----------------------------------------------------------------------
free memory for tables used in pair computations
------------------------------------------------------------------------- */
void PairBuckCoul::free_tables()
{
memory->destroy(rtable);
memory->destroy(drtable);
memory->destroy(ftable);
memory->destroy(dftable);
memory->destroy(ctable);
memory->destroy(dctable);
memory->destroy(etable);
memory->destroy(detable);
memory->destroy(vtable);
memory->destroy(dvtable);
memory->destroy(ptable);
memory->destroy(dptable);
}
/* ---------------------------------------------------------------------- */
double PairBuckCoul::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_buck,
double &fforce)
{
double f, r, r2inv, r6inv, force_coul, force_buck;
double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2, *q = atom->q;
r = sqrt(rsq);
r2inv = 1.0/rsq;
double eng = 0.0;
if ((ewald_order&2) && (rsq < cut_coulsq)) { // coulombic
if (!ncoultablebits || rsq <= tabinnersq) { // series real space
register double x = g_ewald*r;
register double s = force->qqrd2e*q[i]*q[j], t = 1.0/(1.0+EWALD_P*x);
f = s*(1.0-factor_coul)/r; s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-f;
eng += t-f;
}
else { // table real space
register union_int_float_t t;
t.f = rsq;
register const int k = (t.i & ncoulmask) >> ncoulshiftbits;
register double f = (rsq-rtable[k])*drtable[k], qiqj = q[i]*q[j];
t.f = (1.0-factor_coul)*(ctable[k]+f*dctable[k]);
force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f);
eng += qiqj*(etable[k]+f*detable[k]-t.f);
}
} else force_coul = 0.0;
if (rsq < cut_bucksq[itype][jtype]) { // buckingham
register double expr = factor_buck*exp(-sqrt(rsq)*rhoinv[itype][jtype]);
r6inv = r2inv*r2inv*r2inv;
if (ewald_order&64) { // long-range
register double x2 = g2*rsq, a2 = 1.0/x2, t = r6inv*(1.0-factor_buck);
x2 = a2*exp(-x2)*buck_c[itype][jtype];
force_buck = buck1[itype][jtype]*r*expr-
g8*(((6.0*a2+6.0)*a2+3.0)*a2+a2)*x2*rsq+t*buck2[itype][jtype];
eng += buck_a[itype][jtype]*expr-
g6*((a2+1.0)*a2+0.5)*x2+t*buck_c[itype][jtype];
}
else { // cut
force_buck =
buck1[itype][jtype]*r*expr-factor_buck*buck_c[itype][jtype]*r6inv;
eng += buck_a[itype][jtype]*expr-
factor_buck*(buck_c[itype][jtype]*r6inv-offset[itype][jtype]);
}
} else force_buck = 0.0;
fforce = (force_coul+force_buck)*r2inv;
return eng;
}
diff --git a/src/USER-EWALDN/pair_lj_coul.cpp b/src/USER-EWALDN/pair_lj_coul.cpp
index b6ee94bbd..4e1692680 100644
--- a/src/USER-EWALDN/pair_lj_coul.cpp
+++ b/src/USER-EWALDN/pair_lj_coul.cpp
@@ -1,1161 +1,1158 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter J. in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math_vector.h"
#include "pair_lj_coul.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "kspace.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EWALD_F 1.12837917
#define EWALD_P 0.3275911
#define A1 0.254829592
#define A2 -0.284496736
#define A3 1.421413741
#define A4 -1.453152027
#define A5 1.061405429
/* ---------------------------------------------------------------------- */
PairLJCoul::PairLJCoul(LAMMPS *lmp) : Pair(lmp)
{
respa_enable = 1;
ftable = NULL;
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
#define PAIR_ILLEGAL "Illegal pair_style lj/coul command"
#define PAIR_CUTOFF "Only one cut-off allowed when requesting all long"
#define PAIR_MISSING "Cut-offs missing in pair_style lj/coul"
#define PAIR_COUL_CUT "Coulombic cut not supported in pair_style lj/coul"
#define PAIR_LARGEST "Using largest cut-off for lj/coul long long"
#define PAIR_MIX "Mixing forced for lj coefficients"
void PairLJCoul::options(char **arg, int order)
{
char *option[] = {"long", "cut", "off", NULL};
int i;
- if (!*arg) error->all(PAIR_ILLEGAL);
+ if (!*arg) error->all(FLERR,PAIR_ILLEGAL);
for (i=0; option[i]&&strcmp(arg[0], option[i]); ++i);
switch (i) {
- default: error->all(PAIR_ILLEGAL);
+ default: error->all(FLERR,PAIR_ILLEGAL);
case 0: ewald_order |= 1<<order; break; // set kspace r^-order
case 2: ewald_off |= 1<<order; // turn r^-order off
case 1: break;
}
}
void PairLJCoul::settings(int narg, char **arg)
{
- if (narg != 3 && narg != 4) error->all("Illegal pair_style command");
+ if (narg != 3 && narg != 4) error->all(FLERR,"Illegal pair_style command");
ewald_off = 0;
ewald_order = 0;
options(arg, 6);
options(++arg, 1);
- if (!comm->me && ewald_order&(1<<6)) error->warning(PAIR_MIX);
- if (!comm->me && ewald_order==((1<<1)|(1<<6))) error->warning(PAIR_LARGEST);
- if (!*(++arg)) error->all(PAIR_MISSING);
- if (!((ewald_order^ewald_off)&(1<<1))) error->all(PAIR_COUL_CUT);
+ if (!comm->me && ewald_order&(1<<6)) error->warning(FLERR,PAIR_MIX);
+ if (!comm->me && ewald_order==((1<<1)|(1<<6))) error->warning(FLERR,PAIR_LARGEST);
+ if (!*(++arg)) error->all(FLERR,PAIR_MISSING);
+ if (!((ewald_order^ewald_off)&(1<<1))) error->all(FLERR,PAIR_COUL_CUT);
cut_lj_global = force->numeric(*(arg++));
- if (*arg&&(ewald_order&0x42==0x42)) error->all(PAIR_CUTOFF);
+ if (*arg&&(ewald_order&0x42==0x42)) error->all(FLERR,PAIR_CUTOFF);
if (narg == 4) cut_coul = force->numeric(*arg);
else cut_coul = cut_lj_global;
if (allocated) { // reset explicit cuts
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut_lj[i][j] = cut_lj_global;
}
}
/* ----------------------------------------------------------------------
free all arrays
------------------------------------------------------------------------- */
PairLJCoul::~PairLJCoul()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj_read);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(epsilon_read);
memory->destroy(epsilon);
memory->destroy(sigma_read);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
if (ftable) free_tables();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJCoul::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj_read,n+1,n+1,"pair:cut_lj_read");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(epsilon_read,n+1,n+1,"pair:epsilon_read");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma_read,n+1,n+1,"pair:sigma_read");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
extract protected data from object
------------------------------------------------------------------------- */
void *PairLJCoul::extract(char *id, int &dim)
{
char *ids[] = {
"B", "sigma", "epsilon", "ewald_order", "ewald_cut", "ewald_mix",
"cut_coul", NULL};
void *ptrs[] = {
lj4, sigma, epsilon, &ewald_order, &cut_coul, &mix_flag, &cut_coul, NULL};
int i;
for (i=0; ids[i]&&strcmp(ids[i], id); ++i);
if (i <= 2) dim = 2;
else dim = 0;
return ptrs[i];
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJCoul::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_lj_one = cut_lj_global;
if (narg == 5) cut_lj_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon_read[i][j] = epsilon_one;
sigma_read[i][j] = sigma_one;
cut_lj_read[i][j] = cut_lj_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCoul::init_style()
{
char *style1[] = {"ewald", "ewald/n", "pppm", NULL};
char *style6[] = {"ewald/n", NULL};
int i;
// require an atom style with charge defined
if (!atom->q_flag && (ewald_order&(1<<1)))
- error->all(
+ error->all(FLERR,
"Invoking coulombic in pair style lj/coul requires atom attribute q");
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 0 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
} else irequest = neighbor->request(this);
cut_coulsq = cut_coul * cut_coul;
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
// ensure use of KSpace long-range solver, set g_ewald
if (ewald_order&(1<<1)) { // r^-1 kspace
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
for (i=0; style1[i]&&strcmp(force->kspace_style, style1[i]); ++i);
- if (!style1[i]) error->all("Pair style is incompatible with KSpace style");
+ if (!style1[i]) error->all(FLERR,"Pair style is incompatible with KSpace style");
}
if (ewald_order&(1<<6)) { // r^-6 kspace
if (force->kspace == NULL)
- error->all("Pair style is incompatible with KSpace style");
+ error->all(FLERR,"Pair style is incompatible with KSpace style");
for (i=0; style6[i]&&strcmp(force->kspace_style, style6[i]); ++i);
- if (!style6[i]) error->all("Pair style is incompatible with KSpace style");
+ if (!style6[i]) error->all(FLERR,"Pair style is incompatible with KSpace style");
}
if (force->kspace) g_ewald = force->kspace->g_ewald;
// setup force tables
if (ncoultablebits) init_tables();
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
regular or rRESPA
------------------------------------------------------------------------- */
void PairLJCoul::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listinner = ptr;
else if (id == 2) listmiddle = ptr;
else if (id == 3) listouter = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJCoul::init_one(int i, int j)
{
if ((ewald_order&(1<<6))||(setflag[i][j] == 0)) {
epsilon[i][j] = mix_energy(epsilon_read[i][i],epsilon_read[j][j],
sigma_read[i][i],sigma_read[j][j]);
sigma[i][j] = mix_distance(sigma_read[i][i],sigma_read[j][j]);
if (ewald_order&(1<<6))
cut_lj[i][j] = cut_lj_global;
else
cut_lj[i][j] = mix_distance(cut_lj_read[i][i],cut_lj_read[j][j]);
}
else {
sigma[i][j] = sigma_read[i][j];
epsilon[i][j] = epsilon_read[i][j];
cut_lj[i][j] = cut_lj_read[i][j];
}
double cut = MAX(cut_lj[i][j], cut_coul);
cutsq[i][j] = cut*cut;
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
// check interior rRESPA cutoff
if (cut_respa && MIN(cut_lj[i][j],cut_coul) < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
if (offset_flag) {
double ratio = sigma[i][j] / cut_lj[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
cutsq[j][i] = cutsq[i][j];
cut_ljsq[j][i] = cut_ljsq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCoul::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon_read[i][j],sizeof(double),1,fp);
fwrite(&sigma_read[i][j],sizeof(double),1,fp);
fwrite(&cut_lj_read[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCoul::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon_read[i][j],sizeof(double),1,fp);
fread(&sigma_read[i][j],sizeof(double),1,fp);
fread(&cut_lj_read[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon_read[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma_read[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj_read[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCoul::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
fwrite(&ewald_order,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCoul::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
fread(&ewald_order,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
MPI_Bcast(&ewald_order,1,MPI_INT,0,world);
}
/* ----------------------------------------------------------------------
compute pair interactions
------------------------------------------------------------------------- */
void PairLJCoul::compute(int eflag, int vflag)
{
double evdwl,ecoul,fpair;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x, *x0 = x[0];
double **f = atom->f, *f0 = f[0], *fi = f0;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6);
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni;
double qi, qri, *cutsqi, *cut_ljsqi, *lj1i, *lj2i, *lj3i, *lj4i, *offseti;
double rsq, r2inv, force_coul, force_lj;
double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2;
vector xi, d;
ineighn = (ineigh = list->ilist)+list->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
if (order1) qri = (qi = q[i])*qqrd2e; // initialize constants
offseti = offset[typei = type[i]];
lj1i = lj1[typei]; lj2i = lj2[typei]; lj3i = lj3[typei]; lj4i = lj4[typei];
cutsqi = cutsq[typei]; cut_ljsqi = cut_ljsq[typei];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
jneighn = (jneigh = list->firstneigh[i])+list->numneigh[i];
for (; jneigh<jneighn; ++jneigh) { // loop over neighbors
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cutsqi[typej = type[j]]) continue;
r2inv = 1.0/rsq;
if (order1 && (rsq < cut_coulsq)) { // coulombic
if (!ncoultablebits || rsq <= tabinnersq) { // series real space
register double r = sqrt(rsq), x = g_ewald*r;
register double s = qri*q[j], t = 1.0/(1.0+EWALD_P*x);
if (ni == 0) {
s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s;
if (eflag) ecoul = t;
}
else { // special case
r = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r;
if (eflag) ecoul = t-r;
}
} // table real space
else {
register union_int_float_t t;
t.f = rsq;
register const int k = (t.i & ncoulmask)>>ncoulshiftbits;
register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j];
if (ni == 0) {
force_coul = qiqj*(ftable[k]+f*dftable[k]);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]);
}
else { // special case
t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]);
force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]-t.f);
}
}
}
else force_coul = ecoul = 0.0;
if (rsq < cut_ljsqi[typej]) { // lj
if (order6) { // long-range lj
register double rn = r2inv*r2inv*r2inv;
register double x2 = g2*rsq, a2 = 1.0/x2;
x2 = a2*exp(-x2)*lj4i[typej];
if (ni == 0) {
force_lj =
(rn*=rn)*lj1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq;
if (eflag)
evdwl = rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2;
}
else { // special case
register double f = special_lj[ni], t = rn*(1.0-f);
force_lj = f*(rn *= rn)*lj1i[typej]-
g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*lj2i[typej];
if (eflag)
evdwl = f*rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2+t*lj4i[typej];
}
}
else { // cut lj
register double rn = r2inv*r2inv*r2inv;
if (ni == 0) {
force_lj = rn*(rn*lj1i[typej]-lj2i[typej]);
if (eflag) evdwl = rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej];
}
else { // special case
register double f = special_lj[ni];
force_lj = f*rn*(rn*lj1i[typej]-lj2i[typej]);
if (eflag)
evdwl = f * (rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej]);
}
}
}
else force_lj = evdwl = 0.0;
fpair = (force_coul+force_lj)*r2inv;
if (newton_pair || j < nlocal) {
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*fpair; fj[0] -= f;
fi[1] += f = d[1]*fpair; fj[1] -= f;
fi[2] += f = d[2]*fpair; fj[2] -= f;
}
else {
fi[0] += d[0]*fpair;
fi[1] += d[1]*fpair;
fi[2] += d[2]*fpair;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,d[0],d[1],d[2]);
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairLJCoul::compute_inner()
{
double rsq, r2inv, force_coul, force_lj, fpair;
int *type = atom->type;
int nlocal = atom->nlocal;
double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
double cut_out_on = cut_respa[0];
double cut_out_off = cut_respa[1];
double cut_out_diff = cut_out_off - cut_out_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni;
int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1);
double qri, *cut_ljsqi, *lj1i, *lj2i;
vector xi, d;
ineighn = (ineigh = list->ilist)+list->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
qri = qqrd2e*q[i];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
cut_ljsqi = cut_ljsq[typei = type[i]];
lj1i = lj1[typei]; lj2i = lj2[typei];
jneighn = (jneigh = list->firstneigh[i])+list->numneigh[i];
for (; jneigh<jneighn; ++jneigh) { // loop over neighbors
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cut_out_off_sq) continue;
r2inv = 1.0/rsq;
if (order1 && (rsq < cut_coulsq)) // coulombic
force_coul = ni == 0 ?
qri*q[j]*sqrt(r2inv) : qri*q[j]*sqrt(r2inv)*special_coul[ni];
if (rsq < cut_ljsqi[typej = type[j]]) { // lennard-jones
register double rn = r2inv*r2inv*r2inv;
force_lj = ni == 0 ?
rn*(rn*lj1i[typej]-lj2i[typej]) :
rn*(rn*lj1i[typej]-lj2i[typej])*special_lj[ni];
}
else force_lj = 0.0;
fpair = (force_coul + force_lj) * r2inv;
if (rsq > cut_out_on_sq) { // switching
register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0);
}
if (newton_pair || j < nlocal) { // force update
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*fpair; fj[0] -= f;
fi[1] += f = d[1]*fpair; fj[1] -= f;
fi[2] += f = d[2]*fpair; fj[2] -= f;
}
else {
fi[0] += d[0]*fpair;
fi[1] += d[1]*fpair;
fi[2] += d[2]*fpair;
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCoul::compute_middle()
{
double rsq, r2inv, force_coul, force_lj, fpair;
int *type = atom->type;
int nlocal = atom->nlocal;
double *x0 = atom->x[0], *f0 = atom->f[0], *fi = f0, *q = atom->q;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
double cut_in_off = cut_respa[0];
double cut_in_on = cut_respa[1];
double cut_out_on = cut_respa[2];
double cut_out_off = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_out_diff = cut_out_off - cut_out_on;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni;
int i, j, order1 = (ewald_order|(ewald_off^-1))&(1<<1);
double qri, *cut_ljsqi, *lj1i, *lj2i;
vector xi, d;
ineighn = (ineigh = list->ilist)+list->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
qri = qqrd2e*q[i];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
cut_ljsqi = cut_ljsq[typei = type[i]];
lj1i = lj1[typei]; lj2i = lj2[typei];
jneighn = (jneigh = list->firstneigh[i])+list->numneigh[i];
for (; jneigh<jneighn; ++jneigh) {
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cut_out_off_sq) continue;
if (rsq <= cut_in_off_sq) continue;
r2inv = 1.0/rsq;
if (order1 && (rsq < cut_coulsq)) // coulombic
force_coul = ni == 0 ?
qri*q[j]*sqrt(r2inv) : qri*q[j]*sqrt(r2inv)*special_coul[ni];
if (rsq < cut_ljsqi[typej = type[j]]) { // lennard-jones
register double rn = r2inv*r2inv*r2inv;
force_lj = ni == 0 ?
rn*(rn*lj1i[typej]-lj2i[typej]) :
rn*(rn*lj1i[typej]-lj2i[typej])*special_lj[ni];
}
else force_lj = 0.0;
fpair = (force_coul + force_lj) * r2inv;
if (rsq < cut_in_on_sq) { // switching
register double rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
if (rsq > cut_out_on_sq) {
register double rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw-3.0);
}
if (newton_pair || j < nlocal) { // force update
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*fpair; fj[0] -= f;
fi[1] += f = d[1]*fpair; fj[1] -= f;
fi[2] += f = d[2]*fpair; fj[2] -= f;
}
else {
fi[0] += d[0]*fpair;
fi[1] += d[1]*fpair;
fi[2] += d[2]*fpair;
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCoul::compute_outer(int eflag, int vflag)
{
double evdwl,ecoul,fpair;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x, *x0 = x[0];
double **f = atom->f, *f0 = f[0], *fi = f0;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
int i, j, order1 = ewald_order&(1<<1), order6 = ewald_order&(1<<6);
int *ineigh, *ineighn, *jneigh, *jneighn, typei, typej, ni, respa_flag;
double qi, qri, *cutsqi, *cut_ljsqi, *lj1i, *lj2i, *lj3i, *lj4i, *offseti;
double rsq, r2inv, force_coul, force_lj;
double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2;
double respa_lj, respa_coul, frespa;
vector xi, d;
double cut_in_off = cut_respa[2];
double cut_in_on = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
ineighn = (ineigh = list->ilist)+list->inum;
for (; ineigh<ineighn; ++ineigh) { // loop over my atoms
i = *ineigh; fi = f0+3*i;
if (order1) qri = (qi = q[i])*qqrd2e; // initialize constants
offseti = offset[typei = type[i]];
lj1i = lj1[typei]; lj2i = lj2[typei]; lj3i = lj3[typei]; lj4i = lj4[typei];
cutsqi = cutsq[typei]; cut_ljsqi = cut_ljsq[typei];
memcpy(xi, x0+(i+(i<<1)), sizeof(vector));
jneighn = (jneigh = list->firstneigh[i])+list->numneigh[i];
for (; jneigh<jneighn; ++jneigh) { // loop over neighbors
j = *jneigh;
ni = sbmask(j);
j &= NEIGHMASK;
{ register double *xj = x0+(j+(j<<1));
d[0] = xi[0] - xj[0]; // pair vector
d[1] = xi[1] - xj[1];
d[2] = xi[2] - xj[2]; }
if ((rsq = vec_dot(d, d)) >= cutsqi[typej = type[j]]) continue;
r2inv = 1.0/rsq;
if ((respa_flag = (rsq>cut_in_off_sq)&&(rsq<cut_in_on_sq))) {
register double rsw = (sqrt(rsq)-cut_in_off)/cut_in_diff;
frespa = rsw*rsw*(3.0-2.0*rsw);
}
if (order1 && (rsq < cut_coulsq)) { // coulombic
if (!ncoultablebits || rsq <= tabinnersq) { // series real space
register double r = sqrt(rsq), s = qri*q[j];
if (respa_flag) // correct for respa
respa_coul = ni == 0 ? frespa*s/r : frespa*s/r*special_coul[ni];
register double x = g_ewald*r, t = 1.0/(1.0+EWALD_P*x);
if (ni == 0) {
s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s;
if (eflag) ecoul = t;
}
else { // correct for special
r = s*(1.0-special_coul[ni])/r; s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r;
if (eflag) ecoul = t-r;
}
} // table real space
else {
if (respa_flag) respa_coul = ni == 0 ? // correct for respa
frespa*qri*q[j]/sqrt(rsq) :
frespa*qri*q[j]/sqrt(rsq)*special_coul[ni];
register union_int_float_t t;
t.f = rsq;
register const int k = (t.i & ncoulmask) >> ncoulshiftbits;
register double f = (rsq-rtable[k])*drtable[k], qiqj = qi*q[j];
if (ni == 0) {
force_coul = qiqj*(ftable[k]+f*dftable[k]);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]);
}
else { // correct for special
t.f = (1.0-special_coul[ni])*(ctable[k]+f*dctable[k]);
force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f);
if (eflag) ecoul = qiqj*(etable[k]+f*detable[k]-t.f);
}
}
}
else force_coul = respa_coul = ecoul = 0.0;
if (rsq < cut_ljsqi[typej]) { // lennard-jones
register double rn = r2inv*r2inv*r2inv;
if (respa_flag) respa_lj = ni == 0 ? // correct for respa
frespa*rn*(rn*lj1i[typej]-lj2i[typej]) :
frespa*rn*(rn*lj1i[typej]-lj2i[typej])*special_lj[ni];
if (order6) { // long-range form
register double x2 = g2*rsq, a2 = 1.0/x2;
x2 = a2*exp(-x2)*lj4i[typej];
if (ni == 0) {
force_lj =
(rn*=rn)*lj1i[typej]-g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq;
if (eflag) evdwl = rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2;
}
else { // correct for special
register double f = special_lj[ni], t = rn*(1.0-f);
force_lj = f*(rn *= rn)*lj1i[typej]-
g8*(((6.0*a2+6.0)*a2+3.0)*a2+1.0)*x2*rsq+t*lj2i[typej];
if (eflag)
evdwl = f*rn*lj3i[typej]-g6*((a2+1.0)*a2+0.5)*x2+t*lj4i[typej];
}
}
else { // cut form
if (ni == 0) {
force_lj = rn*(rn*lj1i[typej]-lj2i[typej]);
if (eflag) evdwl = rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej];
}
else { // correct for special
register double f = special_lj[ni];
force_lj = f*rn*(rn*lj1i[typej]-lj2i[typej]);
if (eflag)
evdwl = f*(rn*(rn*lj3i[typej]-lj4i[typej])-offseti[typej]);
}
}
}
else force_lj = respa_lj = evdwl = 0.0;
fpair = (force_coul+force_lj)*r2inv;
frespa = fpair-(respa_coul+respa_lj)*r2inv;
if (newton_pair || j < nlocal) {
register double *fj = f0+(j+(j<<1)), f;
fi[0] += f = d[0]*frespa; fj[0] -= f;
fi[1] += f = d[1]*frespa; fj[1] -= f;
fi[2] += f = d[2]*frespa; fj[2] -= f;
}
else {
fi[0] += d[0]*frespa;
fi[1] += d[1]*frespa;
fi[2] += d[2]*frespa;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,d[0],d[1],d[2]);
}
}
}
/* ----------------------------------------------------------------------
setup force tables used in compute routines
------------------------------------------------------------------------- */
void PairLJCoul::init_tables()
{
int masklo,maskhi;
double r,grij,expm2,derfc,rsw;
double qqrd2e = force->qqrd2e;
tabinnersq = tabinner*tabinner;
init_bitmap(tabinner,cut_coul,ncoultablebits,
masklo,maskhi,ncoulmask,ncoulshiftbits);
int ntable = 1;
for (int i = 0; i < ncoultablebits; i++) ntable *= 2;
// linear lookup tables of length N = 2^ncoultablebits
// stored value = value at lower edge of bin
// d values = delta from lower edge to upper edge of bin
if (ftable) free_tables();
memory->create(rtable,ntable,"pair:rtable");
memory->create(ftable,ntable,"pair:ftable");
memory->create(ctable,ntable,"pair:ctable");
memory->create(etable,ntable,"pair:etable");
memory->create(drtable,ntable,"pair:drtable");
memory->create(dftable,ntable,"pair:dftable");
memory->create(dctable,ntable,"pair:dctable");
memory->create(detable,ntable,"pair:detable");
if (cut_respa == NULL) {
vtable = ptable = dvtable = dptable = NULL;
} else {
memory->create(vtable,ntable,"pair:vtable");
memory->create(ptable,ntable,"pair:ptable");
memory->create(dvtable,ntable,"pair:dvtable");
memory->create(dptable,ntable,"pair:dptable");
}
union_int_float_t rsq_lookup;
union_int_float_t minrsq_lookup;
int itablemin;
minrsq_lookup.i = 0 << ncoulshiftbits;
minrsq_lookup.i |= maskhi;
for (int i = 0; i < ntable; i++) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tabinnersq) {
rsq_lookup.i = i << ncoulshiftbits;
rsq_lookup.i |= maskhi;
}
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
etable[i] = qqrd2e/r * derfc;
} else {
rtable[i] = rsq_lookup.f;
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
ctable[i] = 0.0;
etable[i] = qqrd2e/r * derfc;
ptable[i] = qqrd2e/r;
vtable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
ftable[i] += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
ctable[i] = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
ftable[i] = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
ctable[i] = qqrd2e/r;
}
}
}
minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f);
}
tabinnersq = minrsq_lookup.f;
int ntablem1 = ntable - 1;
for (int i = 0; i < ntablem1; i++) {
drtable[i] = 1.0/(rtable[i+1] - rtable[i]);
dftable[i] = ftable[i+1] - ftable[i];
dctable[i] = ctable[i+1] - ctable[i];
detable[i] = etable[i+1] - etable[i];
}
if (cut_respa) {
for (int i = 0; i < ntablem1; i++) {
dvtable[i] = vtable[i+1] - vtable[i];
dptable[i] = ptable[i+1] - ptable[i];
}
}
// get the delta values for the last table entries
// tables are connected periodically between 0 and ntablem1
drtable[ntablem1] = 1.0/(rtable[0] - rtable[ntablem1]);
dftable[ntablem1] = ftable[0] - ftable[ntablem1];
dctable[ntablem1] = ctable[0] - ctable[ntablem1];
detable[ntablem1] = etable[0] - etable[ntablem1];
if (cut_respa) {
dvtable[ntablem1] = vtable[0] - vtable[ntablem1];
dptable[ntablem1] = ptable[0] - ptable[ntablem1];
}
// get the correct delta values at itablemax
// smallest r is in bin itablemin
// largest r is in bin itablemax, which is itablemin-1,
// or ntablem1 if itablemin=0
// deltas at itablemax only needed if corresponding rsq < cut*cut
// if so, compute deltas between rsq and cut*cut
double f_tmp,c_tmp,e_tmp,p_tmp,v_tmp;
itablemin = minrsq_lookup.i & ncoulmask;
itablemin >>= ncoulshiftbits;
int itablemax = itablemin - 1;
if (itablemin == 0) itablemax = ntablem1;
rsq_lookup.i = itablemax << ncoulshiftbits;
rsq_lookup.i |= maskhi;
if (rsq_lookup.f < cut_coulsq) {
rsq_lookup.f = cut_coulsq;
r = sqrtf(rsq_lookup.f);
grij = g_ewald * r;
expm2 = exp(-grij*grij);
derfc = erfc(grij);
if (cut_respa == NULL) {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
e_tmp = qqrd2e/r * derfc;
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2 - 1.0);
c_tmp = 0.0;
e_tmp = qqrd2e/r * derfc;
p_tmp = qqrd2e/r;
v_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
if (rsq_lookup.f > cut_respa[2]*cut_respa[2]) {
if (rsq_lookup.f < cut_respa[3]*cut_respa[3]) {
rsw = (r - cut_respa[2])/(cut_respa[3] - cut_respa[2]);
f_tmp += qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
c_tmp = qqrd2e/r * rsw*rsw*(3.0 - 2.0*rsw);
} else {
f_tmp = qqrd2e/r * (derfc + EWALD_F*grij*expm2);
c_tmp = qqrd2e/r;
}
}
}
drtable[itablemax] = 1.0/(rsq_lookup.f - rtable[itablemax]);
dftable[itablemax] = f_tmp - ftable[itablemax];
dctable[itablemax] = c_tmp - ctable[itablemax];
detable[itablemax] = e_tmp - etable[itablemax];
if (cut_respa) {
dvtable[itablemax] = v_tmp - vtable[itablemax];
dptable[itablemax] = p_tmp - ptable[itablemax];
}
}
}
/* ----------------------------------------------------------------------
free memory for tables used in pair computations
------------------------------------------------------------------------- */
void PairLJCoul::free_tables()
{
memory->destroy(rtable);
memory->destroy(drtable);
memory->destroy(ftable);
memory->destroy(dftable);
memory->destroy(ctable);
memory->destroy(dctable);
memory->destroy(etable);
memory->destroy(detable);
memory->destroy(vtable);
memory->destroy(dvtable);
memory->destroy(ptable);
memory->destroy(dptable);
}
/* ---------------------------------------------------------------------- */
double PairLJCoul::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
double r2inv, r6inv, force_coul, force_lj;
double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2, *q = atom->q;
double eng = 0.0;
r2inv = 1.0/rsq;
if ((ewald_order&2) && (rsq < cut_coulsq)) { // coulombic
if (!ncoultablebits || rsq <= tabinnersq) { // series real space
register double r = sqrt(rsq), x = g_ewald*r;
register double s = force->qqrd2e*q[i]*q[j], t = 1.0/(1.0+EWALD_P*x);
r = s*(1.0-factor_coul)/r; s *= g_ewald*exp(-x*x);
force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r;
eng += t-r;
}
else { // table real space
register union_int_float_t t;
t.f = rsq;
register const int k = (t.i & ncoulmask) >> ncoulshiftbits;
register double f = (rsq-rtable[k])*drtable[k], qiqj = q[i]*q[j];
t.f = (1.0-factor_coul)*(ctable[k]+f*dctable[k]);
force_coul = qiqj*(ftable[k]+f*dftable[k]-t.f);
eng += qiqj*(etable[k]+f*detable[k]-t.f);
}
} else force_coul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) { // lennard-jones
r6inv = r2inv*r2inv*r2inv;
if (ewald_order&64) { // long-range
register double x2 = g2*rsq, a2 = 1.0/x2, t = r6inv*(1.0-factor_lj);
x2 = a2*exp(-x2)*lj4[itype][jtype];
force_lj = factor_lj*(r6inv *= r6inv)*lj1[itype][jtype]-
g8*(((6.0*a2+6.0)*a2+3.0)*a2+a2)*x2*rsq+t*lj2[itype][jtype];
eng += factor_lj*r6inv*lj3[itype][jtype]-
g6*((a2+1.0)*a2+0.5)*x2+t*lj4[itype][jtype];
}
else { // cut
force_lj = factor_lj*r6inv*(lj1[itype][jtype]*r6inv-lj2[itype][jtype]);
eng += factor_lj*(r6inv*(r6inv*lj3[itype][jtype]-
lj4[itype][jtype])-offset[itype][jtype]);
}
} else force_lj = 0.0;
fforce = (force_coul+force_lj)*r2inv;
return eng;
}
diff --git a/src/USER-MISC/angle_cosine_shift.cpp b/src/USER-MISC/angle_cosine_shift.cpp
index 4c6c7cf74..2fa2ad2b9 100644
--- a/src/USER-MISC/angle_cosine_shift.cpp
+++ b/src/USER-MISC/angle_cosine_shift.cpp
@@ -1,263 +1,263 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg, science@zqex.dk
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_cosine_shift.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleCosineShift::AngleCosineShift(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleCosineShift::~AngleCosineShift()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(kcost);
memory->destroy(ksint);
memory->destroy(theta);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosineShift::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3];
double rsq1,rsq2,r1,r2,c,s,cps,kcos,ksin,a11,a12,a22;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// c = cosine of angle
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// C= sine of angle
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
// force & energy
if (eflag) eangle = -k[type]-kcos*c-ksin*s;
kcos=kcost[type];
ksin=ksint[type];
cps = c/s; // NOTE absorbed one c
a11 = (-kcos +ksin*cps )*c/ rsq1;
a12 = ( kcos -ksin*cps ) / (r1*r2);
a22 = (-kcos +ksin*cps )*c/ rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosineShift::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(k ,n+1,"Angle:k");
memory->create(ksint ,n+1,"Angle:ksint");
memory->create(kcost ,n+1,"Angle:kcost");
memory->create(theta ,n+1,"Angle:theta");
memory->create(setflag,n+1, "Angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void AngleCosineShift::coeff(int narg, char **arg)
{
- if (narg != 3) error->all("Incorrect args for angle coefficients");
+ if (narg != 3) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double umin = force->numeric(arg[1]);
double theta0 = force->numeric(arg[2]);
// k=Umin/2
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = umin/2;
kcost[i] = umin/2*cos(theta0*3.14159265/180);
ksint[i] = umin/2*sin(theta0*3.14159265/180);
theta[i] = theta0*3.14159265/180;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleCosineShift::equilibrium_angle(int i)
{
return theta[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleCosineShift::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nangletypes,fp);
fwrite(&kcost[1],sizeof(double),atom->nangletypes,fp);
fwrite(&ksint[1],sizeof(double),atom->nangletypes,fp);
fwrite(&theta[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleCosineShift::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0)
{
fread(&k[1],sizeof(double),atom->nangletypes,fp);
fread(&kcost[1],sizeof(double),atom->nangletypes,fp);
fread(&ksint[1],sizeof(double),atom->nangletypes,fp);
fread(&theta[1],sizeof(double),atom->nangletypes,fp);
}
MPI_Bcast(&k[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&kcost[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&ksint[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&theta[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double AngleCosineShift::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double s=sqrt(1.0-c*c);
return -k[type]-kcost[type]*c-ksint[type]*s;
}
diff --git a/src/USER-MISC/angle_cosine_shift_exp.cpp b/src/USER-MISC/angle_cosine_shift_exp.cpp
index 7cbfd5bcf..cd6a4960d 100644
--- a/src/USER-MISC/angle_cosine_shift_exp.cpp
+++ b/src/USER-MISC/angle_cosine_shift_exp.cpp
@@ -1,306 +1,306 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg, science@zqex.dk
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "angle_cosine_shift_exp.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
AngleCosineShiftExp::AngleCosineShiftExp(LAMMPS *lmp) : Angle(lmp) {}
/* ---------------------------------------------------------------------- */
AngleCosineShiftExp::~AngleCosineShiftExp()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(umin);
memory->destroy(a);
memory->destroy(opt1);
memory->destroy(cost);
memory->destroy(sint);
memory->destroy(theta0);
memory->destroy(doExpansion);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosineShiftExp::compute(int eflag, int vflag)
{
int i1,i2,i3,n,type;
double delx1,dely1,delz1,delx2,dely2,delz2;
double eangle,f1[3],f3[3],ff;
double rsq1,rsq2,r1,r2,c,s,cc,ss,a11,a12,a22;
double exp2,aa,uumin,cccpsss,cssmscc;
eangle = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **anglelist = neighbor->anglelist;
int nanglelist = neighbor->nanglelist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nanglelist; n++) {
i1 = anglelist[n][0];
i2 = anglelist[n][1];
i3 = anglelist[n][2];
type = anglelist[n][3];
// 1st bond
delx1 = x[i1][0] - x[i2][0];
dely1 = x[i1][1] - x[i2][1];
delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
// 2nd bond
delx2 = x[i3][0] - x[i2][0];
dely2 = x[i3][1] - x[i2][1];
delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// c = cosine of angle
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
// C= sine of angle
s = sqrt(1.0 - c*c);
if (s < SMALL) s = SMALL;
// force & energy
aa=a[type];
uumin=umin[type];
cccpsss = c*cost[type]+s*sint[type];
cssmscc = c*sint[type]-s*cost[type];
if (doExpansion[type])
{ // |a|<0.01 so use expansions relative precision <1e-5
// std::cout << "Using expansion\n";
if (eflag) eangle = -0.125*(1+cccpsss)*(4+aa*(cccpsss-1))*uumin;
ff=0.25*uumin*cssmscc*(2+aa*cccpsss)/s;
}
else
{
// std::cout << "Not using expansion\n";
exp2=exp(0.5*aa*(1+cccpsss));
if (eflag) eangle = opt1[type]*(1-exp2);
ff=0.5*a[type]*opt1[type]*exp2*cssmscc/s;
}
a11 = ff*c/ rsq1;
a12 = -ff / (r1*r2);
a22 = ff*c/ rsq2;
f1[0] = a11*delx1 + a12*delx2;
f1[1] = a11*dely1 + a12*dely2;
f1[2] = a11*delz1 + a12*delz2;
f3[0] = a22*delx2 + a12*delx1;
f3[1] = a22*dely2 + a12*dely1;
f3[2] = a22*delz2 + a12*delz1;
// apply force to each of 3 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= f1[0] + f3[0];
f[i2][1] -= f1[1] + f3[1];
f[i2][2] -= f1[2] + f3[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (evflag) ev_tally(i1,i2,i3,nlocal,newton_bond,eangle,f1,f3,
delx1,dely1,delz1,delx2,dely2,delz2);
}
}
/* ---------------------------------------------------------------------- */
void AngleCosineShiftExp::allocate()
{
allocated = 1;
int n = atom->nangletypes;
memory->create(doExpansion, n+1, "angle:doExpansion");
memory->create(umin , n+1, "angle:umin");
memory->create(a , n+1, "angle:a");
memory->create(sint , n+1, "angle:sint");
memory->create(cost , n+1, "angle:cost");
memory->create(opt1 , n+1, "angle:opt1");
memory->create(theta0 , n+1, "angle:theta0");
memory->create(setflag , n+1, "angle:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void AngleCosineShiftExp::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for angle coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for angle coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nangletypes,ilo,ihi);
double umin_ = force->numeric(arg[1]);
double theta0_ = force->numeric(arg[2]);
double a_ = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
doExpansion[i]=(fabs(a_)<0.001);
umin[i] = umin_;
a[i] = a_;
cost[i] = cos(theta0_*3.14159265/180);
sint[i] = sin(theta0_*3.14159265/180);
theta0[i]= theta0_*3.14159265/180;
if (!doExpansion[i]) opt1[i]=umin_/(exp(a_)-1);
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for angle coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for angle coefficients");
}
/* ---------------------------------------------------------------------- */
double AngleCosineShiftExp::equilibrium_angle(int i)
{
return theta0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void AngleCosineShiftExp::write_restart(FILE *fp)
{
fwrite(&umin[1],sizeof(double),atom->nangletypes,fp);
fwrite(&a[1],sizeof(double),atom->nangletypes,fp);
fwrite(&cost[1],sizeof(double),atom->nangletypes,fp);
fwrite(&sint[1],sizeof(double),atom->nangletypes,fp);
fwrite(&theta0[1],sizeof(double),atom->nangletypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void AngleCosineShiftExp::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0)
{
fread(&umin[1],sizeof(double),atom->nangletypes,fp);
fread(&a[1],sizeof(double),atom->nangletypes,fp);
fread(&cost[1],sizeof(double),atom->nangletypes,fp);
fread(&sint[1],sizeof(double),atom->nangletypes,fp);
fread(&theta0[1],sizeof(double),atom->nangletypes,fp);
}
MPI_Bcast(&umin[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&a[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&cost[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&sint[1],atom->nangletypes,MPI_DOUBLE,0,world);
MPI_Bcast(&theta0[1],atom->nangletypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nangletypes; i++)
{
setflag[i] = 1;
doExpansion[i]=(fabs(a[i])<0.01);
if (!doExpansion[i]) opt1[i]=umin[i]/(exp(a[i])-1);
}
}
/* ---------------------------------------------------------------------- */
double AngleCosineShiftExp::single(int type, int i1, int i2, int i3)
{
double **x = atom->x;
double delx1 = x[i1][0] - x[i2][0];
double dely1 = x[i1][1] - x[i2][1];
double delz1 = x[i1][2] - x[i2][2];
domain->minimum_image(delx1,dely1,delz1);
double r1 = sqrt(delx1*delx1 + dely1*dely1 + delz1*delz1);
double delx2 = x[i3][0] - x[i2][0];
double dely2 = x[i3][1] - x[i2][1];
double delz2 = x[i3][2] - x[i2][2];
domain->minimum_image(delx2,dely2,delz2);
double r2 = sqrt(delx2*delx2 + dely2*dely2 + delz2*delz2);
double c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double s=sqrt(1.0-c*c);
double cccpsss=c*cost[type]+s*sint[type];
double cssmscc=c*sint[type]-s*cost[type];
if (doExpansion[type])
{
return -0.125*(1+cccpsss)*(4+a[type]*(cccpsss-1))*umin[type];
}
else
{
return opt1[type]*(1-exp(0.5*a[type]*(1+cccpsss)));
}
}
diff --git a/src/USER-MISC/bond_harmonic_shift.cpp b/src/USER-MISC/bond_harmonic_shift.cpp
index b051c7dff..958dad69f 100644
--- a/src/USER-MISC/bond_harmonic_shift.cpp
+++ b/src/USER-MISC/bond_harmonic_shift.cpp
@@ -1,199 +1,199 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg, science@zqex.dk
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "bond_harmonic_shift.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondHarmonicShift::BondHarmonicShift(LAMMPS *lmp) : Bond(lmp) {}
/* ---------------------------------------------------------------------- */
BondHarmonicShift::~BondHarmonicShift()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(r0);
memory->destroy(r1);
}
}
/* ---------------------------------------------------------------------- */
void BondHarmonicShift::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r,dr,rk;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
dr = r - r0[type];
rk = k[type] * dr;
// force & energy
if (r > 0.0) fbond = -2.0*rk/r;
else fbond = 0.0;
if (eflag) ebond = k[type]*(dr*dr -(r0[type]-r1[type])*(r0[type]-r1[type]) );
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondHarmonicShift::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(k , n+1,"bond:k");
memory->create(r0, n+1,"bond:r0");
memory->create(r1, n+1,"bond:r1");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void BondHarmonicShift::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for bond coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double Umin = force->numeric(arg[1]); // energy at minimum
double r0_one = force->numeric(arg[2]); // position of minimum
double r1_one = force->numeric(arg[3]); // position where energy = 0
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = Umin/((r0_one-r1_one)*(r0_one-r1_one));
r0[i] = r0_one;
r1[i] = r1_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondHarmonicShift::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondHarmonicShift::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r1[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondHarmonicShift::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
fread(&r1[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r1[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondHarmonicShift::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
double dr = r - r0[type];
double dr2=r0[type]-r1[type];
return k[type]*(dr*dr - dr2*dr2);
}
diff --git a/src/USER-MISC/bond_harmonic_shift_cut.cpp b/src/USER-MISC/bond_harmonic_shift_cut.cpp
index 68f622488..da78a54ae 100644
--- a/src/USER-MISC/bond_harmonic_shift_cut.cpp
+++ b/src/USER-MISC/bond_harmonic_shift_cut.cpp
@@ -1,202 +1,202 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg, science@zqex.dk
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "bond_harmonic_shift_cut.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
BondHarmonicShiftCut::BondHarmonicShiftCut(LAMMPS *lmp) : Bond(lmp) {}
/* ---------------------------------------------------------------------- */
BondHarmonicShiftCut::~BondHarmonicShiftCut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(k);
memory->destroy(r0);
memory->destroy(r1);
}
}
/* ---------------------------------------------------------------------- */
void BondHarmonicShiftCut::compute(int eflag, int vflag)
{
int i1,i2,n,type;
double delx,dely,delz,ebond,fbond;
double rsq,r,dr,rk;
ebond = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **bondlist = neighbor->bondlist;
int nbondlist = neighbor->nbondlist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < nbondlist; n++) {
i1 = bondlist[n][0];
i2 = bondlist[n][1];
type = bondlist[n][2];
delx = x[i1][0] - x[i2][0];
dely = x[i1][1] - x[i2][1];
delz = x[i1][2] - x[i2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
r = sqrt(rsq);
if (r>r1[type]) continue;
dr = r - r0[type];
rk = k[type] * dr;
// force & energy
if (r > 0.0) fbond = -2.0*rk/r;
else fbond = 0.0;
if (eflag) ebond = k[type]*(dr*dr -(r0[type]-r1[type])*(r0[type]-r1[type]) );
// apply force to each of 2 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += delx*fbond;
f[i1][1] += dely*fbond;
f[i1][2] += delz*fbond;
}
if (newton_bond || i2 < nlocal) {
f[i2][0] -= delx*fbond;
f[i2][1] -= dely*fbond;
f[i2][2] -= delz*fbond;
}
if (evflag) ev_tally(i1,i2,nlocal,newton_bond,ebond,fbond,delx,dely,delz);
}
}
/* ---------------------------------------------------------------------- */
void BondHarmonicShiftCut::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(k , n+1,"bond:k");
memory->create(r0, n+1,"bond:r0");
memory->create(r1, n+1,"bond:r1");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more types
------------------------------------------------------------------------- */
void BondHarmonicShiftCut::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for bond coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for bond coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
double Umin = force->numeric(arg[1]); // energy at minimum
double r0_one = force->numeric(arg[2]); // position of minimum
double r1_one = force->numeric(arg[3]); // position where energy = 0 = cutoff
int count = 0;
for (int i = ilo; i <= ihi; i++) {
k[i] = Umin/((r0_one-r1_one)*(r0_one-r1_one));
r0[i] = r0_one;
r1[i] = r1_one;
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for bond coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for bond coefficients");
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondHarmonicShiftCut::equilibrium_distance(int i)
{
return r0[i];
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void BondHarmonicShiftCut::write_restart(FILE *fp)
{
fwrite(&k[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r0[1],sizeof(double),atom->nbondtypes,fp);
fwrite(&r1[1],sizeof(double),atom->nbondtypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void BondHarmonicShiftCut::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&k[1],sizeof(double),atom->nbondtypes,fp);
fread(&r0[1],sizeof(double),atom->nbondtypes,fp);
fread(&r1[1],sizeof(double),atom->nbondtypes,fp);
}
MPI_Bcast(&k[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[1],atom->nbondtypes,MPI_DOUBLE,0,world);
MPI_Bcast(&r1[1],atom->nbondtypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->nbondtypes; i++) setflag[i] = 1;
}
/* ---------------------------------------------------------------------- */
double BondHarmonicShiftCut::single(int type, double rsq, int i, int j)
{
double r = sqrt(rsq);
if (r>r1[type]) return 0;
double dr = r - r0[type];
double dr2=r0[type]-r1[type];
return k[type]*(dr*dr - dr2*dr2);
}
diff --git a/src/USER-MISC/compute_ackland_atom.cpp b/src/USER-MISC/compute_ackland_atom.cpp
index fa50b5f9d..33b2d8a8e 100644
--- a/src/USER-MISC/compute_ackland_atom.cpp
+++ b/src/USER-MISC/compute_ackland_atom.cpp
@@ -1,387 +1,387 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: G. Ziegenhain, gerolf@ziegenhain.com
Copyright (C) 2007
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_ackland_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "pair.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
#include <math.h>
using namespace LAMMPS_NS;
enum{UNKNOWN,BCC,FCC,HCP,ICO};
/* ---------------------------------------------------------------------- */
ComputeAcklandAtom::ComputeAcklandAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute ackland/atom command");
+ if (narg != 3) error->all(FLERR,"Illegal compute ackland/atom command");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
structure = NULL;
maxneigh = 0;
distsq = NULL;
nearest = NULL;
nearest_n0 = NULL;
nearest_n1 = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeAcklandAtom::~ComputeAcklandAtom()
{
memory->destroy(structure);
memory->destroy(distsq);
memory->destroy(nearest);
memory->destroy(nearest_n0);
memory->destroy(nearest_n1);
}
/* ---------------------------------------------------------------------- */
void ComputeAcklandAtom::init()
{
// need an occasional full neighbor list
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"ackland/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute ackland/atom");
+ error->warning(FLERR,"More than one compute ackland/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeAcklandAtom::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputeAcklandAtom::compute_peratom()
{
int i,j,ii,jj,k,n,inum,jnum;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *ilist,*jlist,*numneigh,**firstneigh;
int chi[8];
invoked_peratom = update->ntimestep;
// grow structure array if necessary
if (atom->nlocal > nmax) {
memory->destroy(structure);
nmax = atom->nmax;
memory->create(structure,nmax,"compute/ackland/atom:ackland");
vector_atom = structure;
}
// invoke full neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// compute structure parameter for each atom in group
// use full neighbor list
double **x = atom->x;
int *mask = atom->mask;
double cutsq = force->pair->cutforce * force->pair->cutforce;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
// ensure distsq and nearest arrays are long enough
if (jnum > maxneigh) {
memory->destroy(distsq);
memory->destroy(nearest);
memory->destroy(nearest_n0);
memory->destroy(nearest_n1);
maxneigh = jnum;
memory->create(distsq,maxneigh,"compute/ackland/atom:distsq");
memory->create(nearest,maxneigh,"compute/ackland/atom:nearest");
memory->create(nearest_n0,maxneigh,"compute/ackland/atom:nearest_n0");
memory->create(nearest_n1,maxneigh,"compute/ackland/atom:nearest_n1");
}
// loop over list of all neighbors within force cutoff
// distsq[] = distance sq to each
// nearest[] = atom indices of neighbors
n = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) {
distsq[n] = rsq;
nearest[n++] = j;
}
}
// Select 6 nearest neighbors
select2(6,n,distsq,nearest);
// Mean squared separation
double r0_sq = 0.;
for (j = 0; j < 6; j++)
r0_sq += distsq[j];
r0_sq /= 6.;
// n0 near neighbors with: distsq<1.45*r0_sq
// n1 near neighbors with: distsq<1.55*r0_sq
double n0_dist_sq = 1.45*r0_sq,
n1_dist_sq = 1.55*r0_sq;
int n0 = 0, n1 = 0;
for (j = 0; j < n; j++) {
if (distsq[j] < n1_dist_sq) {
nearest_n1[n1++] = nearest[j];
if (distsq[j] < n0_dist_sq) {
nearest_n0[n0++] = nearest[j];
}
}
}
// Evaluate all angles <(r_ij,rik) forall n0 particles with: distsq<1.45*r0_sq
double bond_angle;
double norm_j, norm_k;
chi[0] = chi[1] = chi[2] = chi[3] = chi[4] = chi[5] = chi[6] = chi[7] = 0;
double x_ij, y_ij, z_ij, x_ik, y_ik, z_ik;
for (j = 0; j < n0; j++) {
x_ij = x[i][0]-x[nearest_n0[j]][0];
y_ij = x[i][1]-x[nearest_n0[j]][1];
z_ij = x[i][2]-x[nearest_n0[j]][2];
norm_j = sqrt (x_ij*x_ij + y_ij*y_ij + z_ij*z_ij);
if (norm_j <= 0.) continue;
for (k = j+1; k < n0; k++) {
x_ik = x[i][0]-x[nearest_n0[k]][0];
y_ik = x[i][1]-x[nearest_n0[k]][1];
z_ik = x[i][2]-x[nearest_n0[k]][2];
norm_k = sqrt (x_ik*x_ik + y_ik*y_ik + z_ik*z_ik);
if (norm_k <= 0.)
continue;
bond_angle = (x_ij*x_ik + y_ij*y_ik + z_ij*z_ik) / (norm_j*norm_k);
// Histogram for identifying the relevant peaks
if (-1. <= bond_angle && bond_angle < -0.945) { chi[0]++; }
else if (-0.945 <= bond_angle && bond_angle < -0.915) { chi[1]++; }
else if (-0.915 <= bond_angle && bond_angle < -0.755) { chi[2]++; }
else if (-0.755 <= bond_angle && bond_angle < -0.195) { chi[3]++; }
else if (-0.195 <= bond_angle && bond_angle < 0.195) { chi[4]++; }
else if (0.195 <= bond_angle && bond_angle < 0.245) { chi[5]++; }
else if (0.245 <= bond_angle && bond_angle < 0.795) { chi[6]++; }
else if (0.795 <= bond_angle && bond_angle < 1.) { chi[7]++; }
}
}
// Deviations from the different lattice structures
double delta_bcc = 0.35*chi[4]/(double)(chi[5]+chi[6]-chi[4]),
delta_cp = fabs(1.-(double)chi[6]/24.),
delta_fcc = 0.61*(fabs((double)(chi[0]+chi[1]-6.))+(double)chi[2])/6.,
delta_hcp = (fabs((double)chi[0]-3.)+fabs((double)chi[0]+(double)chi[1]+(double)chi[2]+(double)chi[3]-9.))/12.;
// Identification of the local structure according to the reference
if (chi[0] == 7) { delta_bcc = 0.; }
else if (chi[0] == 6) { delta_fcc = 0.; }
else if (chi[0] <= 3) { delta_hcp = 0.; }
if (chi[7] > 0.)
structure[i] = UNKNOWN;
else
if (chi[4] < 3.)
{
if (n1 > 13 || n1 < 11)
structure[i] = UNKNOWN;
else
structure[i] = ICO;
} else
if (delta_bcc <= delta_cp)
{
if (n1 < 11)
structure[i] = UNKNOWN;
else
structure[i] = BCC;
} else
if (n1 > 12 || n1 < 11)
structure[i] = UNKNOWN;
else
if (delta_fcc < delta_hcp)
structure[i] = FCC;
else
structure[i] = HCP;
} else structure[i] = 0.0;
}
}
/* ----------------------------------------------------------------------
2 select routines from Numerical Recipes (slightly modified)
find k smallest values in array of length n
2nd routine sorts auxiliary array at same time
------------------------------------------------------------------------- */
#define SWAP(a,b) tmp = a; a = b; b = tmp;
#define ISWAP(a,b) itmp = a; a = b; b = itmp;
void ComputeAcklandAtom::select(int k, int n, double *arr)
{
int i,ir,j,l,mid;
double a,tmp;
arr--;
l = 1;
ir = n;
for (;;) {
if (ir <= l+1) {
if (ir == l+1 && arr[ir] < arr[l]) {
SWAP(arr[l],arr[ir])
}
return;
} else {
mid=(l+ir) >> 1;
SWAP(arr[mid],arr[l+1])
if (arr[l] > arr[ir]) {
SWAP(arr[l],arr[ir])
}
if (arr[l+1] > arr[ir]) {
SWAP(arr[l+1],arr[ir])
}
if (arr[l] > arr[l+1]) {
SWAP(arr[l],arr[l+1])
}
i = l+1;
j = ir;
a = arr[l+1];
for (;;) {
do i++; while (arr[i] < a);
do j--; while (arr[j] > a);
if (j < i) break;
SWAP(arr[i],arr[j])
}
arr[l+1] = arr[j];
arr[j] = a;
if (j >= k) ir = j-1;
if (j <= k) l = i;
}
}
}
/* ---------------------------------------------------------------------- */
void ComputeAcklandAtom::select2(int k, int n, double *arr, int *iarr)
{
int i,ir,j,l,mid,ia,itmp;
double a,tmp;
arr--;
iarr--;
l = 1;
ir = n;
for (;;) {
if (ir <= l+1) {
if (ir == l+1 && arr[ir] < arr[l]) {
SWAP(arr[l],arr[ir])
ISWAP(iarr[l],iarr[ir])
}
return;
} else {
mid=(l+ir) >> 1;
SWAP(arr[mid],arr[l+1])
ISWAP(iarr[mid],iarr[l+1])
if (arr[l] > arr[ir]) {
SWAP(arr[l],arr[ir])
ISWAP(iarr[l],iarr[ir])
}
if (arr[l+1] > arr[ir]) {
SWAP(arr[l+1],arr[ir])
ISWAP(iarr[l+1],iarr[ir])
}
if (arr[l] > arr[l+1]) {
SWAP(arr[l],arr[l+1])
ISWAP(iarr[l],iarr[l+1])
}
i = l+1;
j = ir;
a = arr[l+1];
ia = iarr[l+1];
for (;;) {
do i++; while (arr[i] < a);
do j--; while (arr[j] > a);
if (j < i) break;
SWAP(arr[i],arr[j])
ISWAP(iarr[i],iarr[j])
}
arr[l+1] = arr[j];
arr[j] = a;
iarr[l+1] = iarr[j];
iarr[j] = ia;
if (j >= k) ir = j-1;
if (j <= k) l = i;
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeAcklandAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/USER-MISC/compute_temp_rotate.cpp b/src/USER-MISC/compute_temp_rotate.cpp
index 60f704e4e..539683f4f 100644
--- a/src/USER-MISC/compute_temp_rotate.cpp
+++ b/src/USER-MISC/compute_temp_rotate.cpp
@@ -1,294 +1,291 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Laurent Joly (U Lyon, France), ljoly.ulyon@gmail.com
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "compute_temp_rotate.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "domain.h"
#include "lattice.h"
#include "error.h"
#include "memory.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
ComputeTempRotate::ComputeTempRotate(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute temp/rotate command");
+ if (narg != 3) error->all(FLERR,"Illegal compute temp/rotate command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempRotate::~ComputeTempRotate()
{
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRotate::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
masstotal = group->mass(igroup);
}
/* ---------------------------------------------------------------------- */
void ComputeTempRotate::dof_compute()
{
double natoms = group->count(igroup);
int nper = domain->dimension;
dof = nper * natoms;
dof -= extra_dof + fix_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempRotate::compute_scalar()
{
double vthermal[3];
double vcm[3],xcm[3],inertia[3][3],angmom[3],omega[3];
int xbox,ybox,zbox;
double dx,dy,dz;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
invoked_scalar = update->ntimestep;
if (dynamic) masstotal = group->mass(igroup);
group->vcm(igroup,masstotal,vcm);
group->xcm(igroup,masstotal,xcm);
group->inertia(igroup,xcm,inertia);
group->angmom(igroup,xcm,angmom);
group->omega(angmom,inertia,omega);
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/rotate:vbiasall");
}
double t = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - xcm[0];
dy = (x[i][1] + ybox*yprd) - xcm[1];
dz = (x[i][2] + zbox*zprd) - xcm[2];
vbiasall[i][0] = vcm[0] + dz*omega[1]-dy*omega[2];
vbiasall[i][1] = vcm[1] + dx*omega[2]-dz*omega[0];
vbiasall[i][2] = vcm[2] + dy*omega[0]-dx*omega[1];
vthermal[0] = v[i][0] - vbiasall[i][0];
vthermal[1] = v[i][1] - vbiasall[i][1];
vthermal[2] = v[i][2] - vbiasall[i][2];
if (rmass)
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * rmass[i];
else
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * mass[type[i]];
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRotate::compute_vector()
{
int i;
double vthermal[3];
double vcm[3],xcm[3],inertia[3][3],angmom[3],omega[3];
int xbox,ybox,zbox;
double dx,dy,dz;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
invoked_vector = update->ntimestep;
if (dynamic) masstotal = group->mass(igroup);
group->vcm(igroup,masstotal,vcm);
group->xcm(igroup,masstotal,xcm);
group->inertia(igroup,xcm,inertia);
group->angmom(igroup,xcm,angmom);
group->omega(angmom,inertia,omega);
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/rotate:vbiasall");
}
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - xcm[0];
dy = (x[i][1] + ybox*yprd) - xcm[1];
dz = (x[i][2] + zbox*zprd) - xcm[2];
vbiasall[i][0] = vcm[0] + dz*omega[1]-dy*omega[2];
vbiasall[i][1] = vcm[1] + dx*omega[2]-dz*omega[0];
vbiasall[i][2] = vcm[2] + dy*omega[0]-dx*omega[1];
vthermal[0] = v[i][0] - vbiasall[i][0];
vthermal[1] = v[i][1] - vbiasall[i][1];
vthermal[2] = v[i][2] - vbiasall[i][2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * vthermal[0]*vthermal[0];
t[1] += massone * vthermal[1]*vthermal[1];
t[2] += massone * vthermal[2]*vthermal[2];
t[3] += massone * vthermal[0]*vthermal[1];
t[4] += massone * vthermal[0]*vthermal[2];
t[5] += massone * vthermal[1]*vthermal[2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempRotate::remove_bias(int i, double *v)
{
v[0] -= vbiasall[i][0];
v[1] -= vbiasall[i][1];
v[2] -= vbiasall[i][2];
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempRotate::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] -= vbiasall[i][0];
v[i][1] -= vbiasall[i][1];
v[i][2] -= vbiasall[i][2];
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempRotate::restore_bias(int i, double *v)
{
v[0] += vbiasall[i][0];
v[1] += vbiasall[i][1];
v[2] += vbiasall[i][2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempRotate::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] += vbiasall[i][0];
v[i][1] += vbiasall[i][1];
v[i][2] += vbiasall[i][2];
}
}
/* ---------------------------------------------------------------------- */
double ComputeTempRotate::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/USER-MISC/dihedral_cosine_shift_exp.cpp b/src/USER-MISC/dihedral_cosine_shift_exp.cpp
index 88258b430..29e15fe6c 100644
--- a/src/USER-MISC/dihedral_cosine_shift_exp.cpp
+++ b/src/USER-MISC/dihedral_cosine_shift_exp.cpp
@@ -1,343 +1,343 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carsten Svaneborg, science@zqex.dk
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "dihedral_cosine_shift_exp.h"
#include "atom.h"
#include "comm.h"
#include "neighbor.h"
#include "domain.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define TOLERANCE 0.05
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
DihedralCosineShiftExp::DihedralCosineShiftExp(LAMMPS *lmp) : Dihedral(lmp) {}
/* ---------------------------------------------------------------------- */
DihedralCosineShiftExp::~DihedralCosineShiftExp()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(umin);
memory->destroy(a);
memory->destroy(opt1);
memory->destroy(cost);
memory->destroy(sint);
memory->destroy(theta);
memory->destroy(doExpansion);
}
}
/* ---------------------------------------------------------------------- */
void DihedralCosineShiftExp::compute(int eflag, int vflag)
{
int i1,i2,i3,i4,i,m,n,type;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double edihedral,f1[3],f2[3],f3[3],f4[3];
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
double c,s,p,sx2,sy2,sz2;
double cccpsss,cssmscc,exp2;
edihedral = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int **dihedrallist = neighbor->dihedrallist;
int ndihedrallist = neighbor->ndihedrallist;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
for (n = 0; n < ndihedrallist; n++) {
i1 = dihedrallist[n][0];
i2 = dihedrallist[n][1];
i3 = dihedrallist[n][2];
i4 = dihedrallist[n][3];
type = dihedrallist[n][4];
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
// c,s calculation
ax = vb1y*vb2zm - vb1z*vb2ym;
ay = vb1z*vb2xm - vb1x*vb2zm;
az = vb1x*vb2ym - vb1y*vb2xm;
bx = vb3y*vb2zm - vb3z*vb2ym;
by = vb3z*vb2xm - vb3x*vb2zm;
bz = vb3x*vb2ym - vb3y*vb2xm;
rasq = ax*ax + ay*ay + az*az;
rbsq = bx*bx + by*by + bz*bz;
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
rg = sqrt(rgsq);
rginv = ra2inv = rb2inv = 0.0;
if (rg > 0) rginv = 1.0/rg;
if (rasq > 0) ra2inv = 1.0/rasq;
if (rbsq > 0) rb2inv = 1.0/rbsq;
rabinv = sqrt(ra2inv*rb2inv);
c = (ax*bx + ay*by + az*bz)*rabinv;
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Dihedral problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
double aa=a[type];
double uumin=umin[type];
cccpsss = c*cost[type]+s*sint[type];
cssmscc = c*sint[type]-s*cost[type];
// eflag=1;
if (doExpansion[type])
{ // |a|<0.001 so use expansions relative precision <1e-5
if (eflag) edihedral = -0.125*(1+cccpsss)*(4+aa*(cccpsss-1))*uumin;
df=0.5*uumin*( cssmscc + 0.5*aa*cccpsss);
}
else
{
exp2=exp(0.5*aa*(1+cccpsss));
if (eflag) edihedral = opt1[type]*(1-exp2);
df= 0.5*opt1[type]*aa* ( exp2*cssmscc );
}
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
fga = fg*ra2inv*rginv;
hgb = hg*rb2inv*rginv;
gaa = -ra2inv*rg;
gbb = rb2inv*rg;
dtfx = gaa*ax;
dtfy = gaa*ay;
dtfz = gaa*az;
dtgx = fga*ax - hgb*bx;
dtgy = fga*ay - hgb*by;
dtgz = fga*az - hgb*bz;
dthx = gbb*bx;
dthy = gbb*by;
dthz = gbb*bz;
sx2 = df*dtgx;
sy2 = df*dtgy;
sz2 = df*dtgz;
f1[0] = df*dtfx;
f1[1] = df*dtfy;
f1[2] = df*dtfz;
f2[0] = sx2 - f1[0];
f2[1] = sy2 - f1[1];
f2[2] = sz2 - f1[2];
f4[0] = df*dthx;
f4[1] = df*dthy;
f4[2] = df*dthz;
f3[0] = -sx2 - f4[0];
f3[1] = -sy2 - f4[1];
f3[2] = -sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (evflag)
ev_tally(i1,i2,i3,i4,nlocal,newton_bond,edihedral,f1,f3,f4,
vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z);
}
}
/* ---------------------------------------------------------------------- */
void DihedralCosineShiftExp::allocate()
{
allocated = 1;
int n = atom->ndihedraltypes;
memory->create(doExpansion, n+1, "dihedral:doExpansion");
memory->create(umin,n+1,"dihedral:umin");
memory->create(a,n+1,"dihedral:a");
memory->create(sint,n+1,"dihedral:sind");
memory->create(cost,n+1,"dihedral:cosd");
memory->create(opt1,n+1,"dihedral:opt1");
memory->create(theta,n+1,"dihedral:opt1");
memory->create(setflag, n+1,"dihedral:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
}
/* ----------------------------------------------------------------------
set coeffs for one type
------------------------------------------------------------------------- */
void DihedralCosineShiftExp::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for dihedral coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for dihedral coefficients");
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->ndihedraltypes,ilo,ihi);
double umin_ = force->numeric(arg[1]);
double theta0_ = force->numeric(arg[2]);
double a_ = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
doExpansion[i]=(fabs(a_)<0.001);
umin[i] = umin_;
a[i] = a_;
cost[i] = cos(theta0_*3.14159265/180);
sint[i] = sin(theta0_*3.14159265/180);
theta[i] = theta0_*3.14159265/180;
if (!doExpansion[i]) opt1[i]=umin_/(exp(a_)-1);
setflag[i] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for dihedral coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for dihedral coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes out coeffs to restart file
------------------------------------------------------------------------- */
void DihedralCosineShiftExp::write_restart(FILE *fp)
{
fwrite(&umin[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&a[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&cost[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&sint[1],sizeof(double),atom->ndihedraltypes,fp);
fwrite(&theta[1],sizeof(double),atom->ndihedraltypes,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads coeffs from restart file, bcasts them
------------------------------------------------------------------------- */
void DihedralCosineShiftExp::read_restart(FILE *fp)
{
allocate();
if (comm->me == 0) {
fread(&umin[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&a[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&cost[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&sint[1],sizeof(double),atom->ndihedraltypes,fp);
fread(&theta[1],sizeof(double),atom->ndihedraltypes,fp);
}
MPI_Bcast(&umin[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&a[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&cost[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&sint[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
MPI_Bcast(&theta[1],atom->ndihedraltypes,MPI_DOUBLE,0,world);
for (int i = 1; i <= atom->ndihedraltypes; i++) {
setflag[i] = 1;
doExpansion[i]=(fabs(a[i])<0.01);
if (!doExpansion[i]) opt1[i]=umin[i]/(exp(a[i])-1);
}
}
diff --git a/src/USER-MISC/fix_addtorque.cpp b/src/USER-MISC/fix_addtorque.cpp
index e12a4658b..bf1a8b58a 100644
--- a/src/USER-MISC/fix_addtorque.cpp
+++ b/src/USER-MISC/fix_addtorque.cpp
@@ -1,292 +1,292 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Laurent Joly (U Lyon, France), ljoly.ulyon@gmail.com
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "fix_addtorque.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "respa.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
#include "group.h"
#include "force.h"
using namespace LAMMPS_NS;
enum{NONE,CONSTANT,EQUAL,ATOM};
/* ---------------------------------------------------------------------- */
FixAddTorque::FixAddTorque(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal fix addtorque command");
+ if (narg != 6) error->all(FLERR,"Illegal fix addtorque command");
scalar_flag = 1;
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extscalar = 1;
extvector = 1;
xstr = ystr = zstr = NULL;
if (strstr(arg[3],"v_") == arg[3]) {
int n = strlen(&arg[3][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[3][2]);
} else {
xvalue = atof(arg[3]);
xstyle = CONSTANT;
}
if (strstr(arg[4],"v_") == arg[4]) {
int n = strlen(&arg[4][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[4][2]);
} else {
yvalue = atof(arg[4]);
ystyle = CONSTANT;
}
if (strstr(arg[5],"v_") == arg[5]) {
int n = strlen(&arg[5][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[5][2]);
} else {
zvalue = atof(arg[5]);
zstyle = CONSTANT;
}
force_flag = 0;
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixAddTorque::~FixAddTorque()
{
delete [] xstr;
delete [] ystr;
delete [] zstr;
}
/* ---------------------------------------------------------------------- */
int FixAddTorque::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAddTorque::init()
{
// check variables
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for fix addtorque does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for fix addtorque does not exist");
if (input->variable->equalstyle(xvar)) xstyle = EQUAL;
- else error->all("Variable for fix addtorque is invalid style");
+ else error->all(FLERR,"Variable for fix addtorque is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for fix addtorque does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for fix addtorque does not exist");
if (input->variable->equalstyle(yvar)) ystyle = EQUAL;
- else error->all("Variable for fix addtorque is invalid style");
+ else error->all(FLERR,"Variable for fix addtorque is invalid style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for fix addtorque does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for fix addtorque does not exist");
if (input->variable->equalstyle(zvar)) zstyle = EQUAL;
- else error->all("Variable for fix addtorque is invalid style");
+ else error->all(FLERR,"Variable for fix addtorque is invalid style");
}
if (xstyle == EQUAL || ystyle == EQUAL || zstyle == EQUAL)
varflag = EQUAL;
else varflag = CONSTANT;
if (strcmp(update->integrate_style,"respa") == 0)
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixAddTorque::setup(int vflag)
{
if (strcmp(update->integrate_style,"verlet") == 0)
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixAddTorque::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAddTorque::post_force(int vflag)
{
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double mvv2e = force->mvv2e;
int xbox,ybox,zbox;
double dx,dy,dz,vx,vy,vz,fx,fy,fz,massone,omegadotr;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double tcm[3],xcm[3],angmom[3],omega[3],itorque[3],domegadt[3],tlocal[3];
double inertia[3][3];
// foriginal[0] = "potential energy" for added force
// foriginal[123] = torque on atoms before extra force added
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
force_flag = 0;
if (varflag == EQUAL) {
// variable torque, wrap with clear/add
modify->clearstep_compute();
if (xstyle == EQUAL) xvalue = input->variable->compute_equal(xvar);
if (ystyle == EQUAL) yvalue = input->variable->compute_equal(yvar);
if (zstyle == EQUAL) zvalue = input->variable->compute_equal(zvar);
modify->addstep_compute(update->ntimestep + 1);
}
atom->check_mass();
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
group->inertia(igroup,xcm,inertia);
group->angmom(igroup,xcm,angmom);
group->omega(angmom,inertia,omega);
tlocal[0] = tlocal[1] = tlocal[2] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - xcm[0];
dy = (x[i][1] + ybox*yprd) - xcm[1];
dz = (x[i][2] + zbox*zprd) - xcm[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
omegadotr = omega[0]*dx+omega[1]*dy+omega[2]*dz;
tlocal[0] += massone * omegadotr * (dy*omega[2] - dz*omega[1]);
tlocal[1] += massone * omegadotr * (dz*omega[0] - dx*omega[2]);
tlocal[2] += massone * omegadotr * (dx*omega[1] - dy*omega[0]);
}
MPI_Allreduce(tlocal,itorque,3,MPI_DOUBLE,MPI_SUM,world);
tcm[0] = xvalue - mvv2e*itorque[0];
tcm[1] = yvalue - mvv2e*itorque[1];
tcm[2] = zvalue - mvv2e*itorque[2];
group->omega(tcm,inertia,domegadt);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - xcm[0];
dy = (x[i][1] + ybox*yprd) - xcm[1];
dz = (x[i][2] + zbox*zprd) - xcm[2];
vx = mvv2e*(dz*omega[1]-dy*omega[2]);
vy = mvv2e*(dx*omega[2]-dz*omega[0]);
vz = mvv2e*(dy*omega[0]-dx*omega[1]);
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
fx = massone * (dz*domegadt[1]-dy*domegadt[2] + vz*omega[1]-vy*omega[2]);
fy = massone * (dx*domegadt[2]-dz*domegadt[0] + vx*omega[2]-vz*omega[0]);
fz = massone * (dy*domegadt[0]-dx*domegadt[1] + vy*omega[0]-vx*omega[1]);
// potential energy = - x dot f
foriginal[0] -= fx*x[i][0] + fy*x[i][1] + fz*x[i][2];
foriginal[1] += dy*f[i][2] - dz*f[i][1];
foriginal[2] += dz*f[i][0] - dx*f[i][2];
foriginal[3] += dx*f[i][1] - dy*f[i][0];
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
}
}
/* ---------------------------------------------------------------------- */
void FixAddTorque::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAddTorque::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
potential energy of added torque
------------------------------------------------------------------------- */
double FixAddTorque::compute_scalar()
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[0];
}
/* ----------------------------------------------------------------------
return components of total torque on fix group before torque was changed
------------------------------------------------------------------------- */
double FixAddTorque::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[n+1];
}
diff --git a/src/USER-MISC/fix_imd.cpp b/src/USER-MISC/fix_imd.cpp
index 5dd013b42..462883a20 100644
--- a/src/USER-MISC/fix_imd.cpp
+++ b/src/USER-MISC/fix_imd.cpp
@@ -1,1476 +1,1476 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
The FixIMD class contains code from VMD and NAMD which is copyrighted
by the Board of Trustees of the University of Illinois and is free to
use with LAMMPS according to point 2 of the UIUC license (10% clause):
" Licensee may, at its own expense, create and freely distribute
complimentary works that interoperate with the Software, directing others to
the TCBG server to license and obtain the Software itself. Licensee may, at
its own expense, modify the Software to make derivative works. Except as
explicitly provided below, this License shall apply to any derivative work
as it does to the original Software distributed by Illinois. Any derivative
work should be clearly marked and renamed to notify users that it is a
modified version and not the original Software distributed by Illinois.
Licensee agrees to reproduce the copyright notice and other proprietary
markings on any derivative work and to include in the documentation of such
work the acknowledgement:
"This software includes code developed by the Theoretical and Computational
Biophysics Group in the Beckman Institute for Advanced Science and
Technology at the University of Illinois at Urbana-Champaign."
Licensee may redistribute without restriction works with up to 1/2 of their
non-comment source code derived from at most 1/10 of the non-comment source
code developed by Illinois and contained in the Software, provided that the
above directions for notice and acknowledgement are observed. Any other
distribution of the Software or any derivative work requires a separate
license with Illinois. Licensee may contact Illinois (vmd@ks.uiuc.edu) to
negotiate an appropriate license for such distribution."
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Axel Kohlmeyer (TempleU)
IMD API, hash, and socket code written by: John E. Stone,
Justin Gullingsrud, and James Phillips, (TCBG, Beckman Institute, UIUC)
------------------------------------------------------------------------- */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_MSC_VER) || defined(__MINGW32_VERSION)
#include <winsock2.h>
#else
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/file.h>
#endif
#include <errno.h>
#include "fix_imd.h"
#include "atom.h"
#include "comm.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "error.h"
#include "group.h"
#include "memory.h"
/* re-usable integer hash table code with static linkage. */
/** hash table top level data structure */
typedef struct inthash_t {
struct inthash_node_t **bucket; /* array of hash nodes */
int size; /* size of the array */
int entries; /* number of entries in table */
int downshift; /* shift cound, used in hash function */
int mask; /* used to select bits for hashing */
} inthash_t;
/** hash table node data structure */
typedef struct inthash_node_t {
int data; /* data in hash node */
int key; /* key for hash lookup */
struct inthash_node_t *next; /* next node in hash chain */
} inthash_node_t;
#define HASH_FAIL -1
#define HASH_LIMIT 0.5
/* initialize new hash table */
static void inthash_init(inthash_t *tptr, int buckets);
/* lookup entry in hash table */
static int inthash_lookup(const inthash_t *tptr, int key);
/* generate list of keys for reverse lookups. */
static int *inthash_keys(inthash_t *tptr);
/* insert an entry into hash table. */
static int inthash_insert(inthash_t *tptr, int key, int data);
/* delete the hash table */
static void inthash_destroy(inthash_t *tptr);
/* adapted sort for in-place sorting of map indices. */
static void id_sort(int *idmap, int left, int right);
/************************************************************************
* integer hash code:
************************************************************************/
/* inthash() - Hash function returns a hash number for a given key.
* tptr: Pointer to a hash table, key: The key to create a hash number for */
static int inthash(const inthash_t *tptr, int key) {
int hashvalue;
hashvalue = (((key*1103515249)>>tptr->downshift) & tptr->mask);
if (hashvalue < 0) {
hashvalue = 0;
}
return hashvalue;
}
/*
* rebuild_table_int() - Create new hash table when old one fills up.
*
* tptr: Pointer to a hash table
*/
static void rebuild_table_int(inthash_t *tptr) {
inthash_node_t **old_bucket, *old_hash, *tmp;
int old_size, h, i;
old_bucket=tptr->bucket;
old_size=tptr->size;
/* create a new table and rehash old buckets */
inthash_init(tptr, old_size<<1);
for (i=0; i<old_size; i++) {
old_hash=old_bucket[i];
while(old_hash) {
tmp=old_hash;
old_hash=old_hash->next;
h=inthash(tptr, tmp->key);
tmp->next=tptr->bucket[h];
tptr->bucket[h]=tmp;
tptr->entries++;
} /* while */
} /* for */
/* free memory used by old table */
free(old_bucket);
return;
}
/*
* inthash_init() - Initialize a new hash table.
*
* tptr: Pointer to the hash table to initialize
* buckets: The number of initial buckets to create
*/
void inthash_init(inthash_t *tptr, int buckets) {
/* make sure we allocate something */
if (buckets==0)
buckets=16;
/* initialize the table */
tptr->entries=0;
tptr->size=2;
tptr->mask=1;
tptr->downshift=29;
/* ensure buckets is a power of 2 */
while (tptr->size<buckets) {
tptr->size<<=1;
tptr->mask=(tptr->mask<<1)+1;
tptr->downshift--;
} /* while */
/* allocate memory for table */
tptr->bucket=(inthash_node_t **) calloc(tptr->size, sizeof(inthash_node_t *));
return;
}
/*
* inthash_lookup() - Lookup an entry in the hash table and return a pointer to
* it or HASH_FAIL if it wasn't found.
*
* tptr: Pointer to the hash table
* key: The key to lookup
*/
int inthash_lookup(const inthash_t *tptr, int key) {
int h;
inthash_node_t *node;
/* find the entry in the hash table */
h=inthash(tptr, key);
for (node=tptr->bucket[h]; node!=NULL; node=node->next) {
if (node->key == key)
break;
}
/* return the entry if it exists, or HASH_FAIL */
return(node ? node->data : HASH_FAIL);
}
/*
* inthash_keys() - Return a list of keys.
* NOTE: the returned list must be freed with free(3).
*/
int *inthash_keys(inthash_t *tptr) {
int *keys;
inthash_node_t *node;
keys = (int *)calloc(tptr->entries, sizeof(int));
for (int i=0; i < tptr->size; ++i) {
for (node=tptr->bucket[i]; node != NULL; node=node->next) {
keys[node->data] = node->key;
}
}
return keys;
}
/*
* inthash_insert() - Insert an entry into the hash table. If the entry already
* exists return a pointer to it, otherwise return HASH_FAIL.
*
* tptr: A pointer to the hash table
* key: The key to insert into the hash table
* data: A pointer to the data to insert into the hash table
*/
int inthash_insert(inthash_t *tptr, int key, int data) {
int tmp;
inthash_node_t *node;
int h;
/* check to see if the entry exists */
if ((tmp=inthash_lookup(tptr, key)) != HASH_FAIL)
return(tmp);
/* expand the table if needed */
while (tptr->entries>=HASH_LIMIT*tptr->size)
rebuild_table_int(tptr);
/* insert the new entry */
h=inthash(tptr, key);
node=(struct inthash_node_t *) malloc(sizeof(inthash_node_t));
node->data=data;
node->key=key;
node->next=tptr->bucket[h];
tptr->bucket[h]=node;
tptr->entries++;
return HASH_FAIL;
}
/*
* inthash_destroy() - Delete the entire table, and all remaining entries.
*
*/
void inthash_destroy(inthash_t *tptr) {
inthash_node_t *node, *last;
int i;
for (i=0; i<tptr->size; i++) {
node = tptr->bucket[i];
while (node != NULL) {
last = node;
node = node->next;
free(last);
}
}
/* free the entire array of buckets */
if (tptr->bucket != NULL) {
free(tptr->bucket);
memset(tptr, 0, sizeof(inthash_t));
}
}
/************************************************************************
* integer list sort code:
************************************************************************/
/* sort for integer map. initial call id_sort(idmap, 0, natoms - 1); */
static void id_sort(int *idmap, int left, int right)
{
int pivot, l_hold, r_hold;
l_hold = left;
r_hold = right;
pivot = idmap[left];
while (left < right) {
while ((idmap[right] >= pivot) && (left < right))
right--;
if (left != right) {
idmap[left] = idmap[right];
left++;
}
while ((idmap[left] <= pivot) && (left < right))
left++;
if (left != right) {
idmap[right] = idmap[left];
right--;
}
}
idmap[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
id_sort(idmap, left, pivot-1);
if (right > pivot)
id_sort(idmap, pivot+1, right);
}
/********** API definitions of the VMD/NAMD code ************************
* This code was taken and adapted from VMD-1.8.7/NAMD-2.7 in Sep 2009. *
* If there are any bugs or problems, please contact akohlmey@gmail.com *
************************************************************************/
/***************************************************************************
*cr
*cr (C) Copyright 1995-2009 The Board of Trustees of the
*cr University of Illinois
*cr All Rights Reserved
*cr
***************************************************************************/
/* part 1: Interactive MD (IMD) API */
#include <limits.h>
#if ( INT_MAX == 2147483647 )
typedef int int32;
#else
typedef short int32;
#endif
typedef struct {
int32 type;
int32 length;
} IMDheader;
#define IMDHEADERSIZE 8
#define IMDVERSION 2
typedef enum IMDType_t {
IMD_DISCONNECT, /**< close IMD connection, leaving sim running */
IMD_ENERGIES, /**< energy data block */
IMD_FCOORDS, /**< atom coordinates */
IMD_GO, /**< start the simulation */
IMD_HANDSHAKE, /**< endianism and version check message */
IMD_KILL, /**< kill the simulation job, shutdown IMD */
IMD_MDCOMM, /**< MDComm style force data */
IMD_PAUSE, /**< pause the running simulation */
IMD_TRATE, /**< set IMD update transmission rate */
IMD_IOERROR /**< indicate an I/O error */
} IMDType; /**< IMD command message type enumerations */
typedef struct {
int32 tstep; /**< integer timestep index */
float T; /**< Temperature in degrees Kelvin */
float Etot; /**< Total energy, in Kcal/mol */
float Epot; /**< Potential energy, in Kcal/mol */
float Evdw; /**< Van der Waals energy, in Kcal/mol */
float Eelec; /**< Electrostatic energy, in Kcal/mol */
float Ebond; /**< Bond energy, Kcal/mol */
float Eangle; /**< Angle energy, Kcal/mol */
float Edihe; /**< Dihedral energy, Kcal/mol */
float Eimpr; /**< Improper energy, Kcal/mol */
} IMDEnergies; /**< IMD simulation energy report structure */
/** Send control messages - these consist of a header with no subsequent data */
static int imd_handshake(void *); /**< check endianness, version compat */
/** Receive header and data */
static IMDType imd_recv_header(void *, int32 *);
/** Receive MDComm-style forces, units are Kcal/mol/angstrom */
static int imd_recv_mdcomm(void *, int32, int32 *, float *);
/** Receive energies */
static int imd_recv_energies(void *, IMDEnergies *);
/** Receive atom coordinates. */
static int imd_recv_fcoords(void *, int32, float *);
/** Prepare IMD data packet header */
static void imd_fill_header(IMDheader *header, IMDType type, int32 length);
/** Write data to socket */
static int32 imd_writen(void *s, const char *ptr, int32 n);
/* part 2: abstracts platform-dependent routines/APIs for using sockets */
typedef struct {
struct sockaddr_in addr; /* address of socket provided by bind() */
int addrlen; /* size of the addr struct */
int sd; /* socket file descriptor */
} imdsocket;
static int imdsock_init(void);
static void *imdsock_create(void);
static int imdsock_bind(void *, int);
static int imdsock_listen(void *);
static void *imdsock_accept(void *); /* return new socket */
static int imdsock_write(void *, const void *, int);
static int imdsock_read(void *, void *, int);
static int imdsock_selread(void *, int);
static int imdsock_selwrite(void *, int);
static void imdsock_shutdown(void *);
static void imdsock_destroy(void *);
/***************************************************************
* End of API definitions of the VMD/NAMD code. *
* The implementation follows at the end of the file. *
***************************************************************/
using namespace LAMMPS_NS;
/* struct for packed data communication of coordinates and forces. */
struct commdata {
int tag;
float x,y,z;
};
/***************************************************************
* create class and parse arguments in LAMMPS script. Syntax:
* fix ID group-ID imd <imd_trate> <imd_port> [unwrap (on|off)] [fscale <imd_fscale>]
***************************************************************/
FixIMD::FixIMD(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (narg < 4)
- error->all("Illegal fix imd command");
+ error->all(FLERR,"Illegal fix imd command");
imd_port = atoi(arg[3]);
if (imd_port < 1024)
- error->all("Illegal fix imd parameter: port < 1024");
+ error->all(FLERR,"Illegal fix imd parameter: port < 1024");
/* default values for optional flags */
unwrap_flag = 0;
nowait_flag = 0;
connect_msg = 1;
imd_fscale = 1.0;
imd_trate = 1;
/* parse optional arguments */
int argsdone = 4;
while (argsdone+1 < narg) {
if (0 == strcmp(arg[argsdone], "unwrap")) {
if (0 == strcmp(arg[argsdone+1], "on")) {
unwrap_flag = 1;
} else {
unwrap_flag = 0;
}
} else if (0 == strcmp(arg[argsdone], "nowait")) {
if (0 == strcmp(arg[argsdone+1], "on")) {
nowait_flag = 1;
} else {
nowait_flag = 0;
}
} else if (0 == strcmp(arg[argsdone], "fscale")) {
imd_fscale = atof(arg[argsdone+1]);
} else if (0 == strcmp(arg[argsdone], "trate")) {
imd_trate = atoi(arg[argsdone+1]);
} else {
- error->all("Unknown fix imd parameter");
+ error->all(FLERR,"Unknown fix imd parameter");
}
++argsdone; ++argsdone;
}
/* sanity check on parameters */
if (imd_trate < 1)
- error->all("Illegal fix imd parameter. trate < 1.");
+ error->all(FLERR,"Illegal fix imd parameter. trate < 1.");
bigint n = group->count(igroup);
- if (n > MAXSMALLINT) error->all("Too many atoms for fix imd");
+ if (n > MAXSMALLINT) error->all(FLERR,"Too many atoms for fix imd");
num_coords = static_cast<int> (n);
MPI_Comm_rank(world,&me);
/* initialize various imd state variables. */
clientsock = NULL;
localsock = NULL;
nlevels_respa = 0;
imd_inactive = 0;
imd_terminate = 0;
imd_forces = 0;
force_buf = NULL;
maxbuf = 0;
msgdata = NULL;
msglen = 0;
comm_buf = NULL;
idmap = NULL;
rev_idmap = NULL;
if (me == 0) {
/* set up incoming socket on MPI rank 0. */
imdsock_init();
localsock = imdsock_create();
clientsock = NULL;
if (imdsock_bind(localsock,imd_port)) {
perror("bind to socket failed");
imdsock_destroy(localsock);
imd_terminate = 1;
} else {
imdsock_listen(localsock);
}
}
MPI_Bcast(&imd_terminate, 1, MPI_INT, 0, world);
if (imd_terminate)
- error->all("LAMMPS Terminated on error in IMD.");
+ error->all(FLERR,"LAMMPS Terminated on error in IMD.");
/* storage required to communicate a single coordinate or force. */
size_one = sizeof(struct commdata);
#if defined(LAMMPS_ASYNC_IMD)
/* set up for i/o worker thread on MPI rank 0.*/
if (me == 0) {
if (screen)
fputs("Using fix imd with asynchronous I/O.\n",screen);
if (logfile)
fputs("Using fix imd with asynchronous I/O.\n",logfile);
/* set up mutex and condition variable for i/o thread */
/* hold mutex before creating i/o thread to keep it waiting. */
pthread_mutex_init(&read_mutex, NULL);
pthread_mutex_init(&write_mutex, NULL);
pthread_cond_init(&write_cond, NULL);
pthread_mutex_lock(&write_mutex);
buf_has_data=0;
pthread_mutex_unlock(&write_mutex);
/* set up and launch i/o thread */
pthread_attr_init(&iot_attr);
pthread_attr_setdetachstate(&iot_attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&iothread, &iot_attr, &fix_imd_ioworker, this);
}
#endif
}
/*********************************
* Clean up on deleting the fix. *
*********************************/
FixIMD::~FixIMD()
{
#if defined(LAMMPS_ASYNC_IMD)
if (me == 0) {
pthread_mutex_lock(&write_mutex);
buf_has_data=-1;
pthread_cond_signal(&write_cond);
pthread_mutex_unlock(&write_mutex);
pthread_join(iothread, NULL);
/* cleanup */
pthread_attr_destroy(&iot_attr);
pthread_mutex_destroy(&write_mutex);
pthread_cond_destroy(&write_cond);
}
#endif
inthash_t *hashtable = (inthash_t *)idmap;
memory->sfree(comm_buf);
memory->sfree(force_buf);
inthash_destroy(hashtable);
delete hashtable;
free(rev_idmap);
// close sockets
imdsock_shutdown(clientsock);
imdsock_destroy(clientsock);
imdsock_shutdown(localsock);
imdsock_destroy(localsock);
clientsock=NULL;
localsock=NULL;
return;
}
/* ---------------------------------------------------------------------- */
int FixIMD::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixIMD::init()
{
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
return;
}
/* ---------------------------------------------------------------------- */
/* (re-)connect to an IMD client (e.g. VMD). return 1 if
new connection was made, 0 if not. */
int FixIMD::reconnect()
{
/* set up IMD communication, but only if needed. */
imd_inactive = 0;
imd_terminate = 0;
if (me == 0) {
if (clientsock) return 1;
if (screen && connect_msg)
if (nowait_flag)
fprintf(screen,"Listening for IMD connection on port %d. Transfer rate %d.\n",imd_port, imd_trate);
else
fprintf(screen,"Waiting for IMD connection on port %d. Transfer rate %d.\n",imd_port, imd_trate);
connect_msg = 0;
clientsock = NULL;
if (nowait_flag) {
int retval = imdsock_selread(localsock,0);
if (retval > 0) {
clientsock = imdsock_accept(localsock);
} else {
imd_inactive = 1;
return 0;
}
} else {
int retval=0;
do {
retval = imdsock_selread(localsock, 60);
} while (retval <= 0);
clientsock = imdsock_accept(localsock);
}
if (!imd_inactive && !clientsock) {
if (screen)
fprintf(screen, "IMD socket accept error. Dropping connection.\n");
imd_terminate = 1;
return 0;
} else {
/* check endianness and IMD protocol version. */
if (imd_handshake(clientsock)) {
if (screen)
fprintf(screen, "IMD handshake error. Dropping connection.\n");
imdsock_destroy(clientsock);
imd_terminate = 1;
return 0;
} else {
int32 length;
if (imdsock_selread(clientsock, 1) != 1 ||
imd_recv_header(clientsock, &length) != IMD_GO) {
if (screen)
fprintf(screen, "Incompatible IMD client version? Dropping connection.\n");
imdsock_destroy(clientsock);
imd_terminate = 1;
return 0;
} else {
return 1;
}
}
}
}
return 0;
}
/* ---------------------------------------------------------------------- */
/* wait for IMD client (e.g. VMD) to respond, initialize communication
* buffers and collect tag/id maps. */
void FixIMD::setup(int)
{
/* nme: number of atoms in group on this MPI task
* nmax: max number of atoms in group across all MPI tasks
* nlocal: all local atoms
*/
int i,j;
int nmax,nme,nlocal;
int *mask = atom->mask;
int *tag = atom->tag;
nlocal = atom->nlocal;
nme=0;
for (i=0; i < nlocal; ++i)
if (mask[i] & groupbit) ++nme;
MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world);
maxbuf = nmax*size_one;
comm_buf = (void *) memory->smalloc(maxbuf,"imd:comm_buf");
connect_msg = 1;
reconnect();
MPI_Bcast(&imd_inactive, 1, MPI_INT, 0, world);
MPI_Bcast(&imd_terminate, 1, MPI_INT, 0, world);
if (imd_terminate)
- error->all("LAMMPS terminated on error in setting up IMD connection.");
+ error->all(FLERR,"LAMMPS terminated on error in setting up IMD connection.");
/* initialize and build hashtable. */
inthash_t *hashtable=new inthash_t;
inthash_init(hashtable, num_coords);
idmap = (void *)hashtable;
MPI_Status status;
MPI_Request request;
int tmp, ndata;
struct commdata *buf = static_cast<struct commdata *>(comm_buf);
if (me == 0) {
int *taglist = new int[num_coords];
int numtag=0; /* counter to map atom tags to a 0-based consecutive index list */
for (i=0; i < nlocal; ++i) {
if (mask[i] & groupbit) {
taglist[numtag] = tag[i];
++numtag;
}
}
/* loop over procs to receive remote data */
for (i=1; i < comm->nprocs; ++i) {
MPI_Irecv(comm_buf, maxbuf, MPI_BYTE, i, 0, world, &request);
MPI_Send(&tmp, 0, MPI_INT, i, 0, world);
MPI_Wait(&request, &status);
MPI_Get_count(&status, MPI_BYTE, &ndata);
ndata /= size_one;
for (j=0; j < ndata; ++j) {
taglist[numtag] = buf[j].tag;
++numtag;
}
}
/* sort list of tags by value to have consistently the
* same list when running in parallel and build hash table. */
id_sort(taglist, 0, num_coords-1);
for (i=0; i < num_coords; ++i) {
inthash_insert(hashtable, taglist[i], i);
}
delete[] taglist;
/* generate reverse index-to-tag map for communicating
* IMD forces back to the proper atoms */
rev_idmap=inthash_keys(hashtable);
} else {
nme=0;
for (i=0; i < nlocal; ++i) {
if (mask[i] & groupbit) {
buf[nme].tag = tag[i];
++nme;
}
}
/* blocking receive to wait until it is our turn to send data. */
MPI_Recv(&tmp, 0, MPI_INT, 0, 0, world, &status);
MPI_Rsend(comm_buf, nme*size_one, MPI_BYTE, 0, 0, world);
}
return;
}
/* worker threads for asynchronous i/o */
#if defined(LAMMPS_ASYNC_IMD)
/* c bindings wrapper */
void *fix_imd_ioworker(void *t)
{
FixIMD *imd=(FixIMD *)t;
imd->ioworker();
return NULL;
}
/* the real i/o worker thread */
void FixIMD::ioworker()
{
while (1) {
pthread_mutex_lock(&write_mutex);
if (buf_has_data < 0) {
/* master told us to go away */
fprintf(screen,"Asynchronous I/O thread is exiting.\n");
buf_has_data=0;
pthread_mutex_unlock(&write_mutex);
pthread_exit(NULL);
} else if (buf_has_data > 0) {
/* send coordinate data, if client is able to accept */
if (clientsock && imdsock_selwrite(clientsock,0)) {
imd_writen(clientsock, msgdata, msglen);
}
delete[] msgdata;
buf_has_data=0;
pthread_mutex_unlock(&write_mutex);
} else {
/* nothing to write out yet. wait on condition. */
pthread_cond_wait(&write_cond, &write_mutex);
pthread_mutex_unlock(&write_mutex);
}
}
}
#endif
/* ---------------------------------------------------------------------- */
/* Main IMD protocol handler:
* Send coodinates, energies, and add IMD forces to atoms. */
void FixIMD::post_force(int vflag)
{
/* check for reconnect */
if (imd_inactive) {
reconnect();
MPI_Bcast(&imd_inactive, 1, MPI_INT, 0, world);
MPI_Bcast(&imd_terminate, 1, MPI_INT, 0, world);
if (imd_terminate)
- error->all("LAMMPS terminated on error in setting up IMD connection.");
+ error->all(FLERR,"LAMMPS terminated on error in setting up IMD connection.");
if (imd_inactive)
return; /* IMD client has detached and not yet come back. do nothing. */
}
int *tag = atom->tag;
double **x = atom->x;
int *image = atom->image;
int nlocal = atom->nlocal;
int *mask = atom->mask;
struct commdata *buf;
if (me == 0) {
/* process all pending incoming data. */
int imd_paused=0;
while ((imdsock_selread(clientsock, 0) > 0) || imd_paused) {
/* if something requested to turn off IMD while paused get out */
if (imd_inactive) break;
int32 length;
int msg = imd_recv_header(clientsock, &length);
switch(msg) {
case IMD_GO:
if (screen)
fprintf(screen, "Ignoring unexpected IMD_GO message.\n");
break;
case IMD_IOERROR:
if (screen)
fprintf(screen, "IMD connection lost.\n");
/* fallthrough */
case IMD_DISCONNECT: {
/* disconnect from client. wait for new connection. */
imd_paused = 0;
imd_forces = 0;
memory->destroy(force_buf);
force_buf = NULL;
imdsock_destroy(clientsock);
clientsock = NULL;
if (screen)
fprintf(screen, "IMD client detached. LAMMPS run continues.\n");
connect_msg = 1;
reconnect();
if (imd_terminate) imd_inactive = 1;
break;
}
case IMD_KILL:
/* stop the simulation job and shutdown IMD */
if (screen)
fprintf(screen, "IMD client requested termination of run.\n");
imd_inactive = 1;
imd_terminate = 1;
imd_paused = 0;
imdsock_destroy(clientsock);
clientsock = NULL;
break;
case IMD_PAUSE:
/* pause the running simulation. wait for second IMD_PAUSE to continue. */
if (imd_paused) {
if (screen)
fprintf(screen, "Continuing run on IMD client request.\n");
imd_paused = 0;
} else {
if (screen)
fprintf(screen, "Pausing run on IMD client request.\n");
imd_paused = 1;
}
break;
case IMD_TRATE:
/* change the IMD transmission data rate */
if (length > 0)
imd_trate = length;
if (screen)
fprintf(screen, "IMD client requested change of transfer rate. Now it is %d.\n", imd_trate);
break;
case IMD_ENERGIES: {
IMDEnergies dummy_energies;
imd_recv_energies(clientsock, &dummy_energies);
break;
}
case IMD_FCOORDS: {
float *dummy_coords = new float[3*length];
imd_recv_fcoords(clientsock, length, dummy_coords);
delete[] dummy_coords;
break;
}
case IMD_MDCOMM: {
int32 *imd_tags = new int32[length];
float *imd_fdat = new float[3*length];
imd_recv_mdcomm(clientsock, length, imd_tags, imd_fdat);
if (imd_forces < length) { /* grow holding space for forces, if needed. */
memory->destroy(force_buf);
force_buf = (void *) memory->smalloc(length*size_one,
"imd:force_buf");
}
imd_forces = length;
buf = static_cast<struct commdata *>(force_buf);
/* compare data to hash table */
for (int ii=0; ii < length; ++ii) {
buf[ii].tag = rev_idmap[imd_tags[ii]];
buf[ii].x = imd_fdat[3*ii];
buf[ii].y = imd_fdat[3*ii+1];
buf[ii].z = imd_fdat[3*ii+2];
}
delete[] imd_tags;
delete[] imd_fdat;
break;
}
default:
if (screen)
fprintf(screen, "Unhandled incoming IMD message #%d. length=%d\n", msg, length);
break;
}
}
}
/* update all tasks with current settings. */
int old_imd_forces = imd_forces;
MPI_Bcast(&imd_trate, 1, MPI_INT, 0, world);
MPI_Bcast(&imd_inactive, 1, MPI_INT, 0, world);
MPI_Bcast(&imd_forces, 1, MPI_INT, 0, world);
MPI_Bcast(&imd_terminate, 1, MPI_INT, 0, world);
if (imd_terminate)
- error->all("LAMMPS terminated on IMD request.");
+ error->all(FLERR,"LAMMPS terminated on IMD request.");
if (imd_forces > 0) {
/* check if we need to readjust the forces comm buffer on the receiving nodes. */
if (me != 0) {
if (old_imd_forces < imd_forces) { /* grow holding space for forces, if needed. */
if (force_buf != NULL)
memory->sfree(force_buf);
force_buf = memory->smalloc(imd_forces*size_one, "imd:force_buf");
}
}
MPI_Bcast(force_buf, imd_forces*size_one, MPI_BYTE, 0, world);
}
/* Check if we need to communicate coordinates to the client.
* Tuning imd_trate allows to keep the overhead for IMD low
* at the expense of a more jumpy display. Rather than using
* end_of_step() we do everything here in one go.
*
* If we don't communicate, only check if we have forces
* stored away and apply them. */
if (update->ntimestep % imd_trate) {
if (imd_forces > 0) {
double **f = atom->f;
buf = static_cast<struct commdata *>(force_buf);
/* XXX. this is in principle O(N**2) == not good.
* however we assume for now that the number of atoms
* that we manipulate via IMD will be small compared
* to the total system size, so we don't hurt too much. */
for (int j=0; j < imd_forces; ++j) {
for (int i=0; i < nlocal; ++i) {
if (mask[i] & groupbit) {
if (buf[j].tag == tag[i]) {
f[i][0] += imd_fscale*buf[j].x;
f[i][1] += imd_fscale*buf[j].y;
f[i][2] += imd_fscale*buf[j].z;
}
}
}
}
}
return;
}
/* check and potentially grow local communication buffers. */
int i, k, nmax, nme=0;
for (i=0; i < nlocal; ++i)
if (mask[i] & groupbit) ++nme;
MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world);
if (nmax*size_one > maxbuf) {
memory->sfree(comm_buf);
maxbuf = nmax*size_one;
comm_buf = memory->smalloc(maxbuf,"imd:comm_buf");
}
MPI_Status status;
MPI_Request request;
int tmp, ndata;
buf = static_cast<struct commdata *>(comm_buf);
if (me == 0) {
/* collect data into new array. we bypass the IMD API to save
* us one extra copy of the data. */
msglen = 3*sizeof(float)*num_coords+IMDHEADERSIZE;
msgdata = new char[msglen];
imd_fill_header((IMDheader *)msgdata, IMD_FCOORDS, num_coords);
/* array pointer, to the offset where we receive the coordinates. */
float *recvcoord = (float *) (msgdata+IMDHEADERSIZE);
/* add local data */
if (unwrap_flag) {
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double xy = domain->xy;
double xz = domain->xz;
double yz = domain->yz;
for (i=0; i<nlocal; ++i) {
if (mask[i] & groupbit) {
const int j = 3*inthash_lookup((inthash_t *)idmap, tag[i]);
if (j != HASH_FAIL) {
int ix = (image[i] & 1023) - 512;
int iy = (image[i] >> 10 & 1023) - 512;
int iz = (image[i] >> 20) - 512;
if (domain->triclinic) {
recvcoord[j] = x[i][0] + ix * xprd + iy * xy + iz * xz;
recvcoord[j+1] = x[i][1] + iy * yprd + iz * yz;
recvcoord[j+2] = x[i][2] + iz * zprd;
} else {
recvcoord[j] = x[i][0] + ix * xprd;
recvcoord[j+1] = x[i][1] + iy * yprd;
recvcoord[j+2] = x[i][2] + iz * zprd;
}
}
}
}
} else {
for (i=0; i<nlocal; ++i) {
if (mask[i] & groupbit) {
const int j = 3*inthash_lookup((inthash_t *)idmap, tag[i]);
if (j != HASH_FAIL) {
recvcoord[j] = x[i][0];
recvcoord[j+1] = x[i][1];
recvcoord[j+2] = x[i][2];
}
}
}
}
/* loop over procs to receive remote data */
for (i=1; i < comm->nprocs; ++i) {
MPI_Irecv(comm_buf, maxbuf, MPI_BYTE, i, 0, world, &request);
MPI_Send(&tmp, 0, MPI_INT, i, 0, world);
MPI_Wait(&request, &status);
MPI_Get_count(&status, MPI_BYTE, &ndata);
ndata /= size_one;
for (k=0; k<ndata; ++k) {
const int j = 3*inthash_lookup((inthash_t *)idmap, buf[k].tag);
if (j != HASH_FAIL) {
recvcoord[j] = buf[k].x;
recvcoord[j+1] = buf[k].y;
recvcoord[j+2] = buf[k].z;
}
}
}
/* done collecting frame data now communicate with IMD client. */
#if defined(LAMMPS_ASYNC_IMD)
/* wake up i/o worker thread and release lock on i/o buffer
* we can go back to our MD and let the i/o thread do the rest */
buf_has_data=1;
pthread_cond_signal(&write_cond);
pthread_mutex_unlock(&write_mutex);
#else
/* send coordinate data, if client is able to accept */
if (clientsock && imdsock_selwrite(clientsock,0)) {
imd_writen(clientsock, msgdata, msglen);
}
delete[] msgdata;
#endif
} else {
/* copy coordinate data into communication buffer */
nme = 0;
if (unwrap_flag) {
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double xy = domain->xy;
double xz = domain->xz;
double yz = domain->yz;
for (i=0; i<nlocal; ++i) {
if (mask[i] & groupbit) {
int ix = (image[i] & 1023) - 512;
int iy = (image[i] >> 10 & 1023) - 512;
int iz = (image[i] >> 20) - 512;
if (domain->triclinic) {
buf[nme].tag = tag[i];
buf[nme].x = x[i][0] + ix * xprd + iy * xy + iz * xz;
buf[nme].y = x[i][1] + iy * yprd + iz * yz;
buf[nme].z = x[i][2] + iz * zprd;
} else {
buf[nme].tag = tag[i];
buf[nme].x = x[i][0] + ix * xprd;
buf[nme].y = x[i][1] + iy * yprd;
buf[nme].z = x[i][2] + iz * zprd;
}
++nme;
}
}
} else {
for (i=0; i<nlocal; ++i) {
if (mask[i] & groupbit) {
buf[nme].tag = tag[i];
buf[nme].x = x[i][0];
buf[nme].y = x[i][1];
buf[nme].z = x[i][2];
++nme;
}
}
}
/* blocking receive to wait until it is our turn to send data. */
MPI_Recv(&tmp, 0, MPI_INT, 0, 0, world, &status);
MPI_Rsend(comm_buf, nme*size_one, MPI_BYTE, 0, 0, world);
}
return;
}
/* ---------------------------------------------------------------------- */
void FixIMD::post_force_respa(int vflag, int ilevel, int iloop)
{
/* only process IMD on the outmost RESPA level. */
if (ilevel == nlevels_respa-1) post_force(vflag);
return;
}
/* ---------------------------------------------------------------------- */
/* local memory usage. approximately. */
double FixIMD::memory_usage(void)
{
return static_cast<double>(num_coords+maxbuf+imd_forces)*size_one;
}
/* End of FixIMD class implementation. */
/***************************************************************************/
/* NOTE: the following code is the based on the example implementation
* of the IMD protocol API from VMD and NAMD. The UIUC license allows
* to re-use up to 10% of a project's code to be used in other software */
/***************************************************************************
* DESCRIPTION:
* Socket interface, abstracts machine dependent APIs/routines.
***************************************************************************/
int imdsock_init(void) {
#if defined(_MSC_VER) || defined(__MINGW32_VERSION)
int rc = 0;
static int initialized=0;
if (!initialized) {
WSADATA wsdata;
rc = WSAStartup(MAKEWORD(1,1), &wsdata);
if (rc == 0)
initialized = 1;
}
return rc;
#else
return 0;
#endif
}
void * imdsock_create(void) {
imdsocket * s;
s = (imdsocket *) malloc(sizeof(imdsocket));
if (s != NULL)
memset(s, 0, sizeof(imdsocket));
if ((s->sd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
printf("Failed to open socket.");
free(s);
return NULL;
}
return (void *) s;
}
int imdsock_bind(void * v, int port) {
imdsocket *s = (imdsocket *) v;
memset(&(s->addr), 0, sizeof(s->addr));
s->addr.sin_family = PF_INET;
s->addr.sin_port = htons(port);
return bind(s->sd, (struct sockaddr *) &s->addr, sizeof(s->addr));
}
int imdsock_listen(void * v) {
imdsocket *s = (imdsocket *) v;
return listen(s->sd, 5);
}
void *imdsock_accept(void * v) {
int rc;
imdsocket *new_s = NULL, *s = (imdsocket *) v;
#if defined(ARCH_AIX5) || defined(ARCH_AIX5_64) || defined(ARCH_AIX6_64)
unsigned int len;
#define _SOCKLEN_TYPE unsigned int
#elif defined(SOCKLEN_T)
SOCKLEN_T len;
#define _SOCKLEN_TYPE SOCKLEN_T
#elif defined(_POSIX_SOURCE) || (defined(__APPLE__) && defined(__MACH__)) || defined(__linux)
socklen_t len;
#define _SOCKLEN_TYPE socklen_t
#else
#define _SOCKLEN_TYPE int
int len;
#endif
len = sizeof(s->addr);
rc = accept(s->sd, (struct sockaddr *) &s->addr, ( _SOCKLEN_TYPE * ) &len);
if (rc >= 0) {
new_s = (imdsocket *) malloc(sizeof(imdsocket));
if (new_s != NULL) {
*new_s = *s;
new_s->sd = rc;
}
}
return (void *)new_s;
}
int imdsock_write(void * v, const void *buf, int len) {
imdsocket *s = (imdsocket *) v;
#if defined(_MSC_VER) || defined(__MINGW32_VERSION)
return send(s->sd, (const char*) buf, len, 0); /* windows lacks the write() call */
#else
return write(s->sd, buf, len);
#endif
}
int imdsock_read(void * v, void *buf, int len) {
imdsocket *s = (imdsocket *) v;
#if defined(_MSC_VER) || defined(__MINGW32_VERSION)
return recv(s->sd, (char*) buf, len, 0); /* windows lacks the read() call */
#else
return read(s->sd, buf, len);
#endif
}
void imdsock_shutdown(void *v) {
imdsocket * s = (imdsocket *) v;
if (s == NULL)
return;
#if defined(_MSC_VER) || defined(__MINGW32_VERSION)
shutdown(s->sd, SD_SEND);
#else
shutdown(s->sd, 1); /* complete sends and send FIN */
#endif
}
void imdsock_destroy(void * v) {
imdsocket * s = (imdsocket *) v;
if (s == NULL)
return;
#if defined(_MSC_VER) || defined(__MINGW32_VERSION)
closesocket(s->sd);
#else
close(s->sd);
#endif
free(s);
}
int imdsock_selread(void *v, int sec) {
imdsocket *s = (imdsocket *)v;
fd_set rfd;
struct timeval tv;
int rc;
if (v == NULL) return 0;
FD_ZERO(&rfd);
FD_SET(s->sd, &rfd);
memset((void *)&tv, 0, sizeof(struct timeval));
tv.tv_sec = sec;
do {
rc = select(s->sd+1, &rfd, NULL, NULL, &tv);
} while (rc < 0 && errno == EINTR);
return rc;
}
int imdsock_selwrite(void *v, int sec) {
imdsocket *s = (imdsocket *)v;
fd_set wfd;
struct timeval tv;
int rc;
if (v == NULL) return 0;
FD_ZERO(&wfd);
FD_SET(s->sd, &wfd);
memset((void *)&tv, 0, sizeof(struct timeval));
tv.tv_sec = sec;
do {
rc = select(s->sd + 1, NULL, &wfd, NULL, &tv);
} while (rc < 0 && errno == EINTR);
return rc;
}
/* end of socket code. */
/*************************************************************************/
/*************************************************************************/
/* start of imd API code. */
/* Only works with aligned 4-byte quantities, will cause a bus error */
/* on some platforms if used on unaligned data. */
void swap4_aligned(void *v, long ndata) {
int *data = (int *) v;
long i;
int *N;
for (i=0; i<ndata; i++) {
N = data + i;
*N=(((*N>>24)&0xff) | ((*N&0xff)<<24) |
((*N>>8)&0xff00) | ((*N&0xff00)<<8));
}
}
/** structure used to perform byte swapping operations */
typedef union {
int32 i;
struct {
unsigned int highest : 8;
unsigned int high : 8;
unsigned int low : 8;
unsigned int lowest : 8;
} b;
} netint;
static int32 imd_htonl(int32 h) {
netint n;
n.b.highest = h >> 24;
n.b.high = h >> 16;
n.b.low = h >> 8;
n.b.lowest = h;
return n.i;
}
static int32 imd_ntohl(int32 n) {
netint u;
u.i = n;
return (u.b.highest << 24 | u.b.high << 16 | u.b.low << 8 | u.b.lowest);
}
static void imd_fill_header(IMDheader *header, IMDType type, int32 length) {
header->type = imd_htonl((int32)type);
header->length = imd_htonl(length);
}
static void swap_header(IMDheader *header) {
header->type = imd_ntohl(header->type);
header->length= imd_ntohl(header->length);
}
static int32 imd_readn(void *s, char *ptr, int32 n) {
int32 nleft;
int32 nread;
nleft = n;
while (nleft > 0) {
if ((nread = imdsock_read(s, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return -1;
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return n-nleft;
}
static int32 imd_writen(void *s, const char *ptr, int32 n) {
int32 nleft;
int32 nwritten;
nleft = n;
while (nleft > 0) {
if ((nwritten = imdsock_write(s, ptr, nleft)) <= 0) {
if (errno == EINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
int imd_disconnect(void *s) {
IMDheader header;
imd_fill_header(&header, IMD_DISCONNECT, 0);
return (imd_writen(s, (char *)&header, IMDHEADERSIZE) != IMDHEADERSIZE);
}
int imd_handshake(void *s) {
IMDheader header;
imd_fill_header(&header, IMD_HANDSHAKE, 1);
header.length = IMDVERSION; /* Not byteswapped! */
return (imd_writen(s, (char *)&header, IMDHEADERSIZE) != IMDHEADERSIZE);
}
/* The IMD receive functions */
IMDType imd_recv_header(void *s, int32 *length) {
IMDheader header;
if (imd_readn(s, (char *)&header, IMDHEADERSIZE) != IMDHEADERSIZE)
return IMD_IOERROR;
swap_header(&header);
*length = header.length;
return IMDType(header.type);
}
int imd_recv_mdcomm(void *s, int32 n, int32 *indices, float *forces) {
if (imd_readn(s, (char *)indices, 4*n) != 4*n) return 1;
if (imd_readn(s, (char *)forces, 12*n) != 12*n) return 1;
return 0;
}
int imd_recv_energies(void *s, IMDEnergies *energies) {
return (imd_readn(s, (char *)energies, sizeof(IMDEnergies))
!= sizeof(IMDEnergies));
}
int imd_recv_fcoords(void *s, int32 n, float *coords) {
return (imd_readn(s, (char *)coords, 12*n) != 12*n);
}
// Local Variables:
// mode: c++
// compile-command: "make -j4 openmpi"
// c-basic-offset: 2
// fill-column: 76
// indent-tabs-mode: nil
// End:
diff --git a/src/USER-MISC/fix_smd.cpp b/src/USER-MISC/fix_smd.cpp
index 4d251d3fe..836a11cd6 100644
--- a/src/USER-MISC/fix_smd.cpp
+++ b/src/USER-MISC/fix_smd.cpp
@@ -1,403 +1,403 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Axel Kohlmeyer (UPenn)
based on fix spring by: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_smd.h"
#include "atom.h"
#include "comm.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "error.h"
#include "group.h"
using namespace LAMMPS_NS;
enum { SMD_NONE=0,
SMD_TETHER=1<<0, SMD_COUPLE=1<<1,
SMD_CVEL=1<<2, SMD_CFOR=1<<3,
SMD_AUTOX=1<<4, SMD_AUTOY=1<<5, SMD_AUTOZ=1<<6};
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
FixSMD::FixSMD(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
styleflag = SMD_NONE;
k_smd = f_smd = v_smd = -1.0;
xflag = yflag = zflag = 1;
xc = yc = zc = 0.0;
xn = yn = zn = 1.0;
pmf = r_old = r_now = r0 = 0.0;
restart_global = 1;
vector_flag = 1;
size_vector = 7;
global_freq = 1;
extvector = 1;
int argoffs=3;
if (strcmp(arg[argoffs],"cvel") == 0) {
- if (narg < argoffs+3) error->all("Illegal fix smd command");
+ if (narg < argoffs+3) error->all(FLERR,"Illegal fix smd command");
styleflag |= SMD_CVEL;
k_smd = atof(arg[argoffs+1]);
v_smd = atof(arg[argoffs+2]); // to be multiplied by update->dt when used.
argoffs += 3;
} else if (strcmp(arg[argoffs],"cfor") == 0) {
- if (narg < argoffs+2) error->all("Illegal fix smd command");
+ if (narg < argoffs+2) error->all(FLERR,"Illegal fix smd command");
styleflag |= SMD_CFOR;
f_smd = atof(arg[argoffs+1]);
argoffs += 2;
- } else error->all("Illegal fix smd command");
+ } else error->all(FLERR,"Illegal fix smd command");
if (strcmp(arg[argoffs],"tether") == 0) {
- if (narg < argoffs+5) error->all("Illegal fix smd command");
+ if (narg < argoffs+5) error->all(FLERR,"Illegal fix smd command");
styleflag |= SMD_TETHER;
if (strcmp(arg[argoffs+1],"NULL") == 0) xflag = 0;
else xc = atof(arg[argoffs+1]);
if (strcmp(arg[argoffs+2],"NULL") == 0) yflag = 0;
else yc = atof(arg[argoffs+2]);
if (strcmp(arg[argoffs+3],"NULL") == 0) zflag = 0;
else zc = atof(arg[argoffs+3]);
r0 = atof(arg[argoffs+4]);
- if (r0 < 0) error->all("R0 < 0 for fix smd command");
+ if (r0 < 0) error->all(FLERR,"R0 < 0 for fix smd command");
argoffs += 5;
} else if (strcmp(arg[argoffs],"couple") == 0) {
- if (narg < argoffs+6) error->all("Illegal fix smd command");
+ if (narg < argoffs+6) error->all(FLERR,"Illegal fix smd command");
styleflag |= SMD_COUPLE;
igroup2 = group->find(arg[argoffs+1]);
if (igroup2 == -1)
- error->all("Could not find fix smd couple group ID");
+ error->all(FLERR,"Could not find fix smd couple group ID");
if (igroup2 == igroup)
- error->all("Two groups cannot be the same in fix smd couple");
+ error->all(FLERR,"Two groups cannot be the same in fix smd couple");
group2bit = group->bitmask[igroup2];
if (strcmp(arg[argoffs+2],"NULL") == 0) xflag = 0;
else if (strcmp(arg[argoffs+2],"auto") == 0) styleflag |= SMD_AUTOX;
else xc = atof(arg[argoffs+2]);
if (strcmp(arg[argoffs+3],"NULL") == 0) yflag = 0;
else if (strcmp(arg[argoffs+3],"auto") == 0) styleflag |= SMD_AUTOY;
else yc = atof(arg[argoffs+3]);
if (strcmp(arg[argoffs+4],"NULL") == 0) zflag = 0;
else if (strcmp(arg[argoffs+4],"auto") == 0) styleflag |= SMD_AUTOZ;
else zc = atof(arg[argoffs+4]);
r0 = atof(arg[argoffs+5]);
- if (r0 < 0) error->all("R0 < 0 for fix smd command");
+ if (r0 < 0) error->all(FLERR,"R0 < 0 for fix smd command");
argoffs +=6;
- } else error->all("Illegal fix smd command");
+ } else error->all(FLERR,"Illegal fix smd command");
force_flag = 0;
ftotal[0] = ftotal[1] = ftotal[2] = 0.0;
}
/* ---------------------------------------------------------------------- */
int FixSMD::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixSMD::init()
{
double xcm[3], xcm2[3];
masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
double dx,dy,dz;
if (styleflag & SMD_TETHER) {
dx = xc - xcm[0];
dy = yc - xcm[1];
dz = zc - xcm[2];
} else { /* SMD_COUPLE */
masstotal2 = group->mass(igroup2);
group->xcm(igroup2,masstotal2,xcm2);
if (styleflag & SMD_AUTOX) dx = xcm2[0] - xcm[0];
else dx = xc;
if (styleflag & SMD_AUTOY) dy = xcm2[1] - xcm[1];
else dy = yc;
if (styleflag & SMD_AUTOZ) dz = xcm2[2] - xcm[2];
else dz = zc;
}
if (!xflag) dx = 0.0;
if (!yflag) dy = 0.0;
if (!zflag) dz = 0.0;
r_old = sqrt(dx*dx + dy*dy + dz*dz);
if (r_old > SMALL) {
xn = dx/r_old;
yn = dy/r_old;
zn = dz/r_old;
}
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixSMD::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixSMD::post_force(int vflag)
{
if (styleflag & SMD_TETHER) smd_tether();
else smd_couple();
if (styleflag & SMD_CVEL) r_old += v_smd * update->dt;
}
/* ---------------------------------------------------------------------- */
void FixSMD::smd_tether()
{
double xcm[3];
group->xcm(igroup,masstotal,xcm);
// fx,fy,fz = components of k * (r-r0)
double dx,dy,dz,fx,fy,fz,r,dr;
dx = xcm[0] - xc;
dy = xcm[1] - yc;
dz = xcm[2] - zc;
r_now = sqrt(dx*dx + dy*dy + dz*dz);
if (!xflag) dx = 0.0;
if (!yflag) dy = 0.0;
if (!zflag) dz = 0.0;
r = sqrt(dx*dx + dy*dy + dz*dz);
if (styleflag & SMD_CVEL) {
if(r > SMALL) {
double fsign;
fsign = (v_smd<0.0) ? -1.0 : 1.0;
dr = r - r0 - r_old;
fx = k_smd*dx*dr/r;
fy = k_smd*dy*dr/r;
fz = k_smd*dz*dr/r;
pmf += (fx*xn + fy*yn + fz*zn) * v_smd * update->dt;
}
} else {
r_old = r;
fx = f_smd*dx/r;
fy = f_smd*dy/r;
fz = f_smd*dz/r;
}
// apply restoring force to atoms in group
// f = -k*(r-r0)*mass/masstotal
double **f = atom->f;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
int nlocal = atom->nlocal;
ftotal[0] = ftotal[1] = ftotal[2] = 0.0;
force_flag = 0;
double massfrac;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massfrac = mass[type[i]]/masstotal;
f[i][0] -= fx*massfrac;
f[i][1] -= fy*massfrac;
f[i][2] -= fz*massfrac;
ftotal[0] -= fx*massfrac;
ftotal[1] -= fy*massfrac;
ftotal[2] -= fz*massfrac;
}
}
/* ---------------------------------------------------------------------- */
void FixSMD::smd_couple()
{
double xcm[3],xcm2[3];
group->xcm(igroup,masstotal,xcm);
group->xcm(igroup2,masstotal2,xcm2);
// renormalize direction of spring
double dx,dy,dz,r,dr;
if (styleflag & SMD_AUTOX) dx = xcm2[0] - xcm[0];
else dx = xn*r_old;
if (styleflag & SMD_AUTOY) dy = xcm2[1] - xcm[1];
else dy = yn*r_old;
if (styleflag & SMD_AUTOZ) dz = xcm2[2] - xcm[2];
else dz = zn*r_old;
if (!xflag) dx = 0.0;
if (!yflag) dy = 0.0;
if (!zflag) dz = 0.0;
r = sqrt(dx*dx + dy*dy + dz*dz);
if (r > SMALL) {
xn = dx/r; yn = dy/r; zn = dz/r;
}
double fx,fy,fz;
if (styleflag & SMD_CVEL) {
dx = xcm2[0] - xcm[0];
dy = xcm2[1] - xcm[1];
dz = xcm2[2] - xcm[2];
r_now = sqrt(dx*dx + dy*dy + dz*dz);
dx -= xn*r_old;
dy -= yn*r_old;
dz -= zn*r_old;
if (!xflag) dx = 0.0;
if (!yflag) dy = 0.0;
if (!zflag) dz = 0.0;
r = sqrt(dx*dx + dy*dy + dz*dz);
dr = r - r0;
if (r > SMALL) {
double fsign;
fsign = (v_smd<0.0) ? -1.0 : 1.0;
fx = k_smd*dx*dr/r;
fy = k_smd*dy*dr/r;
fz = k_smd*dz*dr/r;
pmf += (fx*xn + fy*yn + fz*zn) * fsign * v_smd * update->dt;
}
} else {
dx = xcm2[0] - xcm[0];
dy = xcm2[1] - xcm[1];
dz = xcm2[2] - xcm[2];
r_now = sqrt(dx*dx + dy*dy + dz*dz);
r_old = r;
fx = f_smd*xn;
fy = f_smd*yn;
fz = f_smd*zn;
}
// apply restoring force to atoms in group
// f = -k*(r-r0)*mass/masstotal
double **f = atom->f;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
int nlocal = atom->nlocal;
ftotal[0] = ftotal[1] = ftotal[2] = 0.0;
force_flag = 0;
double massfrac;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
massfrac = mass[type[i]]/masstotal;
f[i][0] += fx*massfrac;
f[i][1] += fy*massfrac;
f[i][2] += fz*massfrac;
ftotal[0] += fx*massfrac;
ftotal[1] += fy*massfrac;
ftotal[2] += fz*massfrac;
}
if (mask[i] & group2bit) {
massfrac = mass[type[i]]/masstotal2;
f[i][0] -= fx*massfrac;
f[i][1] -= fy*massfrac;
f[i][2] -= fz*massfrac;
}
}
}
/* ---------------------------------------------------------------------- */
void FixSMD::write_restart(FILE *fp)
{
#define RESTART_ITEMS 5
double buf[RESTART_ITEMS], fsign;
if (comm->me == 0) {
// make sure we project the force into the direction of the pulling.
fsign = (v_smd<0.0) ? -1.0 : 1.0;
buf[0] = r_old;
buf[1] = xn*fsign;
buf[2] = yn*fsign;
buf[3] = zn*fsign;
buf[4] = pmf;
int size = RESTART_ITEMS*sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(&buf[0],sizeof(double),RESTART_ITEMS,fp);
}
}
/* ---------------------------------------------------------------------- */
void FixSMD::restart(char *buf)
{
double *list = (double *)buf;
r_old = list[0];
xn=list[1];
yn=list[2];
zn=list[3];
pmf=list[4];
}
/* ---------------------------------------------------------------------- */
void FixSMD::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ----------------------------------------------------------------------
return components of total smd force on fix group
------------------------------------------------------------------------- */
double FixSMD::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(ftotal,ftotal_all,3,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
if (styleflag & SMD_CVEL) {
ftotal_all[3]=ftotal_all[0]*xn+ftotal_all[1]*yn+ftotal_all[2]*zn;
ftotal_all[4]=r_old;
} else {
ftotal_all[3]=f_smd;
ftotal_all[4]=r_old;
}
ftotal_all[5]=r_now;
ftotal_all[6]=pmf;
}
return ftotal_all[n];
}
diff --git a/src/USER-MISC/pair_cdeam.cpp b/src/USER-MISC/pair_cdeam.cpp
index 2d0e224f1..b2e6265a2 100644
--- a/src/USER-MISC/pair_cdeam.cpp
+++ b/src/USER-MISC/pair_cdeam.cpp
@@ -1,642 +1,642 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Alexander Stukowski
Technical University of Darmstadt,
Germany Department of Materials Science
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_cdeam.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
// This is for debugging purposes. The ASSERT() macro is used in the code to check
// if everything runs as expected. Change this to #if 0 if you don't need the checking.
#if 0
#define ASSERT(cond) ((!(cond)) ? my_failure(error,__FILE__,__LINE__) : my_noop())
inline void my_noop() {}
inline void my_failure(Error* error, const char* file, int line) {
char str[1024];
sprintf(str,"Assertion failure: File %s, line %i", file, line);
- error->one(str);
+ error->one(FLERR,str);
}
#else
#define ASSERT(cond)
#endif
#define MAXLINE 1024 // This sets the maximum line length in EAM input files.
PairCDEAM::PairCDEAM(LAMMPS *lmp, int _cdeamVersion) : PairEAM(lmp), PairEAMAlloy(lmp), cdeamVersion(_cdeamVersion)
{
single_enable = 0;
rhoB = NULL;
D_values = NULL;
hcoeff = NULL;
// Set communication buffer sizes needed by this pair style.
if(cdeamVersion == 1) {
comm_forward = 4;
comm_reverse = 3;
}
else if(cdeamVersion == 2) {
comm_forward = 3;
comm_reverse = 2;
}
else {
- error->all("Invalid CD-EAM potential version.");
+ error->all(FLERR,"Invalid CD-EAM potential version.");
}
}
PairCDEAM::~PairCDEAM()
{
memory->destroy(rhoB);
memory->destroy(D_values);
if(hcoeff) delete[] hcoeff;
}
void PairCDEAM::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,rhoip,rhojp,recip,phi;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = eflag_atom = 0;
// Grow per-atom arrays if necessary
if(atom->nmax > nmax) {
memory->destroy(rho);
memory->destroy(fp);
memory->destroy(rhoB);
memory->destroy(D_values);
nmax = atom->nmax;
memory->create(rho,nmax,"pair:rho");
memory->create(rhoB,nmax,"pair:rhoB");
memory->create(fp,nmax,"pair:fp");
memory->create(D_values,nmax,"pair:D_values");
}
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// Zero out per-atom arrays.
int m = nlocal + atom->nghost;
for(i = 0; i < m; i++) {
rho[i] = 0.0;
rhoB[i] = 0.0;
D_values[i] = 0.0;
}
// Stage I
// Compute rho and rhoB at each local atom site.
// Additionally calculate the D_i values here if we are using the one-site formulation.
// For the two-site formulation we have to calculate the D values in an extra loop (Stage II).
for(ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for(jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if(rsq < cutforcesq) {
jtype = type[j];
double r = sqrt(rsq);
const EAMTableIndex index = radiusToTableIndex(r);
double localrho = RhoOfR(index, jtype, itype);
rho[i] += localrho;
if(jtype == speciesB) rhoB[i] += localrho;
if(newton_pair || j < nlocal) {
localrho = RhoOfR(index, itype, jtype);
rho[j] += localrho;
if(itype == speciesB) rhoB[j] += localrho;
}
if(cdeamVersion == 1 && itype != jtype) {
// Note: if the i-j interaction is not concentration dependent (because either
// i or j are not species A or B) then its contribution to D_i and D_j should
// be ignored.
// This if-clause is only required for a ternary.
if((itype == speciesA && jtype == speciesB) || (jtype == speciesA && itype == speciesB)) {
double Phi_AB = PhiOfR(index, itype, jtype, 1.0 / r);
D_values[i] += Phi_AB;
if(newton_pair || j < nlocal)
D_values[j] += Phi_AB;
}
}
}
}
}
// Communicate and sum densities.
if(newton_pair) {
communicationStage = 1;
comm->reverse_comm_pair(this);
}
// fp = derivative of embedding energy at each atom
// phi = embedding energy at each atom
for(ii = 0; ii < inum; ii++) {
i = ilist[ii];
EAMTableIndex index = rhoToTableIndex(rho[i]);
fp[i] = FPrimeOfRho(index, type[i]);
if(eflag) {
phi = FofRho(index, type[i]);
if (eflag_global) eng_vdwl += phi;
if (eflag_atom) eatom[i] += phi;
}
}
// Communicate derivative of embedding function and densities
// and D_values (this for one-site formulation only).
communicationStage = 2;
comm->forward_comm_pair(this);
// The electron densities may not drop to zero because then the concentration would no longer be defined.
// But the concentration is not needed anyway if there is no interaction with another atom, which is the case
// if the electron density is exactly zero. That's why the following lines have been commented out.
//
//for(i = 0; i < nlocal + atom->nghost; i++) {
// if(rho[i] == 0 && (type[i] == speciesA || type[i] == speciesB))
- // error->one("CD-EAM potential routine: Detected atom with zero electron density.");
+ // error->one(FLERR,"CD-EAM potential routine: Detected atom with zero electron density.");
//}
// Stage II
// This is only required for the original two-site formulation of the CD-EAM potential.
if(cdeamVersion == 2) {
// Compute intermediate value D_i for each atom.
for(ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
// This code line is required for ternary alloys.
if(itype != speciesA && itype != speciesB) continue;
double x_i = rhoB[i] / rho[i]; // Concentration at atom i.
for(jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = type[j];
if(itype == jtype) continue;
// This code line is required for ternary alloys.
if(jtype != speciesA && jtype != speciesB) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if(rsq < cutforcesq) {
double r = sqrt(rsq);
const EAMTableIndex index = radiusToTableIndex(r);
// The concentration independent part of the cross pair potential.
double Phi_AB = PhiOfR(index, itype, jtype, 1.0 / r);
// Average concentration of two sites
double x_ij = 0.5 * (x_i + rhoB[j]/rho[j]);
// Calculate derivative of h(x_ij) polynomial function.
double h_prime = evalHprime(x_ij);
D_values[i] += h_prime * Phi_AB / (2.0 * rho[i] * rho[i]);
if(newton_pair || j < nlocal)
D_values[j] += h_prime * Phi_AB / (2.0 * rho[j] * rho[j]);
}
}
}
// Communicate and sum D values.
if(newton_pair) {
communicationStage = 3;
comm->reverse_comm_pair(this);
}
communicationStage = 4;
comm->forward_comm_pair(this);
}
// Stage III
// Compute force acting on each atom.
for(ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
// Concentration at site i
double x_i = -1.0; // The value -1 indicates: no concentration dependence for all interactions of atom i.
// It will be replaced by the concentration at site i if atom i is either A or B.
double D_i, h_prime_i;
// This if-clause is only required for ternary alloys.
if((itype == speciesA || itype == speciesB) && rho[i] != 0.0) {
// Compute local concentration at site i.
x_i = rhoB[i]/rho[i];
ASSERT(x_i >= 0 && x_i<=1.0);
if(cdeamVersion == 1) {
// Calculate derivative of h(x_i) polynomial function.
h_prime_i = evalHprime(x_i);
D_i = D_values[i] * h_prime_i / (2.0 * rho[i] * rho[i]);
}
else if(cdeamVersion == 2) {
D_i = D_values[i];
}
else ASSERT(false);
}
for(jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if(rsq < cutforcesq) {
jtype = type[j];
double r = sqrt(rsq);
const EAMTableIndex index = radiusToTableIndex(r);
// rhoip = derivative of (density at atom j due to atom i)
// rhojp = derivative of (density at atom i due to atom j)
// psip needs both fp[i] and fp[j] terms since r_ij appears in two
// terms of embed eng: Fi(sum rho_ij) and Fj(sum rho_ji)
// hence embed' = Fi(sum rho_ij) rhojp + Fj(sum rho_ji) rhoip
rhoip = RhoPrimeOfR(index, itype, jtype);
rhojp = RhoPrimeOfR(index, jtype, itype);
fpair = fp[i]*rhojp + fp[j]*rhoip;
recip = 1.0/r;
double x_j = -1; // The value -1 indicates: no concentration dependence for this i-j pair
// because atom j is not of species A nor B.
// This code line is required for ternary alloy.
if(jtype == speciesA || jtype == speciesB) {
ASSERT(rho[i] != 0.0);
ASSERT(rho[j] != 0.0);
// Compute local concentration at site j.
x_j = rhoB[j]/rho[j];
ASSERT(x_j >= 0 && x_j<=1.0);
double D_j;
if(cdeamVersion == 1) {
// Calculate derivative of h(x_j) polynomial function.
double h_prime_j = evalHprime(x_j);
D_j = D_values[j] * h_prime_j / (2.0 * rho[j] * rho[j]);
}
else if(cdeamVersion == 2) {
D_j = D_values[j];
}
else ASSERT(false);
double t2 = -rhoB[j];
if(itype == speciesB) t2 += rho[j];
fpair += D_j * rhoip * t2;
}
// This if-clause is only required for a ternary alloy.
// Actually we don't need it at all because D_i should be zero anyway if
// atom i has no concentration dependent interactions (because it is not species A or B).
if(x_i != -1.0) {
double t1 = -rhoB[i];
if(jtype == speciesB) t1 += rho[i];
fpair += D_i * rhojp * t1;
}
double phip;
double phi = PhiOfR(index, itype, jtype, recip, phip);
if(itype == jtype || x_i == -1.0 || x_j == -1.0) {
// Case of no concentration dependence.
fpair += phip;
}
else {
// We have a concentration dependence for the i-j interaction.
double h;
if(cdeamVersion == 1) {
// Calculate h(x_i) polynomial function.
double h_i = evalH(x_i);
// Calculate h(x_j) polynomial function.
double h_j = evalH(x_j);
h = 0.5 * (h_i + h_j);
}
else if(cdeamVersion == 2) {
// Average concentration.
double x_ij = 0.5 * (x_i + x_j);
// Calculate h(x_ij) polynomial function.
h = evalH(x_ij);
}
else ASSERT(false);
fpair += h * phip;
phi *= h;
}
// Divide by r_ij and negate to get forces from gradient.
fpair /= -r;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if(newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if(eflag) evdwl = phi;
if(evflag) ev_tally(i,j,nlocal,newton_pair,evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if(vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairCDEAM::coeff(int narg, char **arg)
{
PairEAMAlloy::coeff(narg, arg);
// Make sure the EAM file is a CD-EAM binary alloy.
if(setfl->nelements < 2)
- error->all("The EAM file must contain at least 2 elements to be used with the eam/cd pair style.");
+ error->all(FLERR,"The EAM file must contain at least 2 elements to be used with the eam/cd pair style.");
// Read in the coefficients of the h polynomial from the end of the EAM file.
read_h_coeff(arg[2]);
// Determine which atom type is the A species and which is the B species in the alloy.
// By default take the first element (index 0) in the EAM file as the A species
// and the second element (index 1) in the EAM file as the B species.
speciesA = -1;
speciesB = -1;
for(int i = 1; i <= atom->ntypes; i++) {
if(map[i] == 0) {
if(speciesA >= 0)
- error->all("The first element from the EAM file may only be mapped to a single atom type.");
+ error->all(FLERR,"The first element from the EAM file may only be mapped to a single atom type.");
speciesA = i;
}
if(map[i] == 1) {
if(speciesB >= 0)
- error->all("The second element from the EAM file may only be mapped to a single atom type.");
+ error->all(FLERR,"The second element from the EAM file may only be mapped to a single atom type.");
speciesB = i;
}
}
if(speciesA < 0)
- error->all("The first element from the EAM file must be mapped to exactly one atom type.");
+ error->all(FLERR,"The first element from the EAM file must be mapped to exactly one atom type.");
if(speciesB < 0)
- error->all("The second element from the EAM file must be mapped to exactly one atom type.");
+ error->all(FLERR,"The second element from the EAM file must be mapped to exactly one atom type.");
}
/* ----------------------------------------------------------------------
Reads in the h(x) polynomial coefficients
------------------------------------------------------------------------- */
void PairCDEAM::read_h_coeff(char *filename)
{
if(comm->me == 0) {
// Open potential file
FILE *fp;
char line[MAXLINE];
char nextline[MAXLINE];
fp = fopen(filename,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open EAM potential file %s", filename);
- error->one(str);
+ error->one(FLERR,str);
}
// h coefficients are stored at the end of the file.
// Skip to last line of file.
while(fgets(nextline, MAXLINE, fp) != NULL) {
strcpy(line, nextline);
}
char* ptr = strtok(line, " \t\n\r\f");
int degree = atoi(ptr);
nhcoeff = degree+1;
hcoeff = new double[nhcoeff];
int i = 0;
while((ptr = strtok(NULL," \t\n\r\f")) != NULL && i < nhcoeff) {
hcoeff[i++] = atof(ptr);
}
if(i != nhcoeff || nhcoeff < 1)
- error->one("Failed to read h(x) function coefficients from EAM file.");
+ error->one(FLERR,"Failed to read h(x) function coefficients from EAM file.");
// Close the potential file.
fclose(fp);
}
MPI_Bcast(&nhcoeff, 1, MPI_INT, 0, world);
if(comm->me != 0) hcoeff = new double[nhcoeff];
MPI_Bcast(hcoeff, nhcoeff, MPI_DOUBLE, 0, world);
}
/* ---------------------------------------------------------------------- */
int PairCDEAM::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
if(communicationStage == 2) {
if(cdeamVersion == 1) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = fp[j];
buf[m++] = rho[j];
buf[m++] = rhoB[j];
buf[m++] = D_values[j];
}
return 4;
}
else if(cdeamVersion == 2) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = fp[j];
buf[m++] = rho[j];
buf[m++] = rhoB[j];
}
return 3;
}
else { ASSERT(false); return 0; }
}
else if(communicationStage == 4) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = D_values[j];
}
return 1;
}
else return 0;
}
/* ---------------------------------------------------------------------- */
void PairCDEAM::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if(communicationStage == 2) {
if(cdeamVersion == 1) {
for(i = first; i < last; i++) {
fp[i] = buf[m++];
rho[i] = buf[m++];
rhoB[i] = buf[m++];
D_values[i] = buf[m++];
}
}
else if(cdeamVersion == 2) {
for(i = first; i < last; i++) {
fp[i] = buf[m++];
rho[i] = buf[m++];
rhoB[i] = buf[m++];
}
}
else ASSERT(false);
}
else if(communicationStage == 4) {
for(i = first; i < last; i++) {
D_values[i] = buf[m++];
}
}
}
/* ---------------------------------------------------------------------- */
int PairCDEAM::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if(communicationStage == 1) {
if(cdeamVersion == 1) {
for(i = first; i < last; i++) {
buf[m++] = rho[i];
buf[m++] = rhoB[i];
buf[m++] = D_values[i];
}
return 3;
}
else if(cdeamVersion == 2) {
for(i = first; i < last; i++) {
buf[m++] = rho[i];
buf[m++] = rhoB[i];
}
return 2;
}
else { ASSERT(false); return 0; }
}
else if(communicationStage == 3) {
for(i = first; i < last; i++) {
buf[m++] = D_values[i];
}
return 1;
}
else return 0;
}
/* ---------------------------------------------------------------------- */
void PairCDEAM::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
if(communicationStage == 1) {
if(cdeamVersion == 1) {
for(i = 0; i < n; i++) {
j = list[i];
rho[j] += buf[m++];
rhoB[j] += buf[m++];
D_values[j] += buf[m++];
}
}
else if(cdeamVersion == 2) {
for(i = 0; i < n; i++) {
j = list[i];
rho[j] += buf[m++];
rhoB[j] += buf[m++];
}
}
else ASSERT(false);
}
else if(communicationStage == 3) {
for(i = 0; i < n; i++) {
j = list[i];
D_values[j] += buf[m++];
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double PairCDEAM::memory_usage()
{
double bytes = 2 * nmax * sizeof(double);
return PairEAMAlloy::memory_usage() + bytes;
}
diff --git a/src/USER-MISC/pair_dipole_sf.cpp b/src/USER-MISC/pair_dipole_sf.cpp
index f43757179..8adf06635 100644
--- a/src/USER-MISC/pair_dipole_sf.cpp
+++ b/src/USER-MISC/pair_dipole_sf.cpp
@@ -1,507 +1,504 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mario Orsi (U Southampton), orsimario@gmail.com
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_dipole_sf.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairDipoleSF::PairDipoleSF(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
}
/* ---------------------------------------------------------------------- */
PairDipoleSF::~PairDipoleSF()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
}
}
/* ---------------------------------------------------------------------- */
void PairDipoleSF::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fx,fy,fz;
double rsq,rinv,r2inv,r6inv,r3inv,r5inv;
double forcecoulx,forcecouly,forcecoulz,crossx,crossy,crossz;
double tixcoul,tiycoul,tizcoul,tjxcoul,tjycoul,tjzcoul;
double fq,pdotp,pidotr,pjdotr,pre1,pre2,pre3,pre4;
double forcelj,factor_coul,factor_lj;
double presf,afac,bfac,pqfac,qpfac,forceljcut,forceljsf;
double aforcecoulx,aforcecouly,aforcecoulz;
double bforcecoulx,bforcecouly,bforcecoulz;
double rcutlj2inv, rcutcoul2inv,rcutlj6inv;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
double **mu = atom->mu;
double **torque = atom->torque;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
rinv = sqrt(r2inv);
// atom can have both a charge and dipole
// i,j = charge-charge, dipole-dipole, dipole-charge, or charge-dipole
forcecoulx = forcecouly = forcecoulz = 0.0;
tixcoul = tiycoul = tizcoul = 0.0;
tjxcoul = tjycoul = tjzcoul = 0.0;
if (rsq < cut_coulsq[itype][jtype]) {
if (qtmp != 0.0 && q[j] != 0.0) {
pre1 = qtmp*q[j]*rinv*(r2inv-1.0/cut_coulsq[itype][jtype]);
forcecoulx += pre1*delx;
forcecouly += pre1*dely;
forcecoulz += pre1*delz;
}
if (mu[i][3] > 0.0 && mu[j][3] > 0.0) {
r3inv = r2inv*rinv;
r5inv = r3inv*r2inv;
rcutcoul2inv=1.0/cut_coulsq[itype][jtype];
pdotp = mu[i][0]*mu[j][0] + mu[i][1]*mu[j][1] + mu[i][2]*mu[j][2];
pidotr = mu[i][0]*delx + mu[i][1]*dely + mu[i][2]*delz;
pjdotr = mu[j][0]*delx + mu[j][1]*dely + mu[j][2]*delz;
afac = 1.0 - rsq*rsq * rcutcoul2inv*rcutcoul2inv;
pre1 = afac * ( pdotp - 3.0 * r2inv * pidotr * pjdotr );
aforcecoulx = pre1*delx;
aforcecouly = pre1*dely;
aforcecoulz = pre1*delz;
bfac = 1.0 - 4.0*rsq*sqrt(rsq)*rcutcoul2inv*sqrt(rcutcoul2inv) +
3.0*rsq*rsq*rcutcoul2inv*rcutcoul2inv;
presf = 2.0 * r2inv * pidotr * pjdotr;
bforcecoulx = bfac * (pjdotr*mu[i][0]+pidotr*mu[j][0]-presf*delx);
bforcecouly = bfac * (pjdotr*mu[i][1]+pidotr*mu[j][1]-presf*dely);
bforcecoulz = bfac * (pjdotr*mu[i][2]+pidotr*mu[j][2]-presf*delz);
forcecoulx += 3.0 * r5inv * ( aforcecoulx + bforcecoulx );
forcecouly += 3.0 * r5inv * ( aforcecouly + bforcecouly );
forcecoulz += 3.0 * r5inv * ( aforcecoulz + bforcecoulz );
pre2 = 3.0 * bfac * r5inv * pjdotr;
pre3 = 3.0 * bfac * r5inv * pidotr;
pre4 = -bfac * r3inv;
crossx = pre4 * (mu[i][1]*mu[j][2] - mu[i][2]*mu[j][1]);
crossy = pre4 * (mu[i][2]*mu[j][0] - mu[i][0]*mu[j][2]);
crossz = pre4 * (mu[i][0]*mu[j][1] - mu[i][1]*mu[j][0]);
tixcoul += crossx + pre2 * (mu[i][1]*delz - mu[i][2]*dely);
tiycoul += crossy + pre2 * (mu[i][2]*delx - mu[i][0]*delz);
tizcoul += crossz + pre2 * (mu[i][0]*dely - mu[i][1]*delx);
tjxcoul += -crossx + pre3 * (mu[j][1]*delz - mu[j][2]*dely);
tjycoul += -crossy + pre3 * (mu[j][2]*delx - mu[j][0]*delz);
tjzcoul += -crossz + pre3 * (mu[j][0]*dely - mu[j][1]*delx);
}
if (mu[i][3] > 0.0 && q[j] != 0.0) {
r3inv = r2inv*rinv;
r5inv = r3inv*r2inv;
pidotr = mu[i][0]*delx + mu[i][1]*dely + mu[i][2]*delz;
rcutcoul2inv=1.0/cut_coulsq[itype][jtype];
pre1 = 3.0 * q[j] * r5inv * pidotr * (1-rsq*rcutcoul2inv);
pqfac = 1.0 - 3.0*rsq*rcutcoul2inv +
2.0*rsq*sqrt(rsq)*rcutcoul2inv*sqrt(rcutcoul2inv);
pre2 = q[j] * r3inv * pqfac;
forcecoulx += pre2*mu[i][0] - pre1*delx;
forcecouly += pre2*mu[i][1] - pre1*dely;
forcecoulz += pre2*mu[i][2] - pre1*delz;
tixcoul += pre2 * (mu[i][1]*delz - mu[i][2]*dely);
tiycoul += pre2 * (mu[i][2]*delx - mu[i][0]*delz);
tizcoul += pre2 * (mu[i][0]*dely - mu[i][1]*delx);
}
if (mu[j][3] > 0.0 && qtmp != 0.0) {
r3inv = r2inv*rinv;
r5inv = r3inv*r2inv;
pjdotr = mu[j][0]*delx + mu[j][1]*dely + mu[j][2]*delz;
rcutcoul2inv=1.0/cut_coulsq[itype][jtype];
pre1 = 3.0 * qtmp * r5inv * pjdotr * (1-rsq*rcutcoul2inv);
qpfac = 1.0 - 3.0*rsq*rcutcoul2inv +
2.0*rsq*sqrt(rsq)*rcutcoul2inv*sqrt(rcutcoul2inv);
pre2 = qtmp * r3inv * qpfac;
forcecoulx += pre1*delx - pre2*mu[j][0];
forcecouly += pre1*dely - pre2*mu[j][1];
forcecoulz += pre1*delz - pre2*mu[j][2];
tjxcoul += -pre2 * (mu[j][1]*delz - mu[j][2]*dely);
tjycoul += -pre2 * (mu[j][2]*delx - mu[j][0]*delz);
tjzcoul += -pre2 * (mu[j][0]*dely - mu[j][1]*delx);
}
}
// LJ interaction
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forceljcut = r6inv*(lj1[itype][jtype]*r6inv-lj2[itype][jtype])*r2inv;
rcutlj2inv = 1.0 / cut_ljsq[itype][jtype];
rcutlj6inv = rcutlj2inv * rcutlj2inv * rcutlj2inv;
forceljsf = (lj1[itype][jtype]*rcutlj6inv - lj2[itype][jtype]) *
rcutlj6inv * rcutlj2inv;
forcelj = factor_lj * (forceljcut - forceljsf);
} else forcelj = 0.0;
// total force
fq = factor_coul*qqrd2e;
fx = fq*forcecoulx + delx*forcelj;
fy = fq*forcecouly + dely*forcelj;
fz = fq*forcecoulz + delz*forcelj;
// force & torque accumulation
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
torque[i][0] += fq*tixcoul;
torque[i][1] += fq*tiycoul;
torque[i][2] += fq*tizcoul;
if (newton_pair || j < nlocal) {
f[j][0] -= fx;
f[j][1] -= fy;
f[j][2] -= fz;
torque[j][0] += fq*tjxcoul;
torque[j][1] += fq*tjycoul;
torque[j][2] += fq*tjzcoul;
}
if (eflag) {
if (rsq < cut_coulsq[itype][jtype]) {
ecoul = qtmp * q[j] * rinv *
pow((1.0-sqrt(rsq)/sqrt(cut_coulsq[itype][jtype])),2);
if (mu[i][3] > 0.0 && mu[j][3] > 0.0)
ecoul += bfac * (r3inv*pdotp - 3.0*r5inv*pidotr*pjdotr);
if (mu[i][3] > 0.0 && q[j] != 0.0)
ecoul += -q[j] * r3inv * pqfac * pidotr;
if (mu[j][3] > 0.0 && qtmp != 0.0)
ecoul += qtmp * r3inv * qpfac * pjdotr;
ecoul *= factor_coul*qqrd2e;
} else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype])+
rcutlj6inv*(6*lj3[itype][jtype]*rcutlj6inv-3*lj4[itype][jtype])*
rsq*rcutlj2inv+
rcutlj6inv*(-7*lj3[itype][jtype]*rcutlj6inv+4*lj4[itype][jtype]);
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally_xyz(i,j,nlocal,newton_pair,
evdwl,ecoul,fx,fy,fz,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairDipoleSF::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"pair:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"pair:cut_coulsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairDipoleSF::settings(int narg, char **arg)
{
if (narg < 1 || narg > 2)
- error->all("Incorrect args in pair_style command");
+ error->all(FLERR,"Incorrect args in pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul_global = cut_lj_global;
else cut_coul_global = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_lj[i][j] = cut_lj_global;
cut_coul[i][j] = cut_coul_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairDipoleSF::coeff(int narg, char **arg)
{
if (narg < 4 || narg > 6)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_lj_one = cut_lj_global;
double cut_coul_one = cut_coul_global;
if (narg >= 5) cut_coul_one = cut_lj_one = force->numeric(arg[4]);
if (narg == 6) cut_coul_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_lj[i][j] = cut_lj_one;
cut_coul[i][j] = cut_coul_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairDipoleSF::init_style()
{
if (!atom->q_flag || !atom->mu_flag || !atom->torque_flag)
- error->all("Pair dipole/sf requires atom attributes q, mu, torque");
+ error->all(FLERR,"Pair dipole/sf requires atom attributes q, mu, torque");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairDipoleSF::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]);
cut_coul[i][j] = mix_distance(cut_coul[i][i],cut_coul[j][j]);
}
double cut = MAX(cut_lj[i][j],cut_coul[i][j]);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
cut_coulsq[i][j] = cut_coul[i][j] * cut_coul[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
cut_ljsq[j][i] = cut_ljsq[i][j];
cut_coulsq[j][i] = cut_coulsq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDipoleSF::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
fwrite(&cut_coul[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDipoleSF::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
fread(&cut_coul[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDipoleSF::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul_global,sizeof(double),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDipoleSF::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul_global,sizeof(double),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
diff --git a/src/USER-MISC/pair_edip.cpp b/src/USER-MISC/pair_edip.cpp
index 369877ab3..77e5ee20d 100755
--- a/src/USER-MISC/pair_edip.cpp
+++ b/src/USER-MISC/pair_edip.cpp
@@ -1,1053 +1,1053 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Luca Ferraro (CASPUR)
email: luca.ferraro@caspur.it
Environment Dependent Interatomic Potential
References:
1) J. F. Justo, M. Z. Bazant, E. Kaxiras, V. V. Bulatov, S. Yip
Phys. Rev. B 58, 2539 (1998)
------------------------------------------------------------------------- */
#include "math.h"
#include "float.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_edip.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
#define DELTA 4
/* ---------------------------------------------------------------------- */
PairEDIP::PairEDIP(LAMMPS *lmp) : Pair(lmp)
{
single_enable = 0;
one_coeff = 1;
nelements = 0;
elements = NULL;
nparams = maxparam = 0;
params = NULL;
elem2param = NULL;
}
/* ----------------------------------------------------------------------
check if allocated, since class can be destructed when incomplete
------------------------------------------------------------------------- */
PairEDIP::~PairEDIP()
{
if (elements)
for (int i = 0; i < nelements; i++) delete [] elements[i];
delete [] elements;
memory->destroy(params);
memory->destroy(elem2param);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
deallocateGrids();
deallocatePreLoops();
}
}
/* ---------------------------------------------------------------------- */
void PairEDIP::compute(int eflag, int vflag)
{
int i,j,k,ii,inum,jnum;
int itype,jtype,ktype,ijparam,ikparam,ijkparam;
double xtmp,ytmp,ztmp,evdwl;
int *ilist,*jlist,*numneigh,**firstneigh;
register int preForceCoord_counter;
double invR_ij;
double invR_ik;
double directorCos_ij_x;
double directorCos_ij_y;
double directorCos_ij_z;
double directorCos_ik_x;
double directorCos_ik_y;
double directorCos_ik_z;
double cosTeta;
int interpolIDX;
double interpolTMP;
double interpolDeltaX;
double interpolY1;
double interpolY2;
double invRMinusCutoffA;
double sigmaInvRMinusCutoffA;
double gammInvRMinusCutoffA;
double cosTetaDiff;
double cosTetaDiffCosTetaDiff;
double cutoffFunction_ij;
double exp2B_ij;
double exp2BDerived_ij;
double pow2B_ij;
double pow2BDerived_ij;
double exp3B_ij;
double exp3BDerived_ij;
double exp3B_ik;
double exp3BDerived_ik;
double qFunction;
double qFunctionDerived;
double tauFunction;
double tauFunctionDerived;
double expMinusBetaZeta_iZeta_i;
double qFunctionCosTetaDiffCosTetaDiff;
double expMinusQFunctionCosTetaDiffCosTetaDiff;
double zeta_i;
double zeta_iDerived;
double zeta_iDerivedInvR_ij;
double forceModCoord_factor;
double forceModCoord;
double forceModCoord_ij;
double forceMod2B;
double forceMod3B_factor1_ij;
double forceMod3B_factor2_ij;
double forceMod3B_factor2;
double forceMod3B_factor1_ik;
double forceMod3B_factor2_ik;
double potentia3B_factor;
double potential2B_factor;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over full neighbor list of my atoms
for (ii = 0; ii < inum; ii++) {
zeta_i = 0.0;
int numForceCoordPairs = 0;
i = ilist[ii];
itype = map[type[i]];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
// pre-loop to compute environment coordination f(Z)
for (int neighbor_j = 0; neighbor_j < jnum; neighbor_j++) {
j = jlist[neighbor_j];
j &= NEIGHMASK;
double dr_ij[3], r_ij;
dr_ij[0] = xtmp - x[j][0];
dr_ij[1] = ytmp - x[j][1];
dr_ij[2] = ztmp - x[j][2];
r_ij = dr_ij[0]*dr_ij[0] + dr_ij[1]*dr_ij[1] + dr_ij[2]*dr_ij[2];
jtype = map[type[j]];
ijparam = elem2param[itype][jtype][jtype];
if (r_ij > params[ijparam].cutsq) continue;
r_ij = sqrt(r_ij);
invR_ij = 1.0 / r_ij;
preInvR_ij[neighbor_j] = invR_ij;
invRMinusCutoffA = 1.0 / (r_ij - cutoffA);
sigmaInvRMinusCutoffA = sigma * invRMinusCutoffA;
gammInvRMinusCutoffA = gamm * invRMinusCutoffA;
interpolDeltaX = r_ij - GRIDSTART;
interpolTMP = (interpolDeltaX * GRIDDENSITY);
interpolIDX = (int) interpolTMP;
interpolY1 = exp3B[interpolIDX];
interpolY2 = exp3B[interpolIDX+1];
exp3B_ij = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
exp3BDerived_ij = - exp3B_ij * gammInvRMinusCutoffA * invRMinusCutoffA;
preExp3B_ij[neighbor_j] = exp3B_ij;
preExp3BDerived_ij[neighbor_j] = exp3BDerived_ij;
interpolY1 = exp2B[interpolIDX];
interpolY2 = exp2B[interpolIDX+1];
exp2B_ij = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
exp2BDerived_ij = - exp2B_ij * sigmaInvRMinusCutoffA * invRMinusCutoffA;
preExp2B_ij[neighbor_j] = exp2B_ij;
preExp2BDerived_ij[neighbor_j] = exp2BDerived_ij;
interpolY1 = pow2B[interpolIDX];
interpolY2 = pow2B[interpolIDX+1];
pow2B_ij = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
prePow2B_ij[neighbor_j] = pow2B_ij;
// zeta and its derivative
if (r_ij < cutoffC) zeta_i += 1.0;
else {
interpolY1 = cutoffFunction[interpolIDX];
interpolY2 = cutoffFunction[interpolIDX+1];
cutoffFunction_ij = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
zeta_i += cutoffFunction_ij;
interpolY1 = cutoffFunctionDerived[interpolIDX];
interpolY2 = cutoffFunctionDerived[interpolIDX+1];
zeta_iDerived = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
zeta_iDerivedInvR_ij = zeta_iDerived * invR_ij;
preForceCoord_counter=numForceCoordPairs*5;
preForceCoord[preForceCoord_counter+0]=zeta_iDerivedInvR_ij;
preForceCoord[preForceCoord_counter+1]=dr_ij[0];
preForceCoord[preForceCoord_counter+2]=dr_ij[1];
preForceCoord[preForceCoord_counter+3]=dr_ij[2];
preForceCoord[preForceCoord_counter+4]=j;
numForceCoordPairs++;
}
}
// quantities depending on zeta_i
interpolDeltaX = zeta_i;
interpolTMP = (interpolDeltaX * GRIDDENSITY);
interpolIDX = (int) interpolTMP;
interpolY1 = expMinusBetaZeta_iZeta_iGrid[interpolIDX];
interpolY2 = expMinusBetaZeta_iZeta_iGrid[interpolIDX+1];
expMinusBetaZeta_iZeta_i = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
interpolY1 = qFunctionGrid[interpolIDX];
interpolY2 = qFunctionGrid[interpolIDX+1];
qFunction = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
interpolY1 = tauFunctionGrid[interpolIDX];
interpolY2 = tauFunctionGrid[interpolIDX+1];
tauFunction = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
interpolY1 = tauFunctionDerivedGrid[interpolIDX];
interpolY2 = tauFunctionDerivedGrid[interpolIDX+1];
tauFunctionDerived = interpolY1 + (interpolY2 - interpolY1) *
(interpolTMP-interpolIDX);
qFunctionDerived = -mu * qFunction;
forceModCoord_factor = 2.0 * beta * zeta_i * expMinusBetaZeta_iZeta_i;
forceModCoord = 0.0;
// two-body interactions, skip half of them
for (int neighbor_j = 0; neighbor_j < jnum; neighbor_j++) {
double dr_ij[3], r_ij, f_ij[3];
j = jlist[neighbor_j];
j &= NEIGHMASK;
dr_ij[0] = x[j][0] - xtmp;
dr_ij[1] = x[j][1] - ytmp;
dr_ij[2] = x[j][2] - ztmp;
r_ij = dr_ij[0]*dr_ij[0] + dr_ij[1]*dr_ij[1] + dr_ij[2]*dr_ij[2];
jtype = map[type[j]];
ijparam = elem2param[itype][jtype][jtype];
if (r_ij > params[ijparam].cutsq) continue;
r_ij = sqrt(r_ij);
invR_ij = preInvR_ij[neighbor_j];
pow2B_ij = prePow2B_ij[neighbor_j];
potential2B_factor = pow2B_ij - expMinusBetaZeta_iZeta_i;
exp2B_ij = preExp2B_ij[neighbor_j];
pow2BDerived_ij = - rho * invR_ij * pow2B_ij;
forceModCoord += (forceModCoord_factor*exp2B_ij);
exp2BDerived_ij = preExp2BDerived_ij[neighbor_j];
forceMod2B = exp2BDerived_ij * potential2B_factor +
exp2B_ij * pow2BDerived_ij;
directorCos_ij_x = invR_ij * dr_ij[0];
directorCos_ij_y = invR_ij * dr_ij[1];
directorCos_ij_z = invR_ij * dr_ij[2];
exp3B_ij = preExp3B_ij[neighbor_j];
exp3BDerived_ij = preExp3BDerived_ij[neighbor_j];
f_ij[0] = forceMod2B * directorCos_ij_x;
f_ij[1] = forceMod2B * directorCos_ij_y;
f_ij[2] = forceMod2B * directorCos_ij_z;
f[j][0] -= f_ij[0];
f[j][1] -= f_ij[1];
f[j][2] -= f_ij[2];
f[i][0] += f_ij[0];
f[i][1] += f_ij[1];
f[i][2] += f_ij[2];
// potential energy
evdwl = (exp2B_ij * potential2B_factor);
if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0,
-forceMod2B*invR_ij, dr_ij[0], dr_ij[1], dr_ij[2]);
// three-body Forces
for (int neighbor_k = neighbor_j + 1; neighbor_k < jnum; neighbor_k++) {
double dr_ik[3], r_ik, f_ik[3];
k = jlist[neighbor_k];
k &= NEIGHMASK;
ktype = map[type[k]];
ikparam = elem2param[itype][ktype][ktype];
ijkparam = elem2param[itype][jtype][ktype];
dr_ik[0] = x[k][0] - xtmp;
dr_ik[1] = x[k][1] - ytmp;
dr_ik[2] = x[k][2] - ztmp;
r_ik = dr_ik[0]*dr_ik[0] + dr_ik[1]*dr_ik[1] + dr_ik[2]*dr_ik[2];
if (r_ik > params[ikparam].cutsq) continue;
r_ik = sqrt(r_ik);
invR_ik = preInvR_ij[neighbor_k];
directorCos_ik_x = invR_ik * dr_ik[0];
directorCos_ik_y = invR_ik * dr_ik[1];
directorCos_ik_z = invR_ik * dr_ik[2];
cosTeta = directorCos_ij_x * directorCos_ik_x +
directorCos_ij_y * directorCos_ik_y +
directorCos_ij_z * directorCos_ik_z;
cosTetaDiff = cosTeta + tauFunction;
cosTetaDiffCosTetaDiff = cosTetaDiff * cosTetaDiff;
qFunctionCosTetaDiffCosTetaDiff = cosTetaDiffCosTetaDiff * qFunction;
expMinusQFunctionCosTetaDiffCosTetaDiff =
exp(-qFunctionCosTetaDiffCosTetaDiff);
potentia3B_factor = lambda *
((1.0 - expMinusQFunctionCosTetaDiffCosTetaDiff) +
eta * qFunctionCosTetaDiffCosTetaDiff);
exp3B_ik = preExp3B_ij[neighbor_k];
exp3BDerived_ik = preExp3BDerived_ij[neighbor_k];
forceMod3B_factor1_ij = - exp3BDerived_ij * exp3B_ik *
potentia3B_factor;
forceMod3B_factor2 = 2.0 * lambda * exp3B_ij * exp3B_ik *
qFunction * cosTetaDiff *
(eta + expMinusQFunctionCosTetaDiffCosTetaDiff);
forceMod3B_factor2_ij = forceMod3B_factor2 * invR_ij;
f_ij[0] = forceMod3B_factor1_ij * directorCos_ij_x +
forceMod3B_factor2_ij *
(cosTeta * directorCos_ij_x - directorCos_ik_x);
f_ij[1] = forceMod3B_factor1_ij * directorCos_ij_y +
forceMod3B_factor2_ij *
(cosTeta * directorCos_ij_y - directorCos_ik_y);
f_ij[2] = forceMod3B_factor1_ij * directorCos_ij_z +
forceMod3B_factor2_ij *
(cosTeta * directorCos_ij_z - directorCos_ik_z);
forceMod3B_factor1_ik = - exp3BDerived_ik * exp3B_ij *
potentia3B_factor;
forceMod3B_factor2_ik = forceMod3B_factor2 * invR_ik;
f_ik[0] = forceMod3B_factor1_ik * directorCos_ik_x +
forceMod3B_factor2_ik *
(cosTeta * directorCos_ik_x - directorCos_ij_x);
f_ik[1] = forceMod3B_factor1_ik * directorCos_ik_y +
forceMod3B_factor2_ik *
(cosTeta * directorCos_ik_y - directorCos_ij_y);
f_ik[2] = forceMod3B_factor1_ik * directorCos_ik_z +
forceMod3B_factor2_ik *
(cosTeta * directorCos_ik_z - directorCos_ij_z);
forceModCoord += (forceMod3B_factor2 *
(tauFunctionDerived - 0.5 * mu * cosTetaDiff));
f[j][0] += f_ij[0];
f[j][1] += f_ij[1];
f[j][2] += f_ij[2];
f[k][0] += f_ik[0];
f[k][1] += f_ik[1];
f[k][2] += f_ik[2];
f[i][0] -= f_ij[0] + f_ik[0];
f[i][1] -= f_ij[1] + f_ik[1];
f[i][2] -= f_ij[2] + f_ik[2];
// potential energy
evdwl = (exp3B_ij * exp3B_ik * potentia3B_factor);
if (evflag) ev_tally3(i,j,k,evdwl,0.0,f_ij,f_ik,dr_ij,dr_ik);
}
}
// forces due to environment coordination f(Z)
for (int idx = 0; idx < numForceCoordPairs; idx++) {
double dr_ij[3], f_ij[3];
preForceCoord_counter = idx * 5;
zeta_iDerivedInvR_ij=preForceCoord[preForceCoord_counter+0];
dr_ij[0]=preForceCoord[preForceCoord_counter+1];
dr_ij[1]=preForceCoord[preForceCoord_counter+2];
dr_ij[2]=preForceCoord[preForceCoord_counter+3];
j = static_cast<int> (preForceCoord[preForceCoord_counter+4]);
forceModCoord_ij = forceModCoord * zeta_iDerivedInvR_ij;
f_ij[0] = forceModCoord_ij * dr_ij[0];
f_ij[1] = forceModCoord_ij * dr_ij[1];
f_ij[2] = forceModCoord_ij * dr_ij[2];
f[j][0] -= f_ij[0];
f[j][1] -= f_ij[1];
f[j][2] -= f_ij[2];
f[i][0] += f_ij[0];
f[i][1] += f_ij[1];
f[i][2] += f_ij[2];
// potential energy
evdwl = 0.0;
if (evflag) ev_tally(i, j, nlocal, newton_pair, evdwl, 0.0,
forceModCoord_ij, dr_ij[0], dr_ij[1], dr_ij[2]);
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairEDIP::allocateGrids(void)
{
int numGridPointsOneCutoffFunction;
int numGridPointsNotOneCutoffFunction;
int numGridPointsCutoffFunction;
int numGridPointsR;
int numGridPointsRTotal;
int numGridPointsQFunctionGrid;
int numGridPointsExpMinusBetaZeta_iZeta_i;
int numGridPointsTauFunctionGrid;
double maxArgumentTauFunctionGrid;
double maxArgumentQFunctionGrid;
double maxArgumentExpMinusBetaZeta_iZeta_i;
double const leftLimitToZero = -DBL_MIN * 1000.0;
// tauFunctionGrid
maxArgumentTauFunctionGrid = leadDimInteractionList;
numGridPointsTauFunctionGrid = (int)
((maxArgumentTauFunctionGrid) * GRIDDENSITY) + 2;
memory->create(tauFunctionGrid,numGridPointsTauFunctionGrid,
"edip:tauFunctionGrid");
memory->create(tauFunctionDerivedGrid,numGridPointsTauFunctionGrid,
"edip:tauFunctionDerivedGrid");
// expMinusBetaZeta_iZeta_iGrid
maxArgumentExpMinusBetaZeta_iZeta_i = leadDimInteractionList;
numGridPointsExpMinusBetaZeta_iZeta_i = (int)
((maxArgumentExpMinusBetaZeta_iZeta_i) * GRIDDENSITY) + 2;
memory->create(expMinusBetaZeta_iZeta_iGrid,
numGridPointsExpMinusBetaZeta_iZeta_i,
"edip:expMinusBetaZeta_iZeta_iGrid");
// qFunctionGrid
maxArgumentQFunctionGrid = leadDimInteractionList;
numGridPointsQFunctionGrid = (int)
((maxArgumentQFunctionGrid) * GRIDDENSITY) + 2;
memory->create(qFunctionGrid,numGridPointsQFunctionGrid,"edip:qFunctionGrid");
// cutoffFunction
numGridPointsOneCutoffFunction = (int) ((cutoffC - GRIDSTART) * GRIDDENSITY);
numGridPointsNotOneCutoffFunction = (int) ((cutoffA-cutoffC) * GRIDDENSITY);
numGridPointsCutoffFunction = numGridPointsOneCutoffFunction +
numGridPointsNotOneCutoffFunction+2;
memory->create(cutoffFunction,numGridPointsCutoffFunction,
"edip:cutoffFunction");
memory->create(cutoffFunctionDerived,numGridPointsCutoffFunction,
"edip:cutoffFunctionDerived");
// pow2B
numGridPointsR = (int)
((cutoffA + leftLimitToZero - GRIDSTART) * GRIDDENSITY);
numGridPointsRTotal = numGridPointsR + 2;
memory->create(pow2B,numGridPointsRTotal,"edip:pow2B");
memory->create(exp2B,numGridPointsRTotal,"edip:exp2B");
memory->create(exp3B,numGridPointsRTotal,"edip:exp3B");
}
/* ----------------------------------------------------------------------
pre-calculated structures
------------------------------------------------------------------------- */
void PairEDIP::allocatePreLoops(void)
{
memory->create(preInvR_ij,leadDimInteractionList,"edip:preInvR_ij");
memory->create(preExp3B_ij,leadDimInteractionList,"edip:preExp3B_ij");
memory->create(preExp3BDerived_ij,leadDimInteractionList,
"edip:preExp3BDerived_ij");
memory->create(preExp2B_ij,leadDimInteractionList,"edip:preExp2B_ij");
memory->create(preExp2BDerived_ij,leadDimInteractionList,
"edip:preExp2BDerived_ij");
memory->create(prePow2B_ij,leadDimInteractionList,"edip:prePow2B_ij");
memory->create(preForceCoord,5*leadDimInteractionList,"edip:preForceCoord");
}
/* ----------------------------------------------------------------------
deallocate grids
------------------------------------------------------------------------- */
void PairEDIP::deallocateGrids(void)
{
memory->destroy(cutoffFunction);
memory->destroy(cutoffFunctionDerived);
memory->destroy(pow2B);
memory->destroy(exp2B);
memory->destroy(exp3B);
memory->destroy(qFunctionGrid);
memory->destroy(expMinusBetaZeta_iZeta_iGrid);
memory->destroy(tauFunctionGrid);
memory->destroy(tauFunctionDerivedGrid);
}
/* ----------------------------------------------------------------------
deallocate preLoops
------------------------------------------------------------------------- */
void PairEDIP::deallocatePreLoops(void)
{
memory->destroy(preInvR_ij);
memory->destroy(preExp3B_ij);
memory->destroy(preExp3BDerived_ij);
memory->destroy(preExp2B_ij);
memory->destroy(preExp2BDerived_ij);
memory->destroy(prePow2B_ij);
memory->destroy(preForceCoord);
}
/* ---------------------------------------------------------------------- */
void PairEDIP::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairEDIP::settings(int narg, char **arg)
{
- if (narg != 0) error->all("Illegal pair_style command");
+ if (narg != 0) error->all(FLERR,"Illegal pair_style command");
}
/* ---------------------------------------------------------------------- */
void PairEDIP::initGrids(void)
{
int l;
int numGridPointsOneCutoffFunction;
int numGridPointsNotOneCutoffFunction;
int numGridPointsCutoffFunction;
int numGridPointsR;
int numGridPointsRTotal;
int numGridPointsQFunctionGrid;
int numGridPointsExpMinusBetaZeta_iZeta_i;
int numGridPointsTauFunctionGrid;
double maxArgumentTauFunctionGrid;
double maxArgumentQFunctionGrid;
double maxArgumentExpMinusBetaZeta_iZeta_i;
double r;
double temp;
double temp3;
double temp4;
double deltaArgumentR;
double deltaArgumentCutoffFunction;
double deltaArgumentQFunctionGrid;
double deltaArgumentTauFunctionGrid;
double deltaArgumentExpMinusBetaZeta_iZeta_i;
double const leftLimitToZero = -DBL_MIN * 1000.0;
// tauFunctionGrid
maxArgumentTauFunctionGrid = leadDimInteractionList;
numGridPointsTauFunctionGrid = (int)
((maxArgumentTauFunctionGrid) * GRIDDENSITY) + 2;
r = 0.0;
deltaArgumentTauFunctionGrid = 1.0 / GRIDDENSITY;
for (l = 0; l < numGridPointsTauFunctionGrid; l++) {
tauFunctionGrid[l] = u1 + u2 * u3 * exp(-u4 * r) -
u2 * exp(-2.0 * u4 * r);
tauFunctionDerivedGrid[l] = - u2 * u3 * u4 * exp(-u4 * r) +
2.0 * u2 * u4 * exp(-2.0 * u4 * r);
r += deltaArgumentTauFunctionGrid;
}
// expMinusBetaZeta_iZeta_iGrid
maxArgumentExpMinusBetaZeta_iZeta_i = leadDimInteractionList;
numGridPointsExpMinusBetaZeta_iZeta_i = (int)
((maxArgumentExpMinusBetaZeta_iZeta_i) * GRIDDENSITY) + 2;
r = 0.0;
deltaArgumentExpMinusBetaZeta_iZeta_i = 1.0 / GRIDDENSITY;
for (l = 0; l < numGridPointsExpMinusBetaZeta_iZeta_i; l++) {
expMinusBetaZeta_iZeta_iGrid[l] = exp(-beta * r * r);
r += deltaArgumentExpMinusBetaZeta_iZeta_i;
}
// qFunctionGrid
maxArgumentQFunctionGrid = leadDimInteractionList;
numGridPointsQFunctionGrid =
(int) ((maxArgumentQFunctionGrid) * GRIDDENSITY) + 2;
r = 0.0;
deltaArgumentQFunctionGrid = 1.0 / GRIDDENSITY;
for (l = 0; l < numGridPointsQFunctionGrid; l++) {
qFunctionGrid[l] = Q0 * exp(-mu * r);
r += deltaArgumentQFunctionGrid;
}
// cutoffFunction
numGridPointsOneCutoffFunction =
(int) ((cutoffC - GRIDSTART) * GRIDDENSITY);
numGridPointsNotOneCutoffFunction =
(int) ((cutoffA-cutoffC) * GRIDDENSITY);
numGridPointsCutoffFunction =
numGridPointsOneCutoffFunction+numGridPointsNotOneCutoffFunction+2;
r = GRIDSTART;
deltaArgumentCutoffFunction = 1.0 / GRIDDENSITY;
for (l = 0; l < numGridPointsOneCutoffFunction; l++) {
cutoffFunction[l] = 1.0;
cutoffFunctionDerived[l] = 0.0;
r += deltaArgumentCutoffFunction;
}
for (l = numGridPointsOneCutoffFunction;
l < numGridPointsCutoffFunction; l++) {
temp = (cutoffA - cutoffC)/(r - cutoffC);
temp3 = temp * temp * temp;
temp4 = temp3 * temp;
cutoffFunction[l] = exp(alpha/(1.0-temp3));
cutoffFunctionDerived[l] = (-3*alpha/(cutoffA-cutoffC)) *
(temp4/((1-temp3)*(1-temp3)))*exp(alpha/(1.0-temp3));
r += deltaArgumentCutoffFunction;
}
// pow2B
numGridPointsR = (int)
((cutoffA + leftLimitToZero - GRIDSTART) * GRIDDENSITY);
numGridPointsRTotal = numGridPointsR + 2;
r = GRIDSTART;
deltaArgumentR = 1.0 / GRIDDENSITY;
for (l = 0; l < numGridPointsR; l++) {
pow2B[l] = pow((B/r),rho);
exp2B[l] = A * exp(sigma/(r-cutoffA));
exp3B[l] = exp(gamm/(r-cutoffA));
r += deltaArgumentR;
}
pow2B[numGridPointsR] = pow((B/r),rho);
exp2B[numGridPointsR]=0;
exp3B[numGridPointsR]=0;
r += deltaArgumentR;
pow2B[numGridPointsR+1] = pow((B/r),rho);
exp2B[numGridPointsR+1]=0;
exp3B[numGridPointsR+1]=0;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairEDIP::coeff(int narg, char **arg)
{
int i,j,n;
if (!allocated) allocate();
if (narg != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// 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;
}
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++;
}
}
// read potential file and initialize potential parameters
read_file(arg[2]);
setup();
// 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;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
if (map[i] >= 0 && map[j] >= 0) {
setflag[i][j] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
// allocate tables and internal structures
allocatePreLoops();
allocateGrids();
initGrids();
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairEDIP::init_style()
{
if (atom->tag_enable == 0)
- error->all("Pair style EDIP requires atom IDs");
+ error->all(FLERR,"Pair style EDIP requires atom IDs");
if (force->newton_pair == 0)
- error->all("Pair style EDIP requires newton pair on");
+ error->all(FLERR,"Pair style EDIP requires newton pair on");
// need a full neighbor list
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairEDIP::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
return cutmax;
}
/* ---------------------------------------------------------------------- */
void PairEDIP::read_file(char *file)
{
int params_per_line = 20;
char **words = new char*[params_per_line+1];
memory->sfree(params);
params = NULL;
nparams = maxparam = 0;
// open file on proc 0
FILE *fp;
if (comm->me == 0) {
fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open EDIP potential file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
// read each set of params from potential file
// one set of params can span multiple lines
// store params if all 3 element tags are in element list
int n,nwords,ielement,jelement,kelement;
char line[MAXLINE],*ptr;
int eof = 0;
while (1) {
if (comm->me == 0) {
ptr = fgets(line,MAXLINE,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
// strip comment, skip line if blank
if ((ptr = strchr(line,'#'))) *ptr = '\0';
nwords = atom->count_words(line);
if (nwords == 0) continue;
// concatenate additional lines until have params_per_line words
while (nwords < params_per_line) {
n = strlen(line);
if (comm->me == 0) {
ptr = fgets(&line[n],MAXLINE-n,fp);
if (ptr == NULL) {
eof = 1;
fclose(fp);
} else n = strlen(line) + 1;
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) break;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
if ((ptr = strchr(line,'#'))) *ptr = '\0';
nwords = atom->count_words(line);
}
if (nwords != params_per_line)
- error->all("Incorrect format in EDIP potential file");
+ error->all(FLERR,"Incorrect format in EDIP potential file");
// words = ptrs to all words in line
nwords = 0;
words[nwords++] = strtok(line," \t\n\r\f");
while ((words[nwords++] = strtok(NULL," \t\n\r\f"))) continue;
// ielement,jelement,kelement = 1st args
// if all 3 args are in element list, then parse this line
// else skip to next entry in file
for (ielement = 0; ielement < nelements; ielement++)
if (strcmp(words[0],elements[ielement]) == 0) break;
if (ielement == nelements) continue;
for (jelement = 0; jelement < nelements; jelement++)
if (strcmp(words[1],elements[jelement]) == 0) break;
if (jelement == nelements) continue;
for (kelement = 0; kelement < nelements; kelement++)
if (strcmp(words[2],elements[kelement]) == 0) break;
if (kelement == nelements) continue;
// load up parameter settings and error check their values
if (nparams == maxparam) {
maxparam += DELTA;
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
"pair:params");
}
params[nparams].ielement = ielement;
params[nparams].jelement = jelement;
params[nparams].kelement = kelement;
params[nparams].A = atof(words[3]);
params[nparams].B = atof(words[4]);
params[nparams].cutoffA = atof(words[5]);
params[nparams].cutoffC = atof(words[6]);
params[nparams].alpha = atof(words[7]);
params[nparams].beta = atof(words[8]);
params[nparams].eta = atof(words[9]);
params[nparams].gamm = atof(words[10]);
params[nparams].lambda = atof(words[11]);
params[nparams].mu = atof(words[12]);
params[nparams].rho = atof(words[13]);
params[nparams].sigma = atof(words[14]);
params[nparams].Q0 = atof(words[15]);
params[nparams].u1 = atof(words[16]);
params[nparams].u2 = atof(words[17]);
params[nparams].u3 = atof(words[18]);
params[nparams].u4 = atof(words[19]);
if (params[nparams].A < 0.0 || params[nparams].B < 0.0 ||
params[nparams].cutoffA < 0.0 || params[nparams].cutoffC < 0.0 ||
params[nparams].alpha < 0.0 || params[nparams].beta < 0.0 ||
params[nparams].eta < 0.0 || params[nparams].gamm < 0.0 ||
params[nparams].lambda < 0.0 || params[nparams].mu < 0.0 ||
params[nparams].rho < 0.0 || params[nparams].sigma < 0.0)
- error->all("Illegal EDIP parameter");
+ error->all(FLERR,"Illegal EDIP parameter");
nparams++;
}
delete [] words;
}
/* ---------------------------------------------------------------------- */
void PairEDIP::setup()
{
int i,j,k,m,n;
double rtmp;
// set elem2param for all triplet combinations
// must be a single exact match to lines read from file
// do not allow for ACB in place of ABC
memory->destroy(elem2param);
memory->create(elem2param,nelements,nelements,nelements,"pair:elem2param");
for (i = 0; i < nelements; i++)
for (j = 0; j < nelements; j++)
for (k = 0; k < nelements; k++) {
n = -1;
for (m = 0; m < nparams; m++) {
if (i == params[m].ielement && j == params[m].jelement &&
k == params[m].kelement) {
- if (n >= 0) error->all("Potential file has duplicate entry");
+ if (n >= 0) error->all(FLERR,"Potential file has duplicate entry");
n = m;
}
}
- if (n < 0) error->all("Potential file is missing an entry");
+ if (n < 0) error->all(FLERR,"Potential file is missing an entry");
elem2param[i][j][k] = n;
}
// set cutoff square
for (m = 0; m < nparams; m++) {
params[m].cutsq = params[m].cutoffA*params[m].cutoffA;
}
// set cutmax to max of all params
cutmax = 0.0;
for (m = 0; m < nparams; m++) {
rtmp = sqrt(params[m].cutsq);
if (rtmp > cutmax) cutmax = rtmp;
}
// this should be removed for multi species parametrizations
A = params[0].A;
B = params[0].B;
rho = params[0].rho;
cutoffA = params[0].cutoffA;
cutoffC = params[0].cutoffC;
sigma = params[0].sigma;
lambda = params[0].lambda;
gamm = params[0].gamm;
eta = params[0].eta;
Q0 = params[0].Q0;
mu = params[0].mu;
beta = params[0].beta;
alpha = params[0].alpha;
u1 = params[0].u1;
u2 = params[0].u2;
u3 = params[0].u3;
u4 = params[0].u4;
}
diff --git a/src/USER-MISC/pair_lj_sf.cpp b/src/USER-MISC/pair_lj_sf.cpp
index b4a278188..633b8be2e 100644
--- a/src/USER-MISC/pair_lj_sf.cpp
+++ b/src/USER-MISC/pair_lj_sf.cpp
@@ -1,358 +1,355 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Laurent Joly (U Lyon), ljoly.ulyon@gmail.com
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_sf.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJShiftedForce::PairLJShiftedForce(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJShiftedForce::~PairLJShiftedForce()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(foffset);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJShiftedForce::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
double r,t;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
if (j < nall) factor_lj = 1.0;
else {
factor_lj = special_lj[j/nall];
j %= nall;
}
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
t = r/cut[itype][jtype];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]) -
t*foffset[itype][jtype];
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) +
(t-1.0)*foffset[itype][jtype] - offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJShiftedForce::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj3,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(foffset,n+1,n+1,"pair:foffset");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJShiftedForce::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
if (cut_global <= 0.0)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJShiftedForce::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_one = cut_global;
if (narg == 5) cut_one = force->numeric(arg[4]);
if (cut_one <= 0.0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJShiftedForce::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
double ratio = sigma[i][j] / cut[i][j];
foffset[i][j] = 4.0 * epsilon[i][j] * (12.0 * pow(ratio,12.0) -
6.0 * pow(ratio,6.0));
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
cut[j][i] = cut[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
foffset[j][i] = foffset[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJShiftedForce::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJShiftedForce::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJShiftedForce::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJShiftedForce::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJShiftedForce::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcelj,philj,r,t;
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
t = r/cut[itype][jtype];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]) -
t*foffset[itype][jtype];
fforce = factor_lj*forcelj*r2inv;
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) +
(t-1.0)*foffset[itype][jtype] - offset[itype][jtype];
return factor_lj*philj;
}
diff --git a/src/USER-REAXC/fix_qeq_reax.cpp b/src/USER-REAXC/fix_qeq_reax.cpp
index 0c7784aad..b68da226f 100644
--- a/src/USER-REAXC/fix_qeq_reax.cpp
+++ b/src/USER-REAXC/fix_qeq_reax.cpp
@@ -1,870 +1,867 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Hasan Metin Aktulga, Purdue University
(now at Lawrence Berkeley National Laboratory, hmaktulga@lbl.gov)
Please cite the related publication:
H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama,
"Parallel Reactive Molecular Dynamics: Numerical Methods and
Algorithmic Techniques", Parallel Computing, in press.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fix_qeq_reax.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define EV_TO_KCAL_PER_MOL 14.4
#define SAFE_ZONE 1.2
#define DANGER_ZONE 0.95
#define LOOSE_ZONE 0.7
#define SQR(x) ((x)*(x))
#define CUBE(x) ((x)*(x)*(x))
#define MIN_CAP 50
#define MIN_NBRS 100
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixQEqReax::FixQEqReax(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 8) error->all("Illegal fix qeq/reax command");
+ if (narg != 8) error->all(FLERR,"Illegal fix qeq/reax command");
nevery = atoi(arg[3]);
swa = atof(arg[4]);
swb = atof(arg[5]);
tolerance = atof(arg[6]);
pertype_parameters(arg[7]);
shld = NULL;
n = n_cap = 0;
N = nmax = 0;
m_fill = m_cap = 0;
pack_flag = 0;
s = NULL;
t = NULL;
nprev = 5;
Hdia_inv = NULL;
b_s = NULL;
b_t = NULL;
b_prc = NULL;
b_prm = NULL;
// CG
p = NULL;
q = NULL;
r = NULL;
d = NULL;
// GMRES
//g = NULL;
//y = NULL;
//hstr = NULL;
//v = NULL;
//h = NULL;
//hc = NULL;
//hs = NULL;
// perform initial allocation of atom-based arrays
// register with Atom class
s_hist = t_hist = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
for( int i = 0; i < atom->nmax; i++ )
for (int j = 0; j < nprev; ++j )
s_hist[i][j] = t_hist[i][j] = 0;
}
/* ---------------------------------------------------------------------- */
FixQEqReax::~FixQEqReax()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
memory->destroy(s_hist);
memory->destroy(t_hist);
deallocate_storage();
deallocate_matrix();
memory->destroy(shld);
if (!reaxflag) {
memory->destroy(chi);
memory->destroy(eta);
memory->destroy(gamma);
}
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::setmask()
{
int mask = 0;
mask |= PRE_FORCE;
mask |= MIN_PRE_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::pertype_parameters(char *arg)
{
if (strcmp(arg,"reax/c") == 0) {
reaxflag = 1;
Pair *pair = force->pair_match("reax/c",1);
- if (pair == NULL) error->all("No pair reax/c for fix qeq/reax");
+ if (pair == NULL) error->all(FLERR,"No pair reax/c for fix qeq/reax");
int tmp;
chi = (double *) pair->extract("chi",tmp);
eta = (double *) pair->extract("eta",tmp);
gamma = (double *) pair->extract("gamma",tmp);
if (chi == NULL || eta == NULL || gamma == NULL)
- error->all("Fix qeq/reax could not extract params from pair reax/c");
+ error->all(FLERR,"Fix qeq/reax could not extract params from pair reax/c");
return;
}
int i,itype,ntypes;
double v1,v2,v3;
FILE *pf;
reaxflag = 0;
ntypes = atom->ntypes;
memory->create(chi,ntypes+1,"qeq/reax:chi");
memory->create(eta,ntypes+1,"qeq/reax:eta");
memory->create(gamma,ntypes+1,"qeq/reax:gamma");
if (comm->me == 0) {
if ((pf = fopen(arg,"r")) == NULL)
- error->one("Fix qeq/reax parameter file could not be found");
+ error->one(FLERR,"Fix qeq/reax parameter file could not be found");
for (i = 1; i <= ntypes && !feof(pf); i++) {
fscanf(pf,"%d %lg %lg %lg",&itype,&v1,&v2,&v3);
if (itype < 1 || itype > ntypes)
- error->one("Fix qeq/reax invalid atom type in param file");
+ error->one(FLERR,"Fix qeq/reax invalid atom type in param file");
chi[itype] = v1;
eta[itype] = v2;
gamma[itype] = v3;
}
- if (i <= ntypes) error->one("Invalid param file for fix qeq/reax");
+ if (i <= ntypes) error->one(FLERR,"Invalid param file for fix qeq/reax");
fclose(pf);
}
MPI_Bcast(&chi[1],ntypes,MPI_DOUBLE,0,world);
MPI_Bcast(&eta[1],ntypes,MPI_DOUBLE,0,world);
MPI_Bcast(&gamma[1],ntypes,MPI_DOUBLE,0,world);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::allocate_storage()
{
nmax = atom->nmax;
memory->create(s,nmax,"qeq:s");
memory->create(t,nmax,"qeq:t");
memory->create(Hdia_inv,nmax,"qeq:Hdia_inv");
memory->create(b_s,nmax,"qeq:b_s");
memory->create(b_t,nmax,"qeq:b_t");
memory->create(b_prc,nmax,"qeq:b_prc");
memory->create(b_prm,nmax,"qeq:b_prm");
memory->create(p,nmax,"qeq:p");
memory->create(q,nmax,"qeq:q");
memory->create(r,nmax,"qeq:r");
memory->create(d,nmax,"qeq:d");
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::deallocate_storage()
{
memory->destroy(s);
memory->destroy(t);
memory->destroy( Hdia_inv );
memory->destroy( b_s );
memory->destroy( b_t );
memory->destroy( b_prc );
memory->destroy( b_prm );
memory->destroy( p );
memory->destroy( q );
memory->destroy( r );
memory->destroy( d );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::reallocate_storage()
{
deallocate_storage();
allocate_storage();
init_storage();
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::allocate_matrix()
{
int i,ii;
n = atom->nlocal;
n_cap = MAX( (int)(n * SAFE_ZONE), MIN_CAP );
// determine the total space for the H matrix
int m = 0;
for( ii = 0; ii < list->inum; ii++ ) {
i = list->ilist[ii];
m += list->numneigh[i];
}
m_cap = MAX( (int)(m * SAFE_ZONE), MIN_CAP * MIN_NBRS );
H.n = n_cap;
H.m = m_cap;
memory->create(H.firstnbr,n_cap,"qeq:H.firstnbr");
memory->create(H.numnbrs,n_cap,"qeq:H.numnbrs");
memory->create(H.jlist,m_cap,"qeq:H.jlist");
memory->create(H.val,m_cap,"qeq:H.val");
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::deallocate_matrix()
{
memory->destroy( H.firstnbr );
memory->destroy( H.numnbrs );
memory->destroy( H.jlist );
memory->destroy( H.val );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::reallocate_matrix()
{
deallocate_matrix();
allocate_matrix();
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init()
{
- if (!atom->q_flag) error->all("Fix qeq/reax requires atom attribute q");
+ if (!atom->q_flag) error->all(FLERR,"Fix qeq/reax requires atom attribute q");
// need a half neighbor list w/ Newton off
// built whenever re-neighboring occurs
int irequest = neighbor->request(this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
neighbor->requests[irequest]->newton = 2;
init_shielding();
init_taper();
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_shielding()
{
int i,j;
int ntypes;
ntypes = atom->ntypes;
memory->create(shld,ntypes+1,ntypes+1,"qeq:shileding");
for( i = 1; i <= ntypes; ++i )
for( j = 1; j <= ntypes; ++j )
shld[i][j] = pow( gamma[i] * gamma[j], -1.5 );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_taper()
{
double d7, swa2, swa3, swb2, swb3;
if (fabs(swa) > 0.01 && comm->me == 0)
- error->warning("Fix qeq/reax has non-zero lower Taper radius cutoff");
+ error->warning(FLERR,"Fix qeq/reax has non-zero lower Taper radius cutoff");
if (swb < 0)
- error->all( "Fix qeq/reax has negative upper Taper radius cutoff");
+ error->all(FLERR, "Fix qeq/reax has negative upper Taper radius cutoff");
else if (swb < 5 && comm->me == 0)
- error->warning("Fix qeq/reax has very low Taper radius cutoff");
+ error->warning(FLERR,"Fix qeq/reax has very low Taper radius cutoff");
d7 = pow( swb - swa, 7 );
swa2 = SQR( swa );
swa3 = CUBE( swa );
swb2 = SQR( swb );
swb3 = CUBE( swb );
Tap[7] = 20.0 / d7;
Tap[6] = -70.0 * (swa + swb) / d7;
Tap[5] = 84.0 * (swa2 + 3.0*swa*swb + swb2) / d7;
Tap[4] = -35.0 * (swa3 + 9.0*swa2*swb + 9.0*swa*swb2 + swb3 ) / d7;
Tap[3] = 140.0 * (swa3*swb + 3.0*swa2*swb2 + swa*swb3 ) / d7;
Tap[2] =-210.0 * (swa3*swb2 + swa2*swb3) / d7;
Tap[1] = 140.0 * swa3 * swb3 / d7;
Tap[0] = (-35.0*swa3*swb2*swb2 + 21.0*swa2*swb3*swb2 +
7.0*swa*swb3*swb3 + swb3*swb3*swb ) / d7;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::setup_pre_force(int vflag)
{
neighbor->build_one(list->index);
allocate_storage();
init_storage();
allocate_matrix();
pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::setup_pre_force_respa(int vflag, int ilevel)
{
if (ilevel < nlevels_respa-1) return;
setup_pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::min_setup_pre_force(int vflag)
{
setup_pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_storage()
{
N = atom->nlocal + atom->nghost;
for( int i = 0; i < N; i++ ) {
Hdia_inv[i] = 1. / eta[atom->type[i]];
b_s[i] = -chi[atom->type[i]];
b_t[i] = -1.0;
b_prc[i] = 0;
b_prm[i] = 0;
s[i] = t[i] = 0;
}
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::pre_force(int vflag)
{
double t_start, t_end;
if (update->ntimestep % nevery) return;
if( comm->me == 0 ) t_start = MPI_Wtime();
n = atom->nlocal;
N = atom->nlocal + atom->nghost;
// grow arrays if necessary
// need to be atom->nmax in length
if( atom->nmax > nmax ) reallocate_storage();
if( n > n_cap*DANGER_ZONE || m_fill > m_cap*DANGER_ZONE )
reallocate_matrix();
init_matvec();
matvecs = CG(b_s, s); // CG on s - parallel
matvecs += CG(b_t, t); // CG on t - parallel
calculate_Q();
if( comm->me == 0 ) {
t_end = MPI_Wtime();
qeq_time = t_end - t_start;
}
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::pre_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::min_pre_force(int vflag)
{
pre_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::init_matvec()
{
/* fill-in H matrix */
compute_H();
for( int i = 0; i < n; ++i ) {
/* init pre-conditioner for H and init solution vectors */
Hdia_inv[i] = 1. / eta[ atom->type[i] ];
b_s[i] = -chi[ atom->type[i] ];
b_t[i] = -1.0;
/* linear extrapolation for s & t from previous solutions */
//s[i] = 2 * s_hist[i][0] - s_hist[i][1];
//t[i] = 2 * t_hist[i][0] - t_hist[i][1];
/* quadratic extrapolation for s & t from previous solutions */
//s[i] = s_hist[i][2] + 3 * ( s_hist[i][0] - s_hist[i][1] );
t[i] = t_hist[i][2] + 3 * ( t_hist[i][0] - t_hist[i][1] );
/* cubic extrapolation for s & t from previous solutions */
s[i] = 4*(s_hist[i][0]+s_hist[i][2])-(6*s_hist[i][1]+s_hist[i][3]);
//t[i] = 4*(t_hist[i][0]+t_hist[i][2])-(6*t_hist[i][1]+t_hist[i][3]);
}
pack_flag = 2;
comm->forward_comm_fix(this); //Dist_vector( s );
pack_flag = 3;
comm->forward_comm_fix(this); //Dist_vector( t );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::compute_H()
{
int inum, jnum, *ilist, *jlist, *numneigh, **firstneigh;
int i, j, ii, jj, temp, newnbr, flag;
int *type, *tag;
double **x, SMALL = 0.0001;
double dx, dy, dz, r_sqr;
type = atom->type;
tag = atom->tag;
x = atom->x;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// fill in the H matrix
m_fill = 0;
r_sqr = 0;
for( ii = 0; ii < inum; ii++ ) {
i = ilist[ii];
jlist = firstneigh[i];
jnum = numneigh[i];
H.firstnbr[i] = m_fill;
for( jj = 0; jj < jnum; jj++ ) {
j = jlist[jj];
dx = x[j][0] - x[i][0];
dy = x[j][1] - x[i][1];
dz = x[j][2] - x[i][2];
r_sqr = SQR(dx) + SQR(dy) + SQR(dz);
flag = 0;
if (r_sqr <= SQR(swb)) {
if (j < n) flag = 1;
else if (tag[i] < tag[j]) flag = 1;
else if (tag[i] == tag[j]) {
if (dz > SMALL) flag = 1;
else if (fabs(dz) < SMALL) {
if (dy > SMALL) flag = 1;
else if (fabs(dy) < SMALL && dx > SMALL)
flag = 1;
}
}
}
if( flag ) {
H.jlist[m_fill] = j;
H.val[m_fill] = calculate_H( sqrt(r_sqr), shld[type[i]][type[j]] );
m_fill++;
}
}
H.numnbrs[i] = m_fill - H.firstnbr[i];
}
if (m_fill >= H.m) {
char str[128];
sprintf(str,"H matrix size has been exceeded: m_fill=%d H.m=%d\n",
m_fill, H.m );
- error->warning(str);
- error->all("Fix qeq/reax has insufficient QEq matrix size");
+ error->warning(FLERR,str);
+ error->all(FLERR,"Fix qeq/reax has insufficient QEq matrix size");
}
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::calculate_H( double r, double gamma )
{
double Taper, denom;
Taper = Tap[7] * r + Tap[6];
Taper = Taper * r + Tap[5];
Taper = Taper * r + Tap[4];
Taper = Taper * r + Tap[3];
Taper = Taper * r + Tap[2];
Taper = Taper * r + Tap[1];
Taper = Taper * r + Tap[0];
denom = r * r * r + gamma;
denom = pow(denom,0.3333333333333);
return Taper * EV_TO_KCAL_PER_MOL / denom;
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::CG( double *b, double *x )
{
int i, j;
double tmp, alpha, beta, b_norm;
double sig_old, sig_new, sig0;
pack_flag = 1;
sparse_matvec( &H, x, q );
comm->reverse_comm_fix( this ); //Coll_Vector( q );
vector_sum( r , 1., b, -1., q, n );
for( j = 0; j < n; ++j )
d[j] = r[j] * Hdia_inv[j]; //pre-condition
b_norm = parallel_norm( b, n );
sig_new = parallel_dot( r, d, n );
sig0 = sig_new;
for( i = 1; i < 100 && sqrt(sig_new) / b_norm > tolerance; ++i ) {
comm->forward_comm_fix(this); //Dist_vector( d );
sparse_matvec( &H, d, q );
comm->reverse_comm_fix(this); //Coll_vector( q );
tmp = parallel_dot( d, q, n );
alpha = sig_new / tmp;
// comm->me, i, parallel_norm( d, n ), parallel_norm( q, n ), tmp );
vector_add( x, alpha, d, n );
vector_add( r, -alpha, q, n );
// pre-conditioning
for( j = 0; j < n; ++j )
p[j] = r[j] * Hdia_inv[j];
sig_old = sig_new;
sig_new = parallel_dot( r, p, n );
beta = sig_new / sig_old;
vector_sum( d, 1., p, beta, d, n );
}
if (i >= 100 && comm->me == 0)
- error->warning("Fix qeq/reax CG convergence failed");
+ error->warning(FLERR,"Fix qeq/reax CG convergence failed");
return i;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::sparse_matvec( sparse_matrix *A, double *x, double *b )
{
int i, j, itr_j;
for( i = 0; i < n; ++i )
b[i] = eta[ atom->type[i] ] * x[i];
for( i = n; i < N; ++i )
b[i] = 0;
for( i = 0; i < n; ++i ) {
for( itr_j=A->firstnbr[i]; itr_j<A->firstnbr[i]+A->numnbrs[i]; itr_j++) {
j = A->jlist[itr_j];
b[i] += A->val[itr_j] * x[j];
b[j] += A->val[itr_j] * x[i];
}
}
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::calculate_Q()
{
int i, k;
double u, s_sum, t_sum;
double *q = atom->q;
s_sum = parallel_vector_acc( s, n );
t_sum = parallel_vector_acc( t, n);
u = s_sum / t_sum;
for( i = 0; i < n; ++i ) {
q[i] = s[i] - u * t[i];
/* backup s & t */
for( k = 4; k > 0; --k ) {
s_hist[i][k] = s_hist[i][k-1];
t_hist[i][k] = t_hist[i][k-1];
}
s_hist[i][0] = s[i];
t_hist[i][0] = t[i];
}
pack_flag = 4;
comm->forward_comm_fix( this ); //Dist_vector( atom->q );
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int m;
if( pack_flag == 1)
for(m = 0; m < n; m++) buf[m] = d[list[m]];
else if( pack_flag == 2 )
for(m = 0; m < n; m++) buf[m] = s[list[m]];
else if( pack_flag == 3 )
for(m = 0; m < n; m++) buf[m] = t[list[m]];
else if( pack_flag == 4 )
for(m = 0; m < n; m++) buf[m] = atom->q[list[m]];
return 1;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::unpack_comm(int n, int first, double *buf)
{
int i, m;
if( pack_flag == 1)
for(m = 0, i = first; m < n; m++, i++) d[i] = buf[m];
else if( pack_flag == 2)
for(m = 0, i = first; m < n; m++, i++) s[i] = buf[m];
else if( pack_flag == 3)
for(m = 0, i = first; m < n; m++, i++) t[i] = buf[m];
else if( pack_flag == 4)
for(m = 0, i = first; m < n; m++, i++) atom->q[i] = buf[m];
}
/* ---------------------------------------------------------------------- */
int FixQEqReax::pack_reverse_comm(int n, int first, double *buf)
{
int i, m;
for(m = 0, i = first; m < n; m++, i++) buf[m] = q[i];
return 1;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::unpack_reverse_comm(int n, int *list, double *buf)
{
for(int m = 0; m < n; m++) q[list[m]] += buf[m];
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixQEqReax::memory_usage()
{
double bytes;
bytes = atom->nmax*nprev*2 * sizeof(double); // s_hist & t_hist
bytes += atom->nmax*11 * sizeof(double); // storage
bytes += n_cap*2 * sizeof(int); // matrix...
bytes += m_cap * sizeof(int);
bytes += m_cap * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate fictitious charge arrays
------------------------------------------------------------------------- */
void FixQEqReax::grow_arrays(int nmax)
{
memory->grow(s_hist,nmax,nprev,"qeq:s_hist");
memory->grow(t_hist,nmax,nprev,"qeq:t_hist");
}
/* ----------------------------------------------------------------------
copy values within fictitious charge arrays
------------------------------------------------------------------------- */
void FixQEqReax::copy_arrays(int i, int j)
{
for (int m = 0; m < nprev; m++) {
s_hist[j][m] = s_hist[i][m];
t_hist[j][m] = t_hist[i][m];
}
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixQEqReax::pack_exchange(int i, double *buf)
{
for (int m = 0; m < nprev; m++) buf[m] = s_hist[i][m];
for (int m = 0; m < nprev; m++) buf[nprev+m] = t_hist[i][m];
return nprev*2;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixQEqReax::unpack_exchange(int nlocal, double *buf)
{
for (int m = 0; m < nprev; m++) s_hist[nlocal][m] = buf[m];
for (int m = 0; m < nprev; m++) t_hist[nlocal][m] = buf[nprev+m];
return nprev*2;
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::parallel_norm( double *v, int n )
{
int i;
double my_sum, norm_sqr;
my_sum = 0;
for( i = 0; i < n; ++i )
my_sum += SQR( v[i] );
MPI_Allreduce( &my_sum, &norm_sqr, 1, MPI_DOUBLE, MPI_SUM, world );
return sqrt( norm_sqr );
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::parallel_dot( double *v1, double *v2, int n )
{
int i;
double my_dot, res;
my_dot = 0;
res = 0;
for( i = 0; i < n; ++i )
my_dot += v1[i] * v2[i];
MPI_Allreduce( &my_dot, &res, 1, MPI_DOUBLE, MPI_SUM, world );
return res;
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::parallel_vector_acc( double *v, int n )
{
int i;
double my_acc, res;
my_acc = 0;
for( i = 0; i < n; ++i )
my_acc += v[i];
MPI_Allreduce( &my_acc, &res, 1, MPI_DOUBLE, MPI_SUM, world );
return res;
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::norm( double* v1, int k )
{
double ret = 0;
for( --k; k>=0; --k )
ret += ( v1[k] * v1[k] );
return sqrt( ret );
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::vector_sum( double* dest, double c, double* v,
double d, double* y, int k )
{
for( --k; k>=0; --k )
dest[k] = c * v[k] + d * y[k];
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::vector_scale( double* dest, double c, double* v, int k )
{
for( --k; k>=0; --k )
dest[k] = c * v[k];
}
/* ---------------------------------------------------------------------- */
double FixQEqReax::dot( double* v1, double* v2, int k )
{
double ret = 0;
for( --k; k>=0; --k )
ret += v1[k] * v2[k];
return ret;
}
/* ---------------------------------------------------------------------- */
void FixQEqReax::vector_add( double* dest, double c, double* v, int k )
{
for( --k; k>=0; --k )
dest[k] += c * v[k];
}
diff --git a/src/USER-REAXC/pair_reax_c.cpp b/src/USER-REAXC/pair_reax_c.cpp
index 023dc2db3..96bdb293e 100644
--- a/src/USER-REAXC/pair_reax_c.cpp
+++ b/src/USER-REAXC/pair_reax_c.cpp
@@ -1,768 +1,768 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Hasan Metin Aktulga, Purdue University
(now at Lawrence Berkeley National Laboratory, hmaktulga@lbl.gov)
Please cite the related publication:
H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama,
"Parallel Reactive Molecular Dynamics: Numerical Methods and
Algorithmic Techniques", Parallel Computing, in press.
------------------------------------------------------------------------- */
#include "pair_reax_c.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "comm.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "modify.h"
#include "fix.h"
#include "fix_reax_c.h"
#include "memory.h"
#include "error.h"
#include "reaxc_types.h"
#include "reaxc_allocate.h"
#include "reaxc_control.h"
#include "reaxc_ffield.h"
#include "reaxc_forces.h"
#include "reaxc_init_md.h"
#include "reaxc_io_tools.h"
#include "reaxc_list.h"
#include "reaxc_lookup.h"
#include "reaxc_reset_tools.h"
#include "reaxc_traj.h"
#include "reaxc_vector.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairReaxC::PairReaxC(LAMMPS *lmp) : Pair(lmp)
{
system = (reax_system *)
memory->smalloc(sizeof(reax_system),"reax:system");
control = (control_params *)
memory->smalloc(sizeof(control_params),"reax:control");
data = (simulation_data *)
memory->smalloc(sizeof(simulation_data),"reax:data");
workspace = (storage *)
memory->smalloc(sizeof(storage),"reax:storage");
lists = (reax_list *)
memory->smalloc(LIST_N * sizeof(reax_list),"reax:lists");
out_control = (output_controls *)
memory->smalloc(sizeof(output_controls),"reax:out_control");
mpi_data = (mpi_datatypes *)
memory->smalloc(sizeof(mpi_datatypes),"reax:mpi");
MPI_Comm_rank(world,&system->my_rank);
system->my_coords[0] = 0;
system->my_coords[1] = 0;
system->my_coords[2] = 0;
system->num_nbrs = 0;
system->n = 0; // my atoms
system->N = 0; // mine + ghosts
system->bigN = 0; // all atoms in the system
system->local_cap = 0;
system->total_cap = 0;
system->gcell_cap = 0;
system->bndry_cuts.ghost_nonb = 0;
system->bndry_cuts.ghost_hbond = 0;
system->bndry_cuts.ghost_bond = 0;
system->bndry_cuts.ghost_cutoff = 0;
system->my_atoms = NULL;
fix_reax = NULL;
nextra = 14;
pvector = new double[nextra];
setup_flag = 0;
}
/* ---------------------------------------------------------------------- */
PairReaxC::~PairReaxC()
{
if (fix_reax) modify->delete_fix("REAXC");
Close_Output_Files( system, control, out_control, mpi_data );
// deallocate reax data-structures
if( control->tabulate ) Deallocate_Lookup_Tables( system );
if( control->hbond_cut > 0 ) Delete_List( lists+HBONDS, world );
Delete_List( lists+BONDS, world );
Delete_List( lists+THREE_BODIES, world );
Delete_List( lists+FAR_NBRS, world );
// fprintf( stderr, "3\n" );
DeAllocate_Workspace( control, workspace );
DeAllocate_System( system );
//fprintf( stderr, "4\n" );
memory->destroy( system );
memory->destroy( control );
memory->destroy( data );
memory->destroy( workspace );
memory->destroy( lists );
memory->destroy( out_control );
memory->destroy( mpi_data );
//fprintf( stderr, "5\n" );
// deallocate interface storage
if( allocated ) {
memory->destroy(setflag);
memory->destroy(cutsq);
delete [] map;
delete [] chi;
delete [] eta;
delete [] gamma;
}
delete [] pvector;
//fprintf( stderr, "6\n" );
}
/* ---------------------------------------------------------------------- */
void PairReaxC::allocate( )
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
memory->create(cutsq,n+1,n+1,"pair:cutsq");
map = new int[n+1];
chi = new double[n+1];
eta = new double[n+1];
gamma = new double[n+1];
}
/* ---------------------------------------------------------------------- */
void PairReaxC::settings(int narg, char **arg)
{
- if (narg != 1 && narg != 3) error->all("Illegal pair_style command");
+ if (narg != 1 && narg != 3) error->all(FLERR,"Illegal pair_style command");
// read name of control file or use default controls
if (strcmp(arg[0],"NULL") == 0) {
strcpy( control->sim_name, "simulate" );
control->ensemble = 0;
out_control->energy_update_freq = 0;
control->tabulate = 0;
control->reneighbor = 1;
control->vlist_cut = control->nonb_cut;
control->bond_cut = 5.;
control->hbond_cut = 7.50;
control->thb_cut = 0.001;
out_control->write_steps = 0;
out_control->traj_method = 0;
strcpy( out_control->traj_title, "default_title" );
out_control->atom_info = 0;
out_control->bond_info = 0;
out_control->angle_info = 0;
} else Read_Control_File(arg[0], control, out_control);
// default values
qeqflag = 1;
// process optional keywords
int iarg = 1;
while (iarg < narg) {
if (strcmp(arg[iarg],"checkqeq") == 0) {
- if (iarg+2 > narg) error->all("Illegal pair_style reax/c command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reax/c command");
if (strcmp(arg[iarg+1],"yes") == 0) qeqflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) qeqflag = 0;
- else error->all("Illegal pair_style reax/c command");
+ else error->all(FLERR,"Illegal pair_style reax/c command");
iarg += 2;
- } else error->all("Illegal pair_style reax/c command");
+ } else error->all(FLERR,"Illegal pair_style reax/c command");
}
// LAMMPS is responsible for generating nbrs
control->reneighbor = 1;
}
/* ---------------------------------------------------------------------- */
void PairReaxC::coeff( int nargs, char **args )
{
if (!allocated) allocate();
if (nargs != 3 + atom->ntypes)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// insure I,J args are * *
if (strcmp(args[0],"*") != 0 || strcmp(args[1],"*") != 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
// read ffield file
Read_Force_Field(args[2], &(system->reax_param), control);
// read args that map atom types to elements in potential file
// map[i] = which element the Ith atom type is, -1 if NULL
int itmp;
int nreax_types = system->reax_param.num_atom_types;
for (int i = 3; i < nargs; i++) {
if (strcmp(args[i],"NULL") == 0) {
map[i-2] = -1;
continue;
}
itmp = atoi(args[i]) - 1;
map[i-2] = itmp;
// error check
if (itmp < 0 || itmp >= nreax_types)
- error->all("Non-existent ReaxFF type");
+ error->all(FLERR,"Non-existent ReaxFF type");
}
int n = atom->ntypes;
int count = 0;
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++) {
setflag[i][j] = 1;
count++;
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ---------------------------------------------------------------------- */
void PairReaxC::init_style( )
{
- if (!atom->q_flag) error->all("Pair reax/c requires atom attribute q");
+ if (!atom->q_flag) error->all(FLERR,"Pair reax/c requires atom attribute q");
firstwarn = 1;
int iqeq;
for (iqeq = 0; iqeq < modify->nfix; iqeq++)
if (strcmp(modify->fix[iqeq]->style,"qeq/reax") == 0) break;
if (iqeq == modify->nfix && qeqflag == 1)
- error->all("Pair reax/c requires use of fix qeq/reax");
+ error->all(FLERR,"Pair reax/c requires use of fix qeq/reax");
system->n = atom->nlocal; // my atoms
system->N = atom->nlocal + atom->nghost; // mine + ghosts
system->bigN = static_cast<int> (atom->natoms); // all atoms in the system
system->wsize = comm->nprocs;
system->big_box.V = 0;
system->big_box.box_norms[0] = 0;
system->big_box.box_norms[1] = 0;
system->big_box.box_norms[2] = 0;
if (atom->tag_enable == 0)
- error->all("Pair style reax/c requires atom IDs");
+ error->all(FLERR,"Pair style reax/c requires atom IDs");
if (force->newton_pair == 0)
- error->all("Pair style reax/c requires newton pair on");
+ error->all(FLERR,"Pair style reax/c requires newton pair on");
// need a half neighbor list w/ Newton off
// built whenever re-neighboring occurs
int irequest = neighbor->request(this);
neighbor->requests[irequest]->newton = 2;
cutmax = MAX3(control->nonb_cut, control->hbond_cut, 2*control->bond_cut);
for( int i = 0; i < LIST_N; ++i )
lists[i].allocated = 0;
if (fix_reax == NULL) {
char **fixarg = new char*[3];
fixarg[0] = (char *) "REAXC";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "REAXC";
modify->add_fix(3,fixarg);
delete [] fixarg;
fix_reax = (FixReaxC *) modify->fix[modify->nfix-1];
}
}
/* ---------------------------------------------------------------------- */
void PairReaxC::setup( )
{
int oldN;
system->n = atom->nlocal; // my atoms
system->N = atom->nlocal + atom->nghost; // mine + ghosts
oldN = system->N;
system->bigN = static_cast<int> (atom->natoms); // all atoms in the system
if (setup_flag == 0) {
setup_flag = 1;
int *num_bonds = fix_reax->num_bonds;
int *num_hbonds = fix_reax->num_hbonds;
control->vlist_cut = neighbor->cutneighmax;
// determine the local and total capacity
system->local_cap = MAX( (int)(system->n * SAFE_ZONE), MIN_CAP );
system->total_cap = MAX( (int)(system->N * SAFE_ZONE), MIN_CAP );
// initialize my data structures
PreAllocate_Space( system, control, workspace, world );
write_reax_atoms();
int num_nbrs = estimate_reax_lists();
if(!Make_List(system->total_cap, num_nbrs, TYP_FAR_NEIGHBOR,
lists+FAR_NBRS, world))
- error->all("Pair reax/c problem in far neighbor list");
+ error->all(FLERR,"Pair reax/c problem in far neighbor list");
write_reax_lists();
Initialize( system, control, data, workspace, &lists, out_control,
mpi_data, world );
for( int k = 0; k < system->N; ++k ) {
num_bonds[k] = system->my_atoms[k].num_bonds;
num_hbonds[k] = system->my_atoms[k].num_hbonds;
}
} else {
// fill in reax datastructures
write_reax_atoms();
// reset the bond list info for new atoms
for(int k = oldN; k < system->N; ++k)
Set_End_Index( k, Start_Index( k, lists+BONDS ), lists+BONDS );
// check if I need to shrink/extend my data-structs
ReAllocate( system, control, data, workspace, &lists, mpi_data );
}
}
/* ---------------------------------------------------------------------- */
double PairReaxC::init_one(int i, int j)
{
return cutmax;
}
/* ---------------------------------------------------------------------- */
void PairReaxC::compute(int eflag, int vflag)
{
double evdwl,ecoul;
double t_start, t_end;
// communicate num_bonds once every reneighboring
// 2 num arrays stored by fix, grab ptr to them
if (neighbor->ago == 0) comm->forward_comm_fix(fix_reax);
int *num_bonds = fix_reax->num_bonds;
int *num_hbonds = fix_reax->num_hbonds;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = vflag_global = 0;
if ((eflag_atom || vflag_atom) && firstwarn) {
firstwarn = 0;
if (comm->me == 0)
- error->warning("Pair reax/c cannot yet compute "
+ error->warning(FLERR,"Pair reax/c cannot yet compute "
"per-atom energy or stress");
}
if (vflag_global) control->virial = 1;
else control->virial = 0;
system->n = atom->nlocal; // my atoms
system->N = atom->nlocal + atom->nghost; // mine + ghosts
system->bigN = static_cast<int> (atom->natoms); // all atoms in the system
system->big_box.V = 0;
system->big_box.box_norms[0] = 0;
system->big_box.box_norms[1] = 0;
system->big_box.box_norms[2] = 0;
if( comm->me == 0 ) t_start = MPI_Wtime();
// setup data structures
setup();
Reset( system, control, data, workspace, &lists, world );
workspace->realloc.num_far = write_reax_lists();
// timing for filling in the reax lists
if( comm->me == 0 ) {
t_end = MPI_Wtime();
data->timing.nbrs = t_end - t_start;
}
// forces
Compute_Forces(system,control,data,workspace,&lists,out_control,mpi_data);
read_reax_forces();
for(int k = 0; k < system->N; ++k) {
num_bonds[k] = system->my_atoms[k].num_bonds;
num_hbonds[k] = system->my_atoms[k].num_hbonds;
}
// energies and pressure
if (eflag_global) {
evdwl += data->my_en.e_bond;
evdwl += data->my_en.e_ov;
evdwl += data->my_en.e_un;
evdwl += data->my_en.e_lp;
evdwl += data->my_en.e_ang;
evdwl += data->my_en.e_pen;
evdwl += data->my_en.e_coa;
evdwl += data->my_en.e_hb;
evdwl += data->my_en.e_tor;
evdwl += data->my_en.e_con;
evdwl += data->my_en.e_vdW;
ecoul += data->my_en.e_ele;
ecoul += data->my_en.e_pol;
eng_vdwl += evdwl;
eng_coul += ecoul;
// Store the different parts of the energy
// in a list for output by compute pair command
pvector[0] = data->my_en.e_bond;
pvector[1] = data->my_en.e_ov + data->my_en.e_un;
pvector[2] = data->my_en.e_lp;
pvector[3] = 0.0;
pvector[4] = data->my_en.e_ang;
pvector[5] = data->my_en.e_pen;
pvector[6] = data->my_en.e_coa;
pvector[7] = data->my_en.e_hb;
pvector[8] = data->my_en.e_tor;
pvector[9] = data->my_en.e_con;
pvector[10] = data->my_en.e_vdW;
pvector[11] = data->my_en.e_ele;
pvector[12] = 0.0;
pvector[13] = data->my_en.e_pol;
}
if (vflag_fdotr) virial_fdotr_compute();
// #if defined(LOG_PERFORMANCE)
// if( comm->me == 0 && fix_qeq != NULL ) {
// data->timing.s_matvecs += fix_qeq->matvecs;
// data->timing.qEq += fix_qeq->qeq_time;
// }
// #endif
// Set internal timestep counter to that of LAMMPS
data->step = update->ntimestep;
Output_Results( system, control, data, &lists, out_control, mpi_data );
}
/* ---------------------------------------------------------------------- */
void PairReaxC::write_reax_atoms()
{
int *num_bonds = fix_reax->num_bonds;
int *num_hbonds = fix_reax->num_hbonds;
for( int i = 0; i < system->N; ++i ){
system->my_atoms[i].orig_id = atom->tag[i];
system->my_atoms[i].type = map[atom->type[i]];
system->my_atoms[i].x[0] = atom->x[i][0];
system->my_atoms[i].x[1] = atom->x[i][1];
system->my_atoms[i].x[2] = atom->x[i][2];
system->my_atoms[i].q = atom->q[i];
system->my_atoms[i].num_bonds = num_bonds[i];
system->my_atoms[i].num_hbonds = num_hbonds[i];
}
}
/* ---------------------------------------------------------------------- */
void PairReaxC::get_distance( rvec xj, rvec xi, double *d_sqr, rvec *dvec )
{
(*dvec)[0] = xj[0] - xi[0];
(*dvec)[1] = xj[1] - xi[1];
(*dvec)[2] = xj[2] - xi[2];
*d_sqr = SQR((*dvec)[0]) + SQR((*dvec)[1]) + SQR((*dvec)[2]);
}
/* ---------------------------------------------------------------------- */
void PairReaxC::set_far_nbr( far_neighbor_data *fdest,
int j, double d, rvec dvec )
{
fdest->nbr = j;
fdest->d = d;
rvec_Copy( fdest->dvec, dvec );
ivec_MakeZero( fdest->rel_box );
}
/* ---------------------------------------------------------------------- */
int PairReaxC::estimate_reax_lists()
{
int itr_i, itr_j, itr_g, i, j, g;
int nlocal, nghost, num_nbrs, num_marked;
int *ilist, *jlist, *numneigh, **firstneigh, *marked;
double d_sqr, g_d_sqr;
rvec dvec, g_dvec;
double *dist, **x;
reax_list *far_nbrs;
far_neighbor_data *far_list;
x = atom->x;
nlocal = atom->nlocal;
nghost = atom->nghost;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
far_nbrs = lists + FAR_NBRS;
far_list = far_nbrs->select.far_nbr_list;
num_nbrs = 0;
num_marked = 0;
marked = (int*) calloc( system->N, sizeof(int) );
dist = (double*) calloc( system->N, sizeof(double) );
for( itr_i = 0; itr_i < list->inum; ++itr_i ){
i = ilist[itr_i];
marked[i] = 1;
++num_marked;
jlist = firstneigh[i];
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
j &= NEIGHMASK;
get_distance( x[j], x[i], &d_sqr, &dvec );
dist[j] = sqrt(d_sqr);
if( dist[j] <= control->nonb_cut )
++num_nbrs;
}
// compute the nbrs among ghost atoms
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
j &= NEIGHMASK;
if( j >= nlocal && !marked[j] &&
dist[j] <= (control->vlist_cut - control->bond_cut) ){
marked[j] = 1;
++num_marked;
for( itr_g = 0; itr_g < numneigh[i]; ++itr_g ){
g = jlist[itr_g];
g &= NEIGHMASK;
if( g >= nlocal && !marked[g] ){
get_distance( x[g], x[j], &g_d_sqr, &g_dvec );
//g_dvec[0] = x[g][0] - x[j][0];
//g_dvec[1] = x[g][1] - x[j][1];
//g_dvec[2] = x[g][2] - x[j][2];
//g_d_sqr = SQR(g_dvec[0]) + SQR(g_dvec[1]) + SQR(g_dvec[2]);
if( g_d_sqr <= SQR(control->bond_cut) )
++num_nbrs;
}
}
}
}
}
for( i = 0; i < system->N; ++i )
if( !marked[i] ) {
marked[i] = 1;
++num_marked;
for( j = i+1; j < system->N; ++j )
if( !marked[j] ) {
get_distance( x[j], x[i], &d_sqr, &dvec );
if( d_sqr <= SQR(control->bond_cut) )
++num_nbrs;
}
}
free( marked );
free( dist );
return static_cast<int> (MAX( num_nbrs*SAFE_ZONE, MIN_CAP*MIN_NBRS ));
}
/* ---------------------------------------------------------------------- */
int PairReaxC::write_reax_lists()
{
int itr_i, itr_j, itr_g, i, j, g, flag;
int nlocal, nghost, num_nbrs;
int *ilist, *jlist, *numneigh, **firstneigh, *marked, *tag;
double d_sqr, g_d, g_d_sqr;
rvec dvec, g_dvec;
double *dist, **x, SMALL = 0.0001;
reax_list *far_nbrs;
far_neighbor_data *far_list;
x = atom->x;
tag = atom->tag;
nlocal = atom->nlocal;
nghost = atom->nghost;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
far_nbrs = lists + FAR_NBRS;
far_list = far_nbrs->select.far_nbr_list;
num_nbrs = 0;
marked = (int*) calloc( system->N, sizeof(int) );
dist = (double*) calloc( system->N, sizeof(double) );
for( itr_i = 0; itr_i < list->inum; ++itr_i ){
i = ilist[itr_i];
marked[i] = 1;
jlist = firstneigh[i];
Set_Start_Index( i, num_nbrs, far_nbrs );
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
j &= NEIGHMASK;
get_distance( x[j], x[i], &d_sqr, &dvec );
dist[j] = sqrt( d_sqr );
if( dist[j] <= control->nonb_cut ){
set_far_nbr( &far_list[num_nbrs], j, dist[j], dvec );
++num_nbrs;
}
}
Set_End_Index( i, num_nbrs, far_nbrs );
// compute the nbrs among ghost atoms
for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){
j = jlist[itr_j];
j &= NEIGHMASK;
if( j >= nlocal && !marked[j] &&
dist[j] <= (control->vlist_cut - control->bond_cut) ){
marked[j] = 1;
Set_Start_Index( j, num_nbrs, far_nbrs );
for( itr_g = 0; itr_g < numneigh[i]; ++itr_g ){
g = jlist[itr_g];
g &= NEIGHMASK;
if( g >= nlocal && !marked[g] ){
get_distance( x[g], x[j], &g_d_sqr, &g_dvec );
if( g_d_sqr <= SQR(control->bond_cut) ){
g_d = sqrt( g_d_sqr );
set_far_nbr( &far_list[num_nbrs], g, g_d, g_dvec );
++num_nbrs;
}
}
}
Set_End_Index( j, num_nbrs, far_nbrs );
}
}
}
for( i = 0; i < system->N; ++i )
if( !marked[i] ) {
marked[i] = 1;
Set_Start_Index( i, num_nbrs, far_nbrs );
for( j = i+1; j < system->N; ++j )
if( !marked[j] ) {
get_distance( x[j], x[i], &d_sqr, &dvec );
if( d_sqr <= SQR(control->bond_cut) ) {
set_far_nbr( &far_list[num_nbrs], j, sqrt(d_sqr), dvec );
++num_nbrs;
}
}
Set_End_Index( i, num_nbrs, far_nbrs );
}
free( marked );
free( dist );
return num_nbrs;
}
/* ---------------------------------------------------------------------- */
void PairReaxC::read_reax_forces()
{
for( int i = 0; i < system->N; ++i ) {
system->my_atoms[i].f[0] = workspace->f[i][0];
system->my_atoms[i].f[1] = workspace->f[i][1];
system->my_atoms[i].f[2] = workspace->f[i][2];
atom->f[i][0] = -workspace->f[i][0];
atom->f[i][1] = -workspace->f[i][1];
atom->f[i][2] = -workspace->f[i][2];
}
}
/* ---------------------------------------------------------------------- */
void *PairReaxC::extract(char *str, int &dim)
{
dim = 1;
if (strcmp(str,"chi") == 0 && chi) {
for (int i = 1; i <= atom->ntypes; i++)
if (map[i] >= 0) chi[i] = system->reax_param.sbp[map[i]].chi;
else chi[i] = 0.0;
return (void *) chi;
}
if (strcmp(str,"eta") == 0 && eta) {
for (int i = 1; i <= atom->ntypes; i++)
if (map[i] >= 0) eta[i] = system->reax_param.sbp[map[i]].eta;
else eta[i] = 0.0;
return (void *) eta;
}
if (strcmp(str,"gamma") == 0 && gamma) {
for (int i = 1; i <= atom->ntypes; i++)
if (map[i] >= 0) gamma[i] = system->reax_param.sbp[map[i]].gamma;
else gamma[i] = 0.0;
return (void *) gamma;
}
return NULL;
}
diff --git a/src/USER-SPH/atom_vec_meso.cpp b/src/USER-SPH/atom_vec_meso.cpp
index c977a8e32..b69686824 100644
--- a/src/USER-SPH/atom_vec_meso.cpp
+++ b/src/USER-SPH/atom_vec_meso.cpp
@@ -1,868 +1,868 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "atom_vec_meso.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecMeso::AtomVecMeso(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg) {
molecular = 0;
mass_type = 1;
comm_x_only = 0; // we communicate not only x forward but also vest ...
comm_f_only = 0; // we also communicate de and drho in reverse direction
size_forward = 8; // 3 + rho + e + vest[3], that means we may only communicate 5 in hybrid
size_reverse = 5; // 3 + drho + de
size_border = 12; // 6 + rho + e + vest[3] + cv
size_velocity = 3;
size_data_atom = 8;
size_data_vel = 4;
xcol_data = 6;
atom->e_flag = 1;
atom->rho_flag = 1;
atom->cv_flag = 1;
atom->vest_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecMeso::grow(int n) {
if (n == 0)
nmax += DELTA;
else
nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag, nmax, "atom:tag");
type = memory->grow(atom->type, nmax, "atom:type");
mask = memory->grow(atom->mask, nmax, "atom:mask");
image = memory->grow(atom->image, nmax, "atom:image");
x = memory->grow(atom->x, nmax, 3, "atom:x");
v = memory->grow(atom->v, nmax, 3, "atom:v");
f = memory->grow(atom->f, nmax, 3, "atom:f");
rho = memory->grow(atom->rho, nmax, "atom:rho");
drho = memory->grow(atom->drho, nmax, "atom:drho");
e = memory->grow(atom->e, nmax, "atom:e");
de = memory->grow(atom->de, nmax, "atom:de");
vest = memory->grow(atom->vest, nmax, 3, "atom:vest");
cv = memory->grow(atom->cv, nmax, "atom:cv");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecMeso::grow_reset() {
tag = atom->tag;
type = atom->type;
mask = atom->mask;
image = atom->image;
x = atom->x;
v = atom->v;
f = atom->f;
rho = atom->rho;
drho = atom->drho;
e = atom->e;
de = atom->de;
vest = atom->vest;
cv = atom->cv;
}
/* ---------------------------------------------------------------------- */
void AtomVecMeso::copy(int i, int j, int delflag) {
//printf("in AtomVecMeso::copy\n");
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
rho[j] = rho[i];
drho[j] = drho[i];
e[j] = e[i];
de[j] = de[i];
cv[j] = cv[i];
vest[j][0] = vest[i][0];
vest[j][1] = vest[i][1];
vest[j][2] = vest[i][2];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i, j);
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_comm_hybrid(int n, int *list, double *buf) {
//printf("in AtomVecMeso::pack_comm_hybrid\n");
int i, j, m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::unpack_comm_hybrid(int n, int first, double *buf) {
//printf("in AtomVecMeso::unpack_comm_hybrid\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
rho[i] = buf[m++];
e[i] = buf[m++];
vest[i][0] = buf[m++];
vest[i][1] = buf[m++];
vest[i][2] = buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_border_hybrid(int n, int *list, double *buf) {
//printf("in AtomVecMeso::pack_border_hybrid\n");
int i, j, m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::unpack_border_hybrid(int n, int first, double *buf) {
//printf("in AtomVecMeso::unpack_border_hybrid\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
rho[i] = buf[m++];
e[i] = buf[m++];
vest[i][0] = buf[m++];
vest[i][1] = buf[m++];
vest[i][2] = buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_reverse_hybrid(int n, int first, double *buf) {
//printf("in AtomVecMeso::pack_reverse_hybrid\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = drho[i];
buf[m++] = de[i];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::unpack_reverse_hybrid(int n, int *list, double *buf) {
//printf("in AtomVecMeso::unpack_reverse_hybrid\n");
int i, j, m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
drho[j] += buf[m++];
de[j] += buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_comm(int n, int *list, double *buf, int pbc_flag,
int *pbc) {
//printf("in AtomVecMeso::pack_comm\n");
int i, j, m;
double dx, dy, dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0] * domain->xprd;
dy = pbc[1] * domain->yprd;
dz = pbc[2] * domain->zprd;
} else {
dx = pbc[0] * domain->xprd + pbc[5] * domain->xy + pbc[4] * domain->xz;
dy = pbc[1] * domain->yprd + pbc[3] * domain->yz;
dz = pbc[2] * domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_comm_vel(int n, int *list, double *buf, int pbc_flag,
int *pbc) {
//printf("in AtomVecMeso::pack_comm_vel\n");
int i, j, m;
double dx, dy, dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0] * domain->xprd;
dy = pbc[1] * domain->yprd;
dz = pbc[2] * domain->zprd;
} else {
dx = pbc[0] * domain->xprd + pbc[5] * domain->xy + pbc[4] * domain->xz;
dy = pbc[1] * domain->yprd + pbc[3] * domain->yz;
dz = pbc[2] * domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecMeso::unpack_comm(int n, int first, double *buf) {
//printf("in AtomVecMeso::unpack_comm\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
rho[i] = buf[m++];
e[i] = buf[m++];
vest[i][0] = buf[m++];
vest[i][1] = buf[m++];
vest[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecMeso::unpack_comm_vel(int n, int first, double *buf) {
//printf("in AtomVecMeso::unpack_comm_vel\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
rho[i] = buf[m++];
e[i] = buf[m++];
vest[i][0] = buf[m++];
vest[i][1] = buf[m++];
vest[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_reverse(int n, int first, double *buf) {
//printf("in AtomVecMeso::pack_reverse\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
buf[m++] = drho[i];
buf[m++] = de[i];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecMeso::unpack_reverse(int n, int *list, double *buf) {
//printf("in AtomVecMeso::unpack_reverse\n");
int i, j, m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
drho[j] += buf[m++];
de[j] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_border(int n, int *list, double *buf, int pbc_flag,
int *pbc) {
//printf("in AtomVecMeso::pack_border\n");
int i, j, m;
double dx, dy, dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = cv[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0] * domain->xprd;
dy = pbc[1] * domain->yprd;
dz = pbc[2] * domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = cv[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::pack_border_vel(int n, int *list, double *buf, int pbc_flag,
int *pbc) {
//printf("in AtomVecMeso::pack_border_vel\n");
int i, j, m;
double dx, dy, dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = cv[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0] * domain->xprd;
dy = pbc[1] * domain->yprd;
dz = pbc[2] * domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = rho[j];
buf[m++] = e[j];
buf[m++] = cv[j];
buf[m++] = vest[j][0];
buf[m++] = vest[j][1];
buf[m++] = vest[j][2];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecMeso::unpack_border(int n, int first, double *buf) {
//printf("in AtomVecMeso::unpack_border\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax)
grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
rho[i] = buf[m++];
e[i] = buf[m++];
cv[i] = buf[m++];
vest[i][0] = buf[m++];
vest[i][1] = buf[m++];
vest[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecMeso::unpack_border_vel(int n, int first, double *buf) {
//printf("in AtomVecMeso::unpack_border_vel\n");
int i, m, last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax)
grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
rho[i] = buf[m++];
e[i] = buf[m++];
cv[i] = buf[m++];
vest[i][0] = buf[m++];
vest[i][1] = buf[m++];
vest[i][2] = buf[m++];
}
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecMeso::pack_exchange(int i, double *buf) {
//printf("in AtomVecMeso::pack_exchange\n");
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = rho[i];
buf[m++] = e[i];
buf[m++] = cv[i];
buf[m++] = vest[i][0];
buf[m++] = vest[i][1];
buf[m++] = vest[i][2];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i, &buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecMeso::unpack_exchange(double *buf) {
//printf("in AtomVecMeso::unpack_exchange\n");
int nlocal = atom->nlocal;
if (nlocal == nmax)
grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
rho[nlocal] = buf[m++];
e[nlocal] = buf[m++];
cv[nlocal] = buf[m++];
vest[nlocal][0] = buf[m++];
vest[nlocal][1] = buf[m++];
vest[nlocal][2] = buf[m++];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]-> unpack_exchange(nlocal,
&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecMeso::size_restart() {
int i;
int nlocal = atom->nlocal;
int n = 17 * nlocal; // 11 + rho + e + cv + vest[3]
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecMeso::pack_restart(int i, double *buf) {
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = rho[i];
buf[m++] = e[i];
buf[m++] = cv[i];
buf[m++] = vest[i][0];
buf[m++] = vest[i][1];
buf[m++] = vest[i][2];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i, &buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecMeso::unpack_restart(double *buf) {
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra, nmax, atom->nextra_store, "atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
rho[nlocal] = buf[m++];
e[nlocal] = buf[m++];
cv[nlocal] = buf[m++];
vest[nlocal][0] = buf[m++];
vest[nlocal][1] = buf[m++];
vest[nlocal][2] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++)
extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecMeso::create_atom(int itype, double *coord) {
int nlocal = atom->nlocal;
if (nlocal == nmax)
grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
rho[nlocal] = 0.0;
e[nlocal] = 0.0;
cv[nlocal] = 1.0;
vest[nlocal][0] = 0.0;
vest[nlocal][1] = 0.0;
vest[nlocal][2] = 0.0;
de[nlocal] = 0.0;
drho[nlocal] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecMeso::data_atom(double *coord, int imagetmp, char **values) {
int nlocal = atom->nlocal;
if (nlocal == nmax)
grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
rho[nlocal] = atof(values[2]);
e[nlocal] = atof(values[3]);
cv[nlocal] = atof(values[4]);
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
//printf("rho=%f, e=%f, cv=%f, x=%f\n", rho[nlocal], e[nlocal], cv[nlocal], x[nlocal][0]);
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
vest[nlocal][0] = 0.0;
vest[nlocal][1] = 0.0;
vest[nlocal][2] = 0.0;
de[nlocal] = 0.0;
drho[nlocal] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecMeso::data_atom_hybrid(int nlocal, char **values) {
rho[nlocal] = atof(values[0]);
e[nlocal] = atof(values[1]);
cv[nlocal] = atof(values[2]);
return 3;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecMeso::memory_usage() {
bigint bytes = 0;
if (atom->memcheck("tag"))
bytes += memory->usage(tag, nmax);
if (atom->memcheck("type"))
bytes += memory->usage(type, nmax);
if (atom->memcheck("mask"))
bytes += memory->usage(mask, nmax);
if (atom->memcheck("image"))
bytes += memory->usage(image, nmax);
if (atom->memcheck("x"))
bytes += memory->usage(x, nmax);
if (atom->memcheck("v"))
bytes += memory->usage(v, nmax);
if (atom->memcheck("f"))
bytes += memory->usage(f, nmax);
if (atom->memcheck("rho"))
bytes += memory->usage(rho, nmax);
if (atom->memcheck("drho"))
bytes += memory->usage(drho, nmax);
if (atom->memcheck("e"))
bytes += memory->usage(e, nmax);
if (atom->memcheck("de"))
bytes += memory->usage(de, nmax);
if (atom->memcheck("cv"))
bytes += memory->usage(cv, nmax);
if (atom->memcheck("vest"))
bytes += memory->usage(vest, nmax);
return bytes;
}
diff --git a/src/USER-SPH/compute_meso_e_atom.cpp b/src/USER-SPH/compute_meso_e_atom.cpp
index 934818584..4ee0dce51 100644
--- a/src/USER-SPH/compute_meso_e_atom.cpp
+++ b/src/USER-SPH/compute_meso_e_atom.cpp
@@ -1,97 +1,97 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_meso_e_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeMesoEAtom::ComputeMesoEAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Number of arguments for compute meso_e/atom command != 3");
- if (atom->e_flag != 1) error->all("compute meso_e/atom command requires atom_style with energy (e.g. meso)");
+ if (narg != 3) error->all(FLERR,"Number of arguments for compute meso_e/atom command != 3");
+ if (atom->e_flag != 1) error->all(FLERR,"compute meso_e/atom command requires atom_style with energy (e.g. meso)");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
evector = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeMesoEAtom::~ComputeMesoEAtom()
{
memory->sfree(evector);
}
/* ---------------------------------------------------------------------- */
void ComputeMesoEAtom::init()
{
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"evector/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute evector/atom");
+ error->warning(FLERR,"More than one compute evector/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeMesoEAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow evector array if necessary
if (atom->nlocal > nmax) {
memory->sfree(evector);
nmax = atom->nmax;
evector = (double *) memory->smalloc(nmax*sizeof(double),"evector/atom:evector");
vector_atom = evector;
}
double *e = atom->e;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
evector[i] = e[i];
}
else {
evector[i] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeMesoEAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/USER-SPH/compute_meso_rho_atom.cpp b/src/USER-SPH/compute_meso_rho_atom.cpp
index 98aab3ad7..465bbfe16 100644
--- a/src/USER-SPH/compute_meso_rho_atom.cpp
+++ b/src/USER-SPH/compute_meso_rho_atom.cpp
@@ -1,99 +1,99 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_meso_rho_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeMesoRhoAtom::ComputeMesoRhoAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute meso_rho/atom command");
- if (atom->rho_flag != 1) error->all("compute meso_rho/atom command requires atom_style with density (e.g. meso)");
+ if (narg != 3) error->all(FLERR,"Illegal compute meso_rho/atom command");
+ if (atom->rho_flag != 1) error->all(FLERR,"compute meso_rho/atom command requires atom_style with density (e.g. meso)");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
rhoVector = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeMesoRhoAtom::~ComputeMesoRhoAtom()
{
memory->sfree(rhoVector);
}
/* ---------------------------------------------------------------------- */
void ComputeMesoRhoAtom::init()
{
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"rhoVector/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute rhoVector/atom");
+ error->warning(FLERR,"More than one compute rhoVector/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeMesoRhoAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow rhoVector array if necessary
if (atom->nlocal > nmax) {
memory->sfree(rhoVector);
nmax = atom->nmax;
rhoVector = (double *) memory->smalloc(nmax*sizeof(double),"atom:rhoVector");
vector_atom = rhoVector;
}
// compute kinetic energy for each atom in group
double *rho = atom->rho;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
rhoVector[i] = rho[i];
}
else {
rhoVector[i] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeMesoRhoAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/USER-SPH/compute_meso_t_atom.cpp b/src/USER-SPH/compute_meso_t_atom.cpp
index 21a9a4d66..5d4f1177b 100644
--- a/src/USER-SPH/compute_meso_t_atom.cpp
+++ b/src/USER-SPH/compute_meso_t_atom.cpp
@@ -1,101 +1,101 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_meso_t_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeMesoTAtom::ComputeMesoTAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Number of arguments for compute meso_t/atom command != 3");
+ if (narg != 3) error->all(FLERR,"Number of arguments for compute meso_t/atom command != 3");
if ((atom->e_flag != 1) || (atom->cv_flag != 1))
- error->all("compute meso_e/atom command requires atom_style with both energy and heat capacity (e.g. meso)");
+ error->all(FLERR,"compute meso_e/atom command requires atom_style with both energy and heat capacity (e.g. meso)");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
tvector = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeMesoTAtom::~ComputeMesoTAtom()
{
memory->sfree(tvector);
}
/* ---------------------------------------------------------------------- */
void ComputeMesoTAtom::init()
{
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"meso_t/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute meso_t/atom");
+ error->warning(FLERR,"More than one compute meso_t/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeMesoTAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow tvector array if necessary
if (atom->nlocal > nmax) {
memory->sfree(tvector);
nmax = atom->nmax;
tvector = (double *) memory->smalloc(nmax*sizeof(double),"tvector/atom:tvector");
vector_atom = tvector;
}
double *e = atom->e;
double *cv = atom->cv;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (cv[i] > 0.0) {
tvector[i] = e[i] / cv[i];
}
}
else {
tvector[i] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeMesoTAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/USER-SPH/fix_meso.cpp b/src/USER-SPH/fix_meso.cpp
index 0b8576f38..cfab98164 100644
--- a/src/USER-SPH/fix_meso.cpp
+++ b/src/USER-SPH/fix_meso.cpp
@@ -1,167 +1,167 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdio.h"
#include "string.h"
#include "fix_meso.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "pair.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixMeso::FixMeso(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg) {
if ((atom->e_flag != 1) || (atom->rho_flag != 1))
- error->all(
+ error->all(FLERR,
"fix meso command requires atom_style with both energy and density");
if (narg != 3)
- error->all("Illegal number of arguments for fix meso command");
+ error->all(FLERR,"Illegal number of arguments for fix meso command");
time_integrate = 1;
}
/* ---------------------------------------------------------------------- */
int FixMeso::setmask() {
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixMeso::init() {
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixMeso::initial_integrate(int vflag) {
// update v and x and rho and e of atoms in group
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **vest = atom->vest;
double *rho = atom->rho;
double *drho = atom->drho;
double *e = atom->e;
double *de = atom->de;
double *mass = atom->mass;
double *rmass = atom->rmass;
int rmass_flag = atom->rmass_flag;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int i;
double dtfm;
if (igroup == atom->firstgroup)
nlocal = atom->nfirst;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (rmass_flag) {
dtfm = dtf / rmass[i];
} else {
dtfm = dtf / mass[type[i]];
}
e[i] += dtf * de[i]; // half-step update of particle internal energy
rho[i] += dtf * drho[i]; // ... and density
// extrapolate velocity for use with velocity-dependent potentials, e.g. SPH
vest[i][0] = v[i][0] + 2.0 * dtfm * f[i][0];
vest[i][1] = v[i][1] + 2.0 * dtfm * f[i][1];
vest[i][2] = v[i][2] + 2.0 * dtfm * f[i][2];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixMeso::final_integrate() {
// update v, rho, and e of atoms in group
double **v = atom->v;
double **f = atom->f;
double *e = atom->e;
double *de = atom->de;
double *rho = atom->rho;
double *drho = atom->drho;
int *type = atom->type;
int *mask = atom->mask;
double *mass = atom->mass;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup)
nlocal = atom->nfirst;
double dtfm;
double *rmass = atom->rmass;
int rmass_flag = atom->rmass_flag;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (rmass_flag) {
dtfm = dtf / rmass[i];
} else {
dtfm = dtf / mass[type[i]];
}
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
e[i] += dtf * de[i];
rho[i] += dtf * drho[i];
}
}
}
/* ---------------------------------------------------------------------- */
void FixMeso::reset_dt() {
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}
diff --git a/src/USER-SPH/fix_meso_stationary.cpp b/src/USER-SPH/fix_meso_stationary.cpp
index 9a08d28fd..793e8dd21 100644
--- a/src/USER-SPH/fix_meso_stationary.cpp
+++ b/src/USER-SPH/fix_meso_stationary.cpp
@@ -1,122 +1,122 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdio.h"
#include "string.h"
#include "fix_meso_stationary.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
#include "pair.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixMesoStationary::FixMesoStationary(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg) {
if ((atom->e_flag != 1) || (atom->rho_flag != 1))
- error->all(
+ error->all(FLERR,
"fix meso/stationary command requires atom_style with both energy and density, e.g. meso");
if (narg != 3)
- error->all("Illegal number of arguments for fix meso/stationary command");
+ error->all(FLERR,"Illegal number of arguments for fix meso/stationary command");
time_integrate = 0;
}
/* ---------------------------------------------------------------------- */
int FixMesoStationary::setmask() {
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixMesoStationary::init() {
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixMesoStationary::initial_integrate(int vflag) {
double *rho = atom->rho;
double *drho = atom->drho;
double *e = atom->e;
double *de = atom->de;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int i;
if (igroup == atom->firstgroup)
nlocal = atom->nfirst;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
e[i] += dtf * de[i]; // half-step update of particle internal energy
rho[i] += dtf * drho[i]; // ... and density
}
}
}
/* ---------------------------------------------------------------------- */
void FixMesoStationary::final_integrate() {
double *e = atom->e;
double *de = atom->de;
double *rho = atom->rho;
double *drho = atom->drho;
int *type = atom->type;
int *mask = atom->mask;
double *mass = atom->mass;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup)
nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
e[i] += dtf * de[i];
rho[i] += dtf * drho[i];
}
}
}
/* ---------------------------------------------------------------------- */
void FixMesoStationary::reset_dt() {
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}
diff --git a/src/USER-SPH/pair_sph_heatconduction.cpp b/src/USER-SPH/pair_sph_heatconduction.cpp
index e4af6f766..2eacb71cf 100644
--- a/src/USER-SPH/pair_sph_heatconduction.cpp
+++ b/src/USER-SPH/pair_sph_heatconduction.cpp
@@ -1,221 +1,218 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_sph_heatconduction.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
#include "neigh_list.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairSPHHeatConduction::PairSPHHeatConduction(LAMMPS *lmp) :
Pair(lmp) {
}
/* ---------------------------------------------------------------------- */
PairSPHHeatConduction::~PairSPHHeatConduction() {
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(alpha);
}
}
/* ---------------------------------------------------------------------- */
void PairSPHHeatConduction::compute(int eflag, int vflag) {
int i, j, ii, jj, inum, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz;
int *ilist, *jlist, *numneigh, **firstneigh;
double imass, jmass, h, ih, ihsq;
double rsq, wfd, D, deltaE;
if (eflag || vflag)
ev_setup(eflag, vflag);
else
evflag = vflag_fdotr = 0;
double **x = atom->x;
double *e = atom->e;
double *de = atom->de;
double *mass = atom->mass;
double *rho = atom->rho;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms and do heat diffusion
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
imass = mass[itype];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
jtype = type[j];
jmass = mass[jtype];
if (rsq < cutsq[itype][jtype]) {
h = cut[itype][jtype];
ih = 1.0 / h;
ihsq = ih * ih;
// kernel function
wfd = h - sqrt(rsq);
if (domain->dimension == 3) {
// Lucy Kernel, 3d
// Note that wfd, the derivative of the weight function with respect to r,
// is lacking a factor of r.
// The missing factor of r is recovered by
// deltaE, which is missing a factor of 1/r
wfd = -25.066903536973515383e0 * wfd * wfd * ihsq * ihsq * ihsq * ih;
} else {
// Lucy Kernel, 2d
wfd = -19.098593171027440292e0 * wfd * wfd * ihsq * ihsq * ihsq;
}
jmass = mass[jtype];
D = alpha[itype][jtype]; // diffusion coefficient
deltaE = 2.0 * imass * jmass / (imass+jmass);
deltaE *= (rho[i] + rho[j]) / (rho[i] * rho[j]);
deltaE *= D * (e[i] - e[j]) * wfd;
de[i] += deltaE;
if (newton_pair || j < nlocal) {
de[j] -= deltaE;
}
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairSPHHeatConduction::allocate() {
allocated = 1;
int n = atom->ntypes;
memory->create(setflag, n + 1, n + 1, "pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
memory->create(cut, n + 1, n + 1, "pair:cut");
memory->create(alpha, n + 1, n + 1, "pair:alpha");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSPHHeatConduction::settings(int narg, char **arg) {
if (narg != 0)
- error->all(
+ error->all(FLERR,
"Illegal number of setting arguments for pair_style sph/heatconduction");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSPHHeatConduction::coeff(int narg, char **arg) {
if (narg != 4)
- error->all("Incorrect number of args for pair_style sph/heatconduction coefficients");
+ error->all(FLERR,"Incorrect number of args for pair_style sph/heatconduction coefficients");
if (!allocated)
allocate();
int ilo, ihi, jlo, jhi;
force->bounds(arg[0], atom->ntypes, ilo, ihi);
force->bounds(arg[1], atom->ntypes, jlo, jhi);
double alpha_one = force->numeric(arg[2]);
double cut_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
//printf("setting cut[%d][%d] = %f\n", i, j, cut_one);
cut[i][j] = cut_one;
alpha[i][j] = alpha_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSPHHeatConduction::init_one(int i, int j) {
if (setflag[i][j] == 0) {
- error->all("All pair sph/heatconduction coeffs are not set");
+ error->all(FLERR,"All pair sph/heatconduction coeffs are not set");
}
cut[j][i] = cut[i][j];
alpha[j][i] = alpha[i][j];
return cut[i][j];
}
/* ---------------------------------------------------------------------- */
double PairSPHHeatConduction::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj, double &fforce) {
fforce = 0.0;
return 0.0;
}
diff --git a/src/USER-SPH/pair_sph_idealgas.cpp b/src/USER-SPH/pair_sph_idealgas.cpp
index 35baf218c..a477ed060 100644
--- a/src/USER-SPH/pair_sph_idealgas.cpp
+++ b/src/USER-SPH/pair_sph_idealgas.cpp
@@ -1,262 +1,259 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_sph_idealgas.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairSPHIdealGas::PairSPHIdealGas(LAMMPS *lmp) :
Pair(lmp) {
}
/* ---------------------------------------------------------------------- */
PairSPHIdealGas::~PairSPHIdealGas() {
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(viscosity);
}
}
/* ---------------------------------------------------------------------- */
void PairSPHIdealGas::compute(int eflag, int vflag) {
int i, j, ii, jj, inum, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz, fpair;
int *ilist, *jlist, *numneigh, **firstneigh;
double vxtmp, vytmp, vztmp, imass, jmass, fi, fj, fvisc, h, ih, ihsq;
double rsq, wfd, delVdotDelR, mu, deltaE, ci, cj;
if (eflag || vflag)
ev_setup(eflag, vflag);
else
evflag = vflag_fdotr = 0;
double **v = atom->vest;
double **x = atom->x;
double **f = atom->f;
double *rho = atom->rho;
double *mass = atom->mass;
double *de = atom->de;
double *e = atom->e;
double *drho = atom->drho;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
vxtmp = v[i][0];
vytmp = v[i][1];
vztmp = v[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
imass = mass[itype];
fi = 0.4 * e[i] / imass / rho[i]; // ideal gas EOS; this expression is fi = pressure / rho^2
ci = sqrt(0.4*e[i]/imass); // speed of sound with heat capacity ratio gamma=1.4
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
jtype = type[j];
jmass = mass[jtype];
if (rsq < cutsq[itype][jtype]) {
h = cut[itype][jtype];
ih = 1. / h;
ihsq = ih * ih;
wfd = h - sqrt(rsq);
if (domain->dimension == 3) {
// Lucy Kernel, 3d
// Note that wfd, the derivative of the weight function with respect to r,
// is lacking a factor of r.
// The missing factor of r is recovered by
// (1) using delV . delX instead of delV . (delX/r) and
// (2) using f[i][0] += delx * fpair instead of f[i][0] += (delx/r) * fpair
wfd = -25.066903536973515383e0 * wfd * wfd * ihsq * ihsq * ihsq * ih;
} else {
// Lucy Kernel, 2d
wfd = -19.098593171027440292e0 * wfd * wfd * ihsq * ihsq * ihsq;
}
fj = 0.4 * e[j] / jmass / rho[j];
// dot product of velocity delta and distance vector
delVdotDelR = delx * (vxtmp - v[j][0]) + dely * (vytmp - v[j][1])
+ delz * (vztmp - v[j][2]);
// artificial viscosity (Monaghan 1992)
if (delVdotDelR < 0.) {
cj = sqrt(0.4*e[j]/jmass);
mu = h * delVdotDelR / (rsq + 0.01 * h * h);
fvisc = -viscosity[itype][jtype] * (ci + cj) * mu / (rho[i] + rho[j]);
} else {
fvisc = 0.;
}
// total pair force & thermal energy increment
fpair = -imass * jmass * (fi + fj + fvisc) * wfd;
deltaE = -0.5 * fpair * delVdotDelR;
f[i][0] += delx * fpair;
f[i][1] += dely * fpair;
f[i][2] += delz * fpair;
// and change in density
drho[i] += jmass * delVdotDelR * wfd;
// change in thermal energy
de[i] += deltaE;
if (newton_pair || j < nlocal) {
f[j][0] -= delx * fpair;
f[j][1] -= dely * fpair;
f[j][2] -= delz * fpair;
de[j] += deltaE;
drho[j] += imass * delVdotDelR * wfd;
}
if (evflag)
ev_tally(i, j, nlocal, newton_pair, 0.0, 0.0, fpair, delx, dely, delz);
if (evflag)
ev_tally(i, j, nlocal, newton_pair, 0.0, 0.0, fpair, delx, dely,
delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairSPHIdealGas::allocate() {
allocated = 1;
int n = atom->ntypes;
memory->create(setflag, n + 1, n + 1, "pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
memory->create(cut, n + 1, n + 1, "pair:cut");
memory->create(viscosity, n + 1, n + 1, "pair:viscosity");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSPHIdealGas::settings(int narg, char **arg) {
if (narg != 0)
- error->all(
+ error->all(FLERR,
"Illegal number of setting arguments for pair_style sph/idealgas");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSPHIdealGas::coeff(int narg, char **arg) {
if (narg != 4)
- error->all("Incorrect number of args for pair_style sph/idealgas coefficients");
+ error->all(FLERR,"Incorrect number of args for pair_style sph/idealgas coefficients");
if (!allocated)
allocate();
int ilo, ihi, jlo, jhi;
force->bounds(arg[0], atom->ntypes, ilo, ihi);
force->bounds(arg[1], atom->ntypes, jlo, jhi);
double viscosity_one = force->numeric(arg[2]);
double cut_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
viscosity[i][j] = viscosity_one;
//printf("setting cut[%d][%d] = %f\n", i, j, cut_one);
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0)
- error->all("Incorrect args for pair sph/idealgas coefficients");
+ error->all(FLERR,"Incorrect args for pair sph/idealgas coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSPHIdealGas::init_one(int i, int j) {
if (setflag[i][j] == 0) {
- error->all("All pair sph/idealgas coeffs are not set");
+ error->all(FLERR,"All pair sph/idealgas coeffs are not set");
}
cut[j][i] = cut[i][j];
return cut[i][j];
}
/* ---------------------------------------------------------------------- */
double PairSPHIdealGas::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj, double &fforce) {
fforce = 0.0;
return 0.0;
}
diff --git a/src/USER-SPH/pair_sph_lj.cpp b/src/USER-SPH/pair_sph_lj.cpp
index fd92cddc8..4d73ef03f 100644
--- a/src/USER-SPH/pair_sph_lj.cpp
+++ b/src/USER-SPH/pair_sph_lj.cpp
@@ -1,368 +1,365 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_sph_lj.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairSPHLJ::PairSPHLJ(LAMMPS *lmp) :
Pair(lmp) {
}
/* ---------------------------------------------------------------------- */
PairSPHLJ::~PairSPHLJ() {
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(viscosity);
}
}
/* ---------------------------------------------------------------------- */
void PairSPHLJ::compute(int eflag, int vflag) {
int i, j, ii, jj, inum, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz, fpair;
int *ilist, *jlist, *numneigh, **firstneigh;
double vxtmp, vytmp, vztmp, imass, jmass, fi, fj, fvisc, h, ih, ihsq, ihcub;
double rsq, wfd, delVdotDelR, mu, deltaE, ci, cj, lrc;
if (eflag || vflag)
ev_setup(eflag, vflag);
else
evflag = vflag_fdotr = 0;
double **v = atom->vest;
double **x = atom->x;
double **f = atom->f;
double *rho = atom->rho;
double *mass = atom->mass;
double *de = atom->de;
double *e = atom->e;
double *cv = atom->cv;
double *drho = atom->drho;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
vxtmp = v[i][0];
vytmp = v[i][1];
vztmp = v[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
imass = mass[itype];
// compute pressure of particle i with LJ EOS
LJEOS2(rho[i], e[i], cv[i], &fi, &ci);
fi /= (rho[i] * rho[i]);
//printf("fi = %f\n", fi);
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
jtype = type[j];
jmass = mass[jtype];
if (rsq < cutsq[itype][jtype]) {
h = cut[itype][jtype];
ih = 1.0 / h;
ihsq = ih * ih;
ihcub = ihsq * ih;
wfd = h - sqrt(rsq);
if (domain->dimension == 3) {
// Lucy Kernel, 3d
// Note that wfd, the derivative of the weight function with respect to r,
// is lacking a factor of r.
// The missing factor of r is recovered by
// (1) using delV . delX instead of delV . (delX/r) and
// (2) using f[i][0] += delx * fpair instead of f[i][0] += (delx/r) * fpair
wfd = -25.066903536973515383e0 * wfd * wfd * ihsq * ihsq * ihsq * ih;
} else {
// Lucy Kernel, 2d
wfd = -19.098593171027440292e0 * wfd * wfd * ihsq * ihsq * ihsq;
}
// function call to LJ EOS
LJEOS2(rho[j], e[j], cv[j], &fj, &cj);
fj /= (rho[j] * rho[j]);
// apply long-range correction to model a LJ fluid with cutoff
// this implies that the modelled LJ fluid has cutoff == SPH cutoff
lrc = - 11.1701 * (ihcub * ihcub * ihcub - 1.5 * ihcub);
fi += lrc;
fj += lrc;
// dot product of velocity delta and distance vector
delVdotDelR = delx * (vxtmp - v[j][0]) + dely * (vytmp - v[j][1])
+ delz * (vztmp - v[j][2]);
// artificial viscosity (Monaghan 1992)
if (delVdotDelR < 0.) {
mu = h * delVdotDelR / (rsq + 0.01 * h * h);
fvisc = -viscosity[itype][jtype] * (ci + cj) * mu / (rho[i] + rho[j]);
} else {
fvisc = 0.;
}
// total pair force & thermal energy increment
fpair = -imass * jmass * (fi + fj + fvisc) * wfd;
deltaE = -0.5 * fpair * delVdotDelR;
f[i][0] += delx * fpair;
f[i][1] += dely * fpair;
f[i][2] += delz * fpair;
// and change in density
drho[i] += jmass * delVdotDelR * wfd;
// change in thermal energy
de[i] += deltaE;
if (newton_pair || j < nlocal) {
f[j][0] -= delx * fpair;
f[j][1] -= dely * fpair;
f[j][2] -= delz * fpair;
de[j] += deltaE;
drho[j] += imass * delVdotDelR * wfd;
}
if (evflag)
ev_tally(i, j, nlocal, newton_pair, 0.0, 0.0, fpair, delx, dely, delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairSPHLJ::allocate() {
allocated = 1;
int n = atom->ntypes;
memory->create(setflag, n + 1, n + 1, "pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
memory->create(cut, n + 1, n + 1, "pair:cut");
memory->create(viscosity, n + 1, n + 1, "pair:viscosity");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSPHLJ::settings(int narg, char **arg) {
if (narg != 0)
- error->all(
+ error->all(FLERR,
"Illegal number of setting arguments for pair_style sph/lj");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSPHLJ::coeff(int narg, char **arg) {
if (narg != 4)
- error->all(
+ error->all(FLERR,
"Incorrect args for pair_style sph/lj coefficients");
if (!allocated)
allocate();
int ilo, ihi, jlo, jhi;
force->bounds(arg[0], atom->ntypes, ilo, ihi);
force->bounds(arg[1], atom->ntypes, jlo, jhi);
double viscosity_one = force->numeric(arg[2]);
double cut_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
viscosity[i][j] = viscosity_one;
printf("setting cut[%d][%d] = %f\n", i, j, cut_one);
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSPHLJ::init_one(int i, int j) {
if (setflag[i][j] == 0) {
- error->all("All pair sph/lj coeffs are not set");
+ error->all(FLERR,"All pair sph/lj coeffs are not set");
}
cut[j][i] = cut[i][j];
viscosity[j][i] = viscosity[i][j];
return cut[i][j];
}
/* ---------------------------------------------------------------------- */
double PairSPHLJ::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj, double &fforce) {
fforce = 0.0;
return 0.0;
}
/*double PairSPHLJ::LJEOS2(double rho, double e, double cv) {
double T = e / cv;
if (T < 1.e-2) T = 1.e-2;
//printf("%f %f\n", T, rho);
double iT = 0.1e1 / T;
//double itpow1_4 = exp(0.25 * log(iT)); //pow(iT, 0.1e1 / 0.4e1);
double itpow1_4 = pow(iT, 0.1e1 / 0.4e1);
double x = rho * itpow1_4;
double xsq = x * x;
double xpow3 = xsq * x;
double xpow4 = xsq * xsq;
double xpow9 = xpow3 * xpow3 * xpow3;
return (0.1e1 + rho * (0.3629e1 + 0.7264e1 * x + 0.104925e2 * xsq + 0.11460e2
* xpow3 + 0.21760e1 * xpow9 - itpow1_4 * itpow1_4 * (0.5369e1 + 0.13160e2
* x + 0.18525e2 * xsq - 0.17076e2 * xpow3 + 0.9320e1 * xpow4) + iT
* (-0.3492e1 + 0.18698e2 * x - 0.35505e2 * xsq + 0.31816e2 * xpow3
- 0.11195e2 * xpow4)) * itpow1_4) * rho * T;
}*/
/* --------------------------------------------------------------------------------------------- */
/* Lennard-Jones EOS,
Francis H. Ree
"Analytic representation of thermodynamic data for the Lennard‐Jones fluid",
Journal of Chemical Physics 73 pp. 5401-5403 (1980)
*/
void PairSPHLJ::LJEOS2(double rho, double e, double cv, double *p, double *c) {
double T = e/cv;
double beta = 1.0 / T;
double beta_sqrt = sqrt(beta);
double x = rho * sqrt(beta_sqrt);
double xsq = x * x;
double xpow3 = xsq * x;
double xpow4 = xsq * xsq;
/* differential of Helmholtz free energy w.r.t. x */
double diff_A_NkT = 3.629 + 7.264*x - beta*(3.492 - 18.698*x + 35.505*xsq - 31.816*xpow3 + 11.195*xpow4)
- beta_sqrt*(5.369 + 13.16*x + 18.525*xsq - 17.076*xpow3 + 9.32*xpow4)
+ 10.4925*xsq + 11.46*xpow3 + 2.176*xpow4*xpow4*x;
/* differential of Helmholtz free energy w.r.t. x^2 */
double d2A_dx2 = 7.264 + 20.985*x \
+ beta*(18.698 - 71.01*x + 95.448*xsq - 44.78*xpow3)\
- beta_sqrt*(13.16 + 37.05*x - 51.228*xsq + 37.28*xpow3)\
+ 34.38*xsq + 19.584*xpow4*xpow4;
// p = rho k T * (1 + rho * d(A/(NkT))/drho)
// dx/drho = rho/x
*p = rho * T * (1.0 + diff_A_NkT * x); // pressure
double csq = T * (1.0 + 2.0 * diff_A_NkT * x + d2A_dx2 * x * x); // soundspeed squared
if (csq > 0.0) {
*c = sqrt(csq); // soundspeed
} else {
*c = 0.0;
}
}
/* ------------------------------------------------------------------------------ */
/* Jirí Kolafa, Ivo Nezbeda
* "The Lennard-Jones fluid: an accurate analytic and theoretically-based equation of state",
* Fluid Phase Equilibria 100 pp. 1-34 (1994) */
/*double PairSPHLJ::LJEOS2(double rho, double e, double cv) {
double T = e / cv;
double sT = sqrt(T);
double isT = 1.0 / sT;
double dC = -0.063920968 * log(T) + 0.011117524 / T - 0.076383859 / sT
+ 1.080142248 + 0.000693129 * sT;
double eta = 3.141592654 / 6. * rho * (dC * dC * dC);
double zHS = (1 + eta * (1 + eta * (1 - eta / 1.5 * (1 + eta))))
/ ((1. - eta) * (1. - eta) * (1. - eta));
double BC = (((((-0.58544978 * isT + 0.43102052) * isT + .87361369) * isT
- 4.13749995) * isT + 2.90616279) * isT - 7.02181962) / T + 0.02459877;
double gammaBH = 1.92907278;
double sum = ((2.01546797 * 2 + rho * ((-28.17881636) * 3 + rho
* (28.28313847 * 4 + rho * (-10.42402873) * 5))) + (-19.58371655 * 2
+ rho * (+75.62340289 * 3 + rho * ((-120.70586598) * 4 + rho
* (+93.92740328 * 5 + rho * (-27.37737354) * 6)))) / sqrt(T)
+ ((29.34470520 * 2 + rho * ((-112.35356937) * 3 + rho * (+170.64908980
* 4 + rho * ((-123.06669187) * 5 + rho * 34.42288969 * 6))))
+ ((-13.37031968) * 2 + rho * (65.38059570 * 3 + rho
* ((-115.09233113) * 4 + rho * (88.91973082 * 5 + rho
* (-25.62099890) * 6)))) / T) / T) * rho * rho;
return ((zHS + BC / exp(gammaBH * rho * rho) * rho * (1 - 2 * gammaBH * rho
* rho)) * T + sum) * rho;
}
*/
diff --git a/src/USER-SPH/pair_sph_rhosum.cpp b/src/USER-SPH/pair_sph_rhosum.cpp
index b846b1bb4..f022e6dc4 100644
--- a/src/USER-SPH/pair_sph_rhosum.cpp
+++ b/src/USER-SPH/pair_sph_rhosum.cpp
@@ -1,316 +1,313 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_sph_rhosum.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "memory.h"
#include "error.h"
#include "neighbor.h"
#include "update.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairSPHRhoSum::PairSPHRhoSum(LAMMPS *lmp) :
Pair(lmp) {
// set comm size needed by this Pair
comm_forward = 1;
first = 1;
}
/* ---------------------------------------------------------------------- */
PairSPHRhoSum::~PairSPHRhoSum() {
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
}
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairSPHRhoSum::init_style() {
// need a full neighbor list
int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ---------------------------------------------------------------------- */
void PairSPHRhoSum::compute(int eflag, int vflag) {
int i, j, ii, jj, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz;
double r, rsq, imass, h, ih, ihsq;
int *jlist;
double wf;
// neighbor list variables
int inum, *ilist, *numneigh, **firstneigh;
if (eflag || vflag)
ev_setup(eflag, vflag);
else
evflag = vflag_fdotr = 0;
double **x = atom->x;
double *rho = atom->rho;
int *type = atom->type;
double *mass = atom->mass;
// check consistency of pair coefficients
if (first) {
for (i = 1; i <= atom->ntypes; i++) {
for (j = 1; i <= atom->ntypes; i++) {
if (cutsq[i][j] > 0.0) {
if (!setflag[i][i] || !setflag[j][j]) {
if (comm->me == 0) {
printf(
"SPH particle types %d and %d interact, but not all of their single particle properties are set.\n",
i, j);
}
}
}
}
}
first = 0;
}
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// recompute density
// we use a full neighborlist here
if (nstep != 0) {
if ((update->ntimestep % nstep) == 0) {
// initialize density with self-contribution,
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
itype = type[i];
imass = mass[itype];
h = cut[itype][itype];
if (domain->dimension == 3) {
/*
// Lucy kernel, 3d
wf = 2.0889086280811262819e0 / (h * h * h);
*/
// quadric kernel, 3d
wf = 2.1541870227086614782 / (h * h * h);
} else {
/*
// Lucy kernel, 2d
wf = 1.5915494309189533576e0 / (h * h);
*/
// quadric kernel, 2d
wf = 1.5915494309189533576e0 / (h * h);
}
rho[i] = imass * wf;
}
// add density at each atom via kernel function overlap
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
jtype = type[j];
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
if (rsq < cutsq[itype][jtype]) {
h = cut[itype][jtype];
ih = 1.0 / h;
ihsq = ih * ih;
if (domain->dimension == 3) {
/*
// Lucy kernel, 3d
r = sqrt(rsq);
wf = (h - r) * ihsq;
wf = 2.0889086280811262819e0 * (h + 3. * r) * wf * wf * wf * ih;
*/
// quadric kernel, 3d
wf = 1.0 - rsq * ihsq;
wf = wf * wf;
wf = wf * wf;
wf = 2.1541870227086614782e0 * wf * ihsq * ih;
} else {
// Lucy kernel, 2d
//r = sqrt(rsq);
//wf = (h - r) * ihsq;
//wf = 1.5915494309189533576e0 * (h + 3. * r) * wf * wf * wf;
// quadric kernel, 2d
wf = 1.0 - rsq * ihsq;
wf = wf * wf;
wf = wf * wf;
wf = 1.5915494309189533576e0 * wf * ihsq;
}
rho[i] += mass[jtype] * wf;
}
}
}
}
}
// communicate densities
comm->forward_comm_pair(this);
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairSPHRhoSum::allocate() {
allocated = 1;
int n = atom->ntypes;
memory->create(setflag, n + 1, n + 1, "pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
memory->create(cut, n + 1, n + 1, "pair:cut");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSPHRhoSum::settings(int narg, char **arg) {
if (narg != 1)
- error->all(
+ error->all(FLERR,
"Illegal number of setting arguments for pair_style sph/rhosum");
nstep = force->inumeric(arg[0]);
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSPHRhoSum::coeff(int narg, char **arg) {
if (narg != 3)
- error->all("Incorrect number of args for sph/rhosum coefficients");
+ error->all(FLERR,"Incorrect number of args for sph/rhosum coefficients");
if (!allocated)
allocate();
int ilo, ihi, jlo, jhi;
force->bounds(arg[0], atom->ntypes, ilo, ihi);
force->bounds(arg[1], atom->ntypes, jlo, jhi);
double cut_one = force->numeric(arg[2]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
//printf("setting cut[%d][%d] = %f\n", i, j, cut_one);
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSPHRhoSum::init_one(int i, int j) {
if (setflag[i][j] == 0) {
- error->all("All pair sph/rhosum coeffs are not set");
+ error->all(FLERR,"All pair sph/rhosum coeffs are not set");
}
cut[j][i] = cut[i][j];
return cut[i][j];
}
/* ---------------------------------------------------------------------- */
double PairSPHRhoSum::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj, double &fforce) {
fforce = 0.0;
return 0.0;
}
/* ---------------------------------------------------------------------- */
int PairSPHRhoSum::pack_comm(int n, int *list, double *buf, int pbc_flag,
int *pbc) {
int i, j, m;
double *rho = atom->rho;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = rho[j];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void PairSPHRhoSum::unpack_comm(int n, int first, double *buf) {
int i, m, last;
double *rho = atom->rho;
m = 0;
last = first + n;
for (i = first; i < last; i++)
rho[i] = buf[m++];
}
diff --git a/src/USER-SPH/pair_sph_taitwater.cpp b/src/USER-SPH/pair_sph_taitwater.cpp
index 0226d8fed..86723dd4c 100644
--- a/src/USER-SPH/pair_sph_taitwater.cpp
+++ b/src/USER-SPH/pair_sph_taitwater.cpp
@@ -1,303 +1,300 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_sph_taitwater.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairSPHTaitwater::PairSPHTaitwater(LAMMPS *lmp) :
Pair(lmp) {
first = 1;
}
/* ---------------------------------------------------------------------- */
PairSPHTaitwater::~PairSPHTaitwater() {
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(rho0);
memory->destroy(soundspeed);
memory->destroy(B);
memory->destroy(viscosity);
}
}
/* ---------------------------------------------------------------------- */
void PairSPHTaitwater::compute(int eflag, int vflag) {
int i, j, ii, jj, inum, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz, fpair;
int *ilist, *jlist, *numneigh, **firstneigh;
double vxtmp, vytmp, vztmp, imass, jmass, fi, fj, fvisc, h, ih, ihsq;
double rsq, tmp, wfd, delVdotDelR, mu, deltaE;
if (eflag || vflag)
ev_setup(eflag, vflag);
else
evflag = vflag_fdotr = 0;
double **v = atom->vest;
double **x = atom->x;
double **f = atom->f;
double *rho = atom->rho;
double *mass = atom->mass;
double *de = atom->de;
double *drho = atom->drho;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
// check consistency of pair coefficients
if (first) {
for (i = 1; i <= atom->ntypes; i++) {
for (j = 1; i <= atom->ntypes; i++) {
if (cutsq[i][j] > 1.e-32) {
if (!setflag[i][i] || !setflag[j][j]) {
if (comm->me == 0) {
printf(
"SPH particle types %d and %d interact with cutoff=%g, but not all of their single particle properties are set.\n",
i, j, sqrt(cutsq[i][j]));
}
}
}
}
}
first = 0;
}
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
vxtmp = v[i][0];
vytmp = v[i][1];
vztmp = v[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
imass = mass[itype];
// compute pressure of atom i with Tait EOS
tmp = rho[i] / rho0[itype];
fi = tmp * tmp * tmp;
fi = B[itype] * (fi * fi * tmp - 1.0) / (rho[i] * rho[i]);
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
jtype = type[j];
jmass = mass[jtype];
if (rsq < cutsq[itype][jtype]) {
h = cut[itype][jtype];
ih = 1.0 / h;
ihsq = ih * ih;
wfd = h - sqrt(rsq);
if (domain->dimension == 3) {
// Lucy Kernel, 3d
// Note that wfd, the derivative of the weight function with respect to r,
// is lacking a factor of r.
// The missing factor of r is recovered by
// (1) using delV . delX instead of delV . (delX/r) and
// (2) using f[i][0] += delx * fpair instead of f[i][0] += (delx/r) * fpair
wfd = -25.066903536973515383e0 * wfd * wfd * ihsq * ihsq * ihsq * ih;
} else {
// Lucy Kernel, 2d
wfd = -19.098593171027440292e0 * wfd * wfd * ihsq * ihsq * ihsq;
}
// compute pressure of atom j with Tait EOS
tmp = rho[j] / rho0[jtype];
fj = tmp * tmp * tmp;
fj = B[jtype] * (fj * fj * tmp - 1.0) / (rho[j] * rho[j]);
// dot product of velocity delta and distance vector
delVdotDelR = delx * (vxtmp - v[j][0]) + dely * (vytmp - v[j][1])
+ delz * (vztmp - v[j][2]);
// artificial viscosity (Monaghan 1992)
if (delVdotDelR < 0.) {
mu = h * delVdotDelR / (rsq + 0.01 * h * h);
fvisc = -viscosity[itype][jtype] * (soundspeed[itype]
+ soundspeed[jtype]) * mu / (rho[i] + rho[j]);
} else {
fvisc = 0.;
}
// total pair force & thermal energy increment
fpair = -imass * jmass * (fi + fj + fvisc) * wfd;
deltaE = -0.5 * fpair * delVdotDelR;
f[i][0] += delx * fpair;
f[i][1] += dely * fpair;
f[i][2] += delz * fpair;
// and change in density
drho[i] += jmass * delVdotDelR * wfd;
// change in thermal energy
de[i] += deltaE;
if (newton_pair || j < nlocal) {
f[j][0] -= delx * fpair;
f[j][1] -= dely * fpair;
f[j][2] -= delz * fpair;
de[j] += deltaE;
drho[j] += imass * delVdotDelR * wfd;
}
if (evflag)
ev_tally(i, j, nlocal, newton_pair, 0.0, 0.0, fpair, delx, dely, delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairSPHTaitwater::allocate() {
allocated = 1;
int n = atom->ntypes;
memory->create(setflag, n + 1, n + 1, "pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
memory->create(rho0, n + 1, "pair:rho0");
memory->create(soundspeed, n + 1, "pair:soundspeed");
memory->create(B, n + 1, "pair:B");
memory->create(cut, n + 1, n + 1, "pair:cut");
memory->create(viscosity, n + 1, n + 1, "pair:viscosity");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSPHTaitwater::settings(int narg, char **arg) {
if (narg != 0)
- error->all(
+ error->all(FLERR,
"Illegal number of setting arguments for pair_style sph/taitwater");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSPHTaitwater::coeff(int narg, char **arg) {
if (narg != 6)
- error->all(
+ error->all(FLERR,
"Incorrect args for pair_style sph/taitwater coefficients");
if (!allocated)
allocate();
int ilo, ihi, jlo, jhi;
force->bounds(arg[0], atom->ntypes, ilo, ihi);
force->bounds(arg[1], atom->ntypes, jlo, jhi);
double rho0_one = force->numeric(arg[2]);
double soundspeed_one = force->numeric(arg[3]);
double viscosity_one = force->numeric(arg[4]);
double cut_one = force->numeric(arg[5]);
double B_one = soundspeed_one * soundspeed_one * rho0_one / 7.0;
int count = 0;
for (int i = ilo; i <= ihi; i++) {
rho0[i] = rho0_one;
soundspeed[i] = soundspeed_one;
B[i] = B_one;
for (int j = MAX(jlo,i); j <= jhi; j++) {
viscosity[i][j] = viscosity_one;
//printf("setting cut[%d][%d] = %f\n", i, j, cut_one);
cut[i][j] = cut_one;
setflag[i][j] = 1;
//cut[j][i] = cut[i][j];
//viscosity[j][i] = viscosity[i][j];
//setflag[j][i] = 1;
count++;
}
}
if (count == 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSPHTaitwater::init_one(int i, int j) {
if (setflag[i][j] == 0) {
- error->all("Not all pair sph/taitwater coeffs are set");
+ error->all(FLERR,"Not all pair sph/taitwater coeffs are set");
}
cut[j][i] = cut[i][j];
viscosity[j][i] = viscosity[i][j];
return cut[i][j];
}
/* ---------------------------------------------------------------------- */
double PairSPHTaitwater::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj, double &fforce) {
fforce = 0.0;
return 0.0;
}
diff --git a/src/USER-SPH/pair_sph_taitwater_morris.cpp b/src/USER-SPH/pair_sph_taitwater_morris.cpp
index 5e5eb1d09..d1092cf6e 100644
--- a/src/USER-SPH/pair_sph_taitwater_morris.cpp
+++ b/src/USER-SPH/pair_sph_taitwater_morris.cpp
@@ -1,300 +1,297 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_sph_taitwater_morris.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
#include "domain.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairSPHTaitwaterMorris::PairSPHTaitwaterMorris(LAMMPS *lmp) :
Pair(lmp) {
first = 1;
}
/* ---------------------------------------------------------------------- */
PairSPHTaitwaterMorris::~PairSPHTaitwaterMorris() {
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(rho0);
memory->destroy(soundspeed);
memory->destroy(B);
memory->destroy(viscosity);
}
}
/* ---------------------------------------------------------------------- */
void PairSPHTaitwaterMorris::compute(int eflag, int vflag) {
int i, j, ii, jj, inum, jnum, itype, jtype;
double xtmp, ytmp, ztmp, delx, dely, delz, fpair;
int *ilist, *jlist, *numneigh, **firstneigh;
double vxtmp, vytmp, vztmp, imass, jmass, fi, fj, fvisc, h, ih, ihsq, velx, vely, velz;
double rsq, tmp, wfd, delVdotDelR, deltaE;
if (eflag || vflag)
ev_setup(eflag, vflag);
else
evflag = vflag_fdotr = 0;
double **v = atom->vest;
double **x = atom->x;
double **f = atom->f;
double *rho = atom->rho;
double *mass = atom->mass;
double *de = atom->de;
double *drho = atom->drho;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
// check consistency of pair coefficients
if (first) {
for (i = 1; i <= atom->ntypes; i++) {
for (j = 1; i <= atom->ntypes; i++) {
if (cutsq[i][j] > 1.e-32) {
if (!setflag[i][i] || !setflag[j][j]) {
if (comm->me == 0) {
printf(
"SPH particle types %d and %d interact with cutoff=%g, but not all of their single particle properties are set.\n",
i, j, sqrt(cutsq[i][j]));
}
}
}
}
}
first = 0;
}
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
vxtmp = v[i][0];
vytmp = v[i][1];
vztmp = v[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
imass = mass[itype];
// compute pressure of atom i with Tait EOS
tmp = rho[i] / rho0[itype];
fi = tmp * tmp * tmp;
fi = B[itype] * (fi * fi * tmp - 1.0) / (rho[i] * rho[i]);
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx * delx + dely * dely + delz * delz;
jtype = type[j];
jmass = mass[jtype];
if (rsq < cutsq[itype][jtype]) {
h = cut[itype][jtype];
ih = 1.0 / h;
ihsq = ih * ih;
wfd = h - sqrt(rsq);
if (domain->dimension == 3) {
// Lucy Kernel, 3d
// Note that wfd, the derivative of the weight function with respect to r,
// is lacking a factor of r.
// The missing factor of r is recovered by
// (1) using delV . delX instead of delV . (delX/r) and
// (2) using f[i][0] += delx * fpair instead of f[i][0] += (delx/r) * fpair
wfd = -25.066903536973515383e0 * wfd * wfd * ihsq * ihsq * ihsq * ih;
} else {
// Lucy Kernel, 2d
wfd = -19.098593171027440292e0 * wfd * wfd * ihsq * ihsq * ihsq;
}
// compute pressure of atom j with Tait EOS
tmp = rho[j] / rho0[jtype];
fj = tmp * tmp * tmp;
fj = B[jtype] * (fj * fj * tmp - 1.0) / (rho[j] * rho[j]);
velx=vxtmp - v[j][0];
vely=vytmp - v[j][1];
velz=vztmp - v[j][2];
// dot product of velocity delta and distance vector
delVdotDelR = delx * velx + dely * vely + delz * velz;
// Morris Viscosity (Morris, 1996)
fvisc = 2 * viscosity[itype][jtype] / (rho[i] * rho[j]);
fvisc *= imass * jmass * wfd;
// total pair force & thermal energy increment
fpair = -imass * jmass * (fi + fj) * wfd;
deltaE = -0.5 *(fpair * delVdotDelR + fvisc * (velx*velx + vely*vely + velz*velz));
// printf("testvar= %f, %f \n", delx, dely);
f[i][0] += delx * fpair + velx * fvisc;
f[i][1] += dely * fpair + vely * fvisc;
f[i][2] += delz * fpair + velz * fvisc;
// and change in density
drho[i] += jmass * delVdotDelR * wfd;
// change in thermal energy
de[i] += deltaE;
if (newton_pair || j < nlocal) {
f[j][0] -= delx * fpair + velx * fvisc;
f[j][1] -= dely * fpair + vely * fvisc;
f[j][2] -= delz * fpair + velz * fvisc;
de[j] += deltaE;
drho[j] += imass * delVdotDelR * wfd;
}
if (evflag)
ev_tally(i, j, nlocal, newton_pair, 0.0, 0.0, fpair, delx, dely, delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairSPHTaitwaterMorris::allocate() {
allocated = 1;
int n = atom->ntypes;
memory->create(setflag, n + 1, n + 1, "pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq, n + 1, n + 1, "pair:cutsq");
memory->create(rho0, n + 1, "pair:rho0");
memory->create(soundspeed, n + 1, "pair:soundspeed");
memory->create(B, n + 1, "pair:B");
memory->create(cut, n + 1, n + 1, "pair:cut");
memory->create(viscosity, n + 1, n + 1, "pair:viscosity");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSPHTaitwaterMorris::settings(int narg, char **arg) {
if (narg != 0)
- error->all(
+ error->all(FLERR,
"Illegal number of setting arguments for pair_style sph/taitwater/morris");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSPHTaitwaterMorris::coeff(int narg, char **arg) {
if (narg != 6)
- error->all(
+ error->all(FLERR,
"Incorrect args for pair_style sph/taitwater/morris coefficients");
if (!allocated)
allocate();
int ilo, ihi, jlo, jhi;
force->bounds(arg[0], atom->ntypes, ilo, ihi);
force->bounds(arg[1], atom->ntypes, jlo, jhi);
double rho0_one = force->numeric(arg[2]);
double soundspeed_one = force->numeric(arg[3]);
double viscosity_one = force->numeric(arg[4]);
double cut_one = force->numeric(arg[5]);
double B_one = soundspeed_one * soundspeed_one * rho0_one / 7.0;
int count = 0;
for (int i = ilo; i <= ihi; i++) {
rho0[i] = rho0_one;
soundspeed[i] = soundspeed_one;
B[i] = B_one;
for (int j = MAX(jlo,i); j <= jhi; j++) {
viscosity[i][j] = viscosity_one;
//printf("setting cut[%d][%d] = %f\n", i, j, cut_one);
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
if (count == 0)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSPHTaitwaterMorris::init_one(int i, int j) {
if (setflag[i][j] == 0) {
- error->all("Not all pair sph/taitwater/morris coeffs are not set");
+ error->all(FLERR,"Not all pair sph/taitwater/morris coeffs are not set");
}
cut[j][i] = cut[i][j];
viscosity[j][i] = viscosity[i][j];
return cut[i][j];
}
/* ---------------------------------------------------------------------- */
double PairSPHTaitwaterMorris::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj, double &fforce) {
fforce = 0.0;
return 0.0;
}
diff --git a/src/XTC/dump_xtc.cpp b/src/XTC/dump_xtc.cpp
index f5355cdf5..12d3719da 100644
--- a/src/XTC/dump_xtc.cpp
+++ b/src/XTC/dump_xtc.cpp
@@ -1,1207 +1,1207 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Naveen Michaud-Agrawal (Johns Hopkins U)
open-source XDR routines from
Frans van Hoesel (http://md.chem.rug.nl/hoesel)
are included in this file
Axel Kohlmeyer (Temple U)
port to platforms without XDR support
added support for unwrapped trajectories
support for groups
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "limits.h"
#include "dump_xtc.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "output.h"
#include "error.h"
#include "memory.h"
using namespace LAMMPS_NS;
#define EPS 1e-5
#define XTC_MAGIC 1995
#define MYMIN(a,b) ((a) < (b) ? (a) : (b))
#define MYMAX(a,b) ((a) > (b) ? (a) : (b))
int xdropen(XDR *, const char *, const char *);
int xdrclose(XDR *);
void xdrfreebuf();
int xdr3dfcoord(XDR *, float *, int *, float *);
/* ---------------------------------------------------------------------- */
DumpXTC::DumpXTC(LAMMPS *lmp, int narg, char **arg) : Dump(lmp, narg, arg)
{
- if (narg != 5) error->all("Illegal dump xtc command");
+ if (narg != 5) error->all(FLERR,"Illegal dump xtc command");
if (binary || compressed || multifile || multiproc)
- error->all("Invalid dump xtc filename");
+ error->all(FLERR,"Invalid dump xtc filename");
size_one = 3;
sort_flag = 1;
sortcol = 0;
format_default = NULL;
flush_flag = 0;
unwrap_flag = 0;
precision = 1000.0;
// allocate global array for atom coords
bigint n = group->count(igroup);
if (n > MAXSMALLINT/3/sizeof(float))
- error->all("Too many atoms for dump xtc");
+ error->all(FLERR,"Too many atoms for dump xtc");
natoms = static_cast<int> (n);
memory->create(coords,3*natoms,"dump:coords");
// sfactor = conversion of coords to XTC units
// GROMACS standard is nanometers, not Angstroms
sfactor = 0.1;
if (strcmp(update->unit_style,"lj") == 0) sfactor = 1.0;
openfile();
nevery_save = 0;
ntotal = 0;
}
/* ---------------------------------------------------------------------- */
DumpXTC::~DumpXTC()
{
memory->destroy(coords);
if (me == 0) {
xdrclose(&xd);
xdrfreebuf();
}
}
/* ---------------------------------------------------------------------- */
void DumpXTC::init_style()
{
if (sort_flag == 0 || sortcol != 0)
- error->all("Dump xtc requires sorting by atom ID");
+ error->all(FLERR,"Dump xtc requires sorting by atom ID");
// check that flush_flag is not set since dump::write() will use it
- if (flush_flag) error->all("Cannot set dump_modify flush for dump xtc");
+ if (flush_flag) error->all(FLERR,"Cannot set dump_modify flush for dump xtc");
// check that dump frequency has not changed and is not a variable
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
if (output->every_dump[idump] == 0)
- error->all("Cannot use variable every setting for dump xtc");
+ error->all(FLERR,"Cannot use variable every setting for dump xtc");
if (nevery_save == 0) nevery_save = output->every_dump[idump];
else if (nevery_save != output->every_dump[idump])
- error->all("Cannot change dump_modify every for dump xtc");
+ error->all(FLERR,"Cannot change dump_modify every for dump xtc");
}
/* ---------------------------------------------------------------------- */
void DumpXTC::openfile()
{
// XTC maintains it's own XDR file ptr
// set fp to NULL so parent dump class will not use it
fp = NULL;
if (me == 0)
- if (xdropen(&xd,filename,"w") == 0) error->one("Cannot open dump file");
+ if (xdropen(&xd,filename,"w") == 0) error->one(FLERR,"Cannot open dump file");
}
/* ---------------------------------------------------------------------- */
void DumpXTC::write_header(bigint nbig)
{
- if (nbig > MAXSMALLINT) error->all("Too many atoms for dump xtc");
+ if (nbig > MAXSMALLINT) error->all(FLERR,"Too many atoms for dump xtc");
int n = nbig;
if (update->ntimestep > MAXSMALLINT)
- error->all("Too big a timestep for dump xtc");
+ error->all(FLERR,"Too big a timestep for dump xtc");
int ntimestep = update->ntimestep;
// all procs realloc coords if total count grew
if (n != natoms) {
natoms = n;
memory->destroy(coords);
memory->create(coords,3*natoms,"dump:coords");
}
// only proc 0 writes header
if (me != 0) return;
int tmp = XTC_MAGIC;
xdr_int(&xd,&tmp);
xdr_int(&xd,&n);
xdr_int(&xd,&ntimestep);
float time_value = ntimestep * update->dt;
xdr_float(&xd,&time_value);
// cell basis vectors
if (domain->triclinic) {
float zero = 0.0;
float xdim = sfactor * (domain->boxhi[0] - domain->boxlo[0]);
float ydim = sfactor * (domain->boxhi[1] - domain->boxlo[1]);
float zdim = sfactor * (domain->boxhi[2] - domain->boxlo[2]);
float xy = sfactor * domain->xy;
float xz = sfactor * domain->xz;
float yz = sfactor * domain->yz;
xdr_float(&xd,&xdim); xdr_float(&xd,&zero); xdr_float(&xd,&zero);
xdr_float(&xd,&xy ); xdr_float(&xd,&ydim); xdr_float(&xd,&zero);
xdr_float(&xd,&xz ); xdr_float(&xd,&yz ); xdr_float(&xd,&zdim);
} else {
float zero = 0.0;
float xdim = sfactor * (domain->boxhi[0] - domain->boxlo[0]);
float ydim = sfactor * (domain->boxhi[1] - domain->boxlo[1]);
float zdim = sfactor * (domain->boxhi[2] - domain->boxlo[2]);
xdr_float(&xd,&xdim); xdr_float(&xd,&zero); xdr_float(&xd,&zero);
xdr_float(&xd,&zero); xdr_float(&xd,&ydim); xdr_float(&xd,&zero);
xdr_float(&xd,&zero); xdr_float(&xd,&zero); xdr_float(&xd,&zdim);
}
}
/* ---------------------------------------------------------------------- */
int DumpXTC::count()
{
if (igroup == 0) return atom->nlocal;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) m++;
return m;
}
/* ---------------------------------------------------------------------- */
void DumpXTC::pack(int *ids)
{
int m,n;
int *tag = atom->tag;
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
m = n = 0;
if (unwrap_flag == 1) {
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double xy = domain->xy;
double xz = domain->xz;
double yz = domain->yz;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
int ix = (image[i] & 1023) - 512;
int iy = (image[i] >> 10 & 1023) - 512;
int iz = (image[i] >> 20) - 512;
if (domain->triclinic) {
buf[m++] = sfactor * (x[i][0] + ix * xprd + iy * xy + iz * xz);
buf[m++] = sfactor * (x[i][1] + iy * yprd + iz * yz);
buf[m++] = sfactor * (x[i][2] + iz * zprd);
} else {
buf[m++] = sfactor * (x[i][0] + ix * xprd);
buf[m++] = sfactor * (x[i][1] + iy * yprd);
buf[m++] = sfactor * (x[i][2] + iz * zprd);
}
ids[n++] = tag[i];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = sfactor*x[i][0];
buf[m++] = sfactor*x[i][1];
buf[m++] = sfactor*x[i][2];
ids[n++] = tag[i];
}
}
}
/* ---------------------------------------------------------------------- */
void DumpXTC::write_data(int n, double *mybuf)
{
// copy buf atom coords into global array
int m = 0;
int k = 3*ntotal;
for (int i = 0; i < n; i++) {
coords[k++] = mybuf[m++];
coords[k++] = mybuf[m++];
coords[k++] = mybuf[m++];
ntotal++;
}
// if last chunk of atoms in this snapshot, write global arrays to file
if (ntotal == natoms) {
write_frame();
ntotal = 0;
}
}
/* ---------------------------------------------------------------------- */
int DumpXTC::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"unwrap") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1;
else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
return 2;
} else if (strcmp(arg[0],"precision") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
precision = atof(arg[1]);
if ((fabs(precision-10.0) > EPS) && (fabs(precision-100.0) > EPS) &&
(fabs(precision-1000.0) > EPS) && (fabs(precision-10000.0) > EPS) &&
(fabs(precision-100000.0) > EPS) &&
(fabs(precision-1000000.0) > EPS))
- error->all("Illegal dump_modify command");
+ error->all(FLERR,"Illegal dump_modify command");
return 2;
}
return 0;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory in buf and global coords array
------------------------------------------------------------------------- */
bigint DumpXTC::memory_usage()
{
bigint bytes = Dump::memory_usage();
bytes += memory->usage(coords,natoms*3);
return bytes;
}
/* ---------------------------------------------------------------------- */
void DumpXTC::write_frame()
{
xdr3dfcoord(&xd,coords,&natoms,&precision);
}
// ----------------------------------------------------------------------
// C functions that create GROMOS-compatible XDR files
// open-source
// (c) 1995 Frans van Hoesel, hoesel@chem.rug.nl
// ----------------------------------------------------------------------
/*____________________________________________________________________________
|
| Below are the routines to be used by C programmers. Use the 'normal'
| xdr routines to write integers, floats, etc (see man xdr)
|
| int xdropen(XDR *xdrs, const char *filename, const char *type)
| This will open the file with the given filename and the
| given mode. You should pass it an allocated XDR struct
| in xdrs, to be used in all other calls to xdr routines.
| Mode is 'w' to create, or update an file, and for all
| other values of mode the file is opened for reading.
| You need to call xdrclose to flush the output and close
| the file.
|
| Note that you should not use xdrstdio_create, which
| comes with the standard xdr library.
|
| int xdrclose(XDR *xdrs)
| Flush the data to the file, and close the file;
| You should not use xdr_destroy (which comes standard
| with the xdr libraries).
|
| int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision)
| This is \fInot\fR a standard xdr routine. I named it this
| way, because it invites people to use the other xdr
| routines.
|
| (c) 1995 Frans van Hoesel, hoesel@chem.rug.nl
*/
#define MAXID 20
static FILE *xdrfiles[MAXID];
static XDR *xdridptr[MAXID];
static char xdrmodes[MAXID];
static int *ip = NULL;
static int *buf = NULL;
/*___________________________________________________________________________
|
| what follows are the C routines for opening, closing xdr streams
| and the routine to read/write compressed coordinates together
| with some routines to assist in this task (those are marked
| static and cannot be called from user programs)
*/
#define MAXABS INT_MAX-2
#ifndef SQR
#define SQR(x) ((x)*(x))
#endif
static int magicints[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0,
8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127,
524287, 660561,
832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021,
4194304, 5284491, 6658042,
8388607, 10568983, 13316085, 16777216 };
#define FIRSTIDX 9
/* note that magicints[FIRSTIDX-1] == 0 */
#define LASTIDX (sizeof(magicints) / sizeof(*magicints))
/*__________________________________________________________________________
|
| xdropen - open xdr file
|
| This versions differs from xdrstdio_create, because I need to know
| the state of the file (read or write) so I can use xdr3dfcoord
| in eigther read or write mode, and the file descriptor
| so I can close the file (something xdr_destroy doesn't do).
|
*/
int xdropen(XDR *xdrs, const char *filename, const char *type)
{
static int init_done = 0;
enum xdr_op lmode;
int xdrid;
if (init_done == 0) {
for (xdrid = 1; xdrid < MAXID; xdrid++) {
xdridptr[xdrid] = NULL;
}
init_done = 1;
}
xdrid = 1;
while (xdrid < MAXID && xdridptr[xdrid] != NULL) {
xdrid++;
}
if (xdrid == MAXID) {
return 0;
}
if (*type == 'w' || *type == 'W') {
type = (char *) "w+";
lmode = XDR_ENCODE;
} else {
type = (char *) "r";
lmode = XDR_DECODE;
}
xdrfiles[xdrid] = fopen(filename, type);
if (xdrfiles[xdrid] == NULL) {
xdrs = NULL;
return 0;
}
xdrmodes[xdrid] = *type;
/* next test isn't usefull in the case of C language
* but is used for the Fortran interface
* (C users are expected to pass the address of an already allocated
* XDR staructure)
*/
if (xdrs == NULL) {
xdridptr[xdrid] = (XDR *) malloc(sizeof(XDR));
xdrstdio_create(xdridptr[xdrid], xdrfiles[xdrid], lmode);
} else {
xdridptr[xdrid] = xdrs;
xdrstdio_create(xdrs, xdrfiles[xdrid], lmode);
}
return xdrid;
}
/*_________________________________________________________________________
|
| xdrclose - close a xdr file
|
| This will flush the xdr buffers, and destroy the xdr stream.
| It also closes the associated file descriptor (this is *not*
| done by xdr_destroy).
|
*/
int xdrclose(XDR *xdrs)
{
int xdrid;
if (xdrs == NULL) {
fprintf(stderr, "xdrclose: passed a NULL pointer\n");
exit(1);
}
for (xdrid = 1; xdrid < MAXID; xdrid++) {
if (xdridptr[xdrid] == xdrs) {
xdr_destroy(xdrs);
fclose(xdrfiles[xdrid]);
xdridptr[xdrid] = NULL;
return 1;
}
}
fprintf(stderr, "xdrclose: no such open xdr file\n");
exit(1);
return 1;
}
/*_________________________________________________________________________
|
| xdrfreebuf - free the buffers used by xdr3dfcoord
|
*/
void xdrfreebuf()
{
if (ip) free(ip);
if (buf) free(buf);
ip = NULL;
buf = NULL;
}
/*____________________________________________________________________________
|
| sendbits - encode num into buf using the specified number of bits
|
| This routines appends the value of num to the bits already present in
| the array buf. You need to give it the number of bits to use and you
| better make sure that this number of bits is enough to hold the value
| Also num must be positive.
|
*/
static void sendbits(int buf[], int num_of_bits, int num)
{
unsigned int cnt, lastbyte;
int lastbits;
unsigned char * cbuf;
cbuf = ((unsigned char *)buf) + 3 * sizeof(*buf);
cnt = (unsigned int) buf[0];
lastbits = buf[1];
lastbyte =(unsigned int) buf[2];
while (num_of_bits >= 8) {
lastbyte = (lastbyte << 8) | ((num >> (num_of_bits -8)) /* & 0xff*/);
cbuf[cnt++] = lastbyte >> lastbits;
num_of_bits -= 8;
}
if (num_of_bits > 0) {
lastbyte = (lastbyte << num_of_bits) | num;
lastbits += num_of_bits;
if (lastbits >= 8) {
lastbits -= 8;
cbuf[cnt++] = lastbyte >> lastbits;
}
}
buf[0] = cnt;
buf[1] = lastbits;
buf[2] = lastbyte;
if (lastbits>0) {
cbuf[cnt] = lastbyte << (8 - lastbits);
}
}
/*_________________________________________________________________________
|
| sizeofint - calculate bitsize of an integer
|
| return the number of bits needed to store an integer with given max size
|
*/
static int sizeofint(const int size)
{
unsigned int num = 1;
int num_of_bits = 0;
while (size >= num && num_of_bits < 32) {
num_of_bits++;
num <<= 1;
}
return num_of_bits;
}
/*___________________________________________________________________________
|
| sizeofints - calculate 'bitsize' of compressed ints
|
| given the number of small unsigned integers and the maximum value
| return the number of bits needed to read or write them with the
| routines receiveints and sendints. You need this parameter when
| calling these routines. Note that for many calls I can use
| the variable 'smallidx' which is exactly the number of bits, and
| So I don't need to call 'sizeofints for those calls.
*/
static int sizeofints( const int num_of_ints, unsigned int sizes[])
{
int i, num;
unsigned int num_of_bytes, num_of_bits, bytes[32], bytecnt, tmp;
num_of_bytes = 1;
bytes[0] = 1;
num_of_bits = 0;
for (i=0; i < num_of_ints; i++) {
tmp = 0;
for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++) {
tmp = bytes[bytecnt] * sizes[i] + tmp;
bytes[bytecnt] = tmp & 0xff;
tmp >>= 8;
}
while (tmp != 0) {
bytes[bytecnt++] = tmp & 0xff;
tmp >>= 8;
}
num_of_bytes = bytecnt;
}
num = 1;
num_of_bytes--;
while (bytes[num_of_bytes] >= num) {
num_of_bits++;
num *= 2;
}
return num_of_bits + num_of_bytes * 8;
}
/*____________________________________________________________________________
|
| sendints - send a small set of small integers in compressed
|
| this routine is used internally by xdr3dfcoord, to send a set of
| small integers to the buffer.
| Multiplication with fixed (specified maximum ) sizes is used to get
| to one big, multibyte integer. Allthough the routine could be
| modified to handle sizes bigger than 16777216, or more than just
| a few integers, this is not done, because the gain in compression
| isn't worth the effort. Note that overflowing the multiplication
| or the byte buffer (32 bytes) is unchecked and causes bad results.
|
*/
static void sendints(int buf[], const int num_of_ints, const int num_of_bits,
unsigned int sizes[], unsigned int nums[])
{
int i;
unsigned int bytes[32], num_of_bytes, bytecnt, tmp;
tmp = nums[0];
num_of_bytes = 0;
do {
bytes[num_of_bytes++] = tmp & 0xff;
tmp >>= 8;
} while (tmp != 0);
for (i = 1; i < num_of_ints; i++) {
if (nums[i] >= sizes[i]) {
fprintf(stderr,"major breakdown in sendints num %d doesn't "
"match size %d\n", nums[i], sizes[i]);
exit(1);
}
/* use one step multiply */
tmp = nums[i];
for (bytecnt = 0; bytecnt < num_of_bytes; bytecnt++) {
tmp = bytes[bytecnt] * sizes[i] + tmp;
bytes[bytecnt] = tmp & 0xff;
tmp >>= 8;
}
while (tmp != 0) {
bytes[bytecnt++] = tmp & 0xff;
tmp >>= 8;
}
num_of_bytes = bytecnt;
}
if (num_of_bits >= num_of_bytes * 8) {
for (i = 0; i < num_of_bytes; i++) {
sendbits(buf, 8, bytes[i]);
}
sendbits(buf, num_of_bits - num_of_bytes * 8, 0);
} else {
for (i = 0; i < num_of_bytes-1; i++) {
sendbits(buf, 8, bytes[i]);
}
sendbits(buf, num_of_bits- (num_of_bytes -1) * 8, bytes[i]);
}
}
/*___________________________________________________________________________
|
| receivebits - decode number from buf using specified number of bits
|
| extract the number of bits from the array buf and construct an integer
| from it. Return that value.
|
*/
static int receivebits(int buf[], int num_of_bits)
{
int cnt, num;
unsigned int lastbits, lastbyte;
unsigned char * cbuf;
int mask = (1 << num_of_bits) -1;
cbuf = ((unsigned char *)buf) + 3 * sizeof(*buf);
cnt = buf[0];
lastbits = (unsigned int) buf[1];
lastbyte = (unsigned int) buf[2];
num = 0;
while (num_of_bits >= 8) {
lastbyte = ( lastbyte << 8 ) | cbuf[cnt++];
num |= (lastbyte >> lastbits) << (num_of_bits - 8);
num_of_bits -=8;
}
if (num_of_bits > 0) {
if (lastbits < num_of_bits) {
lastbits += 8;
lastbyte = (lastbyte << 8) | cbuf[cnt++];
}
lastbits -= num_of_bits;
num |= (lastbyte >> lastbits) & ((1 << num_of_bits) -1);
}
num &= mask;
buf[0] = cnt;
buf[1] = lastbits;
buf[2] = lastbyte;
return num;
}
/*____________________________________________________________________________
|
| receiveints - decode 'small' integers from the buf array
|
| this routine is the inverse from sendints() and decodes the small integers
| written to buf by calculating the remainder and doing divisions with
| the given sizes[]. You need to specify the total number of bits to be
| used from buf in num_of_bits.
|
*/
static void receiveints(int buf[], const int num_of_ints, int num_of_bits,
unsigned int sizes[], int nums[])
{
int bytes[32];
int i, j, num_of_bytes, p, num;
bytes[1] = bytes[2] = bytes[3] = 0;
num_of_bytes = 0;
while (num_of_bits > 8) {
bytes[num_of_bytes++] = receivebits(buf, 8);
num_of_bits -= 8;
}
if (num_of_bits > 0) {
bytes[num_of_bytes++] = receivebits(buf, num_of_bits);
}
for (i = num_of_ints-1; i > 0; i--) {
num = 0;
for (j = num_of_bytes-1; j >=0; j--) {
num = (num << 8) | bytes[j];
p = num / sizes[i];
bytes[j] = p;
num = num - p * sizes[i];
}
nums[i] = num;
}
nums[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
}
/*____________________________________________________________________________
|
| xdr3dfcoord - read or write compressed 3d coordinates to xdr file.
|
| this routine reads or writes (depending on how you opened the file with
| xdropen() ) a large number of 3d coordinates (stored in *fp).
| The number of coordinates triplets to write is given by *size. On
| read this number may be zero, in which case it reads as many as were written
| or it may specify the number if triplets to read (which should match the
| number written).
| Compression is achieved by first converting all floating numbers to integer
| using multiplication by *precision and rounding to the nearest integer.
| Then the minimum and maximum value are calculated to determine the range.
| The limited range of integers so found, is used to compress the coordinates.
| In addition the differences between succesive coordinates is calculated.
| If the difference happens to be 'small' then only the difference is saved,
| compressing the data even more. The notion of 'small' is changed dynamically
| and is enlarged or reduced whenever needed or possible.
| Extra compression is achieved in the case of GROMOS and coordinates of
| water molecules. GROMOS first writes out the Oxygen position, followed by
| the two hydrogens. In order to make the differences smaller (and thereby
| compression the data better) the order is changed into first one hydrogen
| then the oxygen, followed by the other hydrogen. This is rather special, but
| it shouldn't harm in the general case.
|
*/
int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision)
{
static int oldsize;
int minint[3], maxint[3], mindiff, *lip, diff;
int lint1, lint2, lint3, oldlint1, oldlint2, oldlint3, smallidx;
int minidx, maxidx;
unsigned sizeint[3], sizesmall[3], bitsizeint[3], size3, *luip;
int flag, k;
int small, smaller, larger, i, is_small, is_smaller, run, prevrun;
float *lfp, lf;
int tmp, *thiscoord, prevcoord[3];
unsigned int tmpcoord[30];
int bufsize, xdrid, lsize;
unsigned int bitsize;
float inv_precision;
int errval = 1;
/* find out if xdrs is opened for reading or for writing */
xdrid = 0;
while (xdridptr[xdrid] != xdrs) {
xdrid++;
if (xdrid >= MAXID) {
fprintf(stderr, "xdr error. no open xdr stream\n");
exit (1);
}
}
if (xdrmodes[xdrid] == 'w') {
/* xdrs is open for writing */
if (xdr_int(xdrs, size) == 0)
return 0;
size3 = *size * 3;
/* when the number of coordinates is small, don't try to compress; just
* write them as floats using xdr_vector
*/
if (*size <= 9 ) {
return (xdr_vector(xdrs, (char *) fp, size3, sizeof(*fp),
(xdrproc_t)xdr_float));
}
xdr_float(xdrs, precision);
if (ip == NULL) {
ip = (int *) malloc(size3 * sizeof(*ip));
if (ip == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
bufsize = (int) (size3 * 1.2);
buf = (int *) malloc(bufsize * sizeof(*buf));
if (buf == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
oldsize = *size;
} else if (*size > oldsize) {
ip = (int *) realloc(ip, size3 * sizeof(*ip));
if (ip == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
bufsize = (int) (size3 * 1.2);
buf = (int *) realloc(buf, bufsize * sizeof(*buf));
if (buf == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
oldsize = *size;
}
/* buf[0-2] are special and do not contain actual data */
buf[0] = buf[1] = buf[2] = 0;
minint[0] = minint[1] = minint[2] = INT_MAX;
maxint[0] = maxint[1] = maxint[2] = INT_MIN;
prevrun = -1;
lfp = fp;
lip = ip;
mindiff = INT_MAX;
oldlint1 = oldlint2 = oldlint3 = 0;
while(lfp < fp + size3 ) {
/* find nearest integer */
if (*lfp >= 0.0)
lf = *lfp * *precision + 0.5;
else
lf = *lfp * *precision - 0.5;
if (fabs(lf) > MAXABS) {
/* scaling would cause overflow */
errval = 0;
}
lint1 = (int) lf;
if (lint1 < minint[0]) minint[0] = lint1;
if (lint1 > maxint[0]) maxint[0] = lint1;
*lip++ = lint1;
lfp++;
if (*lfp >= 0.0)
lf = *lfp * *precision + 0.5;
else
lf = *lfp * *precision - 0.5;
if (fabs(lf) > MAXABS) {
/* scaling would cause overflow */
errval = 0;
}
lint2 = (int) lf;
if (lint2 < minint[1]) minint[1] = lint2;
if (lint2 > maxint[1]) maxint[1] = lint2;
*lip++ = lint2;
lfp++;
if (*lfp >= 0.0)
lf = *lfp * *precision + 0.5;
else
lf = *lfp * *precision - 0.5;
if (fabs(lf) > MAXABS) {
/* scaling would cause overflow */
errval = 0;
}
lint3 = (int) lf;
if (lint3 < minint[2]) minint[2] = lint3;
if (lint3 > maxint[2]) maxint[2] = lint3;
*lip++ = lint3;
lfp++;
diff = abs(oldlint1-lint1)+abs(oldlint2-lint2)+abs(oldlint3-lint3);
if (diff < mindiff && lfp > fp + 3)
mindiff = diff;
oldlint1 = lint1;
oldlint2 = lint2;
oldlint3 = lint3;
}
xdr_int(xdrs, &(minint[0]));
xdr_int(xdrs, &(minint[1]));
xdr_int(xdrs, &(minint[2]));
xdr_int(xdrs, &(maxint[0]));
xdr_int(xdrs, &(maxint[1]));
xdr_int(xdrs, &(maxint[2]));
if ((float)maxint[0] - (float)minint[0] >= MAXABS ||
(float)maxint[1] - (float)minint[1] >= MAXABS ||
(float)maxint[2] - (float)minint[2] >= MAXABS) {
/* turning value in unsigned by subtracting minint
* would cause overflow
*/
errval = 0;
}
sizeint[0] = maxint[0] - minint[0]+1;
sizeint[1] = maxint[1] - minint[1]+1;
sizeint[2] = maxint[2] - minint[2]+1;
/* check if one of the sizes is to big to be multiplied */
if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff) {
bitsizeint[0] = sizeofint(sizeint[0]);
bitsizeint[1] = sizeofint(sizeint[1]);
bitsizeint[2] = sizeofint(sizeint[2]);
bitsize = 0; /* flag the use of large sizes */
} else {
bitsize = sizeofints(3, sizeint);
}
lip = ip;
luip = (unsigned int *) ip;
smallidx = FIRSTIDX;
while (smallidx < LASTIDX && magicints[smallidx] < mindiff) {
smallidx++;
}
xdr_int(xdrs, &smallidx);
maxidx = MYMIN(LASTIDX, smallidx + 8) ;
minidx = maxidx - 8; /* often this equal smallidx */
smaller = magicints[MYMAX(FIRSTIDX, smallidx-1)] / 2;
small = magicints[smallidx] / 2;
sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
larger = magicints[maxidx] / 2;
i = 0;
while (i < *size) {
is_small = 0;
thiscoord = (int *)(luip) + i * 3;
if (smallidx < maxidx && i >= 1 &&
abs(thiscoord[0] - prevcoord[0]) < larger &&
abs(thiscoord[1] - prevcoord[1]) < larger &&
abs(thiscoord[2] - prevcoord[2]) < larger) {
is_smaller = 1;
} else if (smallidx > minidx) {
is_smaller = -1;
} else {
is_smaller = 0;
}
if (i + 1 < *size) {
if (abs(thiscoord[0] - thiscoord[3]) < small &&
abs(thiscoord[1] - thiscoord[4]) < small &&
abs(thiscoord[2] - thiscoord[5]) < small) {
/* interchange first with second atom for better
* compression of water molecules
*/
tmp = thiscoord[0]; thiscoord[0] = thiscoord[3];
thiscoord[3] = tmp;
tmp = thiscoord[1]; thiscoord[1] = thiscoord[4];
thiscoord[4] = tmp;
tmp = thiscoord[2]; thiscoord[2] = thiscoord[5];
thiscoord[5] = tmp;
is_small = 1;
}
}
tmpcoord[0] = thiscoord[0] - minint[0];
tmpcoord[1] = thiscoord[1] - minint[1];
tmpcoord[2] = thiscoord[2] - minint[2];
if (bitsize == 0) {
sendbits(buf, bitsizeint[0], tmpcoord[0]);
sendbits(buf, bitsizeint[1], tmpcoord[1]);
sendbits(buf, bitsizeint[2], tmpcoord[2]);
} else {
sendints(buf, 3, bitsize, sizeint, tmpcoord);
}
prevcoord[0] = thiscoord[0];
prevcoord[1] = thiscoord[1];
prevcoord[2] = thiscoord[2];
thiscoord = thiscoord + 3;
i++;
run = 0;
if (is_small == 0 && is_smaller == -1)
is_smaller = 0;
while (is_small && run < 8*3) {
if (is_smaller == -1 && (SQR(thiscoord[0] - prevcoord[0]) +
SQR(thiscoord[1] - prevcoord[1]) +
SQR(thiscoord[2] - prevcoord[2]) >=
smaller * smaller)) {
is_smaller = 0;
}
tmpcoord[run++] = thiscoord[0] - prevcoord[0] + small;
tmpcoord[run++] = thiscoord[1] - prevcoord[1] + small;
tmpcoord[run++] = thiscoord[2] - prevcoord[2] + small;
prevcoord[0] = thiscoord[0];
prevcoord[1] = thiscoord[1];
prevcoord[2] = thiscoord[2];
i++;
thiscoord = thiscoord + 3;
is_small = 0;
if (i < *size &&
abs(thiscoord[0] - prevcoord[0]) < small &&
abs(thiscoord[1] - prevcoord[1]) < small &&
abs(thiscoord[2] - prevcoord[2]) < small) {
is_small = 1;
}
}
if (run != prevrun || is_smaller != 0) {
prevrun = run;
sendbits(buf, 1, 1); /* flag the change in run-length */
sendbits(buf, 5, run+is_smaller+1);
} else {
sendbits(buf, 1, 0); /* flag the fact that runlength did not change */
}
for (k=0; k < run; k+=3) {
sendints(buf, 3, smallidx, sizesmall, &tmpcoord[k]);
}
if (is_smaller != 0) {
smallidx += is_smaller;
if (is_smaller < 0) {
small = smaller;
smaller = magicints[smallidx-1] / 2;
} else {
smaller = small;
small = magicints[smallidx] / 2;
}
sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx];
}
}
if (buf[1] != 0) buf[0]++;;
xdr_int(xdrs, &(buf[0])); /* buf[0] holds the length in bytes */
return errval * (xdr_opaque(xdrs, (caddr_t)&(buf[3]), (u_int)buf[0]));
} else {
/* xdrs is open for reading */
if (xdr_int(xdrs, &lsize) == 0)
return 0;
if (*size != 0 && lsize != *size) {
fprintf(stderr, "wrong number of coordinates in xdr3dfcoor; "
"%d arg vs %d in file", *size, lsize);
}
*size = lsize;
size3 = *size * 3;
if (*size <= 9) {
return (xdr_vector(xdrs, (char *) fp, size3, sizeof(*fp),
(xdrproc_t)xdr_float));
}
xdr_float(xdrs, precision);
if (ip == NULL) {
ip = (int *) malloc(size3 * sizeof(*ip));
if (ip == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
bufsize = (int) (size3 * 1.2);
buf = (int *) malloc(bufsize * sizeof(*buf));
if (buf == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
oldsize = *size;
} else if (*size > oldsize) {
ip = (int *)realloc(ip, size3 * sizeof(*ip));
if (ip == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
bufsize = (int) (size3 * 1.2);
buf = (int *)realloc(buf, bufsize * sizeof(*buf));
if (buf == NULL) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
oldsize = *size;
}
buf[0] = buf[1] = buf[2] = 0;
xdr_int(xdrs, &(minint[0]));
xdr_int(xdrs, &(minint[1]));
xdr_int(xdrs, &(minint[2]));
xdr_int(xdrs, &(maxint[0]));
xdr_int(xdrs, &(maxint[1]));
xdr_int(xdrs, &(maxint[2]));
sizeint[0] = maxint[0] - minint[0]+1;
sizeint[1] = maxint[1] - minint[1]+1;
sizeint[2] = maxint[2] - minint[2]+1;
/* check if one of the sizes is to big to be multiplied */
if ((sizeint[0] | sizeint[1] | sizeint[2] ) > 0xffffff) {
bitsizeint[0] = sizeofint(sizeint[0]);
bitsizeint[1] = sizeofint(sizeint[1]);
bitsizeint[2] = sizeofint(sizeint[2]);
bitsize = 0; /* flag the use of large sizes */
} else {
bitsize = sizeofints(3, sizeint);
}
xdr_int(xdrs, &smallidx);
maxidx = MYMIN(LASTIDX, smallidx + 8) ;
minidx = maxidx - 8; /* often this equal smallidx */
smaller = magicints[MYMAX(FIRSTIDX, smallidx-1)] / 2;
small = magicints[smallidx] / 2;
sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;
larger = magicints[maxidx];
/* buf[0] holds the length in bytes */
if (xdr_int(xdrs, &(buf[0])) == 0)
return 0;
if (xdr_opaque(xdrs, (caddr_t)&(buf[3]), (u_int)buf[0]) == 0)
return 0;
buf[0] = buf[1] = buf[2] = 0;
lfp = fp;
inv_precision = 1.0 / * precision;
run = 0;
i = 0;
lip = ip;
while ( i < lsize ) {
thiscoord = (int *)(lip) + i * 3;
if (bitsize == 0) {
thiscoord[0] = receivebits(buf, bitsizeint[0]);
thiscoord[1] = receivebits(buf, bitsizeint[1]);
thiscoord[2] = receivebits(buf, bitsizeint[2]);
} else {
receiveints(buf, 3, bitsize, sizeint, thiscoord);
}
i++;
thiscoord[0] += minint[0];
thiscoord[1] += minint[1];
thiscoord[2] += minint[2];
prevcoord[0] = thiscoord[0];
prevcoord[1] = thiscoord[1];
prevcoord[2] = thiscoord[2];
flag = receivebits(buf, 1);
is_smaller = 0;
if (flag == 1) {
run = receivebits(buf, 5);
is_smaller = run % 3;
run -= is_smaller;
is_smaller--;
}
if (run > 0) {
thiscoord += 3;
for (k = 0; k < run; k+=3) {
receiveints(buf, 3, smallidx, sizesmall, thiscoord);
i++;
thiscoord[0] += prevcoord[0] - small;
thiscoord[1] += prevcoord[1] - small;
thiscoord[2] += prevcoord[2] - small;
if (k == 0) {
/* interchange first with second atom for better
* compression of water molecules
*/
tmp = thiscoord[0]; thiscoord[0] = prevcoord[0];
prevcoord[0] = tmp;
tmp = thiscoord[1]; thiscoord[1] = prevcoord[1];
prevcoord[1] = tmp;
tmp = thiscoord[2]; thiscoord[2] = prevcoord[2];
prevcoord[2] = tmp;
*lfp++ = prevcoord[0] * inv_precision;
*lfp++ = prevcoord[1] * inv_precision;
*lfp++ = prevcoord[2] * inv_precision;
} else {
prevcoord[0] = thiscoord[0];
prevcoord[1] = thiscoord[1];
prevcoord[2] = thiscoord[2];
}
*lfp++ = thiscoord[0] * inv_precision;
*lfp++ = thiscoord[1] * inv_precision;
*lfp++ = thiscoord[2] * inv_precision;
}
} else {
*lfp++ = thiscoord[0] * inv_precision;
*lfp++ = thiscoord[1] * inv_precision;
*lfp++ = thiscoord[2] * inv_precision;
}
smallidx += is_smaller;
if (is_smaller < 0) {
small = smaller;
if (smallidx > FIRSTIDX) {
smaller = magicints[smallidx - 1] /2;
} else {
smaller = 0;
}
} else if (is_smaller > 0) {
smaller = small;
small = magicints[smallidx] / 2;
}
sizesmall[0] = sizesmall[1] = sizesmall[2] = magicints[smallidx] ;
}
}
return 1;
}
diff --git a/src/angle.cpp b/src/angle.cpp
index 0073044d3..fbed9116a 100644
--- a/src/angle.cpp
+++ b/src/angle.cpp
@@ -1,222 +1,222 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "angle.h"
#include "atom.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Angle::Angle(LAMMPS *lmp) : Pointers(lmp)
{
energy = 0.0;
allocated = 0;
PI = 4.0*atan(1.0);
THIRD = 1.0/3.0;
maxeatom = maxvatom = 0;
eatom = NULL;
vatom = NULL;
}
/* ---------------------------------------------------------------------- */
Angle::~Angle()
{
memory->destroy(eatom);
memory->destroy(vatom);
}
/* ----------------------------------------------------------------------
check if all coeffs are set
------------------------------------------------------------------------- */
void Angle::init()
{
- if (!allocated) error->all("Angle coeffs are not set");
+ if (!allocated) error->all(FLERR,"Angle coeffs are not set");
for (int i = 1; i <= atom->nangletypes; i++)
- if (setflag[i] == 0) error->all("All angle coeffs are not set");
+ if (setflag[i] == 0) error->all(FLERR,"All angle coeffs are not set");
}
/* ----------------------------------------------------------------------
setup for energy, virial computation
see integrate::ev_set() for values of eflag (0-3) and vflag (0-6)
------------------------------------------------------------------------- */
void Angle::ev_setup(int eflag, int vflag)
{
int i,n;
evflag = 1;
eflag_either = eflag;
eflag_global = eflag % 2;
eflag_atom = eflag / 2;
vflag_either = vflag;
vflag_global = vflag % 4;
vflag_atom = vflag / 4;
// reallocate per-atom arrays if necessary
if (eflag_atom && atom->nmax > maxeatom) {
maxeatom = atom->nmax;
memory->destroy(eatom);
memory->create(eatom,maxeatom,"bond:eatom");
}
if (vflag_atom && atom->nmax > maxvatom) {
maxvatom = atom->nmax;
memory->destroy(vatom);
memory->create(vatom,maxvatom,6,"bond:vatom");
}
// zero accumulators
if (eflag_global) energy = 0.0;
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) eatom[i] = 0.0;
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) {
vatom[i][0] = 0.0;
vatom[i][1] = 0.0;
vatom[i][2] = 0.0;
vatom[i][3] = 0.0;
vatom[i][4] = 0.0;
vatom[i][5] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
tally energy and virial into global and per-atom accumulators
virial = r1F1 + r2F2 + r3F3 = (r1-r2) F1 + (r3-r2) F3 = del1*f1 + del2*f3
------------------------------------------------------------------------- */
void Angle::ev_tally(int i, int j, int k, int nlocal, int newton_bond,
double eangle, double *f1, double *f3,
double delx1, double dely1, double delz1,
double delx2, double dely2, double delz2)
{
double eanglethird,v[6];
if (eflag_either) {
if (eflag_global) {
if (newton_bond) energy += eangle;
else {
eanglethird = THIRD*eangle;
if (i < nlocal) energy += eanglethird;
if (j < nlocal) energy += eanglethird;
if (k < nlocal) energy += eanglethird;
}
}
if (eflag_atom) {
eanglethird = THIRD*eangle;
if (newton_bond || i < nlocal) eatom[i] += eanglethird;
if (newton_bond || j < nlocal) eatom[j] += eanglethird;
if (newton_bond || k < nlocal) eatom[k] += eanglethird;
}
}
if (vflag_either) {
v[0] = delx1*f1[0] + delx2*f3[0];
v[1] = dely1*f1[1] + dely2*f3[1];
v[2] = delz1*f1[2] + delz2*f3[2];
v[3] = delx1*f1[1] + delx2*f3[1];
v[4] = delx1*f1[2] + delx2*f3[2];
v[5] = dely1*f1[2] + dely2*f3[2];
if (vflag_global) {
if (newton_bond) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i < nlocal) {
virial[0] += THIRD*v[0];
virial[1] += THIRD*v[1];
virial[2] += THIRD*v[2];
virial[3] += THIRD*v[3];
virial[4] += THIRD*v[4];
virial[5] += THIRD*v[5];
}
if (j < nlocal) {
virial[0] += THIRD*v[0];
virial[1] += THIRD*v[1];
virial[2] += THIRD*v[2];
virial[3] += THIRD*v[3];
virial[4] += THIRD*v[4];
virial[5] += THIRD*v[5];
}
if (k < nlocal) {
virial[0] += THIRD*v[0];
virial[1] += THIRD*v[1];
virial[2] += THIRD*v[2];
virial[3] += THIRD*v[3];
virial[4] += THIRD*v[4];
virial[5] += THIRD*v[5];
}
}
}
if (vflag_atom) {
if (newton_bond || i < nlocal) {
vatom[i][0] += THIRD*v[0];
vatom[i][1] += THIRD*v[1];
vatom[i][2] += THIRD*v[2];
vatom[i][3] += THIRD*v[3];
vatom[i][4] += THIRD*v[4];
vatom[i][5] += THIRD*v[5];
}
if (newton_bond || j < nlocal) {
vatom[j][0] += THIRD*v[0];
vatom[j][1] += THIRD*v[1];
vatom[j][2] += THIRD*v[2];
vatom[j][3] += THIRD*v[3];
vatom[j][4] += THIRD*v[4];
vatom[j][5] += THIRD*v[5];
}
if (newton_bond || k < nlocal) {
vatom[k][0] += THIRD*v[0];
vatom[k][1] += THIRD*v[1];
vatom[k][2] += THIRD*v[2];
vatom[k][3] += THIRD*v[3];
vatom[k][4] += THIRD*v[4];
vatom[k][5] += THIRD*v[5];
}
}
}
}
/* ---------------------------------------------------------------------- */
double Angle::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
return bytes;
}
diff --git a/src/atom.cpp b/src/atom.cpp
index a0f65365e..f42b1250f 100644
--- a/src/atom.cpp
+++ b/src/atom.cpp
@@ -1,1668 +1,1665 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "limits.h"
#include "atom.h"
#include "style_atom.h"
#include "atom_vec.h"
#include "atom_vec_ellipsoid.h"
#include "comm.h"
#include "neighbor.h"
#include "force.h"
#include "modify.h"
#include "fix.h"
#include "output.h"
#include "thermo.h"
#include "update.h"
#include "domain.h"
#include "group.h"
#include "accelerator_cuda.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 1
#define DELTA_MEMSTR 1024
#define EPSILON 1.0e-6
#define CUDA_CHUNK 3000
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
Atom::Atom(LAMMPS *lmp) : Pointers(lmp)
{
natoms = 0;
nlocal = nghost = nmax = 0;
ntypes = 0;
nbondtypes = nangletypes = ndihedraltypes = nimpropertypes = 0;
nbonds = nangles = ndihedrals = nimpropers = 0;
bond_per_atom = angle_per_atom = dihedral_per_atom = improper_per_atom = 0;
extra_bond_per_atom = 0;
firstgroupname = NULL;
sortfreq = 1000;
nextsort = 0;
userbinsize = 0.0;
maxbin = maxnext = 0;
binhead = NULL;
next = permute = NULL;
// initialize atom arrays
// customize by adding new array
tag = type = mask = image = NULL;
x = v = f = NULL;
molecule = NULL;
q = NULL;
mu = NULL;
omega = angmom = torque = NULL;
radius = rmass = NULL;
vfrac = s0 = NULL;
x0 = NULL;
ellipsoid = NULL;
spin = NULL;
eradius = ervel = erforce = NULL;
cs = csforce = vforce = ervelforce = NULL;
etag = NULL;
rho = drho = NULL;
e = de = NULL;
cv = NULL;
vest = NULL;
maxspecial = 1;
nspecial = NULL;
special = NULL;
num_bond = NULL;
bond_type = bond_atom = NULL;
num_angle = NULL;
angle_type = angle_atom1 = angle_atom2 = angle_atom3 = NULL;
num_dihedral = NULL;
dihedral_type = dihedral_atom1 = dihedral_atom2 = NULL;
dihedral_atom3 = dihedral_atom4 = NULL;
num_improper = NULL;
improper_type = improper_atom1 = improper_atom2 = NULL;
improper_atom3 = improper_atom4 = NULL;
// initialize atom style and array existence flags
// customize by adding new flag
sphere_flag = ellipsoid_flag = peri_flag = electron_flag = 0;
wavepacket_flag = sph_flag = 0;
molecule_flag = q_flag = mu_flag = 0;
rmass_flag = radius_flag = omega_flag = torque_flag = angmom_flag = 0;
vfrac_flag = spin_flag = eradius_flag = ervel_flag = erforce_flag = 0;
cs_flag = csforce_flag = vforce_flag = ervelforce_flag= etag_flag = 0;
rho_flag = e_flag = cv_flag = vest_flag = 0;
// ntype-length arrays
mass = NULL;
mass_setflag = NULL;
// callback lists & extra restart info
nextra_grow = nextra_restart = 0;
extra_grow = extra_restart = NULL;
nextra_grow_max = nextra_restart_max = 0;
nextra_store = 0;
extra = NULL;
// default mapping values and hash table primes
tag_enable = 1;
map_style = 0;
map_tag_max = 0;
map_nhash = 0;
nprimes = 38;
primes = new int[nprimes];
int plist[] = {5041,10007,20011,30011,40009,50021,60013,70001,80021,
90001,100003,110017,120011,130003,140009,150001,160001,
170003,180001,190027,200003,210011,220009,230003,240007,
250007,260003,270001,280001,290011,300007,310019,320009,
330017,340007,350003,362881,3628801};
for (int i = 0; i < nprimes; i++) primes[i] = plist[i];
// default atom style = atomic
atom_style = NULL;
avec = NULL;
create_avec("atomic",0,NULL);
}
/* ---------------------------------------------------------------------- */
Atom::~Atom()
{
delete [] atom_style;
delete avec;
delete [] firstgroupname;
memory->destroy(binhead);
memory->destroy(next);
memory->destroy(permute);
// delete atom arrays
// customize by adding new array
memory->destroy(tag);
memory->destroy(type);
memory->destroy(mask);
memory->destroy(image);
memory->destroy(x);
memory->destroy(v);
memory->destroy(f);
memory->destroy(q);
memory->destroy(mu);
memory->destroy(omega);
memory->destroy(angmom);
memory->destroy(torque);
memory->destroy(radius);
memory->destroy(rmass);
memory->destroy(vfrac);
memory->destroy(s0);
memory->destroy(x0);
memory->destroy(ellipsoid);
memory->destroy(spin);
memory->destroy(eradius);
memory->destroy(ervel);
memory->destroy(erforce);
memory->destroy(molecule);
memory->destroy(nspecial);
memory->destroy(special);
memory->destroy(num_bond);
memory->destroy(bond_type);
memory->destroy(bond_atom);
memory->destroy(num_angle);
memory->destroy(angle_type);
memory->destroy(angle_atom1);
memory->destroy(angle_atom2);
memory->destroy(angle_atom3);
memory->destroy(num_dihedral);
memory->destroy(dihedral_type);
memory->destroy(dihedral_atom1);
memory->destroy(dihedral_atom2);
memory->destroy(dihedral_atom3);
memory->destroy(dihedral_atom4);
memory->destroy(num_improper);
memory->destroy(improper_type);
memory->destroy(improper_atom1);
memory->destroy(improper_atom2);
memory->destroy(improper_atom3);
memory->destroy(improper_atom4);
// delete per-type arrays
delete [] mass;
delete [] mass_setflag;
// delete extra arrays
memory->destroy(extra_grow);
memory->destroy(extra_restart);
memory->destroy(extra);
// delete mapping data structures
map_delete();
delete [] primes;
}
/* ----------------------------------------------------------------------
copy modify settings from old Atom class to current Atom class
------------------------------------------------------------------------- */
void Atom::settings(Atom *old)
{
map_style = old->map_style;
}
/* ----------------------------------------------------------------------
create an AtomVec style
called from input script, restart file, replicate
------------------------------------------------------------------------- */
void Atom::create_avec(const char *style, int narg, char **arg, char *suffix)
{
delete [] atom_style;
if (avec) delete avec;
// unset atom style and array existence flags
// may have been set by old avec
// customize by adding new flag
sphere_flag = ellipsoid_flag = peri_flag = electron_flag = 0;
molecule_flag = q_flag = mu_flag = 0;
rmass_flag = radius_flag = omega_flag = torque_flag = angmom_flag = 0;
vfrac_flag = spin_flag = eradius_flag = ervel_flag = erforce_flag = 0;
int sflag;
avec = new_avec(style,narg,arg,suffix,sflag);
if (sflag) {
char estyle[256];
sprintf(estyle,"%s/%s",style,suffix);
int n = strlen(estyle) + 1;
atom_style = new char[n];
strcpy(atom_style,estyle);
} else {
int n = strlen(style) + 1;
atom_style = new char[n];
strcpy(atom_style,style);
}
// if molecular system, default is to have array map
molecular = avec->molecular;
if (map_style == 0 && molecular) map_style = 1;
}
/* ----------------------------------------------------------------------
generate an AtomVec class, first with suffix appended
------------------------------------------------------------------------- */
AtomVec *Atom::new_avec(const char *style, int narg, char **arg,
char *suffix, int &sflag)
{
if (suffix && lmp->suffix_enable) {
sflag = 1;
char estyle[256];
sprintf(estyle,"%s/%s",style,suffix);
if (0) return NULL;
#define ATOM_CLASS
#define AtomStyle(key,Class) \
else if (strcmp(estyle,#key) == 0) return new Class(lmp,narg,arg);
#include "style_atom.h"
#undef AtomStyle
#undef ATOM_CLASS
}
sflag = 0;
if (0) return NULL;
#define ATOM_CLASS
#define AtomStyle(key,Class) \
else if (strcmp(style,#key) == 0) return new Class(lmp,narg,arg);
#include "style_atom.h"
#undef ATOM_CLASS
- else error->all("Invalid atom style");
+ else error->all(FLERR,"Invalid atom style");
return NULL;
}
/* ---------------------------------------------------------------------- */
void Atom::init()
{
// delete extra array since it doesn't persist past first run
if (nextra_store) {
memory->destroy(extra);
extra = NULL;
nextra_store = 0;
}
// check arrays that are atom type in length
check_mass();
// setup of firstgroup
if (firstgroupname) {
firstgroup = group->find(firstgroupname);
if (firstgroup < 0)
- error->all("Could not find atom_modify first group ID");
+ error->all(FLERR,"Could not find atom_modify first group ID");
} else firstgroup = -1;
// init AtomVec
avec->init();
}
/* ---------------------------------------------------------------------- */
void Atom::setup()
{
// setup bins for sorting
// cannot do this in init() because uses neighbor cutoff
if (sortfreq > 0) setup_sort_bins();
}
/* ----------------------------------------------------------------------
return ptr to AtomVec class if matches style or to matching hybrid sub-class
return NULL if no match
------------------------------------------------------------------------- */
AtomVec *Atom::style_match(const char *style)
{
if (strcmp(atom_style,style) == 0) return avec;
else if (strcmp(atom_style,"hybrid") == 0) {
AtomVecHybrid *avec_hybrid = (AtomVecHybrid *) avec;
for (int i = 0; i < avec_hybrid->nstyles; i++)
if (strcmp(avec_hybrid->keywords[i],style) == 0)
return avec_hybrid->styles[i];
}
return NULL;
}
/* ----------------------------------------------------------------------
modify parameters of the atom style
some options can only be invoked before simulation box is defined
first and sort options cannot be used together
------------------------------------------------------------------------- */
void Atom::modify_params(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal atom_modify command");
+ if (narg == 0) error->all(FLERR,"Illegal atom_modify command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"map") == 0) {
- if (iarg+2 > narg) error->all("Illegal atom_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command");
if (strcmp(arg[iarg+1],"array") == 0) map_style = 1;
else if (strcmp(arg[iarg+1],"hash") == 0) map_style = 2;
- else error->all("Illegal atom_modify command");
+ else error->all(FLERR,"Illegal atom_modify command");
if (domain->box_exist)
- error->all("Atom_modify map command after simulation box is defined");
+ error->all(FLERR,"Atom_modify map command after simulation box is defined");
iarg += 2;
} else if (strcmp(arg[iarg],"first") == 0) {
- if (iarg+2 > narg) error->all("Illegal atom_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command");
if (strcmp(arg[iarg+1],"all") == 0) {
delete [] firstgroupname;
firstgroupname = NULL;
} else {
int n = strlen(arg[iarg+1]) + 1;
firstgroupname = new char[n];
strcpy(firstgroupname,arg[iarg+1]);
sortfreq = 0;
}
iarg += 2;
} else if (strcmp(arg[iarg],"sort") == 0) {
- if (iarg+3 > narg) error->all("Illegal atom_modify command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal atom_modify command");
sortfreq = atoi(arg[iarg+1]);
userbinsize = atof(arg[iarg+2]);
if (sortfreq < 0 || userbinsize < 0.0)
- error->all("Illegal atom_modify command");
+ error->all(FLERR,"Illegal atom_modify command");
if (sortfreq >= 0 && firstgroupname)
- error->all("Atom_modify sort and first options "
+ error->all(FLERR,"Atom_modify sort and first options "
"cannot be used together");
iarg += 3;
- } else error->all("Illegal atom_modify command");
+ } else error->all(FLERR,"Illegal atom_modify command");
}
}
/* ----------------------------------------------------------------------
allocate and initialize array or hash table for global -> local map
set map_tag_max = largest atom ID (may be larger than natoms)
for array option:
array length = 1 to largest tag of any atom
set entire array to -1 as initial values
for hash option:
map_nhash = length of hash table
map_nbucket = # of hash buckets, prime larger than map_nhash
so buckets will only be filled with 0 or 1 atoms on average
------------------------------------------------------------------------- */
void Atom::map_init()
{
map_delete();
if (tag_enable == 0)
- error->all("Cannot create an atom map unless atoms have IDs");
+ error->all(FLERR,"Cannot create an atom map unless atoms have IDs");
int max = 0;
for (int i = 0; i < nlocal; i++) max = MAX(max,tag[i]);
MPI_Allreduce(&max,&map_tag_max,1,MPI_INT,MPI_MAX,world);
if (map_style == 1) {
memory->create(map_array,map_tag_max+1,"atom:map_array");
for (int i = 0; i <= map_tag_max; i++) map_array[i] = -1;
} else {
// map_nhash = max of atoms/proc or total atoms, times 2, at least 1000
int nper = static_cast<int> (natoms/comm->nprocs);
map_nhash = MAX(nper,nmax);
if (map_nhash > natoms) map_nhash = static_cast<int> (natoms);
if (comm->nprocs > 1) map_nhash *= 2;
map_nhash = MAX(map_nhash,1000);
// map_nbucket = prime just larger than map_nhash
int n = map_nhash/10000;
n = MIN(n,nprimes-1);
map_nbucket = primes[n];
if (map_nbucket < map_nhash && n < nprimes-1) map_nbucket = primes[n+1];
// set all buckets to empty
// set hash to map_nhash in length
// put all hash entries in free list and point them to each other
map_bucket = new int[map_nbucket];
for (int i = 0; i < map_nbucket; i++) map_bucket[i] = -1;
map_hash = new HashElem[map_nhash];
map_nused = 0;
map_free = 0;
for (int i = 0; i < map_nhash; i++) map_hash[i].next = i+1;
map_hash[map_nhash-1].next = -1;
}
}
/* ----------------------------------------------------------------------
clear global -> local map for all of my own and ghost atoms
for hash table option:
global ID may not be in table if image atom was already cleared
------------------------------------------------------------------------- */
void Atom::map_clear()
{
if (map_style == 1) {
int nall = nlocal + nghost;
for (int i = 0; i < nall; i++) map_array[tag[i]] = -1;
} else {
int previous,global,ibucket,index;
int nall = nlocal + nghost;
for (int i = 0; i < nall; i++) {
// search for key
// if don't find it, done
previous = -1;
global = tag[i];
ibucket = global % map_nbucket;
index = map_bucket[ibucket];
while (index > -1) {
if (map_hash[index].global == global) break;
previous = index;
index = map_hash[index].next;
}
if (index == -1) continue;
// delete the hash entry and add it to free list
// special logic if entry is 1st in the bucket
if (previous == -1) map_bucket[ibucket] = map_hash[index].next;
else map_hash[previous].next = map_hash[index].next;
map_hash[index].next = map_free;
map_free = index;
map_nused--;
}
}
}
/* ----------------------------------------------------------------------
set global -> local map for all of my own and ghost atoms
loop in reverse order so that nearby images take precedence over far ones
and owned atoms take precedence over images
this enables valid lookups of bond topology atoms
for hash table option:
if hash table too small, re-init
global ID may already be in table if image atom was set
------------------------------------------------------------------------- */
void Atom::map_set()
{
if (map_style == 1) {
int nall = nlocal + nghost;
for (int i = nall-1; i >= 0 ; i--) map_array[tag[i]] = i;
} else {
int previous,global,ibucket,index;
int nall = nlocal + nghost;
if (nall > map_nhash) map_init();
for (int i = nall-1; i >= 0 ; i--) {
// search for key
// if found it, just overwrite local value with index
previous = -1;
global = tag[i];
ibucket = global % map_nbucket;
index = map_bucket[ibucket];
while (index > -1) {
if (map_hash[index].global == global) break;
previous = index;
index = map_hash[index].next;
}
if (index > -1) {
map_hash[index].local = i;
continue;
}
// take one entry from free list
// add the new global/local pair as entry at end of bucket list
// special logic if this entry is 1st in bucket
index = map_free;
map_free = map_hash[map_free].next;
if (previous == -1) map_bucket[ibucket] = index;
else map_hash[previous].next = index;
map_hash[index].global = global;
map_hash[index].local = i;
map_hash[index].next = -1;
map_nused++;
}
}
}
/* ----------------------------------------------------------------------
set global to local map for one atom
for hash table option:
global ID may already be in table if atom was already set
------------------------------------------------------------------------- */
void Atom::map_one(int global, int local)
{
if (map_style == 1) map_array[global] = local;
else {
// search for key
// if found it, just overwrite local value with index
int previous = -1;
int ibucket = global % map_nbucket;
int index = map_bucket[ibucket];
while (index > -1) {
if (map_hash[index].global == global) break;
previous = index;
index = map_hash[index].next;
}
if (index > -1) {
map_hash[index].local = local;
return;
}
// take one entry from free list
// add the new global/local pair as entry at end of bucket list
// special logic if this entry is 1st in bucket
index = map_free;
map_free = map_hash[map_free].next;
if (previous == -1) map_bucket[ibucket] = index;
else map_hash[previous].next = index;
map_hash[index].global = global;
map_hash[index].local = local;
map_hash[index].next = -1;
map_nused++;
}
}
/* ----------------------------------------------------------------------
free the array or hash table for global to local mapping
------------------------------------------------------------------------- */
void Atom::map_delete()
{
if (map_style == 1) {
if (map_tag_max) memory->destroy(map_array);
} else {
if (map_nhash) {
delete [] map_bucket;
delete [] map_hash;
}
map_nhash = 0;
}
map_tag_max = 0;
}
/* ----------------------------------------------------------------------
lookup global ID in hash table, return local index
------------------------------------------------------------------------- */
int Atom::map_find_hash(int global)
{
int local = -1;
int index = map_bucket[global % map_nbucket];
while (index > -1) {
if (map_hash[index].global == global) {
local = map_hash[index].local;
break;
}
index = map_hash[index].next;
}
return local;
}
/* ----------------------------------------------------------------------
add unique tags to any atoms with tag = 0
new tags are grouped by proc and start after max current tag
called after creating new atoms
------------------------------------------------------------------------- */
void Atom::tag_extend()
{
// maxtag_all = max tag for all atoms
int maxtag = 0;
for (int i = 0; i < nlocal; i++) maxtag = MAX(maxtag,tag[i]);
int maxtag_all;
MPI_Allreduce(&maxtag,&maxtag_all,1,MPI_INT,MPI_MAX,world);
// notag = # of atoms I own with no tag (tag = 0)
// notag_sum = # of total atoms on procs <= me with no tag
int notag = 0;
for (int i = 0; i < nlocal; i++) if (tag[i] == 0) notag++;
int notag_sum;
MPI_Scan(&notag,&notag_sum,1,MPI_INT,MPI_SUM,world);
// itag = 1st new tag that my untagged atoms should use
int itag = maxtag_all + notag_sum - notag + 1;
for (int i = 0; i < nlocal; i++) if (tag[i] == 0) tag[i] = itag++;
}
/* ----------------------------------------------------------------------
check that atom IDs span range from 1 to Natoms
return 0 if mintag != 1 or maxtag != Natoms
return 1 if OK
doesn't actually check if all tag values are used
------------------------------------------------------------------------- */
int Atom::tag_consecutive()
{
int idmin = MAXTAGINT;
int idmax = 0;
for (int i = 0; i < nlocal; i++) {
idmin = MIN(idmin,tag[i]);
idmax = MAX(idmax,tag[i]);
}
int idminall,idmaxall;
MPI_Allreduce(&idmin,&idminall,1,MPI_INT,MPI_MIN,world);
MPI_Allreduce(&idmax,&idmaxall,1,MPI_INT,MPI_MAX,world);
if (idminall != 1 || idmaxall != static_cast<int> (natoms)) return 0;
return 1;
}
/* ----------------------------------------------------------------------
count and return words in a single line
make copy of line before using strtok so as not to change line
trim anything from '#' onward
------------------------------------------------------------------------- */
int Atom::count_words(const char *line)
{
int n = strlen(line) + 1;
char *copy;
memory->create(copy,n,"atom:copy");
strcpy(copy,line);
char *ptr;
if (ptr = strchr(copy,'#')) *ptr = '\0';
if (strtok(copy," \t\n\r\f") == NULL) {
memory->destroy(copy);
return 0;
}
n = 1;
while (strtok(NULL," \t\n\r\f")) n++;
memory->destroy(copy);
return n;
}
/* ----------------------------------------------------------------------
unpack n lines from Atom section of data file
call style-specific routine to parse line
------------------------------------------------------------------------- */
void Atom::data_atoms(int n, char *buf)
{
int m,imagedata,xptr,iptr;
double xdata[3],lamda[3],sublo[3],subhi[3];
double *coord;
char *next;
next = strchr(buf,'\n');
*next = '\0';
int nwords = count_words(buf);
*next = '\n';
if (nwords != avec->size_data_atom && nwords != avec->size_data_atom + 3)
- error->all("Incorrect atom format in data file");
+ error->all(FLERR,"Incorrect atom format in data file");
char **values = new char*[nwords];
// set bounds for my proc
// if periodic and I am lo/hi proc, adjust bounds by EPSILON
// insures all data atoms will be owned even with round-off
int triclinic = domain->triclinic;
if (triclinic == 0) {
sublo[0] = domain->sublo[0]; subhi[0] = domain->subhi[0];
sublo[1] = domain->sublo[1]; subhi[1] = domain->subhi[1];
sublo[2] = domain->sublo[2]; subhi[2] = domain->subhi[2];
} else {
sublo[0] = domain->sublo_lamda[0]; subhi[0] = domain->subhi_lamda[0];
sublo[1] = domain->sublo_lamda[1]; subhi[1] = domain->subhi_lamda[1];
sublo[2] = domain->sublo_lamda[2]; subhi[2] = domain->subhi_lamda[2];
}
if (domain->xperiodic) {
if (comm->myloc[0] == 0) sublo[0] -= EPSILON;
if (comm->myloc[0] == comm->procgrid[0]-1) subhi[0] += EPSILON;
}
if (domain->yperiodic) {
if (comm->myloc[1] == 0) sublo[1] -= EPSILON;
if (comm->myloc[1] == comm->procgrid[1]-1) subhi[1] += EPSILON;
}
if (domain->zperiodic) {
if (comm->myloc[2] == 0) sublo[2] -= EPSILON;
if (comm->myloc[2] == comm->procgrid[2]-1) subhi[2] += EPSILON;
}
// xptr = which word in line starts xyz coords
// iptr = which word in line starts ix,iy,iz image flags
xptr = avec->xcol_data - 1;
int imageflag = 0;
if (nwords > avec->size_data_atom) imageflag = 1;
if (imageflag) iptr = nwords - 3;
// loop over lines of atom data
// tokenize the line into values
// extract xyz coords and image flags
// remap atom into simulation box
// if atom is in my sub-domain, unpack its values
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
values[0] = strtok(buf," \t\n\r\f");
- if (values[0] == NULL) error->all("Incorrect atom format in data file");
+ if (values[0] == NULL) error->all(FLERR,"Incorrect atom format in data file");
for (m = 1; m < nwords; m++) {
values[m] = strtok(NULL," \t\n\r\f");
- if (values[m] == NULL) error->all("Incorrect atom format in data file");
+ if (values[m] == NULL) error->all(FLERR,"Incorrect atom format in data file");
}
if (imageflag)
imagedata = ((atoi(values[iptr+2]) + 512 & 1023) << 20) |
((atoi(values[iptr+1]) + 512 & 1023) << 10) |
(atoi(values[iptr]) + 512 & 1023);
else imagedata = (512 << 20) | (512 << 10) | 512;
xdata[0] = atof(values[xptr]);
xdata[1] = atof(values[xptr+1]);
xdata[2] = atof(values[xptr+2]);
domain->remap(xdata,imagedata);
if (triclinic) {
domain->x2lamda(xdata,lamda);
coord = lamda;
} else coord = xdata;
if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1] &&
coord[2] >= sublo[2] && coord[2] < subhi[2])
avec->data_atom(xdata,imagedata,values);
buf = next + 1;
}
delete [] values;
}
/* ----------------------------------------------------------------------
unpack n lines from Velocity section of data file
check that atom IDs are > 0 and <= map_tag_max
call style-specific routine to parse line
------------------------------------------------------------------------- */
void Atom::data_vels(int n, char *buf)
{
int j,m,tagdata;
char *next;
next = strchr(buf,'\n');
*next = '\0';
int nwords = count_words(buf);
*next = '\n';
if (nwords != avec->size_data_vel)
- error->all("Incorrect velocity format in data file");
+ error->all(FLERR,"Incorrect velocity format in data file");
char **values = new char*[nwords];
// loop over lines of atom velocities
// tokenize the line into values
// if I own atom tag, unpack its values
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
values[0] = strtok(buf," \t\n\r\f");
for (j = 1; j < nwords; j++)
values[j] = strtok(NULL," \t\n\r\f");
tagdata = atoi(values[0]);
if (tagdata <= 0 || tagdata > map_tag_max)
- error->one("Invalid atom ID in Velocities section of data file");
+ error->one(FLERR,"Invalid atom ID in Velocities section of data file");
if ((m = map(tagdata)) >= 0) avec->data_vel(m,&values[1]);
buf = next + 1;
}
delete [] values;
}
/* ----------------------------------------------------------------------
unpack n lines from atom-style specific section of data file
check that atom IDs are > 0 and <= map_tag_max
call style-specific routine to parse line
------------------------------------------------------------------------- */
void Atom::data_bonus(int n, char *buf, AtomVec *avec_bonus)
{
int j,m,tagdata;
char *next;
next = strchr(buf,'\n');
*next = '\0';
int nwords = count_words(buf);
*next = '\n';
if (nwords != avec_bonus->size_data_bonus)
- error->all("Incorrect bonus data format in data file");
+ error->all(FLERR,"Incorrect bonus data format in data file");
char **values = new char*[nwords];
// loop over lines of bonus atom data
// tokenize the line into values
// if I own atom tag, unpack its values
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
values[0] = strtok(buf," \t\n\r\f");
for (j = 1; j < nwords; j++)
values[j] = strtok(NULL," \t\n\r\f");
tagdata = atoi(values[0]);
if (tagdata <= 0 || tagdata > map_tag_max)
- error->one("Invalid atom ID in Bonus section of data file");
+ error->one(FLERR,"Invalid atom ID in Bonus section of data file");
// ok to call child's data_atom_bonus() method thru parent avec_bonus,
// since data_bonus() was called with child ptr, and method is virtual
if ((m = map(tagdata)) >= 0) avec_bonus->data_atom_bonus(m,&values[1]);
buf = next + 1;
}
delete [] values;
}
/* ----------------------------------------------------------------------
check that atom IDs are > 0 and <= map_tag_max
------------------------------------------------------------------------- */
void Atom::data_bonds(int n, char *buf)
{
int m,tmp,itype,atom1,atom2;
char *next;
int newton_bond = force->newton_bond;
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
*next = '\0';
sscanf(buf,"%d %d %d %d",&tmp,&itype,&atom1,&atom2);
if (atom1 <= 0 || atom1 > map_tag_max ||
atom2 <= 0 || atom2 > map_tag_max)
- error->one("Invalid atom ID in Bonds section of data file");
+ error->one(FLERR,"Invalid atom ID in Bonds section of data file");
if (itype <= 0 || itype > nbondtypes)
- error->one("Invalid bond type in Bonds section of data file");
+ error->one(FLERR,"Invalid bond type in Bonds section of data file");
if ((m = map(atom1)) >= 0) {
bond_type[m][num_bond[m]] = itype;
bond_atom[m][num_bond[m]] = atom2;
num_bond[m]++;
}
if (newton_bond == 0) {
if ((m = map(atom2)) >= 0) {
bond_type[m][num_bond[m]] = itype;
bond_atom[m][num_bond[m]] = atom1;
num_bond[m]++;
}
}
buf = next + 1;
}
}
/* ----------------------------------------------------------------------
check that atom IDs are > 0 and <= map_tag_max
------------------------------------------------------------------------- */
void Atom::data_angles(int n, char *buf)
{
int m,tmp,itype,atom1,atom2,atom3;
char *next;
int newton_bond = force->newton_bond;
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
*next = '\0';
sscanf(buf,"%d %d %d %d %d",&tmp,&itype,&atom1,&atom2,&atom3);
if (atom1 <= 0 || atom1 > map_tag_max ||
atom2 <= 0 || atom2 > map_tag_max ||
atom3 <= 0 || atom3 > map_tag_max)
- error->one("Invalid atom ID in Angles section of data file");
+ error->one(FLERR,"Invalid atom ID in Angles section of data file");
if (itype <= 0 || itype > nangletypes)
- error->one("Invalid angle type in Angles section of data file");
+ error->one(FLERR,"Invalid angle type in Angles section of data file");
if ((m = map(atom2)) >= 0) {
angle_type[m][num_angle[m]] = itype;
angle_atom1[m][num_angle[m]] = atom1;
angle_atom2[m][num_angle[m]] = atom2;
angle_atom3[m][num_angle[m]] = atom3;
num_angle[m]++;
}
if (newton_bond == 0) {
if ((m = map(atom1)) >= 0) {
angle_type[m][num_angle[m]] = itype;
angle_atom1[m][num_angle[m]] = atom1;
angle_atom2[m][num_angle[m]] = atom2;
angle_atom3[m][num_angle[m]] = atom3;
num_angle[m]++;
}
if ((m = map(atom3)) >= 0) {
angle_type[m][num_angle[m]] = itype;
angle_atom1[m][num_angle[m]] = atom1;
angle_atom2[m][num_angle[m]] = atom2;
angle_atom3[m][num_angle[m]] = atom3;
num_angle[m]++;
}
}
buf = next + 1;
}
}
/* ----------------------------------------------------------------------
check that atom IDs are > 0 and <= map_tag_max
------------------------------------------------------------------------- */
void Atom::data_dihedrals(int n, char *buf)
{
int m,tmp,itype,atom1,atom2,atom3,atom4;
char *next;
int newton_bond = force->newton_bond;
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
*next = '\0';
sscanf(buf,"%d %d %d %d %d %d",&tmp,&itype,&atom1,&atom2,&atom3,&atom4);
if (atom1 <= 0 || atom1 > map_tag_max ||
atom2 <= 0 || atom2 > map_tag_max ||
atom3 <= 0 || atom3 > map_tag_max ||
atom4 <= 0 || atom4 > map_tag_max)
- error->one("Invalid atom ID in Dihedrals section of data file");
+ error->one(FLERR,"Invalid atom ID in Dihedrals section of data file");
if (itype <= 0 || itype > ndihedraltypes)
- error->one("Invalid dihedral type in Dihedrals section of data file");
+ error->one(FLERR,"Invalid dihedral type in Dihedrals section of data file");
if ((m = map(atom2)) >= 0) {
dihedral_type[m][num_dihedral[m]] = itype;
dihedral_atom1[m][num_dihedral[m]] = atom1;
dihedral_atom2[m][num_dihedral[m]] = atom2;
dihedral_atom3[m][num_dihedral[m]] = atom3;
dihedral_atom4[m][num_dihedral[m]] = atom4;
num_dihedral[m]++;
}
if (newton_bond == 0) {
if ((m = map(atom1)) >= 0) {
dihedral_type[m][num_dihedral[m]] = itype;
dihedral_atom1[m][num_dihedral[m]] = atom1;
dihedral_atom2[m][num_dihedral[m]] = atom2;
dihedral_atom3[m][num_dihedral[m]] = atom3;
dihedral_atom4[m][num_dihedral[m]] = atom4;
num_dihedral[m]++;
}
if ((m = map(atom3)) >= 0) {
dihedral_type[m][num_dihedral[m]] = itype;
dihedral_atom1[m][num_dihedral[m]] = atom1;
dihedral_atom2[m][num_dihedral[m]] = atom2;
dihedral_atom3[m][num_dihedral[m]] = atom3;
dihedral_atom4[m][num_dihedral[m]] = atom4;
num_dihedral[m]++;
}
if ((m = map(atom4)) >= 0) {
dihedral_type[m][num_dihedral[m]] = itype;
dihedral_atom1[m][num_dihedral[m]] = atom1;
dihedral_atom2[m][num_dihedral[m]] = atom2;
dihedral_atom3[m][num_dihedral[m]] = atom3;
dihedral_atom4[m][num_dihedral[m]] = atom4;
num_dihedral[m]++;
}
}
buf = next + 1;
}
}
/* ----------------------------------------------------------------------
check that atom IDs are > 0 and <= map_tag_max
------------------------------------------------------------------------- */
void Atom::data_impropers(int n, char *buf)
{
int m,tmp,itype,atom1,atom2,atom3,atom4;
char *next;
int newton_bond = force->newton_bond;
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
*next = '\0';
sscanf(buf,"%d %d %d %d %d %d",&tmp,&itype,&atom1,&atom2,&atom3,&atom4);
if (atom1 <= 0 || atom1 > map_tag_max ||
atom2 <= 0 || atom2 > map_tag_max ||
atom3 <= 0 || atom3 > map_tag_max ||
atom4 <= 0 || atom4 > map_tag_max)
- error->one("Invalid atom ID in Impropers section of data file");
+ error->one(FLERR,"Invalid atom ID in Impropers section of data file");
if (itype <= 0 || itype > nimpropertypes)
- error->one("Invalid improper type in Impropers section of data file");
+ error->one(FLERR,"Invalid improper type in Impropers section of data file");
if ((m = map(atom2)) >= 0) {
improper_type[m][num_improper[m]] = itype;
improper_atom1[m][num_improper[m]] = atom1;
improper_atom2[m][num_improper[m]] = atom2;
improper_atom3[m][num_improper[m]] = atom3;
improper_atom4[m][num_improper[m]] = atom4;
num_improper[m]++;
}
if (newton_bond == 0) {
if ((m = map(atom1)) >= 0) {
improper_type[m][num_improper[m]] = itype;
improper_atom1[m][num_improper[m]] = atom1;
improper_atom2[m][num_improper[m]] = atom2;
improper_atom3[m][num_improper[m]] = atom3;
improper_atom4[m][num_improper[m]] = atom4;
num_improper[m]++;
}
if ((m = map(atom3)) >= 0) {
improper_type[m][num_improper[m]] = itype;
improper_atom1[m][num_improper[m]] = atom1;
improper_atom2[m][num_improper[m]] = atom2;
improper_atom3[m][num_improper[m]] = atom3;
improper_atom4[m][num_improper[m]] = atom4;
num_improper[m]++;
}
if ((m = map(atom4)) >= 0) {
improper_type[m][num_improper[m]] = itype;
improper_atom1[m][num_improper[m]] = atom1;
improper_atom2[m][num_improper[m]] = atom2;
improper_atom3[m][num_improper[m]] = atom3;
improper_atom4[m][num_improper[m]] = atom4;
num_improper[m]++;
}
}
buf = next + 1;
}
}
/* ----------------------------------------------------------------------
allocate arrays of length ntypes
only done after ntypes is set
------------------------------------------------------------------------- */
void Atom::allocate_type_arrays()
{
if (avec->mass_type) {
mass = new double[ntypes+1];
mass_setflag = new int[ntypes+1];
for (int itype = 1; itype <= ntypes; itype++) mass_setflag[itype] = 0;
}
}
/* ----------------------------------------------------------------------
set a mass and flag it as set
called from reading of data file
------------------------------------------------------------------------- */
void Atom::set_mass(const char *str)
{
- if (mass == NULL) error->all("Cannot set mass for this atom style");
+ if (mass == NULL) error->all(FLERR,"Cannot set mass for this atom style");
int itype;
double mass_one;
int n = sscanf(str,"%d %lg",&itype,&mass_one);
- if (n != 2) error->all("Invalid mass line in data file");
+ if (n != 2) error->all(FLERR,"Invalid mass line in data file");
- if (itype < 1 || itype > ntypes) error->all("Invalid type for mass set");
+ if (itype < 1 || itype > ntypes) error->all(FLERR,"Invalid type for mass set");
mass[itype] = mass_one;
mass_setflag[itype] = 1;
- if (mass[itype] <= 0.0) error->all("Invalid mass value");
+ if (mass[itype] <= 0.0) error->all(FLERR,"Invalid mass value");
}
/* ----------------------------------------------------------------------
set a mass and flag it as set
called from EAM pair routine
------------------------------------------------------------------------- */
void Atom::set_mass(int itype, double value)
{
- if (mass == NULL) error->all("Cannot set mass for this atom style");
- if (itype < 1 || itype > ntypes) error->all("Invalid type for mass set");
+ if (mass == NULL) error->all(FLERR,"Cannot set mass for this atom style");
+ if (itype < 1 || itype > ntypes) error->all(FLERR,"Invalid type for mass set");
mass[itype] = value;
mass_setflag[itype] = 1;
- if (mass[itype] <= 0.0) error->all("Invalid mass value");
+ if (mass[itype] <= 0.0) error->all(FLERR,"Invalid mass value");
}
/* ----------------------------------------------------------------------
set one or more masses and flag them as set
called from reading of input script
------------------------------------------------------------------------- */
void Atom::set_mass(int narg, char **arg)
{
- if (mass == NULL) error->all("Cannot set mass for this atom style");
+ if (mass == NULL) error->all(FLERR,"Cannot set mass for this atom style");
int lo,hi;
force->bounds(arg[0],ntypes,lo,hi);
- if (lo < 1 || hi > ntypes) error->all("Invalid type for mass set");
+ if (lo < 1 || hi > ntypes) error->all(FLERR,"Invalid type for mass set");
for (int itype = lo; itype <= hi; itype++) {
mass[itype] = atof(arg[1]);
mass_setflag[itype] = 1;
- if (mass[itype] <= 0.0) error->all("Invalid mass value");
+ if (mass[itype] <= 0.0) error->all(FLERR,"Invalid mass value");
}
}
/* ----------------------------------------------------------------------
set all masses as read in from restart file
------------------------------------------------------------------------- */
void Atom::set_mass(double *values)
{
for (int itype = 1; itype <= ntypes; itype++) {
mass[itype] = values[itype];
mass_setflag[itype] = 1;
}
}
/* ----------------------------------------------------------------------
check that all masses have been set
------------------------------------------------------------------------- */
void Atom::check_mass()
{
if (mass == NULL) return;
for (int itype = 1; itype <= ntypes; itype++)
- if (mass_setflag[itype] == 0) error->all("All masses are not set");
+ if (mass_setflag[itype] == 0) error->all(FLERR,"All masses are not set");
}
/* ----------------------------------------------------------------------
check that radii of all particles of itype are the same
return 1 if true, else return 0
also return the radius value for that type
------------------------------------------------------------------------- */
int Atom::radius_consistency(int itype, double &rad)
{
double value = -1.0;
int flag = 0;
for (int i = 0; i < nlocal; i++) {
if (type[i] != itype) continue;
if (value < 0.0) value = radius[i];
else if (value != radius[i]) flag = 1;
}
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall) return 0;
MPI_Allreduce(&value,&rad,1,MPI_DOUBLE,MPI_MAX,world);
return 1;
}
/* ----------------------------------------------------------------------
check that shape of all particles of itype are the same
return 1 if true, else return 0
also return the 3 shape params for itype
------------------------------------------------------------------------- */
int Atom::shape_consistency(int itype,
double &shapex, double &shapey, double &shapez)
{
double zero[3] = {0.0, 0.0, 0.0};
double one[3] = {-1.0, -1.0, -1.0};
double *shape;
AtomVecEllipsoid *avec_ellipsoid =
(AtomVecEllipsoid *) style_match("ellipsoid");
AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus;
int flag = 0;
for (int i = 0; i < nlocal; i++) {
if (type[i] != itype) continue;
if (ellipsoid[i] < 0) shape = zero;
else shape = bonus[ellipsoid[i]].shape;
if (one[0] < 0.0) {
one[0] = shape[0];
one[1] = shape[1];
one[2] = shape[2];
} else if (one[0] != shape[0] || one[1] != shape[1] || one[2] != shape[2])
flag = 1;
}
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall) return 0;
double oneall[3];
MPI_Allreduce(one,oneall,3,MPI_DOUBLE,MPI_MAX,world);
shapex = oneall[0];
shapey = oneall[1];
shapez = oneall[2];
return 1;
}
/* ----------------------------------------------------------------------
reorder owned atoms so those in firstgroup appear first
called by comm->exchange() if atom_modify first group is set
only owned atoms exist at this point, no ghost atoms
------------------------------------------------------------------------- */
void Atom::first_reorder()
{
// insure there is one extra atom location at end of arrays for swaps
if (nlocal == nmax) avec->grow(0);
// loop over owned atoms
// nfirst = index of first atom not in firstgroup
// when find firstgroup atom out of place, swap it with atom nfirst
int bitmask = group->bitmask[firstgroup];
nfirst = 0;
while (nfirst < nlocal && mask[nfirst] & bitmask) nfirst++;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & bitmask && i > nfirst) {
avec->copy(i,nlocal,0);
avec->copy(nfirst,i,0);
avec->copy(nlocal,nfirst,0);
while (nfirst < nlocal && mask[nfirst] & bitmask) nfirst++;
}
}
}
/* ----------------------------------------------------------------------
perform spatial sort of atoms within my sub-domain
always called between comm->exchange() and comm->borders()
don't have to worry about clearing/setting atom->map since done in comm
------------------------------------------------------------------------- */
void Atom::sort()
{
int i,m,n,ix,iy,iz,ibin,empty;
// set next timestep for sorting to take place
nextsort = (update->ntimestep/sortfreq)*sortfreq + sortfreq;
// download data from GPU if necessary
if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->downloadAll();
// re-setup sort bins if needed
if (domain->box_change) setup_sort_bins();
if (nbins == 1) return;
// reallocate per-atom vectors if needed
if (nlocal > maxnext) {
memory->destroy(next);
memory->destroy(permute);
maxnext = atom->nmax;
memory->create(next,maxnext,"atom:next");
memory->create(permute,maxnext,"atom:permute");
}
// insure there is one extra atom location at end of arrays for swaps
if (nlocal == nmax) avec->grow(0);
// bin atoms in reverse order so linked list will be in forward order
for (i = 0; i < nbins; i++) binhead[i] = -1;
for (i = nlocal-1; i >= 0; i--) {
ix = static_cast<int> ((x[i][0]-bboxlo[0])*bininvx);
iy = static_cast<int> ((x[i][1]-bboxlo[1])*bininvy);
iz = static_cast<int> ((x[i][2]-bboxlo[2])*bininvz);
ix = MAX(ix,0);
iy = MAX(iy,0);
iz = MAX(iz,0);
ix = MIN(ix,nbinx-1);
iy = MIN(iy,nbiny-1);
iz = MIN(iz,nbinz-1);
ibin = iz*nbiny*nbinx + iy*nbinx + ix;
next[i] = binhead[ibin];
binhead[ibin] = i;
}
// permute = desired permutation of atoms
// permute[I] = J means Ith new atom will be Jth old atom
n = 0;
for (m = 0; m < nbins; m++) {
i = binhead[m];
while (i >= 0) {
permute[n++] = i;
i = next[i];
}
}
// current = current permutation, just reuse next vector
// current[I] = J means Ith current atom is Jth old atom
int *current = next;
for (i = 0; i < nlocal; i++) current[i] = i;
// reorder local atom list, when done, current = permute
// perform "in place" using copy() to extra atom location at end of list
// inner while loop processes one cycle of the permutation
// copy before inner-loop moves an atom to end of atom list
// copy after inner-loop moves atom at end of list back into list
// empty = location in atom list that is currently empty
for (i = 0; i < nlocal; i++) {
if (current[i] == permute[i]) continue;
avec->copy(i,nlocal,0);
empty = i;
while (permute[empty] != i) {
avec->copy(permute[empty],empty,0);
empty = current[empty] = permute[empty];
}
avec->copy(nlocal,empty,0);
current[empty] = permute[empty];
}
// upload data back to GPU if necessary
if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->uploadAll();
// sanity check that current = permute
//int flag = 0;
//for (i = 0; i < nlocal; i++)
// if (current[i] != permute[i]) flag = 1;
//int flagall;
//MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
- //if (flagall) error->all("Atom sort did not operate correctly");
+ //if (flagall) error->all(FLERR,"Atom sort did not operate correctly");
}
/* ----------------------------------------------------------------------
setup bins for spatial sorting of atoms
------------------------------------------------------------------------- */
void Atom::setup_sort_bins()
{
// binsize:
// user setting if explicitly set
// 1/2 of neighbor cutoff for non-CUDA
// CUDA_CHUNK atoms/proc for CUDA
// check if neighbor cutoff = 0.0
double binsize;
if (userbinsize > 0.0) binsize = userbinsize;
else if (!lmp->cuda) binsize = 0.5 * neighbor->cutneighmax;
else {
if (domain->dimension == 3) {
double vol = (domain->boxhi[0]-domain->boxlo[0]) *
(domain->boxhi[1]-domain->boxlo[1]) *
(domain->boxhi[2]-domain->boxlo[2]);
binsize = pow(1.0*CUDA_CHUNK/natoms*vol,1.0/3.0);
} else {
double area = (domain->boxhi[0]-domain->boxlo[0]) *
(domain->boxhi[1]-domain->boxlo[1]);
binsize = pow(1.0*CUDA_CHUNK/natoms*area,1.0/2.0);
}
}
- if (binsize == 0.0) error->all("Atom sorting has bin size = 0.0");
+ if (binsize == 0.0) error->all(FLERR,"Atom sorting has bin size = 0.0");
double bininv = 1.0/binsize;
// nbin xyz = local bins
// bbox lo/hi = bounding box of my sub-domain
if (domain->triclinic)
domain->bbox(domain->sublo_lamda,domain->subhi_lamda,bboxlo,bboxhi);
else {
bboxlo[0] = domain->sublo[0];
bboxlo[1] = domain->sublo[1];
bboxlo[2] = domain->sublo[2];
bboxhi[0] = domain->subhi[0];
bboxhi[1] = domain->subhi[1];
bboxhi[2] = domain->subhi[2];
}
nbinx = static_cast<int> ((bboxhi[0]-bboxlo[0]) * bininv);
nbiny = static_cast<int> ((bboxhi[1]-bboxlo[1]) * bininv);
nbinz = static_cast<int> ((bboxhi[2]-bboxlo[2]) * bininv);
if (domain->dimension == 2) nbinz = 1;
if (nbinx == 0) nbinx = 1;
if (nbiny == 0) nbiny = 1;
if (nbinz == 0) nbinz = 1;
bininvx = nbinx / (bboxhi[0]-bboxlo[0]);
bininvy = nbiny / (bboxhi[1]-bboxlo[1]);
bininvz = nbinz / (bboxhi[2]-bboxlo[2]);
if (1.0*nbinx*nbiny*nbinz > INT_MAX)
- error->one("Too many atom sorting bins");
+ error->one(FLERR,"Too many atom sorting bins");
nbins = nbinx*nbiny*nbinz;
// reallocate per-bin memory if needed
if (nbins > maxbin) {
memory->destroy(binhead);
maxbin = nbins;
memory->create(binhead,maxbin,"atom:binhead");
}
}
/* ----------------------------------------------------------------------
register a callback to a fix so it can manage atom-based arrays
happens when fix is created
flag = 0 for grow, 1 for restart
------------------------------------------------------------------------- */
void Atom::add_callback(int flag)
{
int ifix;
// find the fix
// if find NULL ptr:
// it's this one, since it is being replaced and has just been deleted
// at this point in re-creation
// if don't find NULL ptr:
// i is set to nfix = new one currently being added at end of list
for (ifix = 0; ifix < modify->nfix; ifix++)
if (modify->fix[ifix] == NULL) break;
// add callback to lists, reallocating if necessary
if (flag == 0) {
if (nextra_grow == nextra_grow_max) {
nextra_grow_max += DELTA;
memory->grow(extra_grow,nextra_grow_max,"atom:extra_grow");
}
extra_grow[nextra_grow] = ifix;
nextra_grow++;
} else if (flag == 1) {
if (nextra_restart == nextra_restart_max) {
nextra_restart_max += DELTA;
memory->grow(extra_restart,nextra_restart_max,"atom:extra_restart");
}
extra_restart[nextra_restart] = ifix;
nextra_restart++;
}
}
/* ----------------------------------------------------------------------
unregister a callback to a fix
happens when fix is deleted, called by its destructor
flag = 0 for grow, 1 for restart
------------------------------------------------------------------------- */
void Atom::delete_callback(const char *id, int flag)
{
int ifix;
for (ifix = 0; ifix < modify->nfix; ifix++)
if (strcmp(id,modify->fix[ifix]->id) == 0) break;
// compact the list of callbacks
if (flag == 0) {
int match;
for (match = 0; match < nextra_grow; match++)
if (extra_grow[match] == ifix) break;
for (int i = match; i < nextra_grow-1; i++)
extra_grow[i] = extra_grow[i+1];
nextra_grow--;
} else if (flag == 1) {
int match;
for (match = 0; match < nextra_grow; match++)
if (extra_restart[match] == ifix) break;
for (int i = ifix; i < nextra_restart-1; i++)
extra_restart[i] = extra_restart[i+1];
nextra_restart--;
}
}
/* ----------------------------------------------------------------------
decrement ptrs in callback lists to fixes beyond the deleted ifix
happens after fix is deleted
------------------------------------------------------------------------- */
void Atom::update_callback(int ifix)
{
for (int i = 0; i < nextra_grow; i++)
if (extra_grow[i] > ifix) extra_grow[i]--;
for (int i = 0; i < nextra_restart; i++)
if (extra_restart[i] > ifix) extra_restart[i]--;
}
/* ----------------------------------------------------------------------
return a pointer to a named internal variable
if don't recognize name, return NULL
customize by adding names
------------------------------------------------------------------------- */
void *Atom::extract(char *name)
{
if (strcmp(name,"id") == 0) return (void *) tag;
if (strcmp(name,"type") == 0) return (void *) type;
if (strcmp(name,"x") == 0) return (void *) x;
if (strcmp(name,"v") == 0) return (void *) v;
if (strcmp(name,"f") == 0) return (void *) f;
if (strcmp(name,"mass") == 0) return (void *) mass;
if (strcmp(name,"rmass") == 0) return (void *) rmass;
return NULL;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
call to avec tallies per-atom vectors
add in global to local mapping storage
------------------------------------------------------------------------- */
bigint Atom::memory_usage()
{
memlength = DELTA_MEMSTR;
memory->create(memstr,memlength,"atom:memstr");
memstr[0] = '\0';
bigint bytes = avec->memory_usage();
memory->destroy(memstr);
if (map_style == 1)
bytes += memory->usage(map_array,map_tag_max+1);
else if (map_style == 2) {
bytes += map_nbucket*sizeof(int);
bytes += map_nhash*sizeof(HashElem);
}
if (maxnext) {
bytes += memory->usage(next,maxnext);
bytes += memory->usage(permute,maxnext);
}
return bytes;
}
/* ----------------------------------------------------------------------
accumulate per-atom vec names in memstr, padded by spaces
return 1 if padded str is not already in memlist, else 0
------------------------------------------------------------------------- */
int Atom::memcheck(const char *str)
{
int n = strlen(str) + 3;
char *padded = new char[n];
strcpy(padded," ");
strcat(padded,str);
strcat(padded," ");
if (strstr(memstr,padded)) {
delete [] padded;
return 0;
}
if (strlen(memstr) + n >= memlength) {
memlength += DELTA_MEMSTR;
memory->grow(memstr,memlength,"atom:memstr");
}
strcat(memstr,padded);
delete [] padded;
return 1;
}
diff --git a/src/atom_vec_atomic.cpp b/src/atom_vec_atomic.cpp
index a0bf79a12..e4e2dcf5e 100644
--- a/src/atom_vec_atomic.cpp
+++ b/src/atom_vec_atomic.cpp
@@ -1,636 +1,636 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "atom_vec_atomic.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecAtomic::AtomVecAtomic(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 0;
mass_type = 1;
comm_x_only = comm_f_only = 1;
size_forward = 3;
size_reverse = 3;
size_border = 6;
size_velocity = 3;
size_data_atom = 5;
size_data_vel = 4;
xcol_data = 3;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecAtomic::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecAtomic::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecAtomic::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomic::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomic::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomic::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomic::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomic::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomic::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomic::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomic::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomic::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
}
}
/* ---------------------------------------------------------------------- */
void AtomVecAtomic::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecAtomic::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecAtomic::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecAtomic::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 11 * nlocal;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecAtomic::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecAtomic::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecAtomic::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecAtomic::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecAtomic::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
return bytes;
}
diff --git a/src/atom_vec_charge.cpp b/src/atom_vec_charge.cpp
index 5def3bd99..81fc7a8ef 100644
--- a/src/atom_vec_charge.cpp
+++ b/src/atom_vec_charge.cpp
@@ -1,703 +1,703 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "atom_vec_charge.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecCharge::AtomVecCharge(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 0;
mass_type = 1;
comm_x_only = comm_f_only = 1;
size_forward = 3;
size_reverse = 3;
size_border = 7;
size_velocity = 3;
size_data_atom = 6;
size_data_vel = 4;
xcol_data = 4;
atom->q_flag = 1;
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecCharge::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
q = memory->grow(atom->q,nmax,"atom:q");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecCharge::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
q = atom->q;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecCharge::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
q[j] = q[i];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecCharge::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecCharge::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecCharge::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = q[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = q[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecCharge::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecCharge::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
q[i] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++)
q[i] = buf[m++];
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecCharge::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = q[i];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecCharge::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
q[nlocal] = buf[m++];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecCharge::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 12 * nlocal;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecCharge::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = q[i];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecCharge::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
q[nlocal] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecCharge::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
q[nlocal] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecCharge::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
q[nlocal] = atof(values[2]);
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecCharge::data_atom_hybrid(int nlocal, char **values)
{
q[nlocal] = atof(values[0]);
return 1;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecCharge::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("q")) bytes += memory->usage(q,nmax);
return bytes;
}
diff --git a/src/atom_vec_ellipsoid.cpp b/src/atom_vec_ellipsoid.cpp
index 2ccb91a6c..d0cf4ce11 100755
--- a/src/atom_vec_ellipsoid.cpp
+++ b/src/atom_vec_ellipsoid.cpp
@@ -1,1259 +1,1259 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "atom_vec_ellipsoid.h"
#include "math_extra.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
#define DELTA_BONUS 10000
/* ---------------------------------------------------------------------- */
AtomVecEllipsoid::AtomVecEllipsoid(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 0;
comm_x_only = comm_f_only = 0;
size_forward = 7;
size_reverse = 6;
size_border = 14;
size_velocity = 6;
size_data_atom = 7;
size_data_vel = 7;
size_data_bonus = 8;
xcol_data = 5;
atom->ellipsoid_flag = 1;
atom->rmass_flag = atom->angmom_flag = atom->torque_flag = 1;
PI = 4.0*atan(1.0);
nlocal_bonus = nghost_bonus = nmax_bonus = 0;
bonus = NULL;
}
/* ---------------------------------------------------------------------- */
AtomVecEllipsoid::~AtomVecEllipsoid()
{
memory->sfree(bonus);
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecEllipsoid::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
rmass = memory->grow(atom->rmass,nmax,"atom:rmass");
angmom = memory->grow(atom->angmom,nmax,3,"atom:angmom");
torque = memory->grow(atom->torque,nmax,3,"atom:torque");
ellipsoid = memory->grow(atom->ellipsoid,nmax,"atom:ellipsoid");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecEllipsoid::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
rmass = atom->rmass; angmom = atom->angmom; torque = atom->torque;
}
/* ----------------------------------------------------------------------
grow bonus data structure
------------------------------------------------------------------------- */
void AtomVecEllipsoid::grow_bonus()
{
nmax_bonus += DELTA_BONUS;
if (nmax_bonus < 0 || nmax_bonus > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
bonus = (Bonus *) memory->srealloc(bonus,nmax_bonus*sizeof(Bonus),
"atom:bonus");
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecEllipsoid::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
rmass[j] = rmass[i];
angmom[j][0] = angmom[i][0];
angmom[j][1] = angmom[i][1];
angmom[j][2] = angmom[i][2];
// if delflag and atom J has bonus data, then delete it
if (delflag && ellipsoid[j] >= 0) {
copy_bonus(nlocal_bonus-1,ellipsoid[j]);
nlocal_bonus--;
}
// if atom I has bonus data and not deleting I, repoint I's bonus to J
if (ellipsoid[i] >= 0 && i != j) bonus[ellipsoid[i]].ilocal = j;
ellipsoid[j] = ellipsoid[i];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ----------------------------------------------------------------------
copy bonus data from I to J, effectively deleting the J entry
insure index pointers between per-atom and bonus data are updated
------------------------------------------------------------------------- */
void AtomVecEllipsoid::copy_bonus(int i, int j)
{
memcpy(&bonus[j],&bonus[i],sizeof(Bonus));
ellipsoid[bonus[j].ilocal] = j;
}
/* ----------------------------------------------------------------------
clear ghost info in bonus data
called before ghosts are recommunicated in comm and irregular
------------------------------------------------------------------------- */
void AtomVecEllipsoid::clear_bonus()
{
nghost_bonus = 0;
}
/* ----------------------------------------------------------------------
set shape values in bonus data for particle I
oriented aligned with xyz axes
this may create or delete entry in bonus data
------------------------------------------------------------------------- */
void AtomVecEllipsoid::set_shape(int i,
double shapex, double shapey, double shapez)
{
if (ellipsoid[i] < 0) {
if (shapex == 0.0 && shapey == 0.0 && shapez == 0.0) return;
if (nlocal_bonus == nmax_bonus) grow_bonus();
double *shape = bonus[nlocal_bonus].shape;
double *quat = bonus[nlocal_bonus].quat;
shape[0] = shapex;
shape[1] = shapey;
shape[2] = shapez;
quat[0] = 1.0;
quat[1] = 0.0;
quat[2] = 0.0;
quat[3] = 0.0;
bonus[nlocal_bonus].ilocal = i;
ellipsoid[i] = nlocal_bonus++;
} else if (shapex == 0.0 && shapey == 0.0 && shapez == 0.0) {
copy_bonus(nlocal_bonus-1,ellipsoid[i]);
nlocal_bonus--;
ellipsoid[i] = -1;
} else {
double *shape = bonus[ellipsoid[i]].shape;
shape[0] = shapex;
shape[1] = shapey;
shape[2] = shapez;
}
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
double *quat;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
if (ellipsoid[j] >= 0) {
quat = bonus[ellipsoid[j]].quat;
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (ellipsoid[j] >= 0) {
quat = bonus[ellipsoid[j]].quat;
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
double *quat;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
if (ellipsoid[j] >= 0) {
quat = bonus[ellipsoid[j]].quat;
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (ellipsoid[j] >= 0) {
quat = bonus[ellipsoid[j]].quat;
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (ellipsoid[j] >= 0) {
quat = bonus[ellipsoid[j]].quat;
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_comm_hybrid(int n, int *list, double *buf)
{
int i,j,m;
double *quat;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
if (ellipsoid[j] >= 0) {
quat = bonus[ellipsoid[j]].quat;
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecEllipsoid::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
double *quat;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
if (ellipsoid[i] >= 0) {
quat = bonus[ellipsoid[i]].quat;
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
}
}
}
/* ---------------------------------------------------------------------- */
void AtomVecEllipsoid::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
double *quat;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
if (ellipsoid[i] >= 0) {
quat = bonus[ellipsoid[i]].quat;
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
}
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
angmom[i][0] = buf[m++];
angmom[i][1] = buf[m++];
angmom[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::unpack_comm_hybrid(int n, int first, double *buf)
{
int i,m,last;
double *quat;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (ellipsoid[i] >= 0) {
quat = bonus[ellipsoid[i]].quat;
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
buf[m++] = torque[i][0];
buf[m++] = torque[i][1];
buf[m++] = torque[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_reverse_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = torque[i][0];
buf[m++] = torque[i][1];
buf[m++] = torque[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecEllipsoid::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
torque[j][0] += buf[m++];
torque[j][1] += buf[m++];
torque[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::unpack_reverse_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
torque[j][0] += buf[m++];
torque[j][1] += buf[m++];
torque[j][2] += buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
double *shape,*quat;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
if (ellipsoid[j] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
shape = bonus[ellipsoid[j]].shape;
quat = bonus[ellipsoid[j]].quat;
buf[m++] = shape[0];
buf[m++] = shape[1];
buf[m++] = shape[2];
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
if (ellipsoid[j] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
shape = bonus[ellipsoid[j]].shape;
quat = bonus[ellipsoid[j]].quat;
buf[m++] = shape[0];
buf[m++] = shape[1];
buf[m++] = shape[2];
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
double *shape,*quat;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
if (ellipsoid[j] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
shape = bonus[ellipsoid[j]].shape;
quat = bonus[ellipsoid[j]].quat;
buf[m++] = shape[0];
buf[m++] = shape[1];
buf[m++] = shape[2];
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
if (ellipsoid[j] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
quat = bonus[ellipsoid[j]].quat;
buf[m++] = shape[0];
buf[m++] = shape[1];
buf[m++] = shape[2];
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
if (ellipsoid[j] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
shape = bonus[ellipsoid[j]].shape;
quat = bonus[ellipsoid[j]].quat;
buf[m++] = shape[0];
buf[m++] = shape[1];
buf[m++] = shape[2];
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
double *shape,*quat;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
if (ellipsoid[j] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
shape = bonus[ellipsoid[j]].shape;
quat = bonus[ellipsoid[j]].quat;
buf[m++] = shape[0];
buf[m++] = shape[1];
buf[m++] = shape[2];
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecEllipsoid::unpack_border(int n, int first, double *buf)
{
int i,j,m,last;
double *shape,*quat;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
ellipsoid[i] = static_cast<int> (buf[m++]);
if (ellipsoid[i] == 0) ellipsoid[i] = -1;
else {
j = nlocal_bonus + nghost_bonus;
if (j == nmax_bonus) grow_bonus();
shape = bonus[j].shape;
quat = bonus[j].quat;
shape[0] = buf[m++];
shape[1] = buf[m++];
shape[2] = buf[m++];
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
bonus[j].ilocal = i;
ellipsoid[i] = j;
nghost_bonus++;
}
}
}
/* ---------------------------------------------------------------------- */
void AtomVecEllipsoid::unpack_border_vel(int n, int first, double *buf)
{
int i,j,m,last;
double *shape,*quat;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
ellipsoid[i] = static_cast<int> (buf[m++]);
if (ellipsoid[i] == 0) ellipsoid[i] = -1;
else {
if (j == nmax_bonus) grow_bonus();
shape = bonus[j].shape;
quat = bonus[j].quat;
shape[0] = buf[m++];
shape[1] = buf[m++];
shape[2] = buf[m++];
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
bonus[j].ilocal = i;
ellipsoid[i] = j;
nghost_bonus++;
}
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
angmom[i][0] = buf[m++];
angmom[i][1] = buf[m++];
angmom[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::unpack_border_hybrid(int n, int first, double *buf)
{
int i,j,m,last;
double *shape,*quat;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
ellipsoid[i] = static_cast<int> (buf[m++]);
if (ellipsoid[i] == 0) ellipsoid[i] = -1;
else {
j = nlocal_bonus + nghost_bonus;
if (j == nmax_bonus) grow_bonus();
shape = bonus[j].shape;
quat = bonus[j].quat;
shape[0] = buf[m++];
shape[1] = buf[m++];
shape[2] = buf[m++];
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
bonus[j].ilocal = i;
ellipsoid[i] = j;
nghost_bonus++;
}
}
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = rmass[i];
buf[m++] = angmom[i][0];
buf[m++] = angmom[i][1];
buf[m++] = angmom[i][2];
if (ellipsoid[i] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
int j = ellipsoid[i];
double *shape = bonus[j].shape;
double *quat = bonus[j].quat;
buf[m++] = shape[0];
buf[m++] = shape[1];
buf[m++] = shape[2];
buf[m++] = quat[0];
buf[m++] = quat[1];
buf[m++] = quat[2];
buf[m++] = quat[3];
}
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecEllipsoid::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
rmass[nlocal] = buf[m++];
angmom[nlocal][0] = buf[m++];
angmom[nlocal][1] = buf[m++];
angmom[nlocal][2] = buf[m++];
ellipsoid[nlocal] = static_cast<int> (buf[m++]);
if (ellipsoid[nlocal] == 0) ellipsoid[nlocal] = -1;
else {
if (nlocal_bonus == nmax_bonus) grow_bonus();
double *shape = bonus[nlocal_bonus].shape;
double *quat = bonus[nlocal_bonus].quat;
shape[0] = buf[m++];
shape[1] = buf[m++];
shape[2] = buf[m++];
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
bonus[nlocal_bonus].ilocal = nlocal;
ellipsoid[nlocal] = nlocal_bonus++;
}
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecEllipsoid::size_restart()
{
int i;
int n = 0;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (ellipsoid[i] >= 0) n += 23;
else n += 16;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including bonus data
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecEllipsoid::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = rmass[i];
buf[m++] = angmom[i][0];
buf[m++] = angmom[i][1];
buf[m++] = angmom[i][2];
if (ellipsoid[i] < 0) buf[m++] = 0;
else {
buf[m++] = 1;
int j = ellipsoid[i];
buf[m++] = bonus[j].shape[0];
buf[m++] = bonus[j].shape[1];
buf[m++] = bonus[j].shape[2];
buf[m++] = bonus[j].quat[0];
buf[m++] = bonus[j].quat[1];
buf[m++] = bonus[j].quat[2];
buf[m++] = bonus[j].quat[3];
}
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including bonus data
------------------------------------------------------------------------- */
int AtomVecEllipsoid::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
rmass[nlocal] = buf[m++];
angmom[nlocal][0] = buf[m++];
angmom[nlocal][1] = buf[m++];
angmom[nlocal][2] = buf[m++];
ellipsoid[nlocal] = static_cast<int> (buf[m++]);
if (ellipsoid[nlocal] == 0) ellipsoid[nlocal] = -1;
else {
if (nlocal_bonus == nmax_bonus) grow_bonus();
double *shape = bonus[nlocal_bonus].shape;
double *quat = bonus[nlocal_bonus].quat;
shape[0] = buf[m++];
shape[1] = buf[m++];
shape[2] = buf[m++];
quat[0] = buf[m++];
quat[1] = buf[m++];
quat[2] = buf[m++];
quat[3] = buf[m++];
bonus[nlocal_bonus].ilocal = nlocal;
ellipsoid[nlocal] = nlocal_bonus++;
}
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecEllipsoid::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
rmass[nlocal] = 1.0;
angmom[nlocal][0] = 0.0;
angmom[nlocal][1] = 0.0;
angmom[nlocal][2] = 0.0;
ellipsoid[nlocal] = -1;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecEllipsoid::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
ellipsoid[nlocal] = atoi(values[2]);
if (ellipsoid[nlocal] == 0) ellipsoid[nlocal] = -1;
else if (ellipsoid[nlocal] == 1) ellipsoid[nlocal] = 0;
- else error->one("Invalid atom type in Atoms section of data file");
+ else error->one(FLERR,"Invalid atom type in Atoms section of data file");
rmass[nlocal] = atof(values[3]);
if (rmass[nlocal] <= 0.0)
- error->one("Invalid density in Atoms section of data file");
+ error->one(FLERR,"Invalid density in Atoms section of data file");
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
angmom[nlocal][0] = 0.0;
angmom[nlocal][1] = 0.0;
angmom[nlocal][2] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecEllipsoid::data_atom_hybrid(int nlocal, char **values)
{
ellipsoid[nlocal] = atoi(values[0]);
if (ellipsoid[nlocal] == 0) ellipsoid[nlocal] = -1;
else if (ellipsoid[nlocal] == 1) ellipsoid[nlocal] = 0;
- else error->one("Invalid atom type in Atoms section of data file");
+ else error->one(FLERR,"Invalid atom type in Atoms section of data file");
rmass[nlocal] = atof(values[1]);
if (rmass[nlocal] <= 0.0)
- error->one("Invalid density in Atoms section of data file");
+ error->one(FLERR,"Invalid density in Atoms section of data file");
return 2;
}
/* ----------------------------------------------------------------------
unpack one line from Ellipsoids section of data file
------------------------------------------------------------------------- */
void AtomVecEllipsoid::data_atom_bonus(int m, char **values)
{
if (ellipsoid[m])
- error->one("Assigning ellipsoid parameters to non-ellipsoid atom");
+ error->one(FLERR,"Assigning ellipsoid parameters to non-ellipsoid atom");
if (nlocal_bonus == nmax_bonus) grow_bonus();
double *shape = bonus[nlocal_bonus].shape;
shape[0] = 0.5 * atof(values[0]);
shape[1] = 0.5 * atof(values[1]);
shape[2] = 0.5 * atof(values[2]);
if (shape[0] <= 0.0 || shape[1] <= 0.0 || shape[2] <= 0.0)
- error->one("Invalid shape in Ellipsoids section of data file");
+ error->one(FLERR,"Invalid shape in Ellipsoids section of data file");
double *quat = bonus[nlocal_bonus].quat;
quat[0] = atof(values[3]);
quat[1] = atof(values[4]);
quat[2] = atof(values[5]);
quat[3] = atof(values[6]);
MathExtra::qnormalize(quat);
// reset ellipsoid mass
// previously stored density in rmass
rmass[m] *= 4.0*PI/3.0 * shape[0]*shape[1]*shape[2];
bonus[nlocal_bonus].ilocal = m;
ellipsoid[m] = nlocal_bonus++;
}
/* ----------------------------------------------------------------------
unpack one line from Velocities section of data file
------------------------------------------------------------------------- */
void AtomVecEllipsoid::data_vel(int m, char **values)
{
v[m][0] = atof(values[0]);
v[m][1] = atof(values[1]);
v[m][2] = atof(values[2]);
angmom[m][0] = atof(values[3]);
angmom[m][1] = atof(values[4]);
angmom[m][2] = atof(values[5]);
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Velocities section of data file
------------------------------------------------------------------------- */
int AtomVecEllipsoid::data_vel_hybrid(int m, char **values)
{
angmom[m][0] = atof(values[0]);
angmom[m][1] = atof(values[1]);
angmom[m][2] = atof(values[2]);
return 3;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecEllipsoid::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("rmass")) bytes += memory->usage(rmass,nmax);
if (atom->memcheck("angmom")) bytes += memory->usage(angmom,nmax,3);
if (atom->memcheck("torque")) bytes += memory->usage(torque,nmax,3);
if (atom->memcheck("ellipsoid")) bytes += memory->usage(ellipsoid,nmax);
bytes += nmax_bonus*sizeof(Bonus);
return bytes;
}
diff --git a/src/atom_vec_hybrid.cpp b/src/atom_vec_hybrid.cpp
index 03c0c501e..b6b1dabde 100644
--- a/src/atom_vec_hybrid.cpp
+++ b/src/atom_vec_hybrid.cpp
@@ -1,879 +1,876 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "atom_vec_hybrid.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecHybrid::AtomVecHybrid(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
int i,k,dummy;
- if (narg < 1) error->all("Illegal atom_style command");
+ if (narg < 1) error->all(FLERR,"Illegal atom_style command");
// create sub-styles
nstyles = narg;
styles = new AtomVec*[nstyles];
keywords = new char*[nstyles];
for (i = 0; i < narg; i++) {
for (k = 0; k < i; k++)
if (strcmp(arg[i],keywords[k]) == 0)
- error->all("Atom style hybrid cannot use same atom style twice");
+ error->all(FLERR,"Atom style hybrid cannot use same atom style twice");
if (strcmp(arg[i],"hybrid") == 0)
- error->all("Atom style hybrid cannot have hybrid as an argument");
+ error->all(FLERR,"Atom style hybrid cannot have hybrid as an argument");
styles[i] = atom->new_avec(arg[i],0,NULL,NULL,dummy);
keywords[i] = new char[strlen(arg[i])+1];
strcpy(keywords[i],arg[i]);
}
// hybrid settings are MAX or MIN of sub-style settings
// hybrid sizes are minimial values plus extra values for each sub-style
molecular = 0;
comm_x_only = comm_f_only = 1;
size_forward = 3;
size_reverse = 3;
size_border = 6;
size_data_atom = 5;
size_data_vel = 4;
xcol_data = 3;
for (k = 0; k < nstyles; k++) {
molecular = MAX(molecular,styles[k]->molecular);
bonds_allow = MAX(bonds_allow,styles[k]->bonds_allow);
angles_allow = MAX(angles_allow,styles[k]->angles_allow);
dihedrals_allow = MAX(dihedrals_allow,styles[k]->dihedrals_allow);
impropers_allow = MAX(impropers_allow,styles[k]->impropers_allow);
mass_type = MAX(mass_type,styles[k]->mass_type);
dipole_type = MAX(dipole_type,styles[k]->dipole_type);
comm_x_only = MIN(comm_x_only,styles[k]->comm_x_only);
comm_f_only = MIN(comm_f_only,styles[k]->comm_f_only);
size_forward += styles[k]->size_forward - 3;
size_reverse += styles[k]->size_reverse - 3;
size_border += styles[k]->size_border - 6;
size_data_atom += styles[k]->size_data_atom - 5;
size_data_vel += styles[k]->size_data_vel - 4;
}
size_velocity = 3;
if (atom->omega_flag) size_velocity += 3;
if (atom->angmom_flag) size_velocity += 3;
}
/* ---------------------------------------------------------------------- */
AtomVecHybrid::~AtomVecHybrid()
{
for (int k = 0; k < nstyles; k++) delete styles[k];
delete [] styles;
for (int k = 0; k < nstyles; k++) delete [] keywords[k];
delete [] keywords;
}
/* ---------------------------------------------------------------------- */
void AtomVecHybrid::init()
{
AtomVec::init();
for (int k = 0; k < nstyles; k++) styles[k]->init();
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecHybrid::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
// sub-styles perform all reallocation
// turn off nextra_grow so hybrid can do that once below
int tmp = atom->nextra_grow;
atom->nextra_grow = 0;
for (int k = 0; k < nstyles; k++) styles[k]->grow(nmax);
atom->nextra_grow = tmp;
// insure hybrid local ptrs and sub-style ptrs are up to date
// for sub-styles, do this in case
// multiple sub-style reallocs of same array occurred
grow_reset();
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecHybrid::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
omega = atom->omega; angmom = atom->angmom;
for (int k = 0; k < nstyles; k++) styles[k]->grow_reset();
}
/* ----------------------------------------------------------------------
copy atom I info to atom J for all sub-styles
------------------------------------------------------------------------- */
void AtomVecHybrid::copy(int i, int j, int delflag)
{
int tmp = atom->nextra_grow;
atom->nextra_grow = 0;
for (int k = 0; k < nstyles; k++) styles[k]->copy(i,j,delflag);
atom->nextra_grow = tmp;
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
void AtomVecHybrid::clear_bonus()
{
for (int k = 0; k < nstyles; k++) styles[k]->clear_bonus();
}
/* ---------------------------------------------------------------------- */
int AtomVecHybrid::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,k,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
// pack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->pack_comm_hybrid(n,list,&buf[m]);
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecHybrid::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,k,m;
double dx,dy,dz,dvx,dvy,dvz;
int omega_flag = atom->omega_flag;
int angmom_flag = atom->angmom_flag;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
if (omega_flag) {
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
if (angmom_flag) {
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
if (omega_flag) {
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
if (angmom_flag) {
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
if (omega_flag) {
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
if (angmom_flag) {
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
}
}
// pack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->pack_comm_hybrid(n,list,&buf[m]);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecHybrid::unpack_comm(int n, int first, double *buf)
{
int i,k,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
// unpack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->unpack_comm_hybrid(n,first,&buf[m]);
}
/* ---------------------------------------------------------------------- */
void AtomVecHybrid::unpack_comm_vel(int n, int first, double *buf)
{
int i,k,m,last;
int omega_flag = atom->omega_flag;
int angmom_flag = atom->angmom_flag;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
if (omega_flag) {
omega[i][0] = buf[m++];
omega[i][1] = buf[m++];
omega[i][2] = buf[m++];
}
if (angmom_flag) {
angmom[i][0] = buf[m++];
angmom[i][1] = buf[m++];
angmom[i][2] = buf[m++];
}
}
// unpack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->unpack_comm_hybrid(n,first,&buf[m]);
}
/* ---------------------------------------------------------------------- */
int AtomVecHybrid::pack_reverse(int n, int first, double *buf)
{
int i,k,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
}
// pack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->pack_reverse_hybrid(n,first,&buf[m]);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecHybrid::unpack_reverse(int n, int *list, double *buf)
{
int i,j,k,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
}
// unpack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->unpack_reverse_hybrid(n,list,&buf[m]);
}
/* ---------------------------------------------------------------------- */
int AtomVecHybrid::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,k,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
}
}
// pack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->pack_border_hybrid(n,list,&buf[m]);
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecHybrid::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,k,m;
double dx,dy,dz,dvx,dvy,dvz;
int omega_flag = atom->omega_flag;
int angmom_flag = atom->angmom_flag;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
if (omega_flag) {
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
if (angmom_flag) {
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
if (omega_flag) {
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
if (angmom_flag) {
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
if (omega_flag) {
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
if (angmom_flag) {
buf[m++] = angmom[j][0];
buf[m++] = angmom[j][1];
buf[m++] = angmom[j][2];
}
}
}
}
// pack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->pack_border_hybrid(n,list,&buf[m]);
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecHybrid::unpack_border(int n, int first, double *buf)
{
int i,k,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
}
// unpack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->unpack_border_hybrid(n,first,&buf[m]);
}
/* ---------------------------------------------------------------------- */
void AtomVecHybrid::unpack_border_vel(int n, int first, double *buf)
{
int i,k,m,last;
int omega_flag = atom->omega_flag;
int angmom_flag = atom->angmom_flag;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
if (omega_flag) {
omega[i][0] = buf[m++];
omega[i][1] = buf[m++];
omega[i][2] = buf[m++];
}
if (angmom_flag) {
angmom[i][0] = buf[m++];
angmom[i][1] = buf[m++];
angmom[i][2] = buf[m++];
}
}
// unpack sub-style contributions as contiguous chunks
for (k = 0; k < nstyles; k++)
m += styles[k]->unpack_border_hybrid(n,first,&buf[m]);
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
pack each sub-style one after the other
------------------------------------------------------------------------- */
int AtomVecHybrid::pack_exchange(int i, double *buf)
{
int k,m;
int tmp = atom->nextra_grow;
atom->nextra_grow = 0;
m = 0;
for (k = 0; k < nstyles; k++)
m += styles[k]->pack_exchange(i,&buf[m]);
atom->nextra_grow = tmp;
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for single atom received from another proc
unpack each sub-style one after the other
grow() occurs here so arrays for all sub-styles are grown
------------------------------------------------------------------------- */
int AtomVecHybrid::unpack_exchange(double *buf)
{
int k,m;
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int tmp = atom->nextra_grow;
atom->nextra_grow = 0;
m = 0;
for (k = 0; k < nstyles; k++) {
m += styles[k]->unpack_exchange(&buf[m]);
atom->nlocal--;
}
atom->nextra_grow = tmp;
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecHybrid::size_restart()
{
int tmp = atom->nextra_restart;
atom->nextra_restart = 0;
int n = 0;
for (int k = 0; k < nstyles; k++)
n += styles[k]->size_restart();
atom->nextra_restart = tmp;
int nlocal = atom->nlocal;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (int i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
pack each sub-style one after the other
------------------------------------------------------------------------- */
int AtomVecHybrid::pack_restart(int i, double *buf)
{
int tmp = atom->nextra_restart;
atom->nextra_restart = 0;
int m = 0;
for (int k = 0; k < nstyles; k++)
m += styles[k]->pack_restart(i,&buf[m]);
atom->nextra_restart = tmp;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
unpack each sub-style one after the other
grow() occurs here so arrays for all sub-styles are grown
------------------------------------------------------------------------- */
int AtomVecHybrid::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int tmp = atom->nextra_store;
atom->nextra_store = 0;
int m = 0;
for (int k = 0; k < nstyles; k++) {
m += styles[k]->unpack_restart(&buf[m]);
atom->nlocal--;
}
atom->nextra_store = tmp;
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
create each sub-style one after the other
grow() occurs here so arrays for all sub-styles are grown
------------------------------------------------------------------------- */
void AtomVecHybrid::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
for (int k = 0; k < nstyles; k++) {
styles[k]->create_atom(itype,coord);
atom->nlocal--;
}
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
grow() occurs here so arrays for all sub-styles are grown
------------------------------------------------------------------------- */
void AtomVecHybrid::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
if (atom->omega_flag) {
omega[nlocal][0] = 0.0;
omega[nlocal][1] = 0.0;
omega[nlocal][2] = 0.0;
}
if (atom->angmom_flag) {
angmom[nlocal][0] = 0.0;
angmom[nlocal][1] = 0.0;
angmom[nlocal][2] = 0.0;
}
// each sub-style parses sub-style specific values
int m = 5;
for (int k = 0; k < nstyles; k++)
m += styles[k]->data_atom_hybrid(nlocal,&values[m]);
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Velocities section of data file
------------------------------------------------------------------------- */
void AtomVecHybrid::data_vel(int m, char **values)
{
v[m][0] = atof(values[0]);
v[m][1] = atof(values[1]);
v[m][2] = atof(values[2]);
// each sub-style parses sub-style specific values
int n = 3;
for (int k = 0; k < nstyles; k++)
n += styles[k]->data_vel_hybrid(m,&values[n]);
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecHybrid::memory_usage()
{
bigint bytes = 0;
for (int k = 0; k < nstyles; k++) bytes += styles[k]->memory_usage();
return bytes;
}
diff --git a/src/atom_vec_sphere.cpp b/src/atom_vec_sphere.cpp
index b17817412..babc91438 100644
--- a/src/atom_vec_sphere.cpp
+++ b/src/atom_vec_sphere.cpp
@@ -1,1059 +1,1059 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "atom_vec_sphere.h"
#include "atom.h"
#include "comm.h"
#include "domain.h"
#include "modify.h"
#include "force.h"
#include "fix.h"
#include "fix_adapt.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
AtomVecSphere::AtomVecSphere(LAMMPS *lmp, int narg, char **arg) :
AtomVec(lmp, narg, arg)
{
molecular = 0;
comm_x_only = 1;
comm_f_only = 0;
size_forward = 3;
size_reverse = 6;
size_border = 8;
size_velocity = 6;
size_data_atom = 7;
size_data_vel = 7;
xcol_data = 5;
atom->sphere_flag = 1;
atom->radius_flag = atom->rmass_flag = atom->omega_flag =
atom->torque_flag = 1;
PI = 4.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
void AtomVecSphere::init()
{
AtomVec::init();
// set radvary if particle diameters are time-varying due to fix adapt
radvary = 0;
comm_x_only = 1;
size_forward = 3;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"adapt") == 0) {
FixAdapt *fix = (FixAdapt *) modify->fix[i];
if (fix->diamflag) {
radvary = 1;
comm_x_only = 0;
size_forward = 5;
}
}
}
/* ----------------------------------------------------------------------
grow atom arrays
n = 0 grows arrays by DELTA
n > 0 allocates arrays to size n
------------------------------------------------------------------------- */
void AtomVecSphere::grow(int n)
{
if (n == 0) nmax += DELTA;
else nmax = n;
atom->nmax = nmax;
if (nmax < 0 || nmax > MAXSMALLINT)
- error->one("Per-processor system is too big");
+ error->one(FLERR,"Per-processor system is too big");
tag = memory->grow(atom->tag,nmax,"atom:tag");
type = memory->grow(atom->type,nmax,"atom:type");
mask = memory->grow(atom->mask,nmax,"atom:mask");
image = memory->grow(atom->image,nmax,"atom:image");
x = memory->grow(atom->x,nmax,3,"atom:x");
v = memory->grow(atom->v,nmax,3,"atom:v");
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
radius = memory->grow(atom->radius,nmax,"atom:radius");
rmass = memory->grow(atom->rmass,nmax,"atom:rmass");
omega = memory->grow(atom->omega,nmax,3,"atom:omega");
torque = memory->grow(atom->torque,nmax,3,"atom:torque");
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
}
/* ----------------------------------------------------------------------
reset local array ptrs
------------------------------------------------------------------------- */
void AtomVecSphere::grow_reset()
{
tag = atom->tag; type = atom->type;
mask = atom->mask; image = atom->image;
x = atom->x; v = atom->v; f = atom->f;
radius = atom->radius; rmass = atom->rmass;
omega = atom->omega; torque = atom->torque;
}
/* ----------------------------------------------------------------------
copy atom I info to atom J
------------------------------------------------------------------------- */
void AtomVecSphere::copy(int i, int j, int delflag)
{
tag[j] = tag[i];
type[j] = type[i];
mask[j] = mask[i];
image[j] = image[i];
x[j][0] = x[i][0];
x[j][1] = x[i][1];
x[j][2] = x[i][2];
v[j][0] = v[i][0];
v[j][1] = v[i][1];
v[j][2] = v[i][2];
radius[j] = radius[i];
rmass[j] = rmass[i];
omega[j][0] = omega[i][0];
omega[j][1] = omega[i][1];
omega[j][2] = omega[i][2];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j);
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
if (radvary == 0) {
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
}
}
} else {
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = radius[j];
buf[m++] = rmass[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = radius[j];
buf[m++] = rmass[j];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_comm_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
if (radvary == 0) {
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
}
}
} else {
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = radius[j];
buf[m++] = rmass[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = radius[j];
buf[m++] = rmass[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = radius[j];
buf[m++] = rmass[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_comm_hybrid(int n, int *list, double *buf)
{
int i,j,m;
if (radvary == 0) return 0;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = radius[j];
buf[m++] = rmass[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecSphere::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
if (radvary == 0) {
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
}
} else {
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
radius[i] = buf[m++];
rmass[i] = buf[m++];
}
}
}
/* ---------------------------------------------------------------------- */
void AtomVecSphere::unpack_comm_vel(int n, int first, double *buf)
{
int i,m,last;
if (radvary == 0) {
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
omega[i][0] = buf[m++];
omega[i][1] = buf[m++];
omega[i][2] = buf[m++];
}
} else {
m = 0;
last = first + n;
for (i = first; i < last; i++) {
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
radius[i] = buf[m++];
rmass[i] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
omega[i][0] = buf[m++];
omega[i][1] = buf[m++];
omega[i][2] = buf[m++];
}
}
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::unpack_comm_hybrid(int n, int first, double *buf)
{
int i,m,last;
if (radvary == 0) return 0;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
radius[i] = buf[m++];
rmass[i] = buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_reverse(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = f[i][0];
buf[m++] = f[i][1];
buf[m++] = f[i][2];
buf[m++] = torque[i][0];
buf[m++] = torque[i][1];
buf[m++] = torque[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_reverse_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = torque[i][0];
buf[m++] = torque[i][1];
buf[m++] = torque[i][2];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecSphere::unpack_reverse(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
f[j][0] += buf[m++];
f[j][1] += buf[m++];
f[j][2] += buf[m++];
torque[j][0] += buf[m++];
torque[j][1] += buf[m++];
torque[j][2] += buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::unpack_reverse_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
torque[j][0] += buf[m++];
torque[j][1] += buf[m++];
torque[j][2] += buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_border(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = radius[j];
buf[m++] = rmass[j];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = radius[j];
buf[m++] = rmass[j];
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_border_vel(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz,dvx,dvy,dvz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0];
buf[m++] = x[j][1];
buf[m++] = x[j][2];
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = radius[j];
buf[m++] = rmass[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0];
dy = pbc[1];
dz = pbc[2];
}
if (!deform_vremap) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = radius[j];
buf[m++] = rmass[j];
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
} else {
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
dvz = pbc[2]*h_rate[2];
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = x[j][0] + dx;
buf[m++] = x[j][1] + dy;
buf[m++] = x[j][2] + dz;
buf[m++] = tag[j];
buf[m++] = type[j];
buf[m++] = mask[j];
buf[m++] = radius[j];
buf[m++] = rmass[j];
if (mask[i] & deform_groupbit) {
buf[m++] = v[j][0] + dvx;
buf[m++] = v[j][1] + dvy;
buf[m++] = v[j][2] + dvz;
} else {
buf[m++] = v[j][0];
buf[m++] = v[j][1];
buf[m++] = v[j][2];
}
buf[m++] = omega[j][0];
buf[m++] = omega[j][1];
buf[m++] = omega[j][2];
}
}
}
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::pack_border_hybrid(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = radius[j];
buf[m++] = rmass[j];
}
return m;
}
/* ---------------------------------------------------------------------- */
void AtomVecSphere::unpack_border(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
radius[i] = buf[m++];
rmass[i] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void AtomVecSphere::unpack_border_vel(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
if (i == nmax) grow(0);
x[i][0] = buf[m++];
x[i][1] = buf[m++];
x[i][2] = buf[m++];
tag[i] = static_cast<int> (buf[m++]);
type[i] = static_cast<int> (buf[m++]);
mask[i] = static_cast<int> (buf[m++]);
radius[i] = buf[m++];
rmass[i] = buf[m++];
v[i][0] = buf[m++];
v[i][1] = buf[m++];
v[i][2] = buf[m++];
omega[i][0] = buf[m++];
omega[i][1] = buf[m++];
omega[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::unpack_border_hybrid(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
radius[i] = buf[m++];
rmass[i] = buf[m++];
}
return m;
}
/* ----------------------------------------------------------------------
pack data for atom I for sending to another proc
xyz must be 1st 3 values, so comm::exchange() can test on them
------------------------------------------------------------------------- */
int AtomVecSphere::pack_exchange(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = radius[i];
buf[m++] = rmass[i];
buf[m++] = omega[i][0];
buf[m++] = omega[i][1];
buf[m++] = omega[i][2];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
buf[0] = m;
return m;
}
/* ---------------------------------------------------------------------- */
int AtomVecSphere::unpack_exchange(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
radius[nlocal] = buf[m++];
rmass[nlocal] = buf[m++];
omega[nlocal][0] = buf[m++];
omega[nlocal][1] = buf[m++];
omega[nlocal][2] = buf[m++];
if (atom->nextra_grow)
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
m += modify->fix[atom->extra_grow[iextra]]->
unpack_exchange(nlocal,&buf[m]);
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
size of restart data for all atoms owned by this proc
include extra data stored by fixes
------------------------------------------------------------------------- */
int AtomVecSphere::size_restart()
{
int i;
int nlocal = atom->nlocal;
int n = 16 * nlocal;
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
for (i = 0; i < nlocal; i++)
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
return n;
}
/* ----------------------------------------------------------------------
pack atom I's data for restart file including extra quantities
xyz must be 1st 3 values, so that read_restart can test on them
molecular types may be negative, but write as positive
------------------------------------------------------------------------- */
int AtomVecSphere::pack_restart(int i, double *buf)
{
int m = 1;
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = mask[i];
buf[m++] = image[i];
buf[m++] = v[i][0];
buf[m++] = v[i][1];
buf[m++] = v[i][2];
buf[m++] = radius[i];
buf[m++] = rmass[i];
buf[m++] = omega[i][0];
buf[m++] = omega[i][1];
buf[m++] = omega[i][2];
if (atom->nextra_restart)
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
buf[0] = m;
return m;
}
/* ----------------------------------------------------------------------
unpack data for one atom from restart file including extra quantities
------------------------------------------------------------------------- */
int AtomVecSphere::unpack_restart(double *buf)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) {
grow(0);
if (atom->nextra_store)
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
}
int m = 1;
x[nlocal][0] = buf[m++];
x[nlocal][1] = buf[m++];
x[nlocal][2] = buf[m++];
tag[nlocal] = static_cast<int> (buf[m++]);
type[nlocal] = static_cast<int> (buf[m++]);
mask[nlocal] = static_cast<int> (buf[m++]);
image[nlocal] = static_cast<int> (buf[m++]);
v[nlocal][0] = buf[m++];
v[nlocal][1] = buf[m++];
v[nlocal][2] = buf[m++];
radius[nlocal] = buf[m++];
rmass[nlocal] = buf[m++];
omega[nlocal][0] = buf[m++];
omega[nlocal][1] = buf[m++];
omega[nlocal][2] = buf[m++];
double **extra = atom->extra;
if (atom->nextra_store) {
int size = static_cast<int> (buf[0]) - m;
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
}
atom->nlocal++;
return m;
}
/* ----------------------------------------------------------------------
create one atom of itype at coord
set other values to defaults
------------------------------------------------------------------------- */
void AtomVecSphere::create_atom(int itype, double *coord)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = 0;
type[nlocal] = itype;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
mask[nlocal] = 1;
image[nlocal] = (512 << 20) | (512 << 10) | 512;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
radius[nlocal] = 0.5;
rmass[nlocal] = 4.0*PI/3.0 * radius[nlocal]*radius[nlocal]*radius[nlocal];
omega[nlocal][0] = 0.0;
omega[nlocal][1] = 0.0;
omega[nlocal][2] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack one line from Atoms section of data file
initialize other atom quantities
------------------------------------------------------------------------- */
void AtomVecSphere::data_atom(double *coord, int imagetmp, char **values)
{
int nlocal = atom->nlocal;
if (nlocal == nmax) grow(0);
tag[nlocal] = atoi(values[0]);
if (tag[nlocal] <= 0)
- error->one("Invalid atom ID in Atoms section of data file");
+ error->one(FLERR,"Invalid atom ID in Atoms section of data file");
type[nlocal] = atoi(values[1]);
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
- error->one("Invalid atom type in Atoms section of data file");
+ error->one(FLERR,"Invalid atom type in Atoms section of data file");
radius[nlocal] = 0.5 * atof(values[2]);
if (radius[nlocal] < 0.0)
- error->one("Invalid radius in Atoms section of data file");
+ error->one(FLERR,"Invalid radius in Atoms section of data file");
double density = atof(values[3]);
if (density <= 0.0)
- error->one("Invalid density in Atoms section of data file");
+ error->one(FLERR,"Invalid density in Atoms section of data file");
if (radius[nlocal] == 0.0) rmass[nlocal] = density;
else
rmass[nlocal] = 4.0*PI/3.0 *
radius[nlocal]*radius[nlocal]*radius[nlocal] * density;
x[nlocal][0] = coord[0];
x[nlocal][1] = coord[1];
x[nlocal][2] = coord[2];
image[nlocal] = imagetmp;
mask[nlocal] = 1;
v[nlocal][0] = 0.0;
v[nlocal][1] = 0.0;
v[nlocal][2] = 0.0;
omega[nlocal][0] = 0.0;
omega[nlocal][1] = 0.0;
omega[nlocal][2] = 0.0;
atom->nlocal++;
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Atoms section of data file
initialize other atom quantities for this sub-style
------------------------------------------------------------------------- */
int AtomVecSphere::data_atom_hybrid(int nlocal, char **values)
{
radius[nlocal] = 0.5 * atof(values[0]);
if (radius[nlocal] < 0.0)
- error->one("Invalid radius in Atoms section of data file");
+ error->one(FLERR,"Invalid radius in Atoms section of data file");
double density = atof(values[1]);
if (density <= 0.0)
- error->one("Invalid density in Atoms section of data file");
+ error->one(FLERR,"Invalid density in Atoms section of data file");
if (radius[nlocal] == 0.0) rmass[nlocal] = density;
else
rmass[nlocal] = 4.0*PI/3.0 *
radius[nlocal]*radius[nlocal]*radius[nlocal] * density;
return 2;
}
/* ----------------------------------------------------------------------
unpack one line from Velocities section of data file
------------------------------------------------------------------------- */
void AtomVecSphere::data_vel(int m, char **values)
{
v[m][0] = atof(values[0]);
v[m][1] = atof(values[1]);
v[m][2] = atof(values[2]);
omega[m][0] = atof(values[3]);
omega[m][1] = atof(values[4]);
omega[m][2] = atof(values[5]);
}
/* ----------------------------------------------------------------------
unpack hybrid quantities from one line in Velocities section of data file
------------------------------------------------------------------------- */
int AtomVecSphere::data_vel_hybrid(int m, char **values)
{
omega[m][0] = atof(values[0]);
omega[m][1] = atof(values[1]);
omega[m][2] = atof(values[2]);
return 3;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint AtomVecSphere::memory_usage()
{
bigint bytes = 0;
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
if (atom->memcheck("radius")) bytes += memory->usage(radius,nmax);
if (atom->memcheck("rmass")) bytes += memory->usage(rmass,nmax);
if (atom->memcheck("omega")) bytes += memory->usage(omega,nmax,3);
if (atom->memcheck("torque")) bytes += memory->usage(torque,nmax,3);
return bytes;
}
diff --git a/src/bond.cpp b/src/bond.cpp
index b4365acf3..92310df65 100644
--- a/src/bond.cpp
+++ b/src/bond.cpp
@@ -1,204 +1,204 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "bond.h"
#include "atom.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* -----------------------------------------------------------------------
set bond contribution to Vdwl energy to 0.0
a particular bond style can override this
------------------------------------------------------------------------- */
Bond::Bond(LAMMPS *lmp) : Pointers(lmp)
{
energy = 0.0;
allocated = 0;
maxeatom = maxvatom = 0;
eatom = NULL;
vatom = NULL;
}
/* ---------------------------------------------------------------------- */
Bond::~Bond()
{
memory->destroy(eatom);
memory->destroy(vatom);
}
/* ----------------------------------------------------------------------
check if all coeffs are set
------------------------------------------------------------------------- */
void Bond::init()
{
- if (!allocated) error->all("Bond coeffs are not set");
+ if (!allocated) error->all(FLERR,"Bond coeffs are not set");
for (int i = 1; i <= atom->nbondtypes; i++)
- if (setflag[i] == 0) error->all("All bond coeffs are not set");
+ if (setflag[i] == 0) error->all(FLERR,"All bond coeffs are not set");
init_style();
}
/* ----------------------------------------------------------------------
setup for energy, virial computation
see integrate::ev_set() for values of eflag (0-3) and vflag (0-6)
------------------------------------------------------------------------- */
void Bond::ev_setup(int eflag, int vflag)
{
int i,n;
evflag = 1;
eflag_either = eflag;
eflag_global = eflag % 2;
eflag_atom = eflag / 2;
vflag_either = vflag;
vflag_global = vflag % 4;
vflag_atom = vflag / 4;
// reallocate per-atom arrays if necessary
if (eflag_atom && atom->nmax > maxeatom) {
maxeatom = atom->nmax;
memory->destroy(eatom);
memory->create(eatom,maxeatom,"bond:eatom");
}
if (vflag_atom && atom->nmax > maxvatom) {
maxvatom = atom->nmax;
memory->destroy(vatom);
memory->create(vatom,maxvatom,6,"bond:vatom");
}
// zero accumulators
if (eflag_global) energy = 0.0;
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) eatom[i] = 0.0;
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) {
vatom[i][0] = 0.0;
vatom[i][1] = 0.0;
vatom[i][2] = 0.0;
vatom[i][3] = 0.0;
vatom[i][4] = 0.0;
vatom[i][5] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
tally energy and virial into global and per-atom accumulators
------------------------------------------------------------------------- */
void Bond::ev_tally(int i, int j, int nlocal, int newton_bond,
double ebond, double fbond,
double delx, double dely, double delz)
{
double ebondhalf,v[6];
if (eflag_either) {
if (eflag_global) {
if (newton_bond) energy += ebond;
else {
ebondhalf = 0.5*ebond;
if (i < nlocal) energy += ebondhalf;
if (j < nlocal) energy += ebondhalf;
}
}
if (eflag_atom) {
ebondhalf = 0.5*ebond;
if (newton_bond || i < nlocal) eatom[i] += ebondhalf;
if (newton_bond || j < nlocal) eatom[j] += ebondhalf;
}
}
if (vflag_either) {
v[0] = delx*delx*fbond;
v[1] = dely*dely*fbond;
v[2] = delz*delz*fbond;
v[3] = delx*dely*fbond;
v[4] = delx*delz*fbond;
v[5] = dely*delz*fbond;
if (vflag_global) {
if (newton_bond) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
if (j < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
}
}
if (vflag_atom) {
if (newton_bond || i < nlocal) {
vatom[i][0] += 0.5*v[0];
vatom[i][1] += 0.5*v[1];
vatom[i][2] += 0.5*v[2];
vatom[i][3] += 0.5*v[3];
vatom[i][4] += 0.5*v[4];
vatom[i][5] += 0.5*v[5];
}
if (newton_bond || j < nlocal) {
vatom[j][0] += 0.5*v[0];
vatom[j][1] += 0.5*v[1];
vatom[j][2] += 0.5*v[2];
vatom[j][3] += 0.5*v[3];
vatom[j][4] += 0.5*v[4];
vatom[j][5] += 0.5*v[5];
}
}
}
}
/* ---------------------------------------------------------------------- */
double Bond::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
return bytes;
}
diff --git a/src/bond_hybrid.cpp b/src/bond_hybrid.cpp
index c06aa5647..435685d5e 100644
--- a/src/bond_hybrid.cpp
+++ b/src/bond_hybrid.cpp
@@ -1,353 +1,353 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "ctype.h"
#include "bond_hybrid.h"
#include "atom.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define EXTRA 1000
/* ---------------------------------------------------------------------- */
BondHybrid::BondHybrid(LAMMPS *lmp) : Bond(lmp)
{
nstyles = 0;
}
/* ---------------------------------------------------------------------- */
BondHybrid::~BondHybrid()
{
if (nstyles) {
for (int i = 0; i < nstyles; i++) delete styles[i];
delete [] styles;
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(map);
delete [] nbondlist;
delete [] maxbond;
for (int i = 0; i < nstyles; i++)
memory->destroy(bondlist[i]);
delete [] bondlist;
}
}
/* ---------------------------------------------------------------------- */
void BondHybrid::compute(int eflag, int vflag)
{
int i,j,m,n;
// save ptrs to original bondlist
int nbondlist_orig = neighbor->nbondlist;
int **bondlist_orig = neighbor->bondlist;
// if this is re-neighbor step, create sub-style bondlists
// nbondlist[] = length of each sub-style list
// realloc sub-style bondlist if necessary
// load sub-style bondlist with 3 values from original bondlist
if (neighbor->ago == 0) {
for (m = 0; m < nstyles; m++) nbondlist[m] = 0;
for (i = 0; i < nbondlist_orig; i++) {
m = map[bondlist_orig[i][2]];
if (m >= 0) nbondlist[m]++;
}
for (m = 0; m < nstyles; m++) {
if (nbondlist[m] > maxbond[m]) {
memory->destroy(bondlist[m]);
maxbond[m] = nbondlist[m] + EXTRA;
memory->create(bondlist[m],maxbond[m],3,"bond_hybrid:bondlist");
}
nbondlist[m] = 0;
}
for (i = 0; i < nbondlist_orig; i++) {
m = map[bondlist_orig[i][2]];
if (m < 0) continue;
n = nbondlist[m];
bondlist[m][n][0] = bondlist_orig[i][0];
bondlist[m][n][1] = bondlist_orig[i][1];
bondlist[m][n][2] = bondlist_orig[i][2];
nbondlist[m]++;
}
}
// call each sub-style's compute function
// set neighbor->bondlist to sub-style bondlist before call
// accumulate sub-style global/peratom energy/virial in hybrid
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
for (m = 0; m < nstyles; m++) {
neighbor->nbondlist = nbondlist[m];
neighbor->bondlist = bondlist[m];
styles[m]->compute(eflag,vflag);
if (eflag_global) energy += styles[m]->energy;
if (vflag_global)
for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double *eatom_substyle = styles[m]->eatom;
for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i];
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
double **vatom_substyle = styles[m]->vatom;
for (i = 0; i < n; i++)
for (j = 0; j < 6; j++)
vatom[i][j] += vatom_substyle[i][j];
}
}
// restore ptrs to original bondlist
neighbor->nbondlist = nbondlist_orig;
neighbor->bondlist = bondlist_orig;
}
/* ---------------------------------------------------------------------- */
void BondHybrid::allocate()
{
allocated = 1;
int n = atom->nbondtypes;
memory->create(map,n+1,"bond:map");
memory->create(setflag,n+1,"bond:setflag");
for (int i = 1; i <= n; i++) setflag[i] = 0;
nbondlist = new int[nstyles];
maxbond = new int[nstyles];
bondlist = new int**[nstyles];
for (int m = 0; m < nstyles; m++) maxbond[m] = 0;
for (int m = 0; m < nstyles; m++) bondlist[m] = NULL;
}
/* ----------------------------------------------------------------------
create one bond style for each arg in list
------------------------------------------------------------------------- */
void BondHybrid::settings(int narg, char **arg)
{
int i,m,istyle;
- if (narg < 1) error->all("Illegal bond_style command");
+ if (narg < 1) error->all(FLERR,"Illegal bond_style command");
// delete old lists, since cannot just change settings
if (nstyles) {
for (int i = 0; i < nstyles; i++) delete styles[i];
delete [] styles;
for (int i = 0; i < nstyles; i++) delete [] keywords[i];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(map);
delete [] nbondlist;
delete [] maxbond;
for (int i = 0; i < nstyles; i++)
memory->destroy(bondlist[i]);
delete [] bondlist;
}
allocated = 0;
// count sub-styles by skipping numeric args
// one exception is 1st arg of style "table", which is non-numeric word
// need a better way to skip these exceptions
nstyles = 0;
i = 0;
while (i < narg) {
if (strcmp(arg[i],"table") == 0) i++;
i++;
while (i < narg && !isalpha(arg[i][0])) i++;
nstyles++;
}
// allocate list of sub-styles
styles = new Bond*[nstyles];
keywords = new char*[nstyles];
// allocate each sub-style and call its settings() with subset of args
// define subset of args for a sub-style by skipping numeric args
// one exception is 1st arg of style "table", which is non-numeric
// need a better way to skip these exceptions
nstyles = 0;
i = 0;
while (i < narg) {
for (m = 0; m < nstyles; m++)
if (strcmp(arg[i],keywords[m]) == 0)
- error->all("Bond style hybrid cannot use same pair style twice");
+ error->all(FLERR,"Bond style hybrid cannot use same pair style twice");
if (strcmp(arg[i],"hybrid") == 0)
- error->all("Bond style hybrid cannot have hybrid as an argument");
+ error->all(FLERR,"Bond style hybrid cannot have hybrid as an argument");
if (strcmp(arg[i],"none") == 0)
- error->all("Bond style hybrid cannot have none as an argument");
+ error->all(FLERR,"Bond style hybrid cannot have none as an argument");
styles[nstyles] = force->new_bond(arg[i]);
keywords[nstyles] = new char[strlen(arg[i])+1];
strcpy(keywords[nstyles],arg[i]);
istyle = i;
if (strcmp(arg[i],"table") == 0) i++;
i++;
while (i < narg && !isalpha(arg[i][0])) i++;
styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]);
nstyles++;
}
}
/* ----------------------------------------------------------------------
set coeffs for one type
---------------------------------------------------------------------- */
void BondHybrid::coeff(int narg, char **arg)
{
if (!allocated) allocate();
int ilo,ihi;
force->bounds(arg[0],atom->nbondtypes,ilo,ihi);
// 2nd arg = bond sub-style name
// allow for "none" as valid sub-style name
int m;
for (m = 0; m < nstyles; m++)
if (strcmp(arg[1],keywords[m]) == 0) break;
int none = 0;
if (m == nstyles) {
if (strcmp(arg[1],"none") == 0) none = 1;
- else error->all("Bond coeff for hybrid has invalid style");
+ else error->all(FLERR,"Bond coeff for hybrid has invalid style");
}
// move 1st arg to 2nd arg
// just copy ptrs, since arg[] points into original input line
arg[1] = arg[0];
// invoke sub-style coeff() starting with 1st arg
if (!none) styles[m]->coeff(narg-1,&arg[1]);
// set setflag and which type maps to which sub-style
// if sub-style is none: set hybrid setflag, wipe out map
for (int i = ilo; i <= ihi; i++) {
setflag[i] = 1;
if (none) map[i] = -1;
else map[i] = m;
}
}
/* ---------------------------------------------------------------------- */
void BondHybrid::init_style()
{
for (int m = 0; m < nstyles; m++)
if (styles[m]) styles[m]->init_style();
}
/* ----------------------------------------------------------------------
return an equilbrium bond length
------------------------------------------------------------------------- */
double BondHybrid::equilibrium_distance(int i)
{
- if (map[i] < 0) error->one("Invoked bond equil distance on bond style none");
+ if (map[i] < 0) error->one(FLERR,"Invoked bond equil distance on bond style none");
return styles[map[i]]->equilibrium_distance(i);
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void BondHybrid::write_restart(FILE *fp)
{
fwrite(&nstyles,sizeof(int),1,fp);
int n;
for (int m = 0; m < nstyles; m++) {
n = strlen(keywords[m]) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(keywords[m],sizeof(char),n,fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void BondHybrid::read_restart(FILE *fp)
{
int me = comm->me;
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
styles = new Bond*[nstyles];
keywords = new char*[nstyles];
allocate();
int n;
for (int m = 0; m < nstyles; m++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
keywords[m] = new char[n];
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
styles[m] = force->new_bond(keywords[m]);
}
}
/* ---------------------------------------------------------------------- */
double BondHybrid::single(int type, double rsq, int i, int j)
{
- if (map[type] < 0) error->one("Invoked bond single on bond style none");
+ if (map[type] < 0) error->one(FLERR,"Invoked bond single on bond style none");
return styles[map[type]]->single(type,rsq,i,j);
}
/* ----------------------------------------------------------------------
memory usage
------------------------------------------------------------------------- */
double BondHybrid::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
for (int m = 0; m < nstyles; m++) bytes += maxbond[m]*3 * sizeof(int);
for (int m = 0; m < nstyles; m++)
if (styles[m]) bytes += styles[m]->memory_usage();
return bytes;
}
diff --git a/src/change_box.cpp b/src/change_box.cpp
index 2bb5ad45f..34f2f67b0 100644
--- a/src/change_box.cpp
+++ b/src/change_box.cpp
@@ -1,64 +1,64 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "change_box.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "output.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{ORTHO,TRICLINIC};
/* ---------------------------------------------------------------------- */
ChangeBox::ChangeBox(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void ChangeBox::command(int narg, char **arg)
{
if (domain->box_exist == 0)
- error->all("Change_box command before simulation box is defined");
- if (narg != 1) error->all("Illegal change_box command");
+ error->all(FLERR,"Change_box command before simulation box is defined");
+ if (narg != 1) error->all(FLERR,"Illegal change_box command");
int style;
if (strcmp(arg[0],"ortho") == 0) style = ORTHO;
else if (strcmp(arg[0],"triclinic") == 0) style = TRICLINIC;
- else error->all("Illegal change_box command");
+ else error->all(FLERR,"Illegal change_box command");
if (style == ORTHO && domain->triclinic == 0)
- error->all("Change_box operation is invalid");
+ error->all(FLERR,"Change_box operation is invalid");
if (style == TRICLINIC && domain->triclinic == 1)
- error->all("Change_box operation is invalid");
+ error->all(FLERR,"Change_box operation is invalid");
if (style == ORTHO &&
(domain->xy != 0.0 || domain->yz != 0.0 || domain->xz != 0.0))
- error->all("Cannot change box to orthogonal when tilt is non-zero");
+ error->all(FLERR,"Cannot change box to orthogonal when tilt is non-zero");
if (output->ndump)
- error->all("Cannot change box with dumps defined");
+ error->all(FLERR,"Cannot change box with dumps defined");
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->no_change_box)
- error->all("Cannot change box with certain fixes defined");
+ error->all(FLERR,"Cannot change box with certain fixes defined");
if (style == ORTHO) domain->triclinic = 0;
else domain->triclinic = 1;
domain->xy = domain->yz = domain->xz = 0.0;
domain->set_global_box();
if (style == TRICLINIC) domain->set_lamda_box();
domain->set_local_box();
}
diff --git a/src/comm.cpp b/src/comm.cpp
index b5008dc3a..e28baab37 100644
--- a/src/comm.cpp
+++ b/src/comm.cpp
@@ -1,1389 +1,1386 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author (triclinic) : Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "comm.h"
#include "atom.h"
#include "atom_vec.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "neighbor.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "compute.h"
#include "output.h"
#include "dump.h"
#include "error.h"
#include "memory.h"
#ifdef _OPENMP
#include "omp.h"
#endif
using namespace LAMMPS_NS;
#define BUFFACTOR 1.5
#define BUFMIN 1000
#define BUFEXTRA 1000
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define BIG 1.0e20
enum{SINGLE,MULTI};
/* ----------------------------------------------------------------------
setup MPI and allocate buffer space
------------------------------------------------------------------------- */
Comm::Comm(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
user_procgrid[0] = user_procgrid[1] = user_procgrid[2] = 0;
grid2proc = NULL;
bordergroup = 0;
style = SINGLE;
multilo = multihi = NULL;
cutghostmulti = NULL;
cutghostuser = 0.0;
ghost_velocity = 0;
// use of OpenMP threads
// query OpenMP for number of threads/process set by user at run-time
// need to be in a parallel area for this operation
nthreads = 1;
#ifdef _OPENMP
#pragma omp parallel default(shared)
{
#pragma omp master
{ nthreads = omp_get_num_threads(); }
}
if (me == 0) {
if (screen)
fprintf(screen," using %d OpenMP thread(s) per MPI task\n",nthreads);
if (logfile)
fprintf(logfile," using %d OpenMP thread(s) per MPI task\n",nthreads);
}
#endif
// initialize comm buffers & exchange memory
maxsend = BUFMIN;
memory->create(buf_send,maxsend+BUFEXTRA,"comm:buf_send");
maxrecv = BUFMIN;
memory->create(buf_recv,maxrecv,"comm:buf_recv");
maxswap = 6;
allocate_swap(maxswap);
sendlist = (int **) memory->smalloc(maxswap*sizeof(int *),"comm:sendlist");
memory->create(maxsendlist,maxswap,"comm:maxsendlist");
for (int i = 0; i < maxswap; i++) {
maxsendlist[i] = BUFMIN;
memory->create(sendlist[i],BUFMIN,"comm:sendlist[i]");
}
}
/* ---------------------------------------------------------------------- */
Comm::~Comm()
{
if (grid2proc) memory->destroy(grid2proc);
free_swap();
if (style == MULTI) {
free_multi();
memory->destroy(cutghostmulti);
}
if (sendlist) for (int i = 0; i < maxswap; i++) memory->destroy(sendlist[i]);
memory->sfree(sendlist);
memory->destroy(maxsendlist);
memory->destroy(buf_send);
memory->destroy(buf_recv);
}
/* ----------------------------------------------------------------------
setup 3d grid of procs based on box size
------------------------------------------------------------------------- */
void Comm::set_procs()
{
procs2box();
if (procgrid[0]*procgrid[1]*procgrid[2] != nprocs)
- error->all("Bad grid of processors");
+ error->all(FLERR,"Bad grid of processors");
if (domain->dimension == 2 && procgrid[2] != 1)
- error->all("Processor count in z must be 1 for 2d simulation");
+ error->all(FLERR,"Processor count in z must be 1 for 2d simulation");
if (grid2proc) memory->destroy(grid2proc);
memory->create(grid2proc,procgrid[0],procgrid[1],procgrid[2],
"comm:grid2proc");
// use MPI Cartesian routines to setup 3d grid of procs
// grid2proc[i][j][k] = proc that owns i,j,k location in grid
// let MPI compute it instead of LAMMPS in case it is machine optimized
int reorder = 0;
int periods[3];
periods[0] = periods[1] = periods[2] = 1;
MPI_Comm cartesian;
MPI_Cart_create(world,3,procgrid,periods,reorder,&cartesian);
MPI_Cart_get(cartesian,3,procgrid,periods,myloc);
MPI_Cart_shift(cartesian,0,1,&procneigh[0][0],&procneigh[0][1]);
MPI_Cart_shift(cartesian,1,1,&procneigh[1][0],&procneigh[1][1]);
MPI_Cart_shift(cartesian,2,1,&procneigh[2][0],&procneigh[2][1]);
int coords[3];
int i,j,k;
for (i = 0; i < procgrid[0]; i++)
for (j = 0; j < procgrid[1]; j++)
for (k = 0; k < procgrid[2]; k++) {
coords[0] = i; coords[1] = j; coords[2] = k;
MPI_Cart_rank(cartesian,coords,&grid2proc[i][j][k]);
}
MPI_Comm_free(&cartesian);
// set lamda box params after procs are assigned
if (domain->triclinic) domain->set_lamda_box();
if (me == 0) {
if (screen) fprintf(screen," %d by %d by %d processor grid\n",
procgrid[0],procgrid[1],procgrid[2]);
if (logfile) fprintf(logfile," %d by %d by %d processor grid\n",
procgrid[0],procgrid[1],procgrid[2]);
}
}
/* ---------------------------------------------------------------------- */
void Comm::init()
{
triclinic = domain->triclinic;
map_style = atom->map_style;
// comm_only = 1 if only x,f are exchanged in forward/reverse comm
// comm_x_only = 0 if ghost_velocity since velocities are added
comm_x_only = atom->avec->comm_x_only;
comm_f_only = atom->avec->comm_f_only;
if (ghost_velocity) comm_x_only = 0;
// set per-atom sizes for forward/reverse/border comm
// augment by velocity quantities if needed
size_forward = atom->avec->size_forward;
size_reverse = atom->avec->size_reverse;
size_border = atom->avec->size_border;
if (ghost_velocity) size_forward += atom->avec->size_velocity;
if (ghost_velocity) size_border += atom->avec->size_velocity;
// maxforward = # of datums in largest forward communication
// maxreverse = # of datums in largest reverse communication
// query pair,fix,compute,dump for their requirements
maxforward = MAX(size_forward,size_border);
maxreverse = size_reverse;
if (force->pair) maxforward = MAX(maxforward,force->pair->comm_forward);
if (force->pair) maxreverse = MAX(maxreverse,force->pair->comm_reverse);
for (int i = 0; i < modify->nfix; i++) {
maxforward = MAX(maxforward,modify->fix[i]->comm_forward);
maxreverse = MAX(maxreverse,modify->fix[i]->comm_reverse);
}
for (int i = 0; i < modify->ncompute; i++) {
maxforward = MAX(maxforward,modify->compute[i]->comm_forward);
maxreverse = MAX(maxreverse,modify->compute[i]->comm_reverse);
}
for (int i = 0; i < output->ndump; i++) {
maxforward = MAX(maxforward,output->dump[i]->comm_forward);
maxreverse = MAX(maxreverse,output->dump[i]->comm_reverse);
}
if (force->newton == 0) maxreverse = 0;
// memory for multi-style communication
if (style == MULTI && multilo == NULL) {
allocate_multi(maxswap);
memory->create(cutghostmulti,atom->ntypes+1,3,"comm:cutghostmulti");
}
if (style == SINGLE && multilo) {
free_multi();
memory->destroy(cutghostmulti);
}
}
/* ----------------------------------------------------------------------
setup spatial-decomposition communication patterns
function of neighbor cutoff(s) & cutghostuser & current box size
single style sets slab boundaries (slablo,slabhi) based on max cutoff
multi style sets type-dependent slab boundaries (multilo,multihi)
------------------------------------------------------------------------- */
void Comm::setup()
{
// cutghost[] = max distance at which ghost atoms need to be acquired
// for orthogonal:
// cutghost is in box coords = neigh->cutghost in all 3 dims
// for triclinic:
// neigh->cutghost = distance between tilted planes in box coords
// cutghost is in lamda coords = distance between those planes
// for multi:
// cutghostmulti = same as cutghost, only for each atom type
int i;
int ntypes = atom->ntypes;
double *prd,*sublo,*subhi;
double cut = MAX(neighbor->cutneighmax,cutghostuser);
if (triclinic == 0) {
prd = domain->prd;
sublo = domain->sublo;
subhi = domain->subhi;
cutghost[0] = cutghost[1] = cutghost[2] = cut;
if (style == MULTI) {
double *cuttype = neighbor->cuttype;
for (i = 1; i <= ntypes; i++)
cutghostmulti[i][0] = cutghostmulti[i][1] = cutghostmulti[i][2] =
cuttype[i];
}
} else {
prd = domain->prd_lamda;
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
double *h_inv = domain->h_inv;
double length0,length1,length2;
length0 = sqrt(h_inv[0]*h_inv[0] + h_inv[5]*h_inv[5] + h_inv[4]*h_inv[4]);
cutghost[0] = cut * length0;
length1 = sqrt(h_inv[1]*h_inv[1] + h_inv[3]*h_inv[3]);
cutghost[1] = cut * length1;
length2 = h_inv[2];
cutghost[2] = cut * length2;
if (style == MULTI) {
double *cuttype = neighbor->cuttype;
for (i = 1; i <= ntypes; i++) {
cutghostmulti[i][0] = cuttype[i] * length0;
cutghostmulti[i][1] = cuttype[i] * length1;
cutghostmulti[i][2] = cuttype[i] * length2;
}
}
}
// need = # of procs I need atoms from in each dim based on max cutoff
// for 2d, don't communicate in z
need[0] = static_cast<int> (cutghost[0] * procgrid[0] / prd[0]) + 1;
need[1] = static_cast<int> (cutghost[1] * procgrid[1] / prd[1]) + 1;
need[2] = static_cast<int> (cutghost[2] * procgrid[2] / prd[2]) + 1;
if (domain->dimension == 2) need[2] = 0;
// if non-periodic, do not communicate further than procgrid-1 away
// this enables very large cutoffs in non-periodic systems
int *periodicity = domain->periodicity;
if (periodicity[0] == 0) need[0] = MIN(need[0],procgrid[0]-1);
if (periodicity[1] == 0) need[1] = MIN(need[1],procgrid[1]-1);
if (periodicity[2] == 0) need[2] = MIN(need[2],procgrid[2]-1);
// allocate comm memory
nswap = 2 * (need[0]+need[1]+need[2]);
if (nswap > maxswap) grow_swap(nswap);
// setup parameters for each exchange:
// sendproc = proc to send to at each swap
// recvproc = proc to recv from at each swap
// for style SINGLE:
// slablo/slabhi = boundaries for slab of atoms to send at each swap
// use -BIG/midpt/BIG to insure all atoms included even if round-off occurs
// if round-off, atoms recvd across PBC can be < or > than subbox boundary
// note that borders() only loops over subset of atoms during each swap
// set slablo > slabhi for swaps across non-periodic boundaries
// this insures no atoms are swapped
// only for procs owning sub-box at non-periodic end of global box
// for style MULTI:
// multilo/multihi is same as slablo/slabhi, only for each atom type
// pbc_flag: 0 = nothing across a boundary, 1 = something across a boundary
// pbc = -1/0/1 for PBC factor in each of 3/6 orthog/triclinic dirs
// for triclinic, slablo/hi and pbc_border will be used in lamda (0-1) coords
// 1st part of if statement is sending to the west/south/down
// 2nd part of if statement is sending to the east/north/up
int dim,ineed;
int iswap = 0;
for (dim = 0; dim < 3; dim++) {
for (ineed = 0; ineed < 2*need[dim]; ineed++) {
pbc_flag[iswap] = 0;
pbc[iswap][0] = pbc[iswap][1] = pbc[iswap][2] =
pbc[iswap][3] = pbc[iswap][4] = pbc[iswap][5] = 0;
if (ineed % 2 == 0) {
sendproc[iswap] = procneigh[dim][0];
recvproc[iswap] = procneigh[dim][1];
if (style == SINGLE) {
if (ineed < 2) slablo[iswap] = -BIG;
else slablo[iswap] = 0.5 * (sublo[dim] + subhi[dim]);
slabhi[iswap] = sublo[dim] + cutghost[dim];
} else {
for (i = 1; i <= ntypes; i++) {
if (ineed < 2) multilo[iswap][i] = -BIG;
else multilo[iswap][i] = 0.5 * (sublo[dim] + subhi[dim]);
multihi[iswap][i] = sublo[dim] + cutghostmulti[i][dim];
}
}
if (myloc[dim] == 0) {
if (periodicity[dim] == 0) {
if (style == SINGLE) slabhi[iswap] = slablo[iswap] - 1.0;
else
for (i = 1; i <= ntypes; i++)
multihi[iswap][i] = multilo[iswap][i] - 1.0;
} else {
pbc_flag[iswap] = 1;
pbc[iswap][dim] = 1;
if (triclinic) {
if (dim == 1) pbc[iswap][5] = 1;
else if (dim == 2) pbc[iswap][4] = pbc[iswap][3] = 1;
}
}
}
} else {
sendproc[iswap] = procneigh[dim][1];
recvproc[iswap] = procneigh[dim][0];
if (style == SINGLE) {
slablo[iswap] = subhi[dim] - cutghost[dim];
if (ineed < 2) slabhi[iswap] = BIG;
else slabhi[iswap] = 0.5 * (sublo[dim] + subhi[dim]);
} else {
for (i = 1; i <= ntypes; i++) {
multilo[iswap][i] = subhi[dim] - cutghostmulti[i][dim];
if (ineed < 2) multihi[iswap][i] = BIG;
else multihi[iswap][i] = 0.5 * (sublo[dim] + subhi[dim]);
}
}
if (myloc[dim] == procgrid[dim]-1) {
if (periodicity[dim] == 0) {
if (style == SINGLE) slabhi[iswap] = slablo[iswap] - 1.0;
else
for (i = 1; i <= ntypes; i++)
multihi[iswap][i] = multilo[iswap][i] - 1.0;
} else {
pbc_flag[iswap] = 1;
pbc[iswap][dim] = -1;
if (triclinic) {
if (dim == 1) pbc[iswap][5] = -1;
else if (dim == 2) pbc[iswap][4] = pbc[iswap][3] = -1;
}
}
}
}
iswap++;
}
}
}
/* ----------------------------------------------------------------------
forward communication of atom coords every timestep
other per-atom attributes may also be sent via pack/unpack routines
------------------------------------------------------------------------- */
void Comm::forward_comm(int dummy)
{
int n;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **x = atom->x;
double *buf;
// exchange data with another proc
// if other proc is self, just copy
// if comm_x_only set, exchange or copy directly to x, don't unpack
for (int iswap = 0; iswap < nswap; iswap++) {
if (sendproc[iswap] != me) {
if (comm_x_only) {
if (size_forward_recv[iswap]) buf = x[firstrecv[iswap]];
else buf = NULL;
MPI_Irecv(buf,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
} else if (ghost_velocity) {
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_recv);
} else {
MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
recvproc[iswap],0,world,&request);
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_recv);
}
} else {
if (comm_x_only) {
if (sendnum[iswap])
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
x[firstrecv[iswap]],pbc_flag[iswap],
pbc[iswap]);
} else if (ghost_velocity) {
n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_send);
} else {
n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_send);
}
}
}
}
/* ----------------------------------------------------------------------
reverse communication of forces on atoms every timestep
other per-atom attributes may also be sent via pack/unpack routines
------------------------------------------------------------------------- */
void Comm::reverse_comm()
{
int n;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
double **f = atom->f;
double *buf;
// exchange data with another proc
// if other proc is self, just copy
// if comm_f_only set, exchange or copy directly from f, don't pack
for (int iswap = nswap-1; iswap >= 0; iswap--) {
if (sendproc[iswap] != me) {
if (comm_f_only) {
MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,
sendproc[iswap],0,world,&request);
if (size_reverse_send[iswap]) buf = f[firstrecv[iswap]];
else buf = NULL;
MPI_Send(buf,size_reverse_send[iswap],MPI_DOUBLE,
recvproc[iswap],0,world);
MPI_Wait(&request,&status);
} else {
MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,
sendproc[iswap],0,world,&request);
n = avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
MPI_Wait(&request,&status);
}
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],buf_recv);
} else {
if (comm_f_only) {
if (sendnum[iswap])
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],
f[firstrecv[iswap]]);
} else {
n = avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
avec->unpack_reverse(sendnum[iswap],sendlist[iswap],buf_send);
}
}
}
}
/* ----------------------------------------------------------------------
exchange: move atoms to correct processors
atoms exchanged with all 6 stencil neighbors
send out atoms that have left my box, receive ones entering my box
atoms will be lost if not inside some proc's box
can happen if atom moves outside of non-periodic bounary
or if atom moves more than one proc away
this routine called before every reneighboring
for triclinic, atoms must be in lamda coords (0-1) before exchange is called
------------------------------------------------------------------------- */
void Comm::exchange()
{
int i,m,nsend,nrecv,nrecv1,nrecv2,nlocal;
double lo,hi,value;
double **x;
double *sublo,*subhi,*buf;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
// clear global->local map for owned and ghost atoms
// b/c atoms migrate to new procs in exchange() and
// new ghosts are created in borders()
// map_set() is done at end of borders()
if (map_style) atom->map_clear();
// subbox bounds for orthogonal or triclinic
if (triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
// loop over dimensions
for (int dim = 0; dim < 3; dim++) {
// fill buffer with atoms leaving my box, using < and >=
// when atom is deleted, fill it in with last atom
x = atom->x;
lo = sublo[dim];
hi = subhi[dim];
nlocal = atom->nlocal;
i = nsend = 0;
while (i < nlocal) {
if (x[i][dim] < lo || x[i][dim] >= hi) {
if (nsend > maxsend) grow_send(nsend,1);
nsend += avec->pack_exchange(i,&buf_send[nsend]);
avec->copy(nlocal-1,i,1);
nlocal--;
} else i++;
}
atom->nlocal = nlocal;
// send/recv atoms in both directions
// if 1 proc in dimension, no send/recv, set recv buf to send buf
// if 2 procs in dimension, single send/recv
// if more than 2 procs in dimension, send/recv to both neighbors
if (procgrid[dim] == 1) {
nrecv = nsend;
buf = buf_send;
} else {
MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][0],0,
&nrecv1,1,MPI_INT,procneigh[dim][1],0,world,&status);
nrecv = nrecv1;
if (procgrid[dim] > 2) {
MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][1],0,
&nrecv2,1,MPI_INT,procneigh[dim][0],0,world,&status);
nrecv += nrecv2;
}
if (nrecv > maxrecv) grow_recv(nrecv);
MPI_Irecv(buf_recv,nrecv1,MPI_DOUBLE,procneigh[dim][1],0,
world,&request);
MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][0],0,world);
MPI_Wait(&request,&status);
if (procgrid[dim] > 2) {
MPI_Irecv(&buf_recv[nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0,
world,&request);
MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][1],0,world);
MPI_Wait(&request,&status);
}
buf = buf_recv;
}
// check incoming atoms to see if they are in my box
// if so, add to my list
m = 0;
while (m < nrecv) {
value = buf[m+dim+1];
if (value >= lo && value < hi) m += avec->unpack_exchange(&buf[m]);
else m += static_cast<int> (buf[m]);
}
}
if (atom->firstgroupname) atom->first_reorder();
}
/* ----------------------------------------------------------------------
borders: list nearby atoms to send to neighboring procs at every timestep
one list is created for every swap that will be made
as list is made, actually do swaps
this does equivalent of a communicate (so don't need to explicitly
call communicate routine on reneighboring timestep)
this routine is called before every reneighboring
for triclinic, atoms must be in lamda coords (0-1) before borders is called
------------------------------------------------------------------------- */
void Comm::borders()
{
int i,n,itype,iswap,dim,ineed,maxneed,smax,rmax;
int nsend,nrecv,nfirst,nlast,ngroup;
double lo,hi;
int *type;
double **x;
double *buf,*mlo,*mhi;
MPI_Request request;
MPI_Status status;
AtomVec *avec = atom->avec;
// clear old ghosts and any ghost bonus data internal to AtomVec
atom->nghost = 0;
atom->avec->clear_bonus();
// do swaps over all 3 dimensions
iswap = 0;
smax = rmax = 0;
for (dim = 0; dim < 3; dim++) {
nlast = 0;
maxneed = 2*need[dim];
for (ineed = 0; ineed < maxneed; ineed++) {
// find atoms within slab boundaries lo/hi using <= and >=
// check atoms between nfirst and nlast
// for first swaps in a dim, check owned and ghost
// for later swaps in a dim, only check newly arrived ghosts
// store sent atom indices in list for use in future timesteps
x = atom->x;
if (style == SINGLE) {
lo = slablo[iswap];
hi = slabhi[iswap];
} else {
type = atom->type;
mlo = multilo[iswap];
mhi = multihi[iswap];
}
if (ineed % 2 == 0) {
nfirst = nlast;
nlast = atom->nlocal + atom->nghost;
}
nsend = 0;
// find send atoms according to SINGLE vs MULTI
// all atoms eligible versus atoms in bordergroup
// only need to limit loop to bordergroup for first sends (ineed < 2)
// on these sends, break loop in two: owned (in group) and ghost
if (!bordergroup || ineed >= 2) {
if (style == SINGLE) {
for (i = nfirst; i < nlast; i++)
if (x[i][dim] >= lo && x[i][dim] <= hi) {
if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
sendlist[iswap][nsend++] = i;
}
} else {
for (i = nfirst; i < nlast; i++) {
itype = type[i];
if (x[i][dim] >= mlo[itype] && x[i][dim] <= mhi[itype]) {
if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
sendlist[iswap][nsend++] = i;
}
}
}
} else {
if (style == SINGLE) {
ngroup = atom->nfirst;
for (i = 0; i < ngroup; i++)
if (x[i][dim] >= lo && x[i][dim] <= hi) {
if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
sendlist[iswap][nsend++] = i;
}
for (i = atom->nlocal; i < nlast; i++)
if (x[i][dim] >= lo && x[i][dim] <= hi) {
if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
sendlist[iswap][nsend++] = i;
}
} else {
ngroup = atom->nfirst;
for (i = 0; i < ngroup; i++) {
itype = type[i];
if (x[i][dim] >= mlo[itype] && x[i][dim] <= mhi[itype]) {
if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
sendlist[iswap][nsend++] = i;
}
}
for (i = atom->nlocal; i < nlast; i++) {
itype = type[i];
if (x[i][dim] >= mlo[itype] && x[i][dim] <= mhi[itype]) {
if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
sendlist[iswap][nsend++] = i;
}
}
}
}
// pack up list of border atoms
if (nsend*size_border > maxsend)
grow_send(nsend*size_border,0);
if (ghost_velocity)
n = avec->pack_border_vel(nsend,sendlist[iswap],buf_send,
pbc_flag[iswap],pbc[iswap]);
else
n = avec->pack_border(nsend,sendlist[iswap],buf_send,
pbc_flag[iswap],pbc[iswap]);
// swap atoms with other proc
// put incoming ghosts at end of my atom arrays
// if swapping with self, simply copy, no messages
if (sendproc[iswap] != me) {
MPI_Sendrecv(&nsend,1,MPI_INT,sendproc[iswap],0,
&nrecv,1,MPI_INT,recvproc[iswap],0,world,&status);
if (nrecv*size_border > maxrecv)
grow_recv(nrecv*size_border);
MPI_Irecv(buf_recv,nrecv*size_border,MPI_DOUBLE,
recvproc[iswap],0,world,&request);
MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else {
nrecv = nsend;
buf = buf_send;
}
// unpack buffer
if (ghost_velocity)
avec->unpack_border_vel(nrecv,atom->nlocal+atom->nghost,buf);
else
avec->unpack_border(nrecv,atom->nlocal+atom->nghost,buf);
// set all pointers & counters
smax = MAX(smax,nsend);
rmax = MAX(rmax,nrecv);
sendnum[iswap] = nsend;
recvnum[iswap] = nrecv;
size_forward_recv[iswap] = nrecv*size_forward;
size_reverse_send[iswap] = nrecv*size_reverse;
size_reverse_recv[iswap] = nsend*size_reverse;
firstrecv[iswap] = atom->nlocal + atom->nghost;
atom->nghost += nrecv;
iswap++;
}
}
// insure send/recv buffers are long enough for all forward & reverse comm
int max = MAX(maxforward*smax,maxreverse*rmax);
if (max > maxsend) grow_send(max,0);
max = MAX(maxforward*rmax,maxreverse*smax);
if (max > maxrecv) grow_recv(max);
// reset global->local map
if (map_style) atom->map_set();
}
/* ----------------------------------------------------------------------
forward communication invoked by a Pair
------------------------------------------------------------------------- */
void Comm::forward_comm_pair(Pair *pair)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = 0; iswap < nswap; iswap++) {
// pack buffer
n = pair->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
pair->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Pair
------------------------------------------------------------------------- */
void Comm::reverse_comm_pair(Pair *pair)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = nswap-1; iswap >= 0; iswap--) {
// pack buffer
n = pair->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
pair->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Fix
------------------------------------------------------------------------- */
void Comm::forward_comm_fix(Fix *fix)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = 0; iswap < nswap; iswap++) {
// pack buffer
n = fix->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
fix->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Fix
------------------------------------------------------------------------- */
void Comm::reverse_comm_fix(Fix *fix)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = nswap-1; iswap >= 0; iswap--) {
// pack buffer
n = fix->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
fix->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Compute
------------------------------------------------------------------------- */
void Comm::forward_comm_compute(Compute *compute)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = 0; iswap < nswap; iswap++) {
// pack buffer
n = compute->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
compute->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Compute
------------------------------------------------------------------------- */
void Comm::reverse_comm_compute(Compute *compute)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = nswap-1; iswap >= 0; iswap--) {
// pack buffer
n = compute->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
compute->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
}
}
/* ----------------------------------------------------------------------
forward communication invoked by a Dump
------------------------------------------------------------------------- */
void Comm::forward_comm_dump(Dump *dump)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = 0; iswap < nswap; iswap++) {
// pack buffer
n = dump->pack_comm(sendnum[iswap],sendlist[iswap],
buf_send,pbc_flag[iswap],pbc[iswap]);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
dump->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
}
}
/* ----------------------------------------------------------------------
reverse communication invoked by a Dump
------------------------------------------------------------------------- */
void Comm::reverse_comm_dump(Dump *dump)
{
int iswap,n;
double *buf;
MPI_Request request;
MPI_Status status;
for (iswap = nswap-1; iswap >= 0; iswap--) {
// pack buffer
n = dump->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
// exchange with another proc
// if self, set recv buffer to send buffer
if (sendproc[iswap] != me) {
MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
world,&request);
MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
MPI_Wait(&request,&status);
buf = buf_recv;
} else buf = buf_send;
// unpack buffer
dump->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
}
}
/* ----------------------------------------------------------------------
assign nprocs to 3d xprd,yprd,zprd box so as to minimize surface area
area = surface area of each of 3 faces of simulation box
for triclinic, area = cross product of 2 edge vectors stored in h matrix
------------------------------------------------------------------------- */
void Comm::procs2box()
{
procgrid[0] = user_procgrid[0];
procgrid[1] = user_procgrid[1];
procgrid[2] = user_procgrid[2];
// all 3 proc counts are specified
if (procgrid[0] && procgrid[1] && procgrid[2]) return;
// 2 out of 3 proc counts are specified
if (procgrid[0] > 0 && procgrid[1] > 0) {
procgrid[2] = nprocs/(procgrid[0]*procgrid[1]);
return;
} else if (procgrid[0] > 0 && procgrid[2] > 0) {
procgrid[1] = nprocs/(procgrid[0]*procgrid[2]);
return;
} else if (procgrid[1] > 0 && procgrid[2] > 0) {
procgrid[0] = nprocs/(procgrid[1]*procgrid[2]);
return;
}
// determine cross-sectional areas for orthogonal and triclinic boxes
// area[0] = xy, area[1] = xz, area[2] = yz
double area[3];
if (domain->triclinic == 0) {
area[0] = domain->xprd * domain->yprd;
area[1] = domain->xprd * domain->zprd;
area[2] = domain->yprd * domain->zprd;
} else {
double *h = domain->h;
double x,y,z;
cross(h[0],0.0,0.0,h[5],h[1],0.0,x,y,z);
area[0] = sqrt(x*x + y*y + z*z);
cross(h[0],0.0,0.0,h[4],h[3],h[2],x,y,z);
area[1] = sqrt(x*x + y*y + z*z);
cross(h[5],h[1],0.0,h[4],h[3],h[2],x,y,z);
area[2] = sqrt(x*x + y*y + z*z);
}
double bestsurf = 2.0 * (area[0]+area[1]+area[2]);
// loop thru all possible factorizations of nprocs
// only consider valid cases that match procgrid settings
// surf = surface area of a proc sub-domain
int ipx,ipy,ipz,valid;
double surf;
ipx = 1;
while (ipx <= nprocs) {
valid = 1;
if (user_procgrid[0] && ipx != user_procgrid[0]) valid = 0;
if (nprocs % ipx) valid = 0;
if (!valid) {
ipx++;
continue;
}
ipy = 1;
while (ipy <= nprocs/ipx) {
valid = 1;
if (user_procgrid[1] && ipy != user_procgrid[1]) valid = 0;
if ((nprocs/ipx) % ipy) valid = 0;
if (!valid) {
ipy++;
continue;
}
ipz = nprocs/ipx/ipy;
valid = 1;
if (user_procgrid[2] && ipz != user_procgrid[2]) valid = 0;
if (domain->dimension == 2 && ipz != 1) valid = 0;
if (!valid) {
ipy++;
continue;
}
surf = area[0]/ipx/ipy + area[1]/ipx/ipz + area[2]/ipy/ipz;
if (surf < bestsurf) {
bestsurf = surf;
procgrid[0] = ipx;
procgrid[1] = ipy;
procgrid[2] = ipz;
}
ipy++;
}
ipx++;
}
}
/* ----------------------------------------------------------------------
vector cross product: c = a x b
------------------------------------------------------------------------- */
void Comm::cross(double ax, double ay, double az,
double bx, double by, double bz,
double &cx, double &cy, double &cz)
{
cx = ay*bz - az*by;
cy = az*bx - ax*bz;
cz = ax*by - ay*bx;
}
/* ----------------------------------------------------------------------
realloc the size of the send buffer as needed with BUFFACTOR & BUFEXTRA
if flag = 1, realloc
if flag = 0, don't need to realloc with copy, just free/malloc
------------------------------------------------------------------------- */
void Comm::grow_send(int n, int flag)
{
maxsend = static_cast<int> (BUFFACTOR * n);
if (flag)
memory->grow(buf_send,(maxsend+BUFEXTRA),"comm:buf_send");
else {
memory->destroy(buf_send);
memory->create(buf_send,maxsend+BUFEXTRA,"comm:buf_send");
}
}
/* ----------------------------------------------------------------------
free/malloc the size of the recv buffer as needed with BUFFACTOR
------------------------------------------------------------------------- */
void Comm::grow_recv(int n)
{
maxrecv = static_cast<int> (BUFFACTOR * n);
memory->destroy(buf_recv);
memory->create(buf_recv,maxrecv,"comm:buf_recv");
}
/* ----------------------------------------------------------------------
realloc the size of the iswap sendlist as needed with BUFFACTOR
------------------------------------------------------------------------- */
void Comm::grow_list(int iswap, int n)
{
maxsendlist[iswap] = static_cast<int> (BUFFACTOR * n);
memory->grow(sendlist[iswap],maxsendlist[iswap],"comm:sendlist[iswap]");
}
/* ----------------------------------------------------------------------
realloc the buffers needed for swaps
------------------------------------------------------------------------- */
void Comm::grow_swap(int n)
{
free_swap();
allocate_swap(n);
if (style == MULTI) {
free_multi();
allocate_multi(n);
}
sendlist = (int **)
memory->srealloc(sendlist,n*sizeof(int *),"comm:sendlist");
memory->grow(maxsendlist,n,"comm:maxsendlist");
for (int i = maxswap; i < n; i++) {
maxsendlist[i] = BUFMIN;
memory->create(sendlist[i],BUFMIN,"comm:sendlist[i]");
}
maxswap = n;
}
/* ----------------------------------------------------------------------
allocation of swap info
------------------------------------------------------------------------- */
void Comm::allocate_swap(int n)
{
memory->create(sendnum,n,"comm:sendnum");
memory->create(recvnum,n,"comm:recvnum");
memory->create(sendproc,n,"comm:sendproc");
memory->create(recvproc,n,"comm:recvproc");
memory->create(size_forward_recv,n,"comm:size");
memory->create(size_reverse_send,n,"comm:size");
memory->create(size_reverse_recv,n,"comm:size");
memory->create(slablo,n,"comm:slablo");
memory->create(slabhi,n,"comm:slabhi");
memory->create(firstrecv,n,"comm:firstrecv");
memory->create(pbc_flag,n,"comm:pbc_flag");
memory->create(pbc,n,6,"comm:pbc");
}
/* ----------------------------------------------------------------------
allocation of multi-type swap info
------------------------------------------------------------------------- */
void Comm::allocate_multi(int n)
{
multilo = memory->create(multilo,n,atom->ntypes+1,"comm:multilo");
multihi = memory->create(multihi,n,atom->ntypes+1,"comm:multihi");
}
/* ----------------------------------------------------------------------
free memory for swaps
------------------------------------------------------------------------- */
void Comm::free_swap()
{
memory->destroy(sendnum);
memory->destroy(recvnum);
memory->destroy(sendproc);
memory->destroy(recvproc);
memory->destroy(size_forward_recv);
memory->destroy(size_reverse_send);
memory->destroy(size_reverse_recv);
memory->destroy(slablo);
memory->destroy(slabhi);
memory->destroy(firstrecv);
memory->destroy(pbc_flag);
memory->destroy(pbc);
}
/* ----------------------------------------------------------------------
free memory for multi-type swaps
------------------------------------------------------------------------- */
void Comm::free_multi()
{
memory->destroy(multilo);
memory->destroy(multihi);
}
/* ----------------------------------------------------------------------
set communication style
------------------------------------------------------------------------- */
void Comm::set(int narg, char **arg)
{
- if (narg < 1) error->all("Illegal communicate command");
+ if (narg < 1) error->all(FLERR,"Illegal communicate command");
if (strcmp(arg[0],"single") == 0) style = SINGLE;
else if (strcmp(arg[0],"multi") == 0) style = MULTI;
- else error->all("Illegal communicate command");
+ else error->all(FLERR,"Illegal communicate command");
int iarg = 1;
while (iarg < narg) {
if (strcmp(arg[iarg],"group") == 0) {
- if (iarg+2 > narg) error->all("Illegal communicate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal communicate command");
bordergroup = group->find(arg[iarg+1]);
if (bordergroup < 0)
- error->all("Invalid group in communicate command");
+ error->all(FLERR,"Invalid group in communicate command");
if (bordergroup && (atom->firstgroupname == NULL ||
strcmp(arg[iarg+1],atom->firstgroupname) != 0))
- error->all("Communicate group != atom_modify first group");
+ error->all(FLERR,"Communicate group != atom_modify first group");
iarg += 2;
} else if (strcmp(arg[iarg],"cutoff") == 0) {
- if (iarg+2 > narg) error->all("Illegal communicate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal communicate command");
cutghostuser = atof(arg[iarg+1]);
if (cutghostuser < 0.0)
- error->all("Invalid cutoff in communicate command");
+ error->all(FLERR,"Invalid cutoff in communicate command");
iarg += 2;
} else if (strcmp(arg[iarg],"vel") == 0) {
- if (iarg+2 > narg) error->all("Illegal communicate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal communicate command");
if (strcmp(arg[iarg+1],"yes") == 0) ghost_velocity = 1;
else if (strcmp(arg[iarg+1],"no") == 0) ghost_velocity = 0;
- else error->all("Illegal communicate command");
+ else error->all(FLERR,"Illegal communicate command");
iarg += 2;
- } else error->all("Illegal communicate command");
+ } else error->all(FLERR,"Illegal communicate command");
}
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint Comm::memory_usage()
{
bigint bytes = 0;
for (int i = 0; i < nswap; i++)
bytes += memory->usage(sendlist[i],maxsendlist[i]);
bytes += memory->usage(buf_send,maxsend+BUFEXTRA);
bytes += memory->usage(buf_recv,maxrecv);
return bytes;
}
diff --git a/src/compute.cpp b/src/compute.cpp
index 230c15919..5b8dc93f2 100644
--- a/src/compute.cpp
+++ b/src/compute.cpp
@@ -1,292 +1,289 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "compute.h"
#include "atom.h"
#include "domain.h"
#include "comm.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 4
#define BIG 2000000000
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
Compute::Compute(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
- if (narg < 3) error->all("Illegal compute command");
+ if (narg < 3) error->all(FLERR,"Illegal compute command");
// compute ID, group, and style
// ID must be all alphanumeric chars or underscores
int n = strlen(arg[0]) + 1;
id = new char[n];
strcpy(id,arg[0]);
for (int i = 0; i < n-1; i++)
if (!isalnum(id[i]) && id[i] != '_')
- error->all("Compute ID must be alphanumeric or underscore characters");
+ error->all(FLERR,"Compute ID must be alphanumeric or underscore characters");
igroup = group->find(arg[1]);
- if (igroup == -1) error->all("Could not find compute group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find compute group ID");
groupbit = group->bitmask[igroup];
n = strlen(arg[2]) + 1;
style = new char[n];
strcpy(style,arg[2]);
// set child class defaults
scalar_flag = vector_flag = array_flag = 0;
peratom_flag = local_flag = 0;
tempflag = pressflag = peflag = 0;
pressatomflag = peatomflag = 0;
tempbias = 0;
timeflag = 0;
comm_forward = comm_reverse = 0;
cudable = 0;
invoked_scalar = invoked_vector = invoked_array = -1;
invoked_peratom = invoked_local = -1;
// set modify defaults
extra_dof = domain->dimension;
dynamic = 0;
// setup list of timesteps
ntime = maxtime = 0;
tlist = NULL;
// setup map for molecule IDs
molmap = NULL;
}
/* ---------------------------------------------------------------------- */
Compute::~Compute()
{
delete [] id;
delete [] style;
memory->destroy(tlist);
memory->destroy(molmap);
}
/* ---------------------------------------------------------------------- */
void Compute::modify_params(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal compute_modify command");
+ if (narg == 0) error->all(FLERR,"Illegal compute_modify command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"extra") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute_modify command");
extra_dof = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"dynamic") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute_modify command");
if (strcmp(arg[iarg+1],"no") == 0) dynamic = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) dynamic = 1;
- else error->all("Illegal compute_modify command");
+ else error->all(FLERR,"Illegal compute_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"thermo") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute_modify command");
if (strcmp(arg[iarg+1],"no") == 0) thermoflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) thermoflag = 1;
- else error->all("Illegal compute_modify command");
+ else error->all(FLERR,"Illegal compute_modify command");
iarg += 2;
- } else error->all("Illegal compute_modify command");
+ } else error->all(FLERR,"Illegal compute_modify command");
}
}
/* ----------------------------------------------------------------------
reset extra_dof to its default value
------------------------------------------------------------------------- */
void Compute::reset_extra_dof()
{
extra_dof = domain->dimension;
}
/* ---------------------------------------------------------------------- */
void Compute::reset_extra_compute_fix(char *)
{
- error->all("Compute does not allow an extra compute or fix to be reset");
+ error->all(FLERR,"Compute does not allow an extra compute or fix to be reset");
}
/* ----------------------------------------------------------------------
add ntimestep to list of timesteps the compute will be called on
do not add if already in list
search from top downward, since list of times is in decreasing order
------------------------------------------------------------------------- */
void Compute::addstep(bigint ntimestep)
{
// i = location in list to insert ntimestep
int i;
for (i = ntime-1; i >= 0; i--) {
if (ntimestep == tlist[i]) return;
if (ntimestep < tlist[i]) break;
}
i++;
// extend list as needed
if (ntime == maxtime) {
maxtime += DELTA;
memory->grow(tlist,maxtime,"compute:tlist");
}
// move remainder of list upward and insert ntimestep
for (int j = ntime-1; j >= i; j--) tlist[j+1] = tlist[j];
tlist[i] = ntimestep;
ntime++;
}
/* ----------------------------------------------------------------------
return 1/0 if ntimestep is or is not in list of calling timesteps
if value(s) on top of list are less than ntimestep, delete them
search from top downward, since list of times is in decreasing order
------------------------------------------------------------------------- */
int Compute::matchstep(bigint ntimestep)
{
for (int i = ntime-1; i >= 0; i--) {
if (ntimestep < tlist[i]) return 0;
if (ntimestep == tlist[i]) return 1;
if (ntimestep > tlist[i]) ntime--;
}
return 0;
}
/* ----------------------------------------------------------------------
clean out list of timesteps to call the compute on
------------------------------------------------------------------------- */
void Compute::clearstep()
{
ntime = 0;
}
/* ----------------------------------------------------------------------
identify molecule IDs with atoms in group
warn if any atom in group has molecule ID = 0
warn if any molecule has only some atoms in group
return Ncount = # of molecules with atoms in group
set molmap to NULL if molecule IDs include all in range from 1 to Ncount
else: molecule IDs range from idlo to idhi
set molmap to vector of length idhi-idlo+1
molmap[id-idlo] = index from 0 to Ncount-1
return idlo and idhi
------------------------------------------------------------------------- */
int Compute::molecules_in_group(int &idlo, int &idhi)
{
int i;
memory->destroy(molmap);
molmap = NULL;
// find lo/hi molecule ID for any atom in group
// warn if atom in group has ID = 0
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int lo = BIG;
int hi = -BIG;
int flag = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (molecule[i] == 0) flag = 1;
lo = MIN(lo,molecule[i]);
hi = MAX(hi,molecule[i]);
}
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall && comm->me == 0)
- error->warning("Atom with molecule ID = 0 included in "
+ error->warning(FLERR,"Atom with molecule ID = 0 included in "
"compute molecule group");
MPI_Allreduce(&lo,&idlo,1,MPI_INT,MPI_MIN,world);
MPI_Allreduce(&hi,&idhi,1,MPI_INT,MPI_MAX,world);
if (idlo == BIG) return 0;
// molmap = vector of length nlen
// set to 1 for IDs that appear in group across all procs, else 0
int nlen = idhi-idlo+1;
memory->create(molmap,nlen,"compute:molmap");
for (i = 0; i < nlen; i++) molmap[i] = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
molmap[molecule[i]-idlo] = 1;
int *molmapall;
memory->create(molmapall,nlen,"compute:molmapall");
MPI_Allreduce(molmap,molmapall,nlen,MPI_INT,MPI_MAX,world);
// nmolecules = # of non-zero IDs in molmap
// molmap[i] = index of molecule, skipping molecules not in group with -1
int nmolecules = 0;
for (i = 0; i < nlen; i++)
if (molmapall[i]) molmap[i] = nmolecules++;
else molmap[i] = -1;
memory->destroy(molmapall);
// warn if any molecule has some atoms in group and some not in group
flag = 0;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) continue;
if (molecule[i] < idlo || molecule[i] > idhi) continue;
if (molmap[molecule[i]-idlo] >= 0) flag = 1;
}
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall && comm->me == 0)
- error->warning("One or more compute molecules has atoms not in group");
+ error->warning(FLERR,"One or more compute molecules has atoms not in group");
// if molmap simply stores 1 to Nmolecules, then free it
if (idlo == 1 && idhi == nmolecules && nlen == nmolecules) {
memory->destroy(molmap);
molmap = NULL;
}
return nmolecules;
}
diff --git a/src/compute_angle_local.cpp b/src/compute_angle_local.cpp
index 6f9bce918..a126348d3 100644
--- a/src/compute_angle_local.cpp
+++ b/src/compute_angle_local.cpp
@@ -1,218 +1,218 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_angle_local.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "domain.h"
#include "force.h"
#include "angle.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
ComputeAngleLocal::ComputeAngleLocal(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute angle/local command");
+ if (narg < 4) error->all(FLERR,"Illegal compute angle/local command");
if (atom->avec->angles_allow == 0)
- error->all("Compute angle/local used when angles are not allowed");
+ error->all(FLERR,"Compute angle/local used when angles are not allowed");
local_flag = 1;
nvalues = narg - 3;
if (nvalues == 1) size_local_cols = 0;
else size_local_cols = nvalues;
tflag = eflag = -1;
nvalues = 0;
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"theta") == 0) tflag = nvalues++;
else if (strcmp(arg[iarg],"eng") == 0) eflag = nvalues++;
- else error->all("Invalid keyword in compute angle/local command");
+ else error->all(FLERR,"Invalid keyword in compute angle/local command");
}
nmax = 0;
vector = NULL;
array = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeAngleLocal::~ComputeAngleLocal()
{
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputeAngleLocal::init()
{
if (force->angle == NULL)
- error->all("No angle style is defined for compute angle/local");
+ error->all(FLERR,"No angle style is defined for compute angle/local");
// do initial memory allocation so that memory_usage() is correct
ncount = compute_angles(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
}
/* ---------------------------------------------------------------------- */
void ComputeAngleLocal::compute_local()
{
invoked_local = update->ntimestep;
// count local entries and compute angle info
ncount = compute_angles(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
ncount = compute_angles(1);
}
/* ----------------------------------------------------------------------
count angles and compute angle info on this proc
only count angle once if newton_angle is off
all atoms in interaction must be in group
all atoms in interaction must be known to proc
if angle is deleted (type = 0), do not count
if angle is turned off (type < 0), still count
if flag is set, compute requested info about angle
if angle is turned off (type < 0), energy = 0.0
------------------------------------------------------------------------- */
int ComputeAngleLocal::compute_angles(int flag)
{
int i,m,n,atom1,atom2,atom3;
double delx1,dely1,delz1,delx2,dely2,delz2;
double rsq1,rsq2,r1,r2,c;
double *tbuf,*ebuf;
double **x = atom->x;
int *num_angle = atom->num_angle;
int **angle_atom1 = atom->angle_atom1;
int **angle_atom2 = atom->angle_atom2;
int **angle_atom3 = atom->angle_atom3;
int **angle_type = atom->angle_type;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (flag) {
if (nvalues == 1) {
if (tflag >= 0) tbuf = vector;
if (eflag >= 0) ebuf = vector;
} else {
if (tflag >= 0) tbuf = &array[0][tflag];
if (eflag >= 0) ebuf = &array[0][eflag];
}
}
Angle *angle = force->angle;
double PI = 4.0*atan(1.0);
m = n = 0;
for (atom2 = 0; atom2 < nlocal; atom2++) {
if (!(mask[atom2] & groupbit)) continue;
for (i = 0; i < num_angle[atom2]; i++) {
if (tag[atom2] != angle_atom2[atom2][i]) continue;
atom1 = atom->map(angle_atom1[atom2][i]);
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
atom3 = atom->map(angle_atom3[atom2][i]);
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
if (angle_type[atom2][i] == 0) continue;
if (flag) {
if (tflag >= 0) {
delx1 = x[atom1][0] - x[atom2][0];
dely1 = x[atom1][1] - x[atom2][1];
delz1 = x[atom1][2] - x[atom2][2];
domain->minimum_image(delx1,dely1,delz1);
rsq1 = delx1*delx1 + dely1*dely1 + delz1*delz1;
r1 = sqrt(rsq1);
delx2 = x[atom3][0] - x[atom2][0];
dely2 = x[atom3][1] - x[atom2][1];
delz2 = x[atom3][2] - x[atom2][2];
domain->minimum_image(delx2,dely2,delz2);
rsq2 = delx2*delx2 + dely2*dely2 + delz2*delz2;
r2 = sqrt(rsq2);
// c = cosine of angle
c = delx1*delx2 + dely1*dely2 + delz1*delz2;
c /= r1*r2;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
tbuf[n] = 180.0*acos(c)/PI;
}
if (eflag >= 0) {
if (angle_type[atom2][i] > 0)
ebuf[n] = angle->single(angle_type[atom2][i],atom1,atom2,atom3);
else ebuf[n] = 0.0;
}
n += nvalues;
}
m++;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void ComputeAngleLocal::reallocate(int n)
{
// grow vector or array and indices array
while (nmax < n) nmax += DELTA;
if (nvalues == 1) {
memory->destroy(vector);
memory->create(vector,nmax,"bond/local:vector");
vector_local = vector;
} else {
memory->destroy(array);
memory->create(array,nmax,nvalues,"bond/local:array");
array_local = array;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeAngleLocal::memory_usage()
{
double bytes = nmax*nvalues * sizeof(double);
return bytes;
}
diff --git a/src/compute_atom_molecule.cpp b/src/compute_atom_molecule.cpp
index 9466ae92a..2bb6f7a51 100644
--- a/src/compute_atom_molecule.cpp
+++ b/src/compute_atom_molecule.cpp
@@ -1,341 +1,341 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "compute_atom_molecule.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "fix.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{COMPUTE,FIX,VARIABLE};
#define INVOKED_PERATOM 8
/* ---------------------------------------------------------------------- */
ComputeAtomMolecule::
ComputeAtomMolecule(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute atom/molecule command");
+ if (narg < 4) error->all(FLERR,"Illegal compute atom/molecule command");
if (atom->molecular == 0)
- error->all("Compute atom/molecule requires molecular atom style");
+ error->all(FLERR,"Compute atom/molecule requires molecular atom style");
// parse args
which = new int[narg-3];
argindex = new int[narg-3];
ids = new char*[narg-3];
value2index = new int[narg-3];
nvalues = 0;
int iarg = 3;
while (iarg < narg) {
if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal compute reduce command");
+ error->all(FLERR,"Illegal compute reduce command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
nvalues++;
delete [] suffix;
- } else error->all("Illegal compute atom/molecule command");
+ } else error->all(FLERR,"Illegal compute atom/molecule command");
iarg++;
}
// setup and error check
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for compute atom/molecule does not exist");
+ error->all(FLERR,"Compute ID for compute atom/molecule does not exist");
if (modify->compute[icompute]->peratom_flag == 0)
- error->all("Compute atom/molecule compute does not "
+ error->all(FLERR,"Compute atom/molecule compute does not "
"calculate per-atom values");
if (argindex[i] == 0 &&
modify->compute[icompute]->size_peratom_cols != 0)
- error->all("Compute atom/molecule compute does not "
+ error->all(FLERR,"Compute atom/molecule compute does not "
"calculate a per-atom vector");
if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0)
- error->all("Compute atom/molecule compute does not "
+ error->all(FLERR,"Compute atom/molecule compute does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_peratom_cols)
- error->all("Compute atom/molecule compute array is "
+ error->all(FLERR,"Compute atom/molecule compute array is "
"accessed out-of-range");
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for compute atom/molecule does not exist");
+ error->all(FLERR,"Fix ID for compute atom/molecule does not exist");
if (modify->fix[ifix]->peratom_flag)
- error->all("Compute atom/molecule fix does not "
+ error->all(FLERR,"Compute atom/molecule fix does not "
"calculate per-atom values");
if (argindex[i] == 0 &&
modify->fix[ifix]->size_peratom_cols != 0)
- error->all("Compute atom/molecule fix does not "
+ error->all(FLERR,"Compute atom/molecule fix does not "
"calculate a per-atom vector");
if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0)
- error->all("Compute atom/molecule fix does not "
+ error->all(FLERR,"Compute atom/molecule fix does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->fix[ifix]->size_peratom_cols)
- error->all("Compute atom/molecule fix array is accessed out-of-range");
+ error->all(FLERR,"Compute atom/molecule fix array is accessed out-of-range");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for compute atom/molecule does not exist");
+ error->all(FLERR,"Variable name for compute atom/molecule does not exist");
if (input->variable->atomstyle(ivariable) == 0)
- error->all("Compute atom/molecule variable is not "
+ error->all(FLERR,"Compute atom/molecule variable is not "
"atom-style variable");
}
}
// setup molecule-based data
nmolecules = molecules_in_group(idlo,idhi);
vone = vector = NULL;
aone = array = NULL;
if (nvalues == 1) {
memory->create(vone,nmolecules,"atom/molecule:vone");
memory->create(vector,nmolecules,"atom/molecule:vector");
vector_flag = 1;
size_vector = nmolecules;
extvector = 0;
} else {
memory->create(aone,nmolecules,nvalues,"atom/molecule:aone");
memory->create(array,nmolecules,nvalues,"atom/molecule:array");
array_flag = 1;
size_array_rows = nmolecules;
size_array_cols = nvalues;
extarray = 0;
}
maxatom = 0;
scratch = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeAtomMolecule::~ComputeAtomMolecule()
{
delete [] which;
delete [] argindex;
for (int m = 0; m < nvalues; m++) delete [] ids[m];
delete [] ids;
delete [] value2index;
memory->destroy(vone);
memory->destroy(vector);
memory->destroy(aone);
memory->destroy(array);
memory->destroy(scratch);
}
/* ---------------------------------------------------------------------- */
void ComputeAtomMolecule::init()
{
int ntmp = molecules_in_group(idlo,idhi);
if (ntmp != nmolecules)
- error->all("Molecule count changed in compute atom/molecule");
+ error->all(FLERR,"Molecule count changed in compute atom/molecule");
// set indices and check validity of all computes,fixes,variables
for (int m = 0; m < nvalues; m++) {
if (which[m] == COMPUTE) {
int icompute = modify->find_compute(ids[m]);
if (icompute < 0)
- error->all("Compute ID for compute atom/molecule does not exist");
+ error->all(FLERR,"Compute ID for compute atom/molecule does not exist");
value2index[m] = icompute;
} else if (which[m] == FIX) {
int ifix = modify->find_fix(ids[m]);
if (ifix < 0)
- error->all("Fix ID for compute atom/molecule does not exist");
+ error->all(FLERR,"Fix ID for compute atom/molecule does not exist");
value2index[m] = ifix;
} else if (which[m] == VARIABLE) {
int ivariable = input->variable->find(ids[m]);
if (ivariable < 0)
- error->all("Variable name for compute atom/molecule does not exist");
+ error->all(FLERR,"Variable name for compute atom/molecule does not exist");
value2index[m] = ivariable;
} else value2index[m] = -1;
}
}
/* ---------------------------------------------------------------------- */
void ComputeAtomMolecule::compute_vector()
{
int i,j,n,imol;
invoked_vector = update->ntimestep;
for (n = 0; n < nmolecules; n++) vone[n] = 0.0;
compute_one(0);
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
j = 0;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
vone[imol] += peratom[j];
}
j += nstride;
}
int me;
MPI_Comm_rank(world,&me);
MPI_Allreduce(vone,vector,nmolecules,MPI_DOUBLE,MPI_SUM,world);
}
/* ---------------------------------------------------------------------- */
void ComputeAtomMolecule::compute_array()
{
int i,j,m,n,imol;
invoked_array = update->ntimestep;
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (m = 0; m < nvalues; m++) {
for (n = 0; n < nmolecules; n++) aone[n][m] = 0.0;
compute_one(m);
j = 0;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
aone[imol][m] += peratom[j];
}
j += nstride;
}
}
MPI_Allreduce(&aone[0][0],&array[0][0],nvalues*nmolecules,
MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
calculate per-atom values for one input M
invoke the appropriate compute,fix,variable
reallocate scratch if necessary for per-atom variable scratch space
------------------------------------------------------------------------- */
void ComputeAtomMolecule::compute_one(int m)
{
int vidx = value2index[m];
int aidx = argindex[m];
// invoke compute if not previously invoked
if (which[m] == COMPUTE) {
Compute *compute = modify->compute[vidx];
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
if (aidx == 0) {
peratom = compute->vector_atom;
nstride = 1;
} else {
peratom = &compute->array_atom[0][aidx-1];
nstride = compute->size_array_cols;
}
// access fix fields, check if fix frequency is a match
} else if (which[m] == FIX) {
if (update->ntimestep % modify->fix[vidx]->peratom_freq)
- error->all("Fix used in compute atom/molecule not computed "
+ error->all(FLERR,"Fix used in compute atom/molecule not computed "
"at compatible time");
Fix *fix = modify->fix[vidx];
if (aidx == 0) {
peratom = fix->vector_atom;
nstride = 1;
} else {
peratom = &fix->array_atom[0][aidx-1];
nstride = fix->size_array_cols;
}
// evaluate atom-style variable
} else if (which[m] == VARIABLE) {
if (atom->nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(scratch);
memory->create(scratch,maxatom,"atom/molecule:scratch");
peratom = scratch;
}
input->variable->compute_atom(vidx,igroup,peratom,1,0);
nstride = 1;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeAtomMolecule::memory_usage()
{
double bytes = 2*nmolecules*nvalues * sizeof(double);
if (molmap) bytes += (idhi-idlo+1) * sizeof(int);
bytes += maxatom * sizeof(double);
return bytes;
}
diff --git a/src/compute_bond_local.cpp b/src/compute_bond_local.cpp
index af1710520..76feec420 100644
--- a/src/compute_bond_local.cpp
+++ b/src/compute_bond_local.cpp
@@ -1,193 +1,193 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_bond_local.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "domain.h"
#include "force.h"
#include "bond.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
ComputeBondLocal::ComputeBondLocal(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute bond/local command");
+ if (narg < 4) error->all(FLERR,"Illegal compute bond/local command");
if (atom->avec->bonds_allow == 0)
- error->all("Compute bond/local used when bonds are not allowed");
+ error->all(FLERR,"Compute bond/local used when bonds are not allowed");
local_flag = 1;
nvalues = narg - 3;
if (nvalues == 1) size_local_cols = 0;
else size_local_cols = nvalues;
dflag = eflag = -1;
nvalues = 0;
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"dist") == 0) dflag = nvalues++;
else if (strcmp(arg[iarg],"eng") == 0) eflag = nvalues++;
- else error->all("Invalid keyword in compute bond/local command");
+ else error->all(FLERR,"Invalid keyword in compute bond/local command");
}
nmax = 0;
vector = NULL;
array = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeBondLocal::~ComputeBondLocal()
{
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputeBondLocal::init()
{
if (force->bond == NULL)
- error->all("No bond style is defined for compute bond/local");
+ error->all(FLERR,"No bond style is defined for compute bond/local");
// do initial memory allocation so that memory_usage() is correct
ncount = compute_bonds(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
}
/* ---------------------------------------------------------------------- */
void ComputeBondLocal::compute_local()
{
invoked_local = update->ntimestep;
// count local entries and compute bond info
ncount = compute_bonds(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
ncount = compute_bonds(1);
}
/* ----------------------------------------------------------------------
count bonds and compute bond info on this proc
only count bond once if newton_bond is off
all atoms in interaction must be in group
all atoms in interaction must be known to proc
if bond is deleted (type = 0), do not count
if bond is turned off (type < 0), still count
if flag is set, compute requested info about bond
if bond is turned off (type < 0), energy = 0.0
------------------------------------------------------------------------- */
int ComputeBondLocal::compute_bonds(int flag)
{
int i,m,n,atom1,atom2;
double delx,dely,delz,rsq;
double *dbuf,*ebuf;
double **x = atom->x;
int *num_bond = atom->num_bond;
int **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
if (flag) {
if (nvalues == 1) {
if (dflag >= 0) dbuf = vector;
if (eflag >= 0) ebuf = vector;
} else {
if (dflag >= 0) dbuf = &array[0][dflag];
if (eflag >= 0) ebuf = &array[0][eflag];
}
}
Bond *bond = force->bond;
m = n = 0;
for (atom1 = 0; atom1 < nlocal; atom1++) {
if (!(mask[atom1] & groupbit)) continue;
for (i = 0; i < num_bond[atom1]; i++) {
atom2 = atom->map(bond_atom[atom1][i]);
if (atom2 < 0 || !(mask[atom2] & groupbit)) continue;
if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue;
if (bond_type[atom1][i] == 0) continue;
if (flag) {
delx = x[atom1][0] - x[atom2][0];
dely = x[atom1][1] - x[atom2][1];
delz = x[atom1][2] - x[atom2][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
if (dflag >= 0) dbuf[n] = sqrt(rsq);
if (eflag >= 0) {
if (bond_type[atom1][i] > 0)
ebuf[n] = bond->single(bond_type[atom1][i],rsq,atom1,atom2);
else ebuf[n] = 0.0;
}
n += nvalues;
}
m++;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void ComputeBondLocal::reallocate(int n)
{
// grow vector or array and indices array
while (nmax < n) nmax += DELTA;
if (nvalues == 1) {
memory->destroy(vector);
memory->create(vector,nmax,"bond/local:vector");
vector_local = vector;
} else {
memory->destroy(array);
memory->create(array,nmax,nvalues,"bond/local:array");
array_local = array;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeBondLocal::memory_usage()
{
double bytes = nmax*nvalues * sizeof(double);
return bytes;
}
diff --git a/src/compute_centro_atom.cpp b/src/compute_centro_atom.cpp
index c166e3c2f..68478955c 100644
--- a/src/compute_centro_atom.cpp
+++ b/src/compute_centro_atom.cpp
@@ -1,333 +1,333 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Michel Perez (U Lyon) for non-fcc lattices
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "compute_centro_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "pair.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeCentroAtom::ComputeCentroAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal compute centro/atom command");
+ if (narg != 4) error->all(FLERR,"Illegal compute centro/atom command");
if (strcmp(arg[3],"fcc") == 0) nnn = 12;
else if (strcmp(arg[3],"bcc") == 0) nnn = 8;
else nnn = atoi(arg[3]);
if (nnn <= 0 || nnn % 2)
- error->all("Illegal neighbor value for compute centro/atom command");
+ error->all(FLERR,"Illegal neighbor value for compute centro/atom command");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
centro = NULL;
maxneigh = 0;
distsq = NULL;
nearest = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeCentroAtom::~ComputeCentroAtom()
{
memory->destroy(centro);
memory->destroy(distsq);
memory->destroy(nearest);
}
/* ---------------------------------------------------------------------- */
void ComputeCentroAtom::init()
{
if (force->pair == NULL)
- error->all("Compute centro/atom requires a pair style be defined");
+ error->all(FLERR,"Compute centro/atom requires a pair style be defined");
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"centro/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute centro/atom");
+ error->warning(FLERR,"More than one compute centro/atom");
// need an occasional full neighbor list
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
}
/* ---------------------------------------------------------------------- */
void ComputeCentroAtom::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputeCentroAtom::compute_peratom()
{
int i,j,k,ii,jj,kk,n,inum,jnum;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq,value;
int *ilist,*jlist,*numneigh,**firstneigh;
invoked_peratom = update->ntimestep;
// grow centro array if necessary
if (atom->nlocal > nmax) {
memory->destroy(centro);
nmax = atom->nmax;
memory->create(centro,nmax,"centro/atom:centro");
vector_atom = centro;
}
// invoke full neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// npairs = number of unique pairs
int nhalf = nnn/2;
int npairs = nnn * (nnn-1) / 2;
double *pairs = new double[npairs];
// compute centro-symmetry parameter for each atom in group
// use full neighbor list
double **x = atom->x;
int *mask = atom->mask;
double cutsq = force->pair->cutforce * force->pair->cutforce;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
// insure distsq and nearest arrays are long enough
if (jnum > maxneigh) {
memory->destroy(distsq);
memory->destroy(nearest);
maxneigh = jnum;
memory->create(distsq,maxneigh,"centro/atom:distsq");
memory->create(nearest,maxneigh,"centro/atom:nearest");
}
// loop over list of all neighbors within force cutoff
// distsq[] = distance sq to each
// nearest[] = atom indices of neighbors
n = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) {
distsq[n] = rsq;
nearest[n++] = j;
}
}
// if not nnn neighbors, centro = 0.0
if (n < nnn) {
centro[i] = 0.0;
continue;
}
// store nnn nearest neighs in 1st nnn locations of distsq and nearest
select2(nnn,n,distsq,nearest);
// R = Ri + Rj for each of npairs i,j pairs among nnn neighbors
// pairs = squared length of each R
n = 0;
for (j = 0; j < nnn; j++) {
jj = nearest[j];
for (k = j+1; k < nnn; k++) {
kk = nearest[k];
delx = x[jj][0] + x[kk][0] - 2.0*xtmp;
dely = x[jj][1] + x[kk][1] - 2.0*ytmp;
delz = x[jj][2] + x[kk][2] - 2.0*ztmp;
pairs[n++] = delx*delx + dely*dely + delz*delz;
}
}
// store nhalf smallest pair distances in 1st nhalf locations of pairs
select(nhalf,npairs,pairs);
// centrosymmetry = sum of nhalf smallest squared values
value = 0.0;
for (j = 0; j < nhalf; j++) value += pairs[j];
centro[i] = value;
} else centro[i] = 0.0;
}
delete [] pairs;
}
/* ----------------------------------------------------------------------
2 select routines from Numerical Recipes (slightly modified)
find k smallest values in array of length n
2nd routine sorts auxiliary array at same time
------------------------------------------------------------------------- */
#define SWAP(a,b) tmp = a; a = b; b = tmp;
#define ISWAP(a,b) itmp = a; a = b; b = itmp;
void ComputeCentroAtom::select(int k, int n, double *arr)
{
int i,ir,j,l,mid;
double a,tmp;
arr--;
l = 1;
ir = n;
for (;;) {
if (ir <= l+1) {
if (ir == l+1 && arr[ir] < arr[l]) {
SWAP(arr[l],arr[ir])
}
return;
} else {
mid=(l+ir) >> 1;
SWAP(arr[mid],arr[l+1])
if (arr[l] > arr[ir]) {
SWAP(arr[l],arr[ir])
}
if (arr[l+1] > arr[ir]) {
SWAP(arr[l+1],arr[ir])
}
if (arr[l] > arr[l+1]) {
SWAP(arr[l],arr[l+1])
}
i = l+1;
j = ir;
a = arr[l+1];
for (;;) {
do i++; while (arr[i] < a);
do j--; while (arr[j] > a);
if (j < i) break;
SWAP(arr[i],arr[j])
}
arr[l+1] = arr[j];
arr[j] = a;
if (j >= k) ir = j-1;
if (j <= k) l = i;
}
}
}
/* ---------------------------------------------------------------------- */
void ComputeCentroAtom::select2(int k, int n, double *arr, int *iarr)
{
int i,ir,j,l,mid,ia,itmp;
double a,tmp;
arr--;
iarr--;
l = 1;
ir = n;
for (;;) {
if (ir <= l+1) {
if (ir == l+1 && arr[ir] < arr[l]) {
SWAP(arr[l],arr[ir])
ISWAP(iarr[l],iarr[ir])
}
return;
} else {
mid=(l+ir) >> 1;
SWAP(arr[mid],arr[l+1])
ISWAP(iarr[mid],iarr[l+1])
if (arr[l] > arr[ir]) {
SWAP(arr[l],arr[ir])
ISWAP(iarr[l],iarr[ir])
}
if (arr[l+1] > arr[ir]) {
SWAP(arr[l+1],arr[ir])
ISWAP(iarr[l+1],iarr[ir])
}
if (arr[l] > arr[l+1]) {
SWAP(arr[l],arr[l+1])
ISWAP(iarr[l],iarr[l+1])
}
i = l+1;
j = ir;
a = arr[l+1];
ia = iarr[l+1];
for (;;) {
do i++; while (arr[i] < a);
do j--; while (arr[j] > a);
if (j < i) break;
SWAP(arr[i],arr[j])
ISWAP(iarr[i],iarr[j])
}
arr[l+1] = arr[j];
arr[j] = a;
iarr[l+1] = iarr[j];
iarr[j] = ia;
if (j >= k) ir = j-1;
if (j <= k) l = i;
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeCentroAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/compute_cluster_atom.cpp b/src/compute_cluster_atom.cpp
index cb42cdbbf..9b8036ad2 100644
--- a/src/compute_cluster_atom.cpp
+++ b/src/compute_cluster_atom.cpp
@@ -1,223 +1,220 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "compute_cluster_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "pair.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
ComputeClusterAtom::ComputeClusterAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal compute cluster/atom command");
+ if (narg != 4) error->all(FLERR,"Illegal compute cluster/atom command");
double cutoff = atof(arg[3]);
cutsq = cutoff*cutoff;
peratom_flag = 1;
size_peratom_cols = 0;
comm_forward = 1;
nmax = 0;
clusterID = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeClusterAtom::~ComputeClusterAtom()
{
memory->destroy(clusterID);
}
/* ---------------------------------------------------------------------- */
void ComputeClusterAtom::init()
{
if (atom->tag_enable == 0)
- error->all("Cannot use compute cluster/atom unless atoms have IDs");
+ error->all(FLERR,"Cannot use compute cluster/atom unless atoms have IDs");
if (force->pair == NULL)
- error->all("Compute cluster/atom requires a pair style be defined");
+ error->all(FLERR,"Compute cluster/atom requires a pair style be defined");
if (sqrt(cutsq) > force->pair->cutforce)
- error->all("Compute cluster/atom cutoff is longer than pairwise cutoff");
+ error->all(FLERR,"Compute cluster/atom cutoff is longer than pairwise cutoff");
// need an occasional full neighbor list
// full required so that pair of atoms on 2 procs both set their clusterID
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"cluster/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute cluster/atom");
+ error->warning(FLERR,"More than one compute cluster/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeClusterAtom::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputeClusterAtom::compute_peratom()
{
int i,j,ii,jj,inum,jnum,n;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *ilist,*jlist,*numneigh,**firstneigh;
invoked_peratom = update->ntimestep;
// grow clusterID array if necessary
if (atom->nlocal+atom->nghost > nmax) {
memory->destroy(clusterID);
nmax = atom->nmax;
memory->create(clusterID,nmax,"cluster/atom:clusterID");
vector_atom = clusterID;
}
// invoke full neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// every atom starts in its own cluster, with clusterID = atomID
int *tag = atom->tag;
int *mask = atom->mask;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit) clusterID[i] = tag[i];
else clusterID[i] = 0;
}
// loop until no more changes on any proc:
// acquire clusterIDs of ghost atoms
// loop over my atoms, checking distance to neighbors
// if both atoms are in cluster, assign lowest clusterID to both
// iterate until no changes in my atoms
// then check if any proc made changes
double **x = atom->x;
int change,done,anychange;
while (1) {
comm->forward_comm_compute(this);
change = 0;
while (1) {
done = 1;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (!(mask[i] & groupbit)) continue;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
n = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
if (!(mask[j] & groupbit)) continue;
if (clusterID[i] == clusterID[j]) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) {
clusterID[i] = clusterID[j] = MIN(clusterID[i],clusterID[j]);
done = 0;
}
}
}
if (!done) change = 1;
if (done) break;
}
// stop if all procs are done
MPI_Allreduce(&change,&anychange,1,MPI_INT,MPI_MAX,world);
if (!anychange) break;
}
}
/* ---------------------------------------------------------------------- */
int ComputeClusterAtom::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = clusterID[j];
}
return 1;
}
/* ---------------------------------------------------------------------- */
void ComputeClusterAtom::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) clusterID[i] = buf[m++];
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeClusterAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/compute_cna_atom.cpp b/src/compute_cna_atom.cpp
index f07ffd6fc..5df5b6891 100644
--- a/src/compute_cna_atom.cpp
+++ b/src/compute_cna_atom.cpp
@@ -1,370 +1,367 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Wan Liang (Chinese Academy of Sciences)
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "compute_cna_atom.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "modify.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
#include "math.h"
using namespace LAMMPS_NS;
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
#define MAXNEAR 16
#define MAXCOMMON 8
enum{UNKNOWN,FCC,HCP,BCC,ICOS,OTHER};
enum{NCOMMON,NBOND,MAXBOND,MINBOND};
/* ---------------------------------------------------------------------- */
ComputeCNAAtom::ComputeCNAAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal compute cna/atom command");
+ if (narg != 4) error->all(FLERR,"Illegal compute cna/atom command");
peratom_flag = 1;
size_peratom_cols = 0;
double cutoff = atof(arg[3]);
- if (cutoff < 0.0) error->all("Illegal compute cna/atom command");
+ if (cutoff < 0.0) error->all(FLERR,"Illegal compute cna/atom command");
cutsq = cutoff*cutoff;
nmax = 0;
nearest = NULL;
nnearest = NULL;
pattern = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeCNAAtom::~ComputeCNAAtom()
{
memory->destroy(nearest);
memory->destroy(nnearest);
memory->destroy(pattern);
}
/* ---------------------------------------------------------------------- */
void ComputeCNAAtom::init()
{
if (force->pair == NULL)
- error->all("Compute cna/atom requires a pair style be defined");
+ error->all(FLERR,"Compute cna/atom requires a pair style be defined");
if (sqrt(cutsq) > force->pair->cutforce)
- error->all("Compute cna/atom cutoff is longer than pairwise cutoff");
+ error->all(FLERR,"Compute cna/atom cutoff is longer than pairwise cutoff");
// cannot use neighbor->cutneighmax b/c neighbor has not yet been init
if (2.0*sqrt(cutsq) > force->pair->cutforce + neighbor->skin &&
comm->me == 0)
- error->warning("Compute cna/atom cutoff may be too large to find "
+ error->warning(FLERR,"Compute cna/atom cutoff may be too large to find "
"ghost atom neighbors");
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"cna/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute cna/atom defined");
+ error->warning(FLERR,"More than one compute cna/atom defined");
// need an occasional full neighbor list
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
}
/* ---------------------------------------------------------------------- */
void ComputeCNAAtom::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputeCNAAtom::compute_peratom()
{
int i,j,k,ii,jj,kk,m,n,inum,jnum,inear,jnear;
int firstflag,ncommon,nbonds,maxbonds,minbonds;
int nfcc,nhcp,nbcc4,nbcc6,nico,cj,ck,cl,cm;
int *ilist,*jlist,*numneigh,**firstneigh;
int cna[MAXNEAR][4],onenearest[MAXNEAR];
int common[MAXCOMMON],bonds[MAXCOMMON];
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
invoked_peratom = update->ntimestep;
// grow arrays if necessary
if (atom->nlocal > nmax) {
memory->destroy(nearest);
memory->destroy(nnearest);
memory->destroy(pattern);
nmax = atom->nmax;
memory->create(nearest,nmax,MAXNEAR,"cna:nearest");
memory->create(nnearest,nmax,"cna:nnearest");
memory->create(pattern,nmax,"cna:cna_pattern");
vector_atom = pattern;
}
// invoke full neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// find the neigbours of each atom within cutoff using full neighbor list
// nearest[] = atom indices of nearest neighbors, up to MAXNEAR
// do this for all atoms, not just compute group
// since CNA calculation requires neighbors of neighbors
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int nerror = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
n = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) {
if (n < MAXNEAR) nearest[i][n++] = j;
else {
nerror++;
break;
}
}
}
nnearest[i] = n;
}
// warning message
int nerrorall;
MPI_Allreduce(&nerror,&nerrorall,1,MPI_INT,MPI_SUM,world);
if (nerrorall && comm->me == 0) {
char str[128];
sprintf(str,"Too many neighbors in CNA for %d atoms",nerrorall);
- error->warning(str,0);
+ error->warning(FLERR,str,0);
}
// compute CNA for each atom in group
// only performed if # of nearest neighbors = 12 or 14 (fcc,hcp)
nerror = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (!(mask[i] & groupbit)) {
pattern[i] = UNKNOWN;
continue;
}
if (nnearest[i] != 12 && nnearest[i] != 14) {
pattern[i] = OTHER;
continue;
}
// loop over near neighbors of I to build cna data structure
// cna[k][NCOMMON] = # of common neighbors of I with each of its neighs
// cna[k][NBONDS] = # of bonds between those common neighbors
// cna[k][MAXBOND] = max # of bonds of any common neighbor
// cna[k][MINBOND] = min # of bonds of any common neighbor
for (m = 0; m < nnearest[i]; m++) {
j = nearest[i][m];
// common = list of neighbors common to atom I and atom J
// if J is an owned atom, use its near neighbor list to find them
// if J is a ghost atom, use full neighbor list of I to find them
// in latter case, must exclude J from I's neighbor list
if (j < nlocal) {
firstflag = 1;
ncommon = 0;
for (inear = 0; inear < nnearest[i]; inear++)
for (jnear = 0; jnear < nnearest[j]; jnear++)
if (nearest[i][inear] == nearest[j][jnear]) {
if (ncommon < MAXCOMMON) common[ncommon++] = nearest[i][inear];
else if (firstflag) {
nerror++;
firstflag = 0;
}
}
} else {
xtmp = x[j][0];
ytmp = x[j][1];
ztmp = x[j][2];
jlist = firstneigh[i];
jnum = numneigh[i];
n = 0;
for (kk = 0; kk < jnum; kk++) {
k = jlist[kk];
k &= NEIGHMASK;
if (k == j) continue;
delx = xtmp - x[k][0];
dely = ytmp - x[k][1];
delz = ztmp - x[k][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) {
if (n < MAXNEAR) onenearest[n++] = k;
else break;
}
}
firstflag = 1;
ncommon = 0;
for (inear = 0; inear < nnearest[i]; inear++)
for (jnear = 0; jnear < n; jnear++)
if (nearest[i][inear] == onenearest[jnear]) {
if (ncommon < MAXCOMMON) common[ncommon++] = nearest[i][inear];
else if (firstflag) {
nerror++;
firstflag = 0;
}
}
}
cna[m][NCOMMON] = ncommon;
// calculate total # of bonds between common neighbor atoms
// also max and min # of common atoms any common atom is bonded to
// bond = pair of atoms within cutoff
for (n = 0; n < ncommon; n++) bonds[n] = 0;
nbonds = 0;
for (jj = 0; jj < ncommon; jj++) {
j = common[jj];
xtmp = x[j][0];
ytmp = x[j][1];
ztmp = x[j][2];
for (kk = jj+1; kk < ncommon; kk++) {
k = common[kk];
delx = xtmp - x[k][0];
dely = ytmp - x[k][1];
delz = ztmp - x[k][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) {
nbonds++;
bonds[jj]++;
bonds[kk]++;
}
}
}
cna[m][NBOND] = nbonds;
maxbonds = 0;
minbonds = MAXCOMMON;
for (n = 0; n < ncommon; n++) {
maxbonds = MAX(bonds[n],maxbonds);
minbonds = MIN(bonds[n],minbonds);
}
cna[m][MAXBOND] = maxbonds;
cna[m][MINBOND] = minbonds;
}
// detect CNA pattern of the atom
nfcc = nhcp = nbcc4 = nbcc6 = nico = 0;
pattern[i] = OTHER;
if (nnearest[i] == 12) {
for (inear = 0; inear < 12; inear++) {
cj = cna[inear][NCOMMON];
ck = cna[inear][NBOND];
cl = cna[inear][MAXBOND];
cm = cna[inear][MINBOND];
if (cj == 4 && ck == 2 && cl == 1 && cm == 1) nfcc++;
else if (cj == 4 && ck == 2 && cl == 2 && cm == 0) nhcp++;
else if (cj == 5 && ck == 5 && cl == 2 && cm == 2) nico++;
}
if (nfcc == 12) pattern[i] = FCC;
else if (nfcc == 6 && nhcp == 6) pattern[i] = HCP;
else if (nico == 12) pattern[i] = ICOS;
} else if (nnearest[i] == 14) {
for (inear = 0; inear < 14; inear++) {
cj = cna[inear][NCOMMON];
ck = cna[inear][NBOND];
cl = cna[inear][MAXBOND];
cm = cna[inear][MINBOND];
if (cj == 4 && ck == 4 && cl == 2 && cm == 2) nbcc4++;
else if (cj == 6 && ck == 6 && cl == 2 && cm == 2) nbcc6++;
}
if (nbcc4 == 6 && nbcc6 == 8) pattern[i] = BCC;
}
}
// warning message
MPI_Allreduce(&nerror,&nerrorall,1,MPI_INT,MPI_SUM,world);
if (nerrorall && comm->me == 0) {
char str[128];
sprintf(str,"Too many common neighbors in CNA %d times",nerrorall);
- error->warning(str);
+ error->warning(FLERR,str);
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeCNAAtom::memory_usage()
{
double bytes = nmax * sizeof(int);
bytes += nmax * MAXNEAR * sizeof(int);
bytes += nmax * sizeof(double);
return bytes;
}
diff --git a/src/compute_com.cpp b/src/compute_com.cpp
index dba4d626b..d0f4296c4 100644
--- a/src/compute_com.cpp
+++ b/src/compute_com.cpp
@@ -1,56 +1,56 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "compute_com.h"
#include "update.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeCOM::ComputeCOM(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute com command");
+ if (narg != 3) error->all(FLERR,"Illegal compute com command");
vector_flag = 1;
size_vector = 3;
extvector = 0;
vector = new double[3];
}
/* ---------------------------------------------------------------------- */
ComputeCOM::~ComputeCOM()
{
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeCOM::init()
{
masstotal = group->mass(igroup);
}
/* ---------------------------------------------------------------------- */
void ComputeCOM::compute_vector()
{
invoked_vector = update->ntimestep;
group->xcm(igroup,masstotal,vector);
}
diff --git a/src/compute_com_molecule.cpp b/src/compute_com_molecule.cpp
index 5218f415a..ad3ba957b 100644
--- a/src/compute_com_molecule.cpp
+++ b/src/compute_com_molecule.cpp
@@ -1,154 +1,154 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "compute_com_molecule.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeCOMMolecule::ComputeCOMMolecule(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute com/molecule command");
+ if (narg != 3) error->all(FLERR,"Illegal compute com/molecule command");
if (atom->molecular == 0)
- error->all("Compute com/molecule requires molecular atom style");
+ error->all(FLERR,"Compute com/molecule requires molecular atom style");
array_flag = 1;
size_array_cols = 3;
extarray = 0;
// setup molecule-based data
nmolecules = molecules_in_group(idlo,idhi);
size_array_rows = nmolecules;
memory->create(massproc,nmolecules,"com/molecule:massproc");
memory->create(masstotal,nmolecules,"com/molecule:masstotal");
memory->create(com,nmolecules,3,"com/molecule:com");
memory->create(comall,nmolecules,3,"com/molecule:comall");
array = comall;
// compute masstotal for each molecule
int *mask = atom->mask;
int *molecule = atom->molecule;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int i,imol;
double massone;
for (i = 0; i < nmolecules; i++) massproc[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
massproc[imol] += massone;
}
MPI_Allreduce(massproc,masstotal,nmolecules,MPI_DOUBLE,MPI_SUM,world);
}
/* ---------------------------------------------------------------------- */
ComputeCOMMolecule::~ComputeCOMMolecule()
{
memory->destroy(massproc);
memory->destroy(masstotal);
memory->destroy(com);
memory->destroy(comall);
}
/* ---------------------------------------------------------------------- */
void ComputeCOMMolecule::init()
{
int ntmp = molecules_in_group(idlo,idhi);
if (ntmp != nmolecules)
- error->all("Molecule count changed in compute com/molecule");
+ error->all(FLERR,"Molecule count changed in compute com/molecule");
}
/* ---------------------------------------------------------------------- */
void ComputeCOMMolecule::compute_array()
{
int i,imol;
double xbox,ybox,zbox;
double massone;
invoked_array = update->ntimestep;
for (i = 0; i < nmolecules; i++)
com[i][0] = com[i][1] = com[i][2] = 0.0;
double **x = atom->x;
int *mask = atom->mask;
int *molecule = atom->molecule;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
com[imol][0] += (x[i][0] + xbox*xprd) * massone;
com[imol][1] += (x[i][1] + ybox*yprd) * massone;
com[imol][2] += (x[i][2] + zbox*zprd) * massone;
}
MPI_Allreduce(&com[0][0],&comall[0][0],3*nmolecules,
MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < nmolecules; i++) {
comall[i][0] /= masstotal[i];
comall[i][1] /= masstotal[i];
comall[i][2] /= masstotal[i];
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeCOMMolecule::memory_usage()
{
double bytes = 2*nmolecules * sizeof(double);
if (molmap) bytes += (idhi-idlo+1) * sizeof(int);
bytes += 2*nmolecules*3 * sizeof(double);
return bytes;
}
diff --git a/src/compute_coord_atom.cpp b/src/compute_coord_atom.cpp
index 5f3c087b3..85fe47ec4 100644
--- a/src/compute_coord_atom.cpp
+++ b/src/compute_coord_atom.cpp
@@ -1,156 +1,156 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "compute_coord_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "force.h"
#include "pair.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeCoordAtom::ComputeCoordAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal compute coord/atom command");
+ if (narg != 4) error->all(FLERR,"Illegal compute coord/atom command");
double cutoff = atof(arg[3]);
cutsq = cutoff*cutoff;
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
coordination = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeCoordAtom::~ComputeCoordAtom()
{
memory->destroy(coordination);
}
/* ---------------------------------------------------------------------- */
void ComputeCoordAtom::init()
{
if (force->pair == NULL)
- error->all("Compute coord/atom requires a pair style be defined");
+ error->all(FLERR,"Compute coord/atom requires a pair style be defined");
if (sqrt(cutsq) > force->pair->cutforce)
- error->all("Compute coord/atom cutoff is longer than pairwise cutoff");
+ error->all(FLERR,"Compute coord/atom cutoff is longer than pairwise cutoff");
// need an occasional full neighbor list
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"coord/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute coord/atom");
+ error->warning(FLERR,"More than one compute coord/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeCoordAtom::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputeCoordAtom::compute_peratom()
{
int i,j,ii,jj,inum,jnum,n;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *ilist,*jlist,*numneigh,**firstneigh;
invoked_peratom = update->ntimestep;
// grow coordination array if necessary
if (atom->nlocal > nmax) {
memory->destroy(coordination);
nmax = atom->nmax;
memory->create(coordination,nmax,"coord/atom:coordination");
vector_atom = coordination;
}
// invoke full neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// compute coordination number for each atom in group
// use full neighbor list to count atoms less than cutoff
double **x = atom->x;
int *mask = atom->mask;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit) {
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
n = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cutsq) n++;
}
coordination[i] = n;
} else coordination[i] = 0.0;
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeCoordAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/compute_dihedral_local.cpp b/src/compute_dihedral_local.cpp
index 361a0f977..621534671 100644
--- a/src/compute_dihedral_local.cpp
+++ b/src/compute_dihedral_local.cpp
@@ -1,235 +1,232 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_dihedral_local.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "domain.h"
#include "force.h"
#include "dihedral.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
-
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-#define SMALL 0.001
+#define SMALL 0.001
/* ---------------------------------------------------------------------- */
ComputeDihedralLocal::ComputeDihedralLocal(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute dihedral/local command");
+ if (narg < 4) error->all(FLERR,"Illegal compute dihedral/local command");
if (atom->avec->dihedrals_allow == 0)
- error->all("Compute dihedral/local used when dihedrals are not allowed");
+ error->all(FLERR,"Compute dihedral/local used when dihedrals are not allowed");
local_flag = 1;
nvalues = narg - 3;
if (nvalues == 1) size_local_cols = 0;
else size_local_cols = nvalues;
pflag = -1;
nvalues = 0;
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"phi") == 0) pflag = nvalues++;
- else error->all("Invalid keyword in compute dihedral/local command");
+ else error->all(FLERR,"Invalid keyword in compute dihedral/local command");
}
nmax = 0;
vector = NULL;
array = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeDihedralLocal::~ComputeDihedralLocal()
{
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputeDihedralLocal::init()
{
if (force->dihedral == NULL)
- error->all("No dihedral style is defined for compute dihedral/local");
+ error->all(FLERR,"No dihedral style is defined for compute dihedral/local");
// do initial memory allocation so that memory_usage() is correct
ncount = compute_dihedrals(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
}
/* ---------------------------------------------------------------------- */
void ComputeDihedralLocal::compute_local()
{
invoked_local = update->ntimestep;
// count local entries and compute dihedral info
ncount = compute_dihedrals(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
ncount = compute_dihedrals(1);
}
/* ----------------------------------------------------------------------
count dihedrals on this proc
only count if 2nd atom is the one storing the dihedral
all atoms in interaction must be in group
all atoms in interaction must be known to proc
if flag is set, compute requested info about dihedral
------------------------------------------------------------------------- */
int ComputeDihedralLocal::compute_dihedrals(int flag)
{
int i,m,n,atom1,atom2,atom3,atom4;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
double s,c;
double *pbuf;
double **x = atom->x;
int *num_dihedral = atom->num_dihedral;
int **dihedral_atom1 = atom->dihedral_atom1;
int **dihedral_atom2 = atom->dihedral_atom2;
int **dihedral_atom3 = atom->dihedral_atom3;
int **dihedral_atom4 = atom->dihedral_atom4;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (flag) {
if (nvalues == 1) {
if (pflag >= 0) pbuf = vector;
} else {
if (pflag >= 0) pbuf = &array[0][pflag];
}
}
double PI = 4.0*atan(1.0);
m = n = 0;
for (atom2 = 0; atom2 < nlocal; atom2++) {
if (!(mask[atom2] & groupbit)) continue;
for (i = 0; i < num_dihedral[atom2]; i++) {
if (tag[atom2] != dihedral_atom2[atom2][i]) continue;
atom1 = atom->map(dihedral_atom1[atom2][i]);
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
atom3 = atom->map(dihedral_atom3[atom2][i]);
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
atom4 = atom->map(dihedral_atom4[atom2][i]);
if (atom4 < 0 || !(mask[atom4] & groupbit)) continue;
if (flag) {
// phi calculation from dihedral style harmonic
if (pflag >= 0) {
vb1x = x[atom1][0] - x[atom2][0];
vb1y = x[atom1][1] - x[atom2][1];
vb1z = x[atom1][2] - x[atom2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
vb2x = x[atom3][0] - x[atom2][0];
vb2y = x[atom3][1] - x[atom2][1];
vb2z = x[atom3][2] - x[atom2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
vb3x = x[atom4][0] - x[atom3][0];
vb3y = x[atom4][1] - x[atom3][1];
vb3z = x[atom4][2] - x[atom3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
ax = vb1y*vb2zm - vb1z*vb2ym;
ay = vb1z*vb2xm - vb1x*vb2zm;
az = vb1x*vb2ym - vb1y*vb2xm;
bx = vb3y*vb2zm - vb3z*vb2ym;
by = vb3z*vb2xm - vb3x*vb2zm;
bz = vb3x*vb2ym - vb3y*vb2xm;
rasq = ax*ax + ay*ay + az*az;
rbsq = bx*bx + by*by + bz*bz;
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
rg = sqrt(rgsq);
rginv = ra2inv = rb2inv = 0.0;
if (rg > 0) rginv = 1.0/rg;
if (rasq > 0) ra2inv = 1.0/rasq;
if (rbsq > 0) rb2inv = 1.0/rbsq;
rabinv = sqrt(ra2inv*rb2inv);
c = (ax*bx + ay*by + az*bz)*rabinv;
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
pbuf[n] = 180.0*atan2(s,c)/PI;
}
n += nvalues;
}
m++;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void ComputeDihedralLocal::reallocate(int n)
{
// grow vector or array and indices array
while (nmax < n) nmax += DELTA;
if (nvalues == 1) {
memory->destroy(vector);
memory->create(vector,nmax,"bond/local:vector");
vector_local = vector;
} else {
memory->destroy(array);
memory->create(array,nmax,nvalues,"bond/local:array");
array_local = array;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeDihedralLocal::memory_usage()
{
double bytes = nmax*nvalues * sizeof(double);
return bytes;
}
diff --git a/src/compute_displace_atom.cpp b/src/compute_displace_atom.cpp
index fbd828be5..59370ea83 100644
--- a/src/compute_displace_atom.cpp
+++ b/src/compute_displace_atom.cpp
@@ -1,160 +1,160 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_displace_atom.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeDisplaceAtom::ComputeDisplaceAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute displace/atom command");
+ if (narg != 3) error->all(FLERR,"Illegal compute displace/atom command");
peratom_flag = 1;
size_peratom_cols = 4;
// create a new fix store/state style
// id = compute-ID + store_state, fix group = compute group
int n = strlen(id) + strlen("_store_state") + 1;
id_fix = new char[n];
strcpy(id_fix,id);
strcat(id_fix,"_store_state");
char **newarg = new char*[7];
newarg[0] = id_fix;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "store/state";
newarg[3] = (char *) "0";
newarg[4] = (char *) "xu";
newarg[5] = (char *) "yu";
newarg[6] = (char *) "zu";
modify->add_fix(7,newarg);
delete [] newarg;
nmax = 0;
displace = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeDisplaceAtom::~ComputeDisplaceAtom()
{
// check nfix in case all fixes have already been deleted
if (modify->nfix) modify->delete_fix(id_fix);
delete [] id_fix;
memory->destroy(displace);
}
/* ---------------------------------------------------------------------- */
void ComputeDisplaceAtom::init()
{
// set fix which stores original atom coords
int ifix = modify->find_fix(id_fix);
- if (ifix < 0) error->all("Could not find compute displace/atom fix ID");
+ if (ifix < 0) error->all(FLERR,"Could not find compute displace/atom fix ID");
fix = modify->fix[ifix];
}
/* ---------------------------------------------------------------------- */
void ComputeDisplaceAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow local displacement array if necessary
if (atom->nlocal > nmax) {
memory->destroy(displace);
nmax = atom->nmax;
memory->create(displace,nmax,4,"displace/atom:displace");
array_atom = displace;
}
// dx,dy,dz = displacement of atom from original position
// original unwrapped position is stored by fix
// for triclinic, need to unwrap current atom coord via h matrix
double **xoriginal = fix->array_atom;
double **x = atom->x;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
double *h = domain->h;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
double dx,dy,dz;
if (domain->triclinic == 0) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xoriginal[i][0];
dy = x[i][1] + ybox*yprd - xoriginal[i][1];
dz = x[i][2] + zbox*zprd - xoriginal[i][2];
displace[i][0] = dx;
displace[i][1] = dy;
displace[i][2] = dz;
displace[i][3] = sqrt(dx*dx + dy*dy + dz*dz);
} else displace[i][0] = displace[i][1] =
displace[i][2] = displace[i][3] = 0.0;
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox - xoriginal[i][0];
dy = x[i][1] + h[1]*ybox + h[3]*zbox - xoriginal[i][1];
dz = x[i][2] + h[2]*zbox - xoriginal[i][2];
displace[i][0] = dx;
displace[i][1] = dy;
displace[i][2] = dz;
displace[i][3] = sqrt(dx*dx + dy*dy + dz*dz);
} else displace[i][0] = displace[i][1] =
displace[i][2] = displace[i][3] = 0.0;
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeDisplaceAtom::memory_usage()
{
double bytes = nmax*4 * sizeof(double);
return bytes;
}
diff --git a/src/compute_erotate_sphere.cpp b/src/compute_erotate_sphere.cpp
index 1aa5ad8d9..47bee4089 100644
--- a/src/compute_erotate_sphere.cpp
+++ b/src/compute_erotate_sphere.cpp
@@ -1,75 +1,75 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "compute_erotate_sphere.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
#define INERTIA 0.4 // moment of inertia prefactor for sphere
/* ---------------------------------------------------------------------- */
ComputeERotateSphere::ComputeERotateSphere(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute erotate/sphere command");
+ if (narg != 3) error->all(FLERR,"Illegal compute erotate/sphere command");
scalar_flag = 1;
extscalar = 1;
// error check
if (!atom->sphere_flag)
- error->all("Compute erotate/sphere requires atom style sphere");
+ error->all(FLERR,"Compute erotate/sphere requires atom style sphere");
}
/* ---------------------------------------------------------------------- */
void ComputeERotateSphere::init()
{
pfactor = 0.5 * force->mvv2e * INERTIA;
}
/* ---------------------------------------------------------------------- */
double ComputeERotateSphere::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **omega = atom->omega;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// sum rotational energy for each particle
// point particles will not contribute due to radius = 0
double erotate = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
erotate += (omega[i][0]*omega[i][0] + omega[i][1]*omega[i][1] +
omega[i][2]*omega[i][2]) * radius[i]*radius[i]*rmass[i];
MPI_Allreduce(&erotate,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
scalar *= pfactor;
return scalar;
}
diff --git a/src/compute_group_group.cpp b/src/compute_group_group.cpp
index ebbfe16d9..5393fae0b 100644
--- a/src/compute_group_group.cpp
+++ b/src/compute_group_group.cpp
@@ -1,216 +1,216 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Naveen Michaud-Agrawal (Johns Hopkins U)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_group_group.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "neigh_list.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeGroupGroup::ComputeGroupGroup(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal compute group/group command");
+ if (narg != 4) error->all(FLERR,"Illegal compute group/group command");
scalar_flag = vector_flag = 1;
size_vector = 3;
extscalar = 1;
extvector = 1;
int n = strlen(arg[3]) + 1;
group2 = new char[n];
strcpy(group2,arg[3]);
jgroup = group->find(group2);
- if (jgroup == -1) error->all("Compute group/group group ID does not exist");
+ if (jgroup == -1) error->all(FLERR,"Compute group/group group ID does not exist");
jgroupbit = group->bitmask[jgroup];
vector = new double[3];
}
/* ---------------------------------------------------------------------- */
ComputeGroupGroup::~ComputeGroupGroup()
{
delete [] group2;
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeGroupGroup::init()
{
if (force->pair == NULL)
- error->all("No pair style defined for compute group/group");
+ error->all(FLERR,"No pair style defined for compute group/group");
// if non-hybrid, then error if single_enable = 0
// if hybrid, let hybrid determine if sub-style sets single_enable = 0
if (force->pair_match("hybrid",0) == NULL && force->pair->single_enable == 0)
- error->all("Pair style does not support compute group/group");
+ error->all(FLERR,"Pair style does not support compute group/group");
pair = force->pair;
cutsq = force->pair->cutsq;
// recheck that group 2 has not been deleted
jgroup = group->find(group2);
- if (jgroup == -1) error->all("Compute group/group group ID does not exist");
+ if (jgroup == -1) error->all(FLERR,"Compute group/group group ID does not exist");
jgroupbit = group->bitmask[jgroup];
// need an occasional half neighbor list
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->occasional = 1;
}
/* ---------------------------------------------------------------------- */
void ComputeGroupGroup::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
double ComputeGroupGroup::compute_scalar()
{
invoked_scalar = invoked_vector = update->ntimestep;
interact();
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeGroupGroup::compute_vector()
{
invoked_scalar = invoked_vector = update->ntimestep;
interact();
}
/* ---------------------------------------------------------------------- */
void ComputeGroupGroup::interact()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz;
double rsq,eng,fpair,factor_coul,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
// invoke half neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
// skip if I,J are not in 2 groups
double one[4],all[4];
one[0] = one[1] = one[2] = one[3] = 0.0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (mask[i] & groupbit) othergroupbit = jgroupbit;
else if (mask[i] & jgroupbit) othergroupbit = groupbit;
else continue;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
if (!(mask[j] & othergroupbit)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
eng = pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,fpair);
// energy only computed once so tally full amount
// force tally is jgroup acting on igroup
if (newton_pair || j < nlocal) {
one[0] += eng;
if (othergroupbit == jgroupbit) {
one[1] += delx*fpair;
one[2] += dely*fpair;
one[3] += delz*fpair;
}
if (othergroupbit == groupbit) {
one[1] -= delx*fpair;
one[2] -= dely*fpair;
one[3] -= delz*fpair;
}
// energy computed twice so tally half amount
// only tally force if I own igroup atom
} else {
one[0] += 0.5*eng;
if (othergroupbit == jgroupbit) {
one[1] += delx*fpair;
one[2] += dely*fpair;
one[3] += delz*fpair;
}
}
}
}
}
MPI_Allreduce(one,all,4,MPI_DOUBLE,MPI_SUM,world);
scalar = all[0];
vector[0] = all[1]; vector[1] = all[2]; vector[2] = all[3];
}
diff --git a/src/compute_gyration.cpp b/src/compute_gyration.cpp
index de2ebf8f1..f192ea3d6 100644
--- a/src/compute_gyration.cpp
+++ b/src/compute_gyration.cpp
@@ -1,49 +1,49 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "compute_gyration.h"
#include "update.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeGyration::ComputeGyration(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute gyration command");
+ if (narg != 3) error->all(FLERR,"Illegal compute gyration command");
scalar_flag = 1;
extscalar = 0;
}
/* ---------------------------------------------------------------------- */
void ComputeGyration::init()
{
masstotal = group->mass(igroup);
}
/* ---------------------------------------------------------------------- */
double ComputeGyration::compute_scalar()
{
invoked_scalar = update->ntimestep;
double xcm[3];
group->xcm(igroup,masstotal,xcm);
scalar = group->gyration(igroup,masstotal,xcm);
return scalar;
}
diff --git a/src/compute_gyration_molecule.cpp b/src/compute_gyration_molecule.cpp
index 80fdca5fa..dd96079d2 100644
--- a/src/compute_gyration_molecule.cpp
+++ b/src/compute_gyration_molecule.cpp
@@ -1,181 +1,181 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "compute_gyration_molecule.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeGyrationMolecule::ComputeGyrationMolecule(LAMMPS *lmp,
int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute gyration/molecule command");
+ if (narg != 3) error->all(FLERR,"Illegal compute gyration/molecule command");
if (atom->molecular == 0)
- error->all("Compute gyration/molecule requires molecular atom style");
+ error->all(FLERR,"Compute gyration/molecule requires molecular atom style");
vector_flag = 1;
extvector = 0;
// setup molecule-based data
nmolecules = molecules_in_group(idlo,idhi);
size_vector = nmolecules;
memory->create(massproc,nmolecules,"gyration/molecule:massproc");
memory->create(masstotal,nmolecules,"gyration/molecule:masstotal");
memory->create(com,nmolecules,3,"gyration/molecule:com");
memory->create(comall,nmolecules,3,"gyration/molecule:comall");
memory->create(rg,nmolecules,"gyration/molecule:rg");
memory->create(rgall,nmolecules,"gyration/molecule:rgall");
vector = rgall;
// compute masstotal for each molecule
int *mask = atom->mask;
int *molecule = atom->molecule;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int i,imol;
double massone;
for (i = 0; i < nmolecules; i++) massproc[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
massproc[imol] += massone;
}
MPI_Allreduce(massproc,masstotal,nmolecules,MPI_DOUBLE,MPI_SUM,world);
}
/* ---------------------------------------------------------------------- */
ComputeGyrationMolecule::~ComputeGyrationMolecule()
{
memory->destroy(massproc);
memory->destroy(masstotal);
memory->destroy(com);
memory->destroy(comall);
memory->destroy(rg);
memory->destroy(rgall);
}
/* ---------------------------------------------------------------------- */
void ComputeGyrationMolecule::init()
{
int ntmp = molecules_in_group(idlo,idhi);
if (ntmp != nmolecules)
- error->all("Molecule count changed in compute gyration/molecule");
+ error->all(FLERR,"Molecule count changed in compute gyration/molecule");
}
/* ---------------------------------------------------------------------- */
void ComputeGyrationMolecule::compute_vector()
{
int i,imol;
double xbox,ybox,zbox,dx,dy,dz;
double massone;
invoked_array = update->ntimestep;
for (i = 0; i < nmolecules; i++)
com[i][0] = com[i][1] = com[i][2] = 0.0;
double **x = atom->x;
int *mask = atom->mask;
int *molecule = atom->molecule;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
com[imol][0] += (x[i][0] + xbox*xprd) * massone;
com[imol][1] += (x[i][1] + ybox*yprd) * massone;
com[imol][2] += (x[i][2] + zbox*zprd) * massone;
}
MPI_Allreduce(&com[0][0],&comall[0][0],3*nmolecules,
MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < nmolecules; i++) {
comall[i][0] /= masstotal[i];
comall[i][1] /= masstotal[i];
comall[i][2] /= masstotal[i];
}
for (i = 0; i < nmolecules; i++) rg[i] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
dx = (x[i][0] + xbox*xprd) - comall[imol][0];
dy = (x[i][1] + ybox*yprd) - comall[imol][1];
dz = (x[i][2] + zbox*zprd) - comall[imol][2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
rg[imol] += (dx*dx + dy*dy + dz*dz) * massone;
}
MPI_Allreduce(rg,rgall,nmolecules,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < nmolecules; i++) rgall[i] = sqrt(rgall[i]/masstotal[i]);
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeGyrationMolecule::memory_usage()
{
double bytes = 4*nmolecules * sizeof(double);
if (molmap) bytes += (idhi-idlo+1) * sizeof(int);
bytes += 2*nmolecules*3 * sizeof(double);
return bytes;
}
diff --git a/src/compute_heat_flux.cpp b/src/compute_heat_flux.cpp
index 28be7c594..f5a38a565 100644
--- a/src/compute_heat_flux.cpp
+++ b/src/compute_heat_flux.cpp
@@ -1,167 +1,167 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: German Samolyuk (ORNL) and
Mario Pinto (Computational Research Lab, Pune, India)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_heat_flux.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "force.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
#define INVOKED_PERATOM 8
/* ---------------------------------------------------------------------- */
ComputeHeatFlux::ComputeHeatFlux(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal compute heat/flux command");
+ if (narg != 6) error->all(FLERR,"Illegal compute heat/flux command");
vector_flag = 1;
size_vector = 6;
extvector = 1;
// store ke/atom, pe/atom, stress/atom IDs used by heat flux computation
// insure they are valid for these computations
int n = strlen(arg[3]) + 1;
id_ke = new char[n];
strcpy(id_ke,arg[3]);
n = strlen(arg[4]) + 1;
id_pe = new char[n];
strcpy(id_pe,arg[4]);
n = strlen(arg[5]) + 1;
id_stress = new char[n];
strcpy(id_stress,arg[5]);
int ike = modify->find_compute(id_ke);
int ipe = modify->find_compute(id_pe);
int istress = modify->find_compute(id_stress);
if (ike < 0 || ipe < 0 || istress < 0)
- error->all("Could not find compute heat/flux compute ID");
+ error->all(FLERR,"Could not find compute heat/flux compute ID");
if (strcmp(modify->compute[ike]->style,"ke/atom") != 0)
- error->all("Compute heat/flux compute ID does not compute ke/atom");
+ error->all(FLERR,"Compute heat/flux compute ID does not compute ke/atom");
if (modify->compute[ipe]->peatomflag == 0)
- error->all("Compute heat/flux compute ID does not compute pe/atom");
+ error->all(FLERR,"Compute heat/flux compute ID does not compute pe/atom");
if (modify->compute[istress]->pressatomflag == 0)
- error->all("Compute heat/flux compute ID does not compute stress/atom");
+ error->all(FLERR,"Compute heat/flux compute ID does not compute stress/atom");
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeHeatFlux::~ComputeHeatFlux()
{
delete [] id_ke;
delete [] id_pe;
delete [] id_stress;
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeHeatFlux::init()
{
// error checks
int ike = modify->find_compute(id_ke);
int ipe = modify->find_compute(id_pe);
int istress = modify->find_compute(id_stress);
if (ike < 0 || ipe < 0 || istress < 0)
- error->all("Could not find compute heat/flux compute ID");
+ error->all(FLERR,"Could not find compute heat/flux compute ID");
c_ke = modify->compute[ike];
c_pe = modify->compute[ipe];
c_stress = modify->compute[istress];
}
/* ---------------------------------------------------------------------- */
void ComputeHeatFlux::compute_vector()
{
invoked_vector = update->ntimestep;
// invoke 3 computes if they haven't been already
if (!(c_ke->invoked_flag & INVOKED_PERATOM)) {
c_ke->compute_peratom();
c_ke->invoked_flag |= INVOKED_PERATOM;
}
if (!(c_pe->invoked_flag & INVOKED_PERATOM)) {
c_pe->compute_peratom();
c_pe->invoked_flag |= INVOKED_PERATOM;
}
if (!(c_stress->invoked_flag & INVOKED_PERATOM)) {
c_stress->compute_peratom();
c_stress->invoked_flag |= INVOKED_PERATOM;
}
// heat flux vector = jc[3] + jv[3]
// jc[3] = convective portion of heat flux = sum_i (ke_i + pe_i) v_i[3]
// jv[3] = virial portion of heat flux = sum_i (stress_tensor_i . v_i[3])
// normalization by volume is not included
double *ke = c_ke->vector_atom;
double *pe = c_pe->vector_atom;
double **stress = c_stress->array_atom;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double jc[3] = {0.0,0.0,0.0};
double jv[3] = {0.0,0.0,0.0};
double eng;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
eng = pe[i] + ke[i];
jc[0] += eng*v[i][0];
jc[1] += eng*v[i][1];
jc[2] += eng*v[i][2];
jv[0] -= stress[i][0]*v[i][0] + stress[i][3]*v[i][1] +
stress[i][4]*v[i][2];
jv[1] -= stress[i][3]*v[i][0] + stress[i][1]*v[i][1] +
stress[i][5]*v[i][2];
jv[2] -= stress[i][4]*v[i][0] + stress[i][5]*v[i][1] +
stress[i][2]*v[i][2];
}
}
// convert jv from stress*volume to energy units via nktv2p factor
double nktv2p = force->nktv2p;
jv[0] /= nktv2p;
jv[1] /= nktv2p;
jv[2] /= nktv2p;
// sum across all procs
// 1st 3 terms are total heat flux
// 2nd 3 terms are just conductive portion
double data[6] = {jc[0]+jv[0],jc[1]+jv[1],jc[2]+jv[2],jc[0],jc[1],jc[2]};
MPI_Allreduce(data,vector,6,MPI_DOUBLE,MPI_SUM,world);
}
diff --git a/src/compute_improper_local.cpp b/src/compute_improper_local.cpp
index 65e4ec1cc..7162277c3 100644
--- a/src/compute_improper_local.cpp
+++ b/src/compute_improper_local.cpp
@@ -1,230 +1,230 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_improper_local.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "domain.h"
#include "force.h"
#include "improper.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
#define SMALL 0.001
/* ---------------------------------------------------------------------- */
ComputeImproperLocal::ComputeImproperLocal(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute improper/local command");
+ if (narg < 4) error->all(FLERR,"Illegal compute improper/local command");
if (atom->avec->impropers_allow == 0)
- error->all("Compute improper/local used when impropers are not allowed");
+ error->all(FLERR,"Compute improper/local used when impropers are not allowed");
local_flag = 1;
nvalues = narg - 3;
if (nvalues == 1) size_local_cols = 0;
else size_local_cols = nvalues;
cflag = -1;
nvalues = 0;
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"chi") == 0) cflag = nvalues++;
- else error->all("Invalid keyword in compute improper/local command");
+ else error->all(FLERR,"Invalid keyword in compute improper/local command");
}
nmax = 0;
vector = NULL;
array = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeImproperLocal::~ComputeImproperLocal()
{
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputeImproperLocal::init()
{
if (force->improper == NULL)
- error->all("No improper style is defined for compute improper/local");
+ error->all(FLERR,"No improper style is defined for compute improper/local");
// do initial memory allocation so that memory_usage() is correct
ncount = compute_impropers(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
}
/* ---------------------------------------------------------------------- */
void ComputeImproperLocal::compute_local()
{
invoked_local = update->ntimestep;
// count local entries and compute improper info
ncount = compute_impropers(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
ncount = compute_impropers(1);
}
/* ----------------------------------------------------------------------
count impropers on this proc
only count if 2nd atom is the one storing the improper
all atoms in interaction must be in group
all atoms in interaction must be known to proc
if flag is set, compute requested info about improper
------------------------------------------------------------------------- */
int ComputeImproperLocal::compute_impropers(int flag)
{
int i,m,n,atom1,atom2,atom3,atom4;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z;
double ss1,ss2,ss3,r1,r2,r3,c0,c1,c2,s1,s2;
double s12,c;
double *cbuf;
double **x = atom->x;
int *num_improper = atom->num_improper;
int **improper_atom1 = atom->improper_atom1;
int **improper_atom2 = atom->improper_atom2;
int **improper_atom3 = atom->improper_atom3;
int **improper_atom4 = atom->improper_atom4;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (flag) {
if (nvalues == 1) {
if (cflag >= 0) cbuf = vector;
} else {
if (cflag >= 0) cbuf = &array[0][cflag];
}
}
double PI = 4.0*atan(1.0);
m = n = 0;
for (atom2 = 0; atom2 < nlocal; atom2++) {
if (!(mask[atom2] & groupbit)) continue;
for (i = 0; i < num_improper[atom2]; i++) {
if (tag[atom2] != improper_atom2[atom2][i]) continue;
atom1 = atom->map(improper_atom1[atom2][i]);
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
atom3 = atom->map(improper_atom3[atom2][i]);
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
atom4 = atom->map(improper_atom4[atom2][i]);
if (atom4 < 0 || !(mask[atom4] & groupbit)) continue;
if (flag) {
// chi calculation from improper style harmonic
if (cflag >= 0) {
vb1x = x[atom1][0] - x[atom2][0];
vb1y = x[atom1][1] - x[atom2][1];
vb1z = x[atom1][2] - x[atom2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
vb2x = x[atom3][0] - x[atom2][0];
vb2y = x[atom3][1] - x[atom2][1];
vb2z = x[atom3][2] - x[atom2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb3x = x[atom4][0] - x[atom3][0];
vb3y = x[atom4][1] - x[atom3][1];
vb3z = x[atom4][2] - x[atom3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
ss1 = 1.0 / (vb1x*vb1x + vb1y*vb1y + vb1z*vb1z);
ss2 = 1.0 / (vb2x*vb2x + vb2y*vb2y + vb2z*vb2z);
ss3 = 1.0 / (vb3x*vb3x + vb3y*vb3y + vb3z*vb3z);
r1 = sqrt(ss1);
r2 = sqrt(ss2);
r3 = sqrt(ss3);
c0 = (vb1x * vb3x + vb1y * vb3y + vb1z * vb3z) * r1 * r3;
c1 = (vb1x * vb2x + vb1y * vb2y + vb1z * vb2z) * r1 * r2;
c2 = -(vb3x * vb2x + vb3y * vb2y + vb3z * vb2z) * r3 * r2;
s1 = 1.0 - c1*c1;
if (s1 < SMALL) s1 = SMALL;
s1 = 1.0 / s1;
s2 = 1.0 - c2*c2;
if (s2 < SMALL) s2 = SMALL;
s2 = 1.0 / s2;
s12 = sqrt(s1*s2);
c = (c1*c2 + c0) * s12;
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
cbuf[n] = 180.0*acos(c)/PI;
}
n += nvalues;
}
m++;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void ComputeImproperLocal::reallocate(int n)
{
// grow vector or array and indices array
while (nmax < n) nmax += DELTA;
if (nvalues == 1) {
memory->destroy(vector);
memory->create(vector,nmax,"bond/local:vector");
vector_local = vector;
} else {
memory->destroy(array);
memory->create(array,nmax,nvalues,"bond/local:array");
array_local = array;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeImproperLocal::memory_usage()
{
double bytes = nmax*nvalues * sizeof(double);
return bytes;
}
diff --git a/src/compute_ke.cpp b/src/compute_ke.cpp
index 2db20db76..629f1488e 100644
--- a/src/compute_ke.cpp
+++ b/src/compute_ke.cpp
@@ -1,72 +1,72 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "compute_ke.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeKE::ComputeKE(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute ke command");
+ if (narg != 3) error->all(FLERR,"Illegal compute ke command");
scalar_flag = 1;
extscalar = 1;
}
/* ---------------------------------------------------------------------- */
void ComputeKE::init()
{
pfactor = 0.5 * force->mvv2e;
}
/* ---------------------------------------------------------------------- */
double ComputeKE::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **v = atom->v;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double ke = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
ke += rmass[i] * (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
ke += mass[type[i]] *
(v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
}
MPI_Allreduce(&ke,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
scalar *= pfactor;
return scalar;
}
diff --git a/src/compute_ke_atom.cpp b/src/compute_ke_atom.cpp
index 0d6fc2d9c..6d9d45268 100644
--- a/src/compute_ke_atom.cpp
+++ b/src/compute_ke_atom.cpp
@@ -1,108 +1,108 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_ke_atom.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "comm.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeKEAtom::ComputeKEAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute ke/atom command");
+ if (narg != 3) error->all(FLERR,"Illegal compute ke/atom command");
peratom_flag = 1;
size_peratom_cols = 0;
nmax = 0;
ke = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeKEAtom::~ComputeKEAtom()
{
memory->destroy(ke);
}
/* ---------------------------------------------------------------------- */
void ComputeKEAtom::init()
{
int count = 0;
for (int i = 0; i < modify->ncompute; i++)
if (strcmp(modify->compute[i]->style,"ke/atom") == 0) count++;
if (count > 1 && comm->me == 0)
- error->warning("More than one compute ke/atom");
+ error->warning(FLERR,"More than one compute ke/atom");
}
/* ---------------------------------------------------------------------- */
void ComputeKEAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow ke array if necessary
if (atom->nlocal > nmax) {
memory->destroy(ke);
nmax = atom->nmax;
memory->create(ke,nmax,"ke/atom:ke");
vector_atom = ke;
}
// compute kinetic energy for each atom in group
double mvv2e = force->mvv2e;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
if (rmass)
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
ke[i] = 0.5 * mvv2e * rmass[i] *
(v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
} else ke[i] = 0.0;
}
else
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
ke[i] = 0.5 * mvv2e * mass[type[i]] *
(v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]);
} else ke[i] = 0.0;
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeKEAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/compute_msd.cpp b/src/compute_msd.cpp
index 3fcb99e89..bf2d00332 100644
--- a/src/compute_msd.cpp
+++ b/src/compute_msd.cpp
@@ -1,189 +1,189 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_msd.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeMSD::ComputeMSD(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal compute msd command");
+ if (narg < 3) error->all(FLERR,"Illegal compute msd command");
vector_flag = 1;
size_vector = 4;
extvector = 0;
// optional args
comflag = 0;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"com") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute msd command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute msd command");
if (strcmp(arg[iarg+1],"no") == 0) comflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) comflag = 1;
- else error->all("Illegal compute msd command");
+ else error->all(FLERR,"Illegal compute msd command");
iarg += 2;
- } else error->all("Illegal compute msd command");
+ } else error->all(FLERR,"Illegal compute msd command");
}
// create a new fix store/state style with or without com keyword
// id = compute-ID + store_state, fix group = compute group
int n = strlen(id) + strlen("_store_state") + 1;
id_fix = new char[n];
strcpy(id_fix,id);
strcat(id_fix,"_store_state");
char **newarg = new char*[9];
newarg[0] = id_fix;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "store/state";
newarg[3] = (char *) "0";
newarg[4] = (char *) "xu";
newarg[5] = (char *) "yu";
newarg[6] = (char *) "zu";
newarg[7] = (char *) "com";
newarg[8] = (char *) "yes";
if (comflag) modify->add_fix(9,newarg);
else modify->add_fix(7,newarg);
delete [] newarg;
vector = new double[4];
}
/* ---------------------------------------------------------------------- */
ComputeMSD::~ComputeMSD()
{
// check nfix in case all fixes have already been deleted
if (modify->nfix) modify->delete_fix(id_fix);
delete [] id_fix;
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeMSD::init()
{
// set fix which stores original atom coords
int ifix = modify->find_fix(id_fix);
- if (ifix < 0) error->all("Could not find compute msd fix ID");
+ if (ifix < 0) error->all(FLERR,"Could not find compute msd fix ID");
fix = modify->fix[ifix];
// nmsd = # of atoms in group
int *mask = atom->mask;
int nlocal = atom->nlocal;
nmsd = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) nmsd++;
int nmsd_all;
MPI_Allreduce(&nmsd,&nmsd_all,1,MPI_INT,MPI_SUM,world);
nmsd = nmsd_all;
masstotal = group->mass(igroup);
}
/* ---------------------------------------------------------------------- */
void ComputeMSD::compute_vector()
{
invoked_vector = update->ntimestep;
// cm = current center of mass
double cm[3];
if (comflag) group->xcm(igroup,masstotal,cm);
else cm[0] = cm[1] = cm[2] = 0.0;
// dx,dy,dz = displacement of atom from original position
// original unwrapped position is stored by fix
// relative to center of mass if comflag is set
// for triclinic, need to unwrap current atom coord via h matrix
double **xoriginal = fix->array_atom;
double **x = atom->x;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
double *h = domain->h;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double dx,dy,dz;
int xbox,ybox,zbox;
double msd[4];
msd[0] = msd[1] = msd[2] = msd[3] = 0.0;
if (domain->triclinic == 0) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - cm[0] - xoriginal[i][0];
dy = x[i][1] + ybox*yprd - cm[1] - xoriginal[i][1];
dz = x[i][2] + zbox*zprd - cm[2] - xoriginal[i][2];
msd[0] += dx*dx;
msd[1] += dy*dy;
msd[2] += dz*dz;
msd[3] += dx*dx + dy*dy + dz*dz;
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox -
cm[0] - xoriginal[i][0];
dy = x[i][1] + h[1]*ybox + h[3]*zbox - cm[1] - xoriginal[i][1];
dz = x[i][2] + h[2]*zbox - cm[2] - xoriginal[i][2];
msd[0] += dx*dx;
msd[1] += dy*dy;
msd[2] += dz*dz;
msd[3] += dx*dx + dy*dy + dz*dz;
}
}
MPI_Allreduce(msd,vector,4,MPI_DOUBLE,MPI_SUM,world);
if (nmsd) {
vector[0] /= nmsd;
vector[1] /= nmsd;
vector[2] /= nmsd;
vector[3] /= nmsd;
}
}
diff --git a/src/compute_msd_molecule.cpp b/src/compute_msd_molecule.cpp
index a4ad8b021..de8d2f63c 100644
--- a/src/compute_msd_molecule.cpp
+++ b/src/compute_msd_molecule.cpp
@@ -1,187 +1,187 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "compute_msd_molecule.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeMSDMolecule::ComputeMSDMolecule(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute msd/molecule command");
+ if (narg != 3) error->all(FLERR,"Illegal compute msd/molecule command");
if (atom->molecular == 0)
- error->all("Compute msd/molecule requires molecular atom style");
+ error->all(FLERR,"Compute msd/molecule requires molecular atom style");
array_flag = 1;
size_array_cols = 4;
extarray = 0;
// setup molecule-based data and initial COM positions
nmolecules = molecules_in_group(idlo,idhi);
size_array_rows = nmolecules;
memory->create(massproc,nmolecules,"msd/molecule:massproc");
memory->create(masstotal,nmolecules,"msd/molecule:masstotal");
memory->create(com,nmolecules,3,"msd/molecule:com");
memory->create(comall,nmolecules,3,"msd/molecule:comall");
memory->create(cominit,nmolecules,3,"msd/molecule:cominit");
memory->create(msd,nmolecules,4,"msd/molecule:msd");
array = msd;
// compute masstotal for each molecule
int *mask = atom->mask;
int *molecule = atom->molecule;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int i,imol;
double massone;
for (i = 0; i < nmolecules; i++) massproc[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
massproc[imol] += massone;
}
MPI_Allreduce(massproc,masstotal,nmolecules,MPI_DOUBLE,MPI_SUM,world);
// compute initial COM for each molecule
firstflag = 1;
compute_array();
for (i = 0; i < nmolecules; i++) {
cominit[i][0] = comall[i][0];
cominit[i][1] = comall[i][1];
cominit[i][2] = comall[i][2];
}
firstflag = 0;
}
/* ---------------------------------------------------------------------- */
ComputeMSDMolecule::~ComputeMSDMolecule()
{
memory->destroy(massproc);
memory->destroy(masstotal);
memory->destroy(com);
memory->destroy(comall);
memory->destroy(cominit);
memory->destroy(msd);
}
/* ---------------------------------------------------------------------- */
void ComputeMSDMolecule::init()
{
int ntmp = molecules_in_group(idlo,idhi);
if (ntmp != nmolecules)
- error->all("Molecule count changed in compute msd/molecule");
+ error->all(FLERR,"Molecule count changed in compute msd/molecule");
}
/* ---------------------------------------------------------------------- */
void ComputeMSDMolecule::compute_array()
{
int i,imol;
double xbox,ybox,zbox,dx,dy,dz;
double massone;
invoked_array = update->ntimestep;
// compute current COM positions
for (i = 0; i < nmolecules; i++)
com[i][0] = com[i][1] = com[i][2] = 0.0;
double **x = atom->x;
int *mask = atom->mask;
int *molecule = atom->molecule;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
com[imol][0] += (x[i][0] + xbox*xprd) * massone;
com[imol][1] += (x[i][1] + ybox*yprd) * massone;
com[imol][2] += (x[i][2] + zbox*zprd) * massone;
}
MPI_Allreduce(&com[0][0],&comall[0][0],3*nmolecules,
MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < nmolecules; i++) {
comall[i][0] /= masstotal[i];
comall[i][1] /= masstotal[i];
comall[i][2] /= masstotal[i];
}
// MSD is difference between current and initial COM
// cominit does not yet exist when called from constructor
if (firstflag) return;
for (i = 0; i < nmolecules; i++) {
dx = comall[i][0] - cominit[i][0];
dy = comall[i][1] - cominit[i][1];
dz = comall[i][2] - cominit[i][2];
msd[i][0] = dx*dx;
msd[i][1] = dy*dy;
msd[i][2] = dz*dz;
msd[i][3] = dx*dx + dy*dy + dz*dz;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputeMSDMolecule::memory_usage()
{
double bytes = 2*nmolecules * sizeof(double);
if (molmap) bytes += (idhi-idlo+1) * sizeof(int);
bytes += 2*nmolecules*3 * sizeof(double);
bytes += nmolecules*4 * sizeof(double);
return bytes;
}
diff --git a/src/compute_pair.cpp b/src/compute_pair.cpp
index 9617e016a..e5e8dbda0 100644
--- a/src/compute_pair.cpp
+++ b/src/compute_pair.cpp
@@ -1,109 +1,109 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_pair.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{EPAIR,EVDWL,ECOUL};
/* ---------------------------------------------------------------------- */
ComputePair::ComputePair(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4 || narg > 5) error->all("Illegal compute pair command");
- if (igroup) error->all("Compute pair must use group all");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Illegal compute pair command");
+ if (igroup) error->all(FLERR,"Compute pair must use group all");
scalar_flag = 1;
extscalar = 1;
peflag = 1;
timeflag = 1;
int n = strlen(arg[3]) + 1;
pstyle = new char[n];
strcpy(pstyle,arg[3]);
if (narg == 5) {
if (strcmp(arg[4],"epair") == 0) evalue = EPAIR;
if (strcmp(arg[4],"evdwl") == 0) evalue = EVDWL;
if (strcmp(arg[4],"ecoul") == 0) evalue = ECOUL;
} else evalue = EPAIR;
pair = force->pair_match(pstyle,1);
- if (!pair) error->all("Unrecognized pair style in compute pair command");
+ if (!pair) error->all(FLERR,"Unrecognized pair style in compute pair command");
npair = pair->nextra;
if (npair) {
vector_flag = 1;
size_vector = npair;
extvector = 1;
one = new double[npair];
vector = new double[npair];
} else one = vector = NULL;
}
/* ---------------------------------------------------------------------- */
ComputePair::~ComputePair()
{
delete [] pstyle;
delete [] one;
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputePair::init()
{
// recheck for pair style in case it has been deleted
pair = force->pair_match(pstyle,1);
- if (!pair) error->all("Unrecognized pair style in compute pair command");
+ if (!pair) error->all(FLERR,"Unrecognized pair style in compute pair command");
}
/* ---------------------------------------------------------------------- */
double ComputePair::compute_scalar()
{
invoked_scalar = update->ntimestep;
if (update->eflag_global != invoked_scalar)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
double eng;
if (evalue == EPAIR) eng = pair->eng_vdwl + pair->eng_coul;
else if (evalue == EVDWL) eng = pair->eng_vdwl;
else if (evalue == ECOUL) eng = pair->eng_coul;
MPI_Allreduce(&eng,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputePair::compute_vector()
{
invoked_vector = update->ntimestep;
if (update->eflag_global != invoked_vector)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
for (int i = 0; i < npair; i++)
one[i] = pair->pvector[i];
MPI_Allreduce(one,vector,npair,MPI_DOUBLE,MPI_SUM,world);
}
diff --git a/src/compute_pair_local.cpp b/src/compute_pair_local.cpp
index aa209f245..8c35f0170 100644
--- a/src/compute_pair_local.cpp
+++ b/src/compute_pair_local.cpp
@@ -1,229 +1,229 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "compute_pair_local.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "neigh_list.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 10000
/* ---------------------------------------------------------------------- */
ComputePairLocal::ComputePairLocal(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute pair/local command");
+ if (narg < 4) error->all(FLERR,"Illegal compute pair/local command");
local_flag = 1;
nvalues = narg - 3;
if (nvalues == 1) size_local_cols = 0;
else size_local_cols = nvalues;
dflag = eflag = fflag = -1;
nvalues = 0;
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"dist") == 0) dflag = nvalues++;
else if (strcmp(arg[iarg],"eng") == 0) eflag = nvalues++;
else if (strcmp(arg[iarg],"force") == 0) fflag = nvalues++;
- else error->all("Invalid keyword in compute pair/local command");
+ else error->all(FLERR,"Invalid keyword in compute pair/local command");
}
nmax = 0;
vector = NULL;
array = NULL;
}
/* ---------------------------------------------------------------------- */
ComputePairLocal::~ComputePairLocal()
{
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputePairLocal::init()
{
if (force->pair == NULL)
- error->all("No pair style is defined for compute pair/local");
+ error->all(FLERR,"No pair style is defined for compute pair/local");
if (force->pair->single_enable == 0)
- error->all("Pair style does not support compute pair/local");
+ error->all(FLERR,"Pair style does not support compute pair/local");
// need an occasional half neighbor list
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->occasional = 1;
}
/* ---------------------------------------------------------------------- */
void ComputePairLocal::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputePairLocal::compute_local()
{
invoked_local = update->ntimestep;
// count local entries and compute pair info
ncount = compute_pairs(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
ncount = compute_pairs(1);
}
/* ----------------------------------------------------------------------
count pairs and compute pair info on this proc
only count pair once if newton_pair is off
both atom I,J must be in group
if flag is set, compute requested info about pair
------------------------------------------------------------------------- */
int ComputePairLocal::compute_pairs(int flag)
{
int i,j,m,n,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz;
double rsq,eng,fpair,factor_coul,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
double *dbuf,*ebuf,*fbuf;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
// invoke half neighbor list (will copy or build if necessary)
if (flag == 0) neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
// skip if I or J are not in group
if (flag) {
if (nvalues == 1) {
if (dflag >= 0) dbuf = vector;
if (eflag >= 0) ebuf = vector;
if (fflag >= 0) fbuf = vector;
} else {
if (dflag >= 0) dbuf = &array[0][dflag];
if (eflag >= 0) ebuf = &array[0][eflag];
if (fflag >= 0) fbuf = &array[0][fflag];
}
}
Pair *pair = force->pair;
double **cutsq = force->pair->cutsq;
m = n = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (!(mask[i] & groupbit)) continue;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
if (!(mask[j] & groupbit)) continue;
if (newton_pair == 0 && j >= nlocal) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq >= cutsq[itype][jtype]) continue;
if (flag) {
if (dflag >= 0) dbuf[n] = sqrt(rsq);
if (eflag >= 0 || fflag >= 0) {
eng = pair->single(i,j,itype,jtype,rsq,factor_coul,factor_lj,fpair);
if (eflag >= 0) ebuf[n] = eng;
if (fflag >= 0) fbuf[n] = sqrt(rsq)*fpair;
}
n += nvalues;
}
m++;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void ComputePairLocal::reallocate(int n)
{
// grow vector or array and indices array
while (nmax < n) nmax += DELTA;
if (nvalues == 1) {
memory->destroy(vector);
memory->create(vector,nmax,"pair/local:vector");
vector_local = vector;
} else {
memory->destroy(array);
memory->create(array,nmax,nvalues,"pair/local:array");
array_local = array;
}
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputePairLocal::memory_usage()
{
double bytes = nmax*nvalues * sizeof(double);
return bytes;
}
diff --git a/src/compute_pe.cpp b/src/compute_pe.cpp
index 1d72d37fe..c153e15d8 100644
--- a/src/compute_pe.cpp
+++ b/src/compute_pe.cpp
@@ -1,99 +1,99 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_pe.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "modify.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputePE::ComputePE(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal compute pe command");
- if (igroup) error->all("Compute pe must use group all");
+ if (narg < 3) error->all(FLERR,"Illegal compute pe command");
+ if (igroup) error->all(FLERR,"Compute pe must use group all");
scalar_flag = 1;
extscalar = 1;
peflag = 1;
timeflag = 1;
if (narg == 3) {
pairflag = 1;
bondflag = angleflag = dihedralflag = improperflag = 1;
kspaceflag = 1;
thermoflag = 1;
} else {
pairflag = 0;
bondflag = angleflag = dihedralflag = improperflag = 0;
kspaceflag = 0;
thermoflag = 0;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"pair") == 0) pairflag = 1;
else if (strcmp(arg[iarg],"bond") == 0) bondflag = 1;
else if (strcmp(arg[iarg],"angle") == 0) angleflag = 1;
else if (strcmp(arg[iarg],"dihedral") == 0) dihedralflag = 1;
else if (strcmp(arg[iarg],"improper") == 0) improperflag = 1;
else if (strcmp(arg[iarg],"kspace") == 0) kspaceflag = 1;
- else error->all("Illegal compute pe command");
+ else error->all(FLERR,"Illegal compute pe command");
iarg++;
}
}
}
/* ---------------------------------------------------------------------- */
double ComputePE::compute_scalar()
{
invoked_scalar = update->ntimestep;
if (update->eflag_global != invoked_scalar)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
double one = 0.0;
if (pairflag && force->pair)
one += force->pair->eng_vdwl + force->pair->eng_coul;
if (atom->molecular) {
if (bondflag && force->bond) one += force->bond->energy;
if (angleflag && force->angle) one += force->angle->energy;
if (dihedralflag && force->dihedral) one += force->dihedral->energy;
if (improperflag && force->improper) one += force->improper->energy;
}
MPI_Allreduce(&one,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (kspaceflag && force->kspace) scalar += force->kspace->energy;
if (pairflag && force->pair && force->pair->tail_flag) {
double volume = domain->xprd * domain->yprd * domain->zprd;
scalar += force->pair->etail / volume;
}
if (thermoflag && modify->n_thermo_energy) scalar += modify->thermo_energy();
return scalar;
}
diff --git a/src/compute_pe_atom.cpp b/src/compute_pe_atom.cpp
index 3d424e61c..20a16ae5b 100755
--- a/src/compute_pe_atom.cpp
+++ b/src/compute_pe_atom.cpp
@@ -1,182 +1,182 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_pe_atom.h"
#include "atom.h"
#include "update.h"
#include "comm.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputePEAtom::ComputePEAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal compute pe/atom command");
+ if (narg < 3) error->all(FLERR,"Illegal compute pe/atom command");
peratom_flag = 1;
size_peratom_cols = 0;
peatomflag = 1;
timeflag = 1;
comm_reverse = 1;
if (narg == 3) {
pairflag = 1;
bondflag = angleflag = dihedralflag = improperflag = 1;
} else {
pairflag = 0;
bondflag = angleflag = dihedralflag = improperflag = 0;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"pair") == 0) pairflag = 1;
else if (strcmp(arg[iarg],"bond") == 0) bondflag = 1;
else if (strcmp(arg[iarg],"angle") == 0) angleflag = 1;
else if (strcmp(arg[iarg],"dihedral") == 0) dihedralflag = 1;
else if (strcmp(arg[iarg],"improper") == 0) improperflag = 1;
- else error->all("Illegal compute pe/atom command");
+ else error->all(FLERR,"Illegal compute pe/atom command");
iarg++;
}
}
nmax = 0;
energy = NULL;
}
/* ---------------------------------------------------------------------- */
ComputePEAtom::~ComputePEAtom()
{
memory->destroy(energy);
}
/* ---------------------------------------------------------------------- */
void ComputePEAtom::compute_peratom()
{
int i;
invoked_peratom = update->ntimestep;
if (update->eflag_atom != invoked_peratom)
- error->all("Per-atom energy was not tallied on needed timestep");
+ error->all(FLERR,"Per-atom energy was not tallied on needed timestep");
// grow local energy array if necessary
// needs to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(energy);
nmax = atom->nmax;
memory->create(energy,nmax,"pe/atom:energy");
vector_atom = energy;
}
// npair includes ghosts if either newton flag is set
// b/c some bonds/dihedrals call pair::ev_tally with pairwise info
// nbond includes ghosts if newton_bond is set
// ntotal includes ghosts if either newton flag is set
int nlocal = atom->nlocal;
int npair = nlocal;
int nbond = nlocal;
int ntotal = nlocal;
if (force->newton) npair += atom->nghost;
if (force->newton_bond) nbond += atom->nghost;
if (force->newton) ntotal += atom->nghost;
// clear local energy array
for (i = 0; i < ntotal; i++) energy[i] = 0.0;
// add in per-atom contributions from each force
if (pairflag && force->pair) {
double *eatom = force->pair->eatom;
for (i = 0; i < npair; i++) energy[i] += eatom[i];
}
if (bondflag && force->bond) {
double *eatom = force->bond->eatom;
for (i = 0; i < nbond; i++) energy[i] += eatom[i];
}
if (angleflag && force->angle) {
double *eatom = force->angle->eatom;
for (i = 0; i < nbond; i++) energy[i] += eatom[i];
}
if (dihedralflag && force->dihedral) {
double *eatom = force->dihedral->eatom;
for (i = 0; i < nbond; i++) energy[i] += eatom[i];
}
if (improperflag && force->improper) {
double *eatom = force->improper->eatom;
for (i = 0; i < nbond; i++) energy[i] += eatom[i];
}
// communicate ghost energy between neighbor procs
if (force->newton) comm->reverse_comm_compute(this);
// zero energy of atoms not in group
// only do this after comm since ghost contributions must be included
int *mask = atom->mask;
for (i = 0; i < nlocal; i++)
if (!(mask[i] & groupbit)) energy[i] = 0.0;
}
/* ---------------------------------------------------------------------- */
int ComputePEAtom::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) buf[m++] = energy[i];
return 1;
}
/* ---------------------------------------------------------------------- */
void ComputePEAtom::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
energy[j] += buf[m++];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputePEAtom::memory_usage()
{
double bytes = nmax * sizeof(double);
return bytes;
}
diff --git a/src/compute_pressure.cpp b/src/compute_pressure.cpp
index 94391ce52..edd6910cc 100644
--- a/src/compute_pressure.cpp
+++ b/src/compute_pressure.cpp
@@ -1,286 +1,286 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "compute_pressure.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputePressure::ComputePressure(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute pressure command");
- if (igroup) error->all("Compute pressure must use group all");
+ if (narg < 4) error->all(FLERR,"Illegal compute pressure command");
+ if (igroup) error->all(FLERR,"Compute pressure must use group all");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 0;
pressflag = 1;
timeflag = 1;
// store temperature ID used by pressure computation
// insure it is valid for temperature computation
int n = strlen(arg[3]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[3]);
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Could not find compute pressure temperature ID");
+ error->all(FLERR,"Could not find compute pressure temperature ID");
if (modify->compute[icompute]->tempflag == 0)
- error->all("Compute pressure temperature ID does not compute temperature");
+ error->all(FLERR,"Compute pressure temperature ID does not compute temperature");
// process optional args
if (narg == 4) {
keflag = 1;
pairflag = 1;
bondflag = angleflag = dihedralflag = improperflag = 1;
kspaceflag = fixflag = 1;
} else {
keflag = 0;
pairflag = 0;
bondflag = angleflag = dihedralflag = improperflag = 0;
kspaceflag = fixflag = 0;
int iarg = 4;
while (iarg < narg) {
if (strcmp(arg[iarg],"ke") == 0) keflag = 1;
else if (strcmp(arg[iarg],"pair") == 0) pairflag = 1;
else if (strcmp(arg[iarg],"bond") == 0) bondflag = 1;
else if (strcmp(arg[iarg],"angle") == 0) angleflag = 1;
else if (strcmp(arg[iarg],"dihedral") == 0) dihedralflag = 1;
else if (strcmp(arg[iarg],"improper") == 0) improperflag = 1;
else if (strcmp(arg[iarg],"kspace") == 0) kspaceflag = 1;
else if (strcmp(arg[iarg],"fix") == 0) fixflag = 1;
else if (strcmp(arg[iarg],"virial") == 0) {
pairflag = 1;
bondflag = angleflag = dihedralflag = improperflag = 1;
kspaceflag = fixflag = 1;
- } else error->all("Illegal compute pressure command");
+ } else error->all(FLERR,"Illegal compute pressure command");
iarg++;
}
}
vector = new double[6];
nvirial = 0;
vptr = NULL;
}
/* ---------------------------------------------------------------------- */
ComputePressure::~ComputePressure()
{
delete [] id_temp;
delete [] vector;
delete [] vptr;
}
/* ---------------------------------------------------------------------- */
void ComputePressure::init()
{
boltz = force->boltz;
nktv2p = force->nktv2p;
dimension = domain->dimension;
// set temperature compute, must be done in init()
// fixes could have changed or compute_modify could have changed it
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Could not find compute pressure temperature ID");
+ error->all(FLERR,"Could not find compute pressure temperature ID");
temperature = modify->compute[icompute];
// detect contributions to virial
// vptr points to all virial[6] contributions
delete [] vptr;
nvirial = 0;
vptr = NULL;
if (pairflag && force->pair) nvirial++;
if (bondflag && atom->molecular && force->bond) nvirial++;
if (angleflag && atom->molecular && force->angle) nvirial++;
if (dihedralflag && atom->molecular && force->dihedral) nvirial++;
if (improperflag && atom->molecular && force->improper) nvirial++;
if (fixflag)
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->virial_flag) nvirial++;
if (nvirial) {
vptr = new double*[nvirial];
nvirial = 0;
if (pairflag && force->pair) vptr[nvirial++] = force->pair->virial;
if (bondflag && force->bond) vptr[nvirial++] = force->bond->virial;
if (angleflag && force->angle) vptr[nvirial++] = force->angle->virial;
if (dihedralflag && force->dihedral)
vptr[nvirial++] = force->dihedral->virial;
if (improperflag && force->improper)
vptr[nvirial++] = force->improper->virial;
if (fixflag)
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->virial_flag)
vptr[nvirial++] = modify->fix[i]->virial;
}
// flag Kspace contribution separately, since not summed across procs
if (kspaceflag && force->kspace) kspace_virial = force->kspace->virial;
else kspace_virial = NULL;
}
/* ----------------------------------------------------------------------
compute total pressure, averaged over Pxx, Pyy, Pzz
------------------------------------------------------------------------- */
double ComputePressure::compute_scalar()
{
invoked_scalar = update->ntimestep;
if (update->vflag_global != invoked_scalar)
- error->all("Virial was not tallied on needed timestep");
+ error->all(FLERR,"Virial was not tallied on needed timestep");
// invoke temperature it it hasn't been already
double t;
if (keflag) {
if (temperature->invoked_scalar != update->ntimestep)
t = temperature->compute_scalar();
else t = temperature->scalar;
}
if (dimension == 3) {
inv_volume = 1.0 / (domain->xprd * domain->yprd * domain->zprd);
virial_compute(3,3);
if (keflag)
scalar = (temperature->dof * boltz * t +
virial[0] + virial[1] + virial[2]) / 3.0 * inv_volume * nktv2p;
else
scalar = (virial[0] + virial[1] + virial[2]) / 3.0 * inv_volume * nktv2p;
} else {
inv_volume = 1.0 / (domain->xprd * domain->yprd);
virial_compute(2,2);
if (keflag)
scalar = (temperature->dof * boltz * t +
virial[0] + virial[1]) / 2.0 * inv_volume * nktv2p;
else
scalar = (virial[0] + virial[1]) / 2.0 * inv_volume * nktv2p;
}
return scalar;
}
/* ----------------------------------------------------------------------
compute pressure tensor
assume KE tensor has already been computed
------------------------------------------------------------------------- */
void ComputePressure::compute_vector()
{
invoked_vector = update->ntimestep;
if (update->vflag_global != invoked_vector)
- error->all("Virial was not tallied on needed timestep");
+ error->all(FLERR,"Virial was not tallied on needed timestep");
// invoke temperature if it hasn't been already
double *ke_tensor;
if (keflag) {
if (temperature->invoked_vector != update->ntimestep)
temperature->compute_vector();
ke_tensor = temperature->vector;
}
if (dimension == 3) {
inv_volume = 1.0 / (domain->xprd * domain->yprd * domain->zprd);
virial_compute(6,3);
if (keflag) {
for (int i = 0; i < 6; i++)
vector[i] = (ke_tensor[i] + virial[i]) * inv_volume * nktv2p;
} else
for (int i = 0; i < 6; i++)
vector[i] = virial[i] * inv_volume * nktv2p;
} else {
inv_volume = 1.0 / (domain->xprd * domain->yprd);
virial_compute(4,2);
if (keflag) {
vector[0] = (ke_tensor[0] + virial[0]) * inv_volume * nktv2p;
vector[1] = (ke_tensor[1] + virial[1]) * inv_volume * nktv2p;
vector[3] = (ke_tensor[3] + virial[3]) * inv_volume * nktv2p;
vector[2] = vector[4] = vector[5] = 0.0;
} else {
vector[0] = virial[0] * inv_volume * nktv2p;
vector[1] = virial[1] * inv_volume * nktv2p;
vector[3] = virial[3] * inv_volume * nktv2p;
vector[2] = vector[4] = vector[5] = 0.0;
}
}
}
/* ---------------------------------------------------------------------- */
void ComputePressure::virial_compute(int n, int ndiag)
{
int i,j;
double v[6],*vcomponent;
for (i = 0; i < n; i++) v[i] = 0.0;
// sum contributions to virial from forces and fixes
for (j = 0; j < nvirial; j++) {
vcomponent = vptr[j];
for (i = 0; i < n; i++) v[i] += vcomponent[i];
}
// sum virial across procs
MPI_Allreduce(v,virial,n,MPI_DOUBLE,MPI_SUM,world);
// KSpace virial contribution is already summed across procs
if (kspace_virial)
for (i = 0; i < n; i++) virial[i] += kspace_virial[i];
// LJ long-range tail correction
if (force->pair && force->pair->tail_flag)
for (i = 0; i < ndiag; i++) virial[i] += force->pair->ptail * inv_volume;
}
/* ---------------------------------------------------------------------- */
void ComputePressure::reset_extra_compute_fix(char *id_new)
{
delete [] id_temp;
int n = strlen(id_new) + 1;
id_temp = new char[n];
strcpy(id_temp,id_new);
}
diff --git a/src/compute_property_atom.cpp b/src/compute_property_atom.cpp
index b145139d1..f7605d555 100644
--- a/src/compute_property_atom.cpp
+++ b/src/compute_property_atom.cpp
@@ -1,1215 +1,1215 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_property_atom.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "update.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputePropertyAtom::ComputePropertyAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute property/atom command");
+ if (narg < 4) error->all(FLERR,"Illegal compute property/atom command");
peratom_flag = 1;
nvalues = narg - 3;
if (nvalues == 1) size_peratom_cols = 0;
else size_peratom_cols = nvalues;
// parse input values
// customize a new keyword by adding to if statement
pack_choice = new FnPtrPack[nvalues];
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"id") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_id;
} else if (strcmp(arg[iarg],"mol") == 0) {
if (!atom->molecule_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_molecule;
} else if (strcmp(arg[iarg],"type") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_type;
} else if (strcmp(arg[iarg],"mass") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_mass;
} else if (strcmp(arg[iarg],"x") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_x;
} else if (strcmp(arg[iarg],"y") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_y;
} else if (strcmp(arg[iarg],"z") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_z;
} else if (strcmp(arg[iarg],"xs") == 0) {
if (domain->triclinic)
pack_choice[i] = &ComputePropertyAtom::pack_xs_triclinic;
else pack_choice[i] = &ComputePropertyAtom::pack_xs;
} else if (strcmp(arg[iarg],"ys") == 0) {
if (domain->triclinic)
pack_choice[i] = &ComputePropertyAtom::pack_ys_triclinic;
else pack_choice[i] = &ComputePropertyAtom::pack_ys;
} else if (strcmp(arg[iarg],"zs") == 0) {
if (domain->triclinic)
pack_choice[i] = &ComputePropertyAtom::pack_zs_triclinic;
else pack_choice[i] = &ComputePropertyAtom::pack_zs;
} else if (strcmp(arg[iarg],"xu") == 0) {
if (domain->triclinic)
pack_choice[i] = &ComputePropertyAtom::pack_xu_triclinic;
else pack_choice[i] = &ComputePropertyAtom::pack_xu;
} else if (strcmp(arg[iarg],"yu") == 0) {
if (domain->triclinic)
pack_choice[i] = &ComputePropertyAtom::pack_yu_triclinic;
else pack_choice[i] = &ComputePropertyAtom::pack_yu;
} else if (strcmp(arg[iarg],"zu") == 0) {
if (domain->triclinic)
pack_choice[i] = &ComputePropertyAtom::pack_zu_triclinic;
else pack_choice[i] = &ComputePropertyAtom::pack_zu;
} else if (strcmp(arg[iarg],"ix") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_ix;
} else if (strcmp(arg[iarg],"iy") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_iy;
} else if (strcmp(arg[iarg],"iz") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_iz;
} else if (strcmp(arg[iarg],"vx") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_vx;
} else if (strcmp(arg[iarg],"vy") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_vy;
} else if (strcmp(arg[iarg],"vz") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_vz;
} else if (strcmp(arg[iarg],"fx") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_fx;
} else if (strcmp(arg[iarg],"fy") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_fy;
} else if (strcmp(arg[iarg],"fz") == 0) {
pack_choice[i] = &ComputePropertyAtom::pack_fz;
} else if (strcmp(arg[iarg],"q") == 0) {
if (!atom->q_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_q;
} else if (strcmp(arg[iarg],"mux") == 0) {
if (!atom->mu_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_mux;
} else if (strcmp(arg[iarg],"muy") == 0) {
if (!atom->mu_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_muy;
} else if (strcmp(arg[iarg],"muz") == 0) {
if (!atom->mu_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_muz;
} else if (strcmp(arg[iarg],"mu") == 0) {
if (!atom->mu_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_mu;
} else if (strcmp(arg[iarg],"radius") == 0) {
if (!atom->radius_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_radius;
} else if (strcmp(arg[iarg],"diameter") == 0) {
if (!atom->radius_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_diameter;
} else if (strcmp(arg[iarg],"omegax") == 0) {
if (!atom->omega_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_omegax;
} else if (strcmp(arg[iarg],"omegay") == 0) {
if (!atom->omega_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_omegay;
} else if (strcmp(arg[iarg],"omegaz") == 0) {
if (!atom->omega_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_omegaz;
} else if (strcmp(arg[iarg],"angmomx") == 0) {
if (!atom->angmom_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_angmomx;
} else if (strcmp(arg[iarg],"angmomy") == 0) {
if (!atom->angmom_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_angmomy;
} else if (strcmp(arg[iarg],"angmomz") == 0) {
if (!atom->angmom_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_angmomz;
} else if (strcmp(arg[iarg],"shapex") == 0) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Compute property/atom for "
+ if (!avec) error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_shapex;
} else if (strcmp(arg[iarg],"shapey") == 0) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Compute property/atom for "
+ if (!avec) error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_shapey;
} else if (strcmp(arg[iarg],"shapez") == 0) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Compute property/atom for "
+ if (!avec) error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_shapez;
} else if (strcmp(arg[iarg],"quatw") == 0) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Compute property/atom for "
+ if (!avec) error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quatw;
} else if (strcmp(arg[iarg],"quati") == 0) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Compute property/atom for "
+ if (!avec) error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quati;
} else if (strcmp(arg[iarg],"quatj") == 0) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Compute property/atom for "
+ if (!avec) error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quatj;
} else if (strcmp(arg[iarg],"quatk") == 0) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
- if (!avec) error->all("Compute property/atom for "
+ if (!avec) error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_quatk;
} else if (strcmp(arg[iarg],"tqx") == 0) {
if (!atom->torque_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_tqx;
} else if (strcmp(arg[iarg],"tqy") == 0) {
if (!atom->torque_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_tqy;
} else if (strcmp(arg[iarg],"tqz") == 0) {
if (!atom->torque_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_tqz;
} else if (strcmp(arg[iarg],"spin") == 0) {
if (!atom->spin_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_spin;
} else if (strcmp(arg[iarg],"eradius") == 0) {
if (!atom->eradius_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_eradius;
} else if (strcmp(arg[iarg],"ervel") == 0) {
if (!atom->ervel_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_ervel;
} else if (strcmp(arg[iarg],"erforce") == 0) {
if (!atom->erforce_flag)
- error->all("Compute property/atom for "
+ error->all(FLERR,"Compute property/atom for "
"atom property that isn't allocated");
pack_choice[i] = &ComputePropertyAtom::pack_erforce;
- } else error->all("Invalid keyword in compute property/atom command");
+ } else error->all(FLERR,"Invalid keyword in compute property/atom command");
}
nmax = 0;
vector = NULL;
array = NULL;
}
/* ---------------------------------------------------------------------- */
ComputePropertyAtom::~ComputePropertyAtom()
{
delete [] pack_choice;
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::compute_peratom()
{
invoked_peratom = update->ntimestep;
// grow vector or array if necessary
if (atom->nlocal > nmax) {
nmax = atom->nmax;
if (nvalues == 1) {
memory->destroy(vector);
memory->create(vector,nmax,"property/atom:vector");
vector_atom = vector;
} else {
memory->destroy(array);
memory->create(array,nmax,nvalues,"property/atom:array");
array_atom = array;
}
}
// fill vector or array with per-atom values
if (nvalues == 1) {
buf = vector;
(this->*pack_choice[0])(0);
} else {
buf = &array[0][0];
for (int n = 0; n < nvalues; n++)
(this->*pack_choice[n])(n);
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputePropertyAtom::memory_usage()
{
double bytes = nmax*nvalues * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
one method for every keyword compute property/atom can output
the atom property is packed into buf starting at n with stride nvalues
customize a new keyword by adding a method
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_id(int n)
{
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = tag[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_molecule(int n)
{
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = molecule[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_type(int n)
{
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = type[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_mass(int n)
{
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = rmass[i];
else buf[n] = 0.0;
n += nvalues;
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = mass[type[i]];
else buf[n] = 0.0;
n += nvalues;
}
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_x(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = x[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_y(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = x[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_z(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = x[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_xs(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double boxxlo = domain->boxlo[0];
double invxprd = 1.0/domain->xprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = (x[i][0] - boxxlo) * invxprd;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_ys(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double boxylo = domain->boxlo[1];
double invyprd = 1.0/domain->yprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = (x[i][1] - boxylo) * invyprd;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_zs(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double boxzlo = domain->boxlo[2];
double invzprd = 1.0/domain->zprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = (x[i][2] - boxzlo) * invzprd;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_xs_triclinic(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = h_inv[0]*(x[i][0]-boxlo[0]) +
h_inv[5]*(x[i][1]-boxlo[1]) + h_inv[4]*(x[i][2]-boxlo[2]);
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_ys_triclinic(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = h_inv[1]*(x[i][1]-boxlo[1]) + h_inv[3]*(x[i][2]-boxlo[2]);
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_zs_triclinic(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = h_inv[2]*(x[i][2]-boxlo[2]);
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_xu(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = x[i][0] + ((image[i] & 1023) - 512) * xprd;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_yu(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double yprd = domain->yprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = x[i][1] + ((image[i] >> 10 & 1023) - 512) * yprd;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_zu(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double zprd = domain->zprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
buf[n] = x[i][2] + ((image[i] >> 20) - 512) * zprd;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_xu_triclinic(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
int xbox,ybox,zbox;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
buf[n] = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox;
} else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_yu_triclinic(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
int ybox,zbox;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
buf[n] = x[i][1] + h[1]*ybox + h[3]*zbox;
} else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_zu_triclinic(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
int zbox;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
zbox = (image[i] >> 20) - 512;
buf[n] = x[i][2] + h[2]*zbox;
} else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_ix(int n)
{
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = (image[i] & 1023) - 512;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_iy(int n)
{
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = (image[i] >> 10 & 1023) - 512;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_iz(int n)
{
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = (image[i] >> 20) - 512;
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_vx(int n)
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = v[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_vy(int n)
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = v[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_vz(int n)
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = v[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_fx(int n)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = f[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_fy(int n)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = f[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_fz(int n)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = f[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_q(int n)
{
double *q = atom->q;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = q[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_mux(int n)
{
double **mu = atom->mu;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = mu[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_muy(int n)
{
double **mu = atom->mu;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = mu[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_muz(int n)
{
double **mu = atom->mu;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = mu[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_mu(int n)
{
double **mu = atom->mu;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = mu[i][3];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_radius(int n)
{
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = radius[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_diameter(int n)
{
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = 2.0*radius[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_omegax(int n)
{
double **omega = atom->omega;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = omega[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_omegay(int n)
{
double **omega = atom->omega;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = omega[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_omegaz(int n)
{
double **omega = atom->omega;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = omega[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_angmomx(int n)
{
double **angmom = atom->angmom;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = angmom[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_angmomy(int n)
{
double **angmom = atom->angmom;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = angmom[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_angmomz(int n)
{
double **angmom = atom->angmom;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = angmom[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_shapex(int n)
{
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && ellipsoid[i] >= 0)
buf[n] = bonus[ellipsoid[i]].shape[0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_shapey(int n)
{
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && ellipsoid[i] >= 0)
buf[n] = bonus[ellipsoid[i]].shape[1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_shapez(int n)
{
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && ellipsoid[i] >= 0)
buf[n] = bonus[ellipsoid[i]].shape[2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_quatw(int n)
{
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && ellipsoid[i] >= 0)
buf[n] = bonus[ellipsoid[i]].quat[0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_quati(int n)
{
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && ellipsoid[i] >= 0)
buf[n] = bonus[ellipsoid[i]].quat[1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_quatj(int n)
{
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && ellipsoid[i] >= 0)
buf[n] = bonus[ellipsoid[i]].quat[2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_quatk(int n)
{
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if ((mask[i] & groupbit) && ellipsoid[i] >= 0)
buf[n] = bonus[ellipsoid[i]].quat[3];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_tqx(int n)
{
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = torque[i][0];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_tqy(int n)
{
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = torque[i][1];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_tqz(int n)
{
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = torque[i][2];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_spin(int n)
{
int *spin = atom->spin;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = spin[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_eradius(int n)
{
double *eradius = atom->eradius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = eradius[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_ervel(int n)
{
double *ervel = atom->ervel;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = ervel[i];
else buf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyAtom::pack_erforce(int n)
{
double *erforce = atom->erforce;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) buf[n] = erforce[i];
else buf[n] = 0.0;
n += nvalues;
}
}
diff --git a/src/compute_property_local.cpp b/src/compute_property_local.cpp
index a0e615bc4..48ab145d8 100644
--- a/src/compute_property_local.cpp
+++ b/src/compute_property_local.cpp
@@ -1,827 +1,827 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_property_local.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NONE,NEIGH,PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER};
#define DELTA 10000
/* ---------------------------------------------------------------------- */
ComputePropertyLocal::ComputePropertyLocal(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute property/local command");
+ if (narg < 4) error->all(FLERR,"Illegal compute property/local command");
local_flag = 1;
nvalues = narg - 3;
if (nvalues == 1) size_local_cols = 0;
else size_local_cols = nvalues;
pack_choice = new FnPtrPack[nvalues];
kindflag = NONE;
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"natom1") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_patom1;
if (kindflag != NONE && kindflag != NEIGH)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = NEIGH;
} else if (strcmp(arg[iarg],"natom2") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_patom2;
if (kindflag != NONE && kindflag != NEIGH)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = NEIGH;
} else if (strcmp(arg[iarg],"patom1") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_patom1;
if (kindflag != NONE && kindflag != PAIR)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = PAIR;
} else if (strcmp(arg[iarg],"patom2") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_patom2;
if (kindflag != NONE && kindflag != PAIR)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = PAIR;
} else if (strcmp(arg[iarg],"batom1") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_batom1;
if (kindflag != NONE && kindflag != BOND)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = BOND;
} else if (strcmp(arg[iarg],"batom2") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_batom2;
if (kindflag != NONE && kindflag != BOND)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = BOND;
} else if (strcmp(arg[iarg],"btype") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_btype;
if (kindflag != NONE && kindflag != BOND)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = BOND;
} else if (strcmp(arg[iarg],"aatom1") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_aatom1;
if (kindflag != NONE && kindflag != ANGLE)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = ANGLE;
} else if (strcmp(arg[iarg],"aatom2") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_aatom2;
if (kindflag != NONE && kindflag != ANGLE)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = ANGLE;
} else if (strcmp(arg[iarg],"aatom3") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_aatom3;
if (kindflag != NONE && kindflag != ANGLE)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = ANGLE;
} else if (strcmp(arg[iarg],"atype") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_atype;
if (kindflag != NONE && kindflag != ANGLE)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = ANGLE;
} else if (strcmp(arg[iarg],"datom1") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_datom1;
if (kindflag != NONE && kindflag != DIHEDRAL)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = DIHEDRAL;
} else if (strcmp(arg[iarg],"datom2") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_datom2;
if (kindflag != NONE && kindflag != DIHEDRAL)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = DIHEDRAL;
} else if (strcmp(arg[iarg],"datom3") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_datom3;
if (kindflag != NONE && kindflag != DIHEDRAL)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = DIHEDRAL;
} else if (strcmp(arg[iarg],"datom4") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_datom4;
if (kindflag != NONE && kindflag != DIHEDRAL)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = DIHEDRAL;
} else if (strcmp(arg[iarg],"dtype") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_dtype;
if (kindflag != NONE && kindflag != DIHEDRAL)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = DIHEDRAL;
} else if (strcmp(arg[iarg],"iatom1") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_iatom1;
if (kindflag != NONE && kindflag != IMPROPER)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = IMPROPER;
} else if (strcmp(arg[iarg],"iatom2") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_iatom2;
if (kindflag != NONE && kindflag != IMPROPER)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = IMPROPER;
} else if (strcmp(arg[iarg],"iatom3") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_iatom3;
if (kindflag != NONE && kindflag != IMPROPER)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = IMPROPER;
} else if (strcmp(arg[iarg],"iatom4") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_iatom4;
if (kindflag != NONE && kindflag != IMPROPER)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = IMPROPER;
} else if (strcmp(arg[iarg],"itype") == 0) {
pack_choice[i] = &ComputePropertyLocal::pack_itype;
if (kindflag != NONE && kindflag != IMPROPER)
- error->all("Compute property/local cannot use these inputs together");
+ error->all(FLERR,"Compute property/local cannot use these inputs together");
kindflag = IMPROPER;
- } else error->all("Invalid keyword in compute property/local command");
+ } else error->all(FLERR,"Invalid keyword in compute property/local command");
}
// error check
if (kindflag == BOND && atom->avec->bonds_allow == 0)
- error->all("Compute property/local for property that isn't allocated");
+ error->all(FLERR,"Compute property/local for property that isn't allocated");
if (kindflag == ANGLE && atom->avec->angles_allow == 0)
- error->all("Compute property/local for property that isn't allocated");
+ error->all(FLERR,"Compute property/local for property that isn't allocated");
if (kindflag == DIHEDRAL && atom->avec->dihedrals_allow == 0)
- error->all("Compute property/local for property that isn't allocated");
+ error->all(FLERR,"Compute property/local for property that isn't allocated");
if (kindflag == IMPROPER && atom->avec->impropers_allow == 0)
- error->all("Compute property/local for property that isn't allocated");
+ error->all(FLERR,"Compute property/local for property that isn't allocated");
nmax = 0;
vector = NULL;
array = NULL;
indices = NULL;
}
/* ---------------------------------------------------------------------- */
ComputePropertyLocal::~ComputePropertyLocal()
{
delete [] pack_choice;
memory->destroy(vector);
memory->destroy(array);
memory->destroy(indices);
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::init()
{
if (kindflag == NEIGH || kindflag == PAIR) {
if (force->pair == NULL)
- error->all("No pair style is defined for compute property/local");
+ error->all(FLERR,"No pair style is defined for compute property/local");
if (force->pair->single_enable == 0)
- error->all("Pair style does not support compute property/local");
+ error->all(FLERR,"Pair style does not support compute property/local");
}
// for NEIGH/PAIR need an occasional half neighbor list
if (kindflag == NEIGH || kindflag == PAIR) {
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->occasional = 1;
}
// do initial memory allocation so that memory_usage() is correct
// cannot be done yet for NEIGH/PAIR, since neigh list does not exist
if (kindflag == NEIGH) ncount = 0;
else if (kindflag == PAIR) ncount = 0;
else if (kindflag == BOND) ncount = count_bonds(0);
else if (kindflag == ANGLE) ncount = count_angles(0);
else if (kindflag == DIHEDRAL) ncount = count_dihedrals(0);
else if (kindflag == IMPROPER) ncount = count_impropers(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::compute_local()
{
invoked_local = update->ntimestep;
// count local entries and generate list of indices
if (kindflag == NEIGH) ncount = count_pairs(0,0);
else if (kindflag == PAIR) ncount = count_pairs(0,1);
else if (kindflag == BOND) ncount = count_bonds(0);
else if (kindflag == ANGLE) ncount = count_angles(0);
else if (kindflag == DIHEDRAL) ncount = count_dihedrals(0);
else if (kindflag == IMPROPER) ncount = count_impropers(0);
if (ncount > nmax) reallocate(ncount);
size_local_rows = ncount;
if (kindflag == NEIGH) ncount = count_pairs(1,0);
else if (kindflag == PAIR) ncount = count_pairs(1,1);
else if (kindflag == BOND) ncount = count_bonds(1);
else if (kindflag == ANGLE) ncount = count_angles(1);
else if (kindflag == DIHEDRAL) ncount = count_dihedrals(1);
else if (kindflag == IMPROPER) ncount = count_impropers(1);
// fill vector or array with local values
if (nvalues == 1) {
buf = vector;
(this->*pack_choice[0])(0);
} else {
if (array) buf = &array[0][0];
for (int n = 0; n < nvalues; n++)
(this->*pack_choice[n])(n);
}
}
/* ----------------------------------------------------------------------
count pairs and compute pair info on this proc
only count pair once if newton_pair is off
both atom I,J must be in group
if allflag is set, compute requested info about pair
if forceflag = 1, pair must be within force cutoff, else neighbor cutoff
------------------------------------------------------------------------- */
int ComputePropertyLocal::count_pairs(int allflag, int forceflag)
{
int i,j,m,n,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
// invoke half neighbor list (will copy or build if necessary)
if (allflag == 0) neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
// skip if I or J are not in group
double **cutsq = force->pair->cutsq;
m = n = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (!(mask[i] & groupbit)) continue;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
if (!(mask[j] & groupbit)) continue;
if (newton_pair == 0 && j >= nlocal) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (forceflag && rsq >= cutsq[itype][jtype]) continue;
if (allflag) {
indices[m][0] = tag[i];
indices[m][1] = tag[j];
}
m++;
}
}
return m;
}
/* ----------------------------------------------------------------------
count bonds on this proc
only count bond once if newton_bond is off
all atoms in interaction must be in group
all atoms in interaction must be known to proc
if bond is deleted (type = 0), do not count
if bond is turned off (type < 0), still count
------------------------------------------------------------------------- */
int ComputePropertyLocal::count_bonds(int flag)
{
int i,atom1,atom2;
int *num_bond = atom->num_bond;
int **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
int m = 0;
for (atom1 = 0; atom1 < nlocal; atom1++) {
if (!(mask[atom1] & groupbit)) continue;
for (i = 0; i < num_bond[atom1]; i++) {
atom2 = atom->map(bond_atom[atom1][i]);
if (atom2 < 0 || !(mask[atom2] & groupbit)) continue;
if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue;
if (bond_type[atom1][i] == 0) continue;
if (flag) {
indices[m][0] = atom1;
indices[m][1] = i;
}
m++;
}
}
return m;
}
/* ----------------------------------------------------------------------
count angles on this proc
only count if 2nd atom is the one storing the angle
all atoms in interaction must be in group
all atoms in interaction must be known to proc
if angle is deleted (type = 0), do not count
if angle is turned off (type < 0), still count
------------------------------------------------------------------------- */
int ComputePropertyLocal::count_angles(int flag)
{
int i,atom1,atom2,atom3;
int *num_angle = atom->num_angle;
int **angle_atom1 = atom->angle_atom1;
int **angle_atom2 = atom->angle_atom2;
int **angle_atom3 = atom->angle_atom3;
int **angle_type = atom->angle_type;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (atom2 = 0; atom2 < nlocal; atom2++) {
if (!(mask[atom2] & groupbit)) continue;
for (i = 0; i < num_angle[atom2]; i++) {
if (tag[atom2] != angle_atom2[atom2][i]) continue;
atom1 = atom->map(angle_atom1[atom2][i]);
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
atom3 = atom->map(angle_atom3[atom2][i]);
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
if (angle_type[atom2][i] == 0) continue;
if (flag) {
indices[m][0] = atom2;
indices[m][1] = i;
}
m++;
}
}
return m;
}
/* ----------------------------------------------------------------------
count dihedrals on this proc
only count if 2nd atom is the one storing the dihedral
all atoms in interaction must be in group
all atoms in interaction must be known to proc
------------------------------------------------------------------------- */
int ComputePropertyLocal::count_dihedrals(int flag)
{
int i,atom1,atom2,atom3,atom4;
int *num_dihedral = atom->num_dihedral;
int **dihedral_atom1 = atom->dihedral_atom1;
int **dihedral_atom2 = atom->dihedral_atom2;
int **dihedral_atom3 = atom->dihedral_atom3;
int **dihedral_atom4 = atom->dihedral_atom4;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (atom2 = 0; atom2 < nlocal; atom2++) {
if (!(mask[atom2] & groupbit)) continue;
for (i = 0; i < num_dihedral[atom2]; i++) {
if (tag[atom2] != dihedral_atom2[atom2][i]) continue;
atom1 = atom->map(dihedral_atom1[atom2][i]);
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
atom3 = atom->map(dihedral_atom3[atom2][i]);
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
atom4 = atom->map(dihedral_atom4[atom2][i]);
if (atom4 < 0 || !(mask[atom4] & groupbit)) continue;
if (flag) {
indices[m][0] = atom2;
indices[m][1] = i;
}
m++;
}
}
return m;
}
/* ----------------------------------------------------------------------
count impropers on this proc
only count if 2nd atom is the one storing the improper
all atoms in interaction must be in group
all atoms in interaction must be known to proc
------------------------------------------------------------------------- */
int ComputePropertyLocal::count_impropers(int flag)
{
int i,atom1,atom2,atom3,atom4;
int *num_improper = atom->num_improper;
int **improper_atom1 = atom->improper_atom1;
int **improper_atom2 = atom->improper_atom2;
int **improper_atom3 = atom->improper_atom3;
int **improper_atom4 = atom->improper_atom4;
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (atom2 = 0; atom2 < nlocal; atom2++) {
if (!(mask[atom2] & groupbit)) continue;
for (i = 0; i < num_improper[atom2]; i++) {
if (tag[atom2] != improper_atom2[atom2][i]) continue;
atom1 = atom->map(improper_atom1[atom2][i]);
if (atom1 < 0 || !(mask[atom1] & groupbit)) continue;
atom3 = atom->map(improper_atom3[atom2][i]);
if (atom3 < 0 || !(mask[atom3] & groupbit)) continue;
atom4 = atom->map(improper_atom4[atom2][i]);
if (atom4 < 0 || !(mask[atom4] & groupbit)) continue;
if (flag) {
indices[m][0] = atom2;
indices[m][1] = i;
}
m++;
}
}
return m;
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::reallocate(int n)
{
// grow vector or array and indices array
while (nmax < n) nmax += DELTA;
if (nvalues == 1) {
memory->destroy(vector);
memory->create(vector,nmax,"property/local:vector");
vector_local = vector;
} else {
memory->destroy(array);
memory->create(array,nmax,nvalues,"property/local:array");
array_local = array;
}
memory->destroy(indices);
memory->create(indices,nmax,2,"property/local:indices");
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputePropertyLocal::memory_usage()
{
double bytes = nmax*nvalues * sizeof(double);
bytes += nmax*2 * sizeof(int);
return bytes;
}
/* ----------------------------------------------------------------------
one method for every keyword compute property/local can output
the atom property is packed into buf starting at n with stride nvalues
customize a new keyword by adding a method
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_patom1(int n)
{
for (int m = 0; m < ncount; m++) {
buf[n] = indices[m][0];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_patom2(int n)
{
for (int m = 0; m < ncount; m++) {
buf[n] = indices[m][1];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_batom1(int n)
{
int i;
int *tag = atom->tag;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
buf[n] = tag[i];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_batom2(int n)
{
int i,j;
int **bond_atom = atom->bond_atom;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = bond_atom[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_btype(int n)
{
int i,j;
int **bond_type = atom->bond_type;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = bond_type[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_aatom1(int n)
{
int i,j;
int **angle_atom1 = atom->angle_atom1;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = angle_atom1[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_aatom2(int n)
{
int i,j;
int **angle_atom2 = atom->angle_atom2;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = angle_atom2[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_aatom3(int n)
{
int i,j;
int **angle_atom3 = atom->angle_atom3;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = angle_atom3[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_atype(int n)
{
int i,j;
int **angle_type = atom->angle_type;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = angle_type[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_datom1(int n)
{
int i,j;
int **dihedral_atom1 = atom->dihedral_atom1;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = dihedral_atom1[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_datom2(int n)
{
int i,j;
int **dihedral_atom2 = atom->dihedral_atom2;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = dihedral_atom2[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_datom3(int n)
{
int i,j;
int **dihedral_atom3 = atom->dihedral_atom3;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = dihedral_atom3[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_datom4(int n)
{
int i,j;
int **dihedral_atom4 = atom->dihedral_atom4;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = dihedral_atom4[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_dtype(int n)
{
int i,j;
int **dihedral_type = atom->dihedral_type;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = dihedral_type[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_iatom1(int n)
{
int i,j;
int **improper_atom1 = atom->improper_atom1;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = improper_atom1[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_iatom2(int n)
{
int i,j;
int **improper_atom2 = atom->improper_atom2;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = improper_atom2[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_iatom3(int n)
{
int i,j;
int **improper_atom3 = atom->improper_atom3;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = improper_atom3[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_iatom4(int n)
{
int i,j;
int **improper_atom4 = atom->improper_atom4;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = improper_atom4[i][j];
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyLocal::pack_itype(int n)
{
int i,j;
int **improper_type = atom->improper_type;
for (int m = 0; m < ncount; m++) {
i = indices[m][0];
j = indices[m][1];
buf[n] = improper_type[i][j];
n += nvalues;
}
}
diff --git a/src/compute_property_molecule.cpp b/src/compute_property_molecule.cpp
index 7ccf0208a..65ec20ef0 100644
--- a/src/compute_property_molecule.cpp
+++ b/src/compute_property_molecule.cpp
@@ -1,171 +1,171 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "compute_property_molecule.h"
#include "atom.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputePropertyMolecule::
ComputePropertyMolecule(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute property/molecule command");
+ if (narg < 4) error->all(FLERR,"Illegal compute property/molecule command");
if (atom->molecular == 0)
- error->all("Compute property/molecule requires molecular atom style");
+ error->all(FLERR,"Compute property/molecule requires molecular atom style");
nvalues = narg - 3;
pack_choice = new FnPtrPack[nvalues];
int i;
for (int iarg = 3; iarg < narg; iarg++) {
i = iarg-3;
if (strcmp(arg[iarg],"mol") == 0)
pack_choice[i] = &ComputePropertyMolecule::pack_mol;
else if (strcmp(arg[iarg],"count") == 0)
pack_choice[i] = &ComputePropertyMolecule::pack_count;
- else error->all("Invalid keyword in compute property/molecule command");
+ else error->all(FLERR,"Invalid keyword in compute property/molecule command");
}
// setup molecule-based data
nmolecules = molecules_in_group(idlo,idhi);
vector = NULL;
array = NULL;
if (nvalues == 1) {
memory->create(vector,nmolecules,"property/molecule:vector");
vector_flag = 1;
size_vector = nmolecules;
extvector = 0;
} else {
memory->create(array,nmolecules,nvalues,"property/molecule:array");
array_flag = 1;
size_array_rows = nmolecules;
size_array_cols = nvalues;
extarray = 0;
}
// fill vector or array with molecule values
if (nvalues == 1) {
buf = vector;
(this->*pack_choice[0])(0);
} else {
if (array) buf = &array[0][0];
for (int n = 0; n < nvalues; n++)
(this->*pack_choice[n])(n);
}
}
/* ---------------------------------------------------------------------- */
ComputePropertyMolecule::~ComputePropertyMolecule()
{
delete [] pack_choice;
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputePropertyMolecule::init()
{
int ntmp = molecules_in_group(idlo,idhi);
if (ntmp != nmolecules)
- error->all("Molecule count changed in compute property/molecule");
+ error->all(FLERR,"Molecule count changed in compute property/molecule");
}
/* ---------------------------------------------------------------------- */
void ComputePropertyMolecule::compute_vector()
{
invoked_vector = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void ComputePropertyMolecule::compute_array()
{
invoked_array = update->ntimestep;
}
/* ----------------------------------------------------------------------
memory usage of local data
------------------------------------------------------------------------- */
double ComputePropertyMolecule::memory_usage()
{
double bytes = nmolecules*nvalues * sizeof(double);
if (molmap) bytes += (idhi-idlo+1) * sizeof(int);
return bytes;
}
/* ----------------------------------------------------------------------
one method for every keyword compute property/molecule can output
the atom property is packed into buf starting at n with stride nvalues
customize a new keyword by adding a method
------------------------------------------------------------------------- */
void ComputePropertyMolecule::pack_mol(int n)
{
for (int m = idlo; m <= idhi; m++)
if (molmap == NULL || molmap[m-idlo] >= 0) {
buf[n] = m;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void ComputePropertyMolecule::pack_count(int n)
{
int i,m,imol;
int *count_one = new int[nmolecules];
for (m = 0; m < nmolecules; m++) count_one[m] = 0;
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
imol = molecule[i];
if (molmap) imol = molmap[imol-idlo];
else imol--;
count_one[imol]++;
}
int *count_all = new int[nmolecules];
MPI_Allreduce(count_one,count_all,nmolecules,MPI_INT,MPI_SUM,world);
for (m = 0; m < nmolecules; m++)
if (molmap == NULL || molmap[m] >= 0) {
buf[n] = count_all[m];
n += nvalues;
}
delete [] count_one;
delete [] count_all;
}
diff --git a/src/compute_rdf.cpp b/src/compute_rdf.cpp
index 96a11ab27..9dbe3aded 100644
--- a/src/compute_rdf.cpp
+++ b/src/compute_rdf.cpp
@@ -1,309 +1,309 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Paul Crozier (SNL), Jeff Greathouse (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "compute_rdf.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "neigh_list.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeRDF::ComputeRDF(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4 || (narg-4) % 2) error->all("Illegal compute rdf command");
+ if (narg < 4 || (narg-4) % 2) error->all(FLERR,"Illegal compute rdf command");
array_flag = 1;
extarray = 0;
nbin = atoi(arg[3]);
- if (nbin < 1) error->all("Illegal compute rdf command");
+ if (nbin < 1) error->all(FLERR,"Illegal compute rdf command");
if (narg == 4) npairs = 1;
else npairs = (narg-4)/2;
size_array_rows = nbin;
size_array_cols = 1 + 2*npairs;
int ntypes = atom->ntypes;
memory->create(rdfpair,npairs,ntypes+1,ntypes+1,"rdf:rdfpair");
memory->create(nrdfpair,ntypes+1,ntypes+1,"rdf:nrdfpair");
ilo = new int[npairs];
ihi = new int[npairs];
jlo = new int[npairs];
jhi = new int[npairs];
if (narg == 4) {
ilo[0] = 1; ihi[0] = ntypes;
jlo[0] = 1; jhi[0] = ntypes;
npairs = 1;
} else {
npairs = 0;
int iarg = 4;
while (iarg < narg) {
force->bounds(arg[iarg],atom->ntypes,ilo[npairs],ihi[npairs]);
force->bounds(arg[iarg+1],atom->ntypes,jlo[npairs],jhi[npairs]);
if (ilo[npairs] > ihi[npairs] || jlo[npairs] > jhi[npairs])
- error->all("Illegal compute rdf command");
+ error->all(FLERR,"Illegal compute rdf command");
npairs++;
iarg += 2;
}
}
int i,j;
for (i = 1; i <= ntypes; i++)
for (j = 1; j <= ntypes; j++)
nrdfpair[i][j] = 0;
for (int m = 0; m < npairs; m++)
for (i = ilo[m]; i <= ihi[m]; i++)
for (j = jlo[m]; j <= jhi[m]; j++)
rdfpair[nrdfpair[i][j]++][i][j] = m;
memory->create(hist,npairs,nbin,"rdf:hist");
memory->create(histall,npairs,nbin,"rdf:histall");
memory->create(array,nbin,1+2*npairs,"rdf:array");
typecount = new int[ntypes+1];
icount = new int[npairs];
jcount = new int[npairs];
}
/* ---------------------------------------------------------------------- */
ComputeRDF::~ComputeRDF()
{
memory->destroy(rdfpair);
memory->destroy(nrdfpair);
delete [] ilo;
delete [] ihi;
delete [] jlo;
delete [] jhi;
memory->destroy(hist);
memory->destroy(histall);
memory->destroy(array);
delete [] typecount;
delete [] icount;
delete [] jcount;
}
/* ---------------------------------------------------------------------- */
void ComputeRDF::init()
{
int i,m;
if (force->pair) delr = force->pair->cutforce / nbin;
- else error->all("Compute rdf requires a pair style be defined");
+ else error->all(FLERR,"Compute rdf requires a pair style be defined");
delrinv = 1.0/delr;
// set 1st column of output array to bin coords
for (int i = 0; i < nbin; i++)
array[i][0] = (i+0.5) * delr;
// count atoms of each type that are also in group
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
int ntypes = atom->ntypes;
for (i = 1; i <= ntypes; i++) typecount[i] = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) typecount[type[i]]++;
// icount = # of I atoms participating in I,J pairs for each histogram
// jcount = # of J atoms participating in I,J pairs for each histogram
for (m = 0; m < npairs; m++) {
icount[m] = 0;
for (i = ilo[m]; i <= ihi[m]; i++) icount[m] += typecount[i];
jcount[m] = 0;
for (i = jlo[m]; i <= jhi[m]; i++) jcount[m] += typecount[i];
}
int *scratch = new int[npairs];
MPI_Allreduce(icount,scratch,npairs,MPI_INT,MPI_SUM,world);
for (i = 0; i < npairs; i++) icount[i] = scratch[i];
MPI_Allreduce(jcount,scratch,npairs,MPI_INT,MPI_SUM,world);
for (i = 0; i < npairs; i++) jcount[i] = scratch[i];
delete [] scratch;
// need an occasional half neighbor list
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->compute = 1;
neighbor->requests[irequest]->occasional = 1;
}
/* ---------------------------------------------------------------------- */
void ComputeRDF::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void ComputeRDF::compute_array()
{
int i,j,m,ii,jj,inum,jnum,itype,jtype,ipair,jpair,ibin,ihisto;
double xtmp,ytmp,ztmp,delx,dely,delz,r;
int *ilist,*jlist,*numneigh,**firstneigh;
double factor_lj,factor_coul;
invoked_array = update->ntimestep;
// invoke half neighbor list (will copy or build if necessary)
neighbor->build_one(list->index);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// zero the histogram counts
for (i = 0; i < npairs; i++)
for (j = 0; j < nbin; j++)
hist[i][j] = 0;
// tally the RDF
// both atom i and j must be in fix group
// itype,jtype must have been specified by user
// consider I,J as one interaction even if neighbor pair is stored on 2 procs
// tally I,J pair each time I is central atom, and each time J is central
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (!(mask[i] & groupbit)) continue;
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
// if both weighting factors are 0, skip this pair
// could be 0 and still be in neigh list for long-range Coulombics
// want consistency with non-charged pairs which wouldn't be in list
if (factor_lj == 0.0 && factor_coul == 0.0) continue;
if (!(mask[j] & groupbit)) continue;
jtype = type[j];
ipair = nrdfpair[itype][jtype];
jpair = nrdfpair[jtype][itype];
if (!ipair && !jpair) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
r = sqrt(delx*delx + dely*dely + delz*delz);
ibin = static_cast<int> (r*delrinv);
if (ibin >= nbin) continue;
if (ipair)
for (ihisto = 0; ihisto < ipair; ihisto++)
hist[rdfpair[ihisto][itype][jtype]][ibin] += 1.0;
if (newton_pair || j < nlocal) {
if (jpair)
for (ihisto = 0; ihisto < jpair; ihisto++)
hist[rdfpair[ihisto][jtype][itype]][ibin] += 1.0;
}
}
}
// sum histograms across procs
MPI_Allreduce(hist[0],histall[0],npairs*nbin,MPI_DOUBLE,MPI_SUM,world);
// convert counts to g(r) and coord(r) and copy into output array
// nideal = # of J atoms surrounding single I atom in a single bin
// assuming J atoms are at uniform density
double constant,nideal,gr,ncoord,rlower,rupper;
double PI = 4.0*atan(1.0);
if (domain->dimension == 3) {
constant = 4.0*PI / (3.0*domain->xprd*domain->yprd*domain->zprd);
for (m = 0; m < npairs; m++) {
ncoord = 0.0;
for (ibin = 0; ibin < nbin; ibin++) {
rlower = ibin*delr;
rupper = (ibin+1)*delr;
nideal = constant *
(rupper*rupper*rupper - rlower*rlower*rlower) * jcount[m];
if (icount[m]*nideal != 0.0)
gr = histall[m][ibin] / (icount[m]*nideal);
else gr = 0.0;
ncoord += gr*nideal;
array[ibin][1+2*m] = gr;
array[ibin][2+2*m] = ncoord;
}
}
} else {
constant = PI / (domain->xprd*domain->yprd);
for (m = 0; m < npairs; m++) {
ncoord = 0.0;
for (ibin = 0; ibin < nbin; ibin++) {
rlower = ibin*delr;
rupper = (ibin+1)*delr;
nideal = constant * (rupper*rupper - rlower*rlower) * jcount[m];
if (icount[m]*nideal != 0.0)
gr = histall[m][ibin] / (icount[m]*nideal);
else gr = 0.0;
ncoord += gr*nideal;
array[ibin][1+2*m] = gr;
array[ibin][2+2*m] = ncoord;
}
}
}
}
diff --git a/src/compute_reduce.cpp b/src/compute_reduce.cpp
index 8764afe75..3872661a6 100644
--- a/src/compute_reduce.cpp
+++ b/src/compute_reduce.cpp
@@ -1,656 +1,654 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "string.h"
#include "stdlib.h"
#include "compute_reduce.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "force.h"
#include "comm.h"
#include "group.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{SUM,MINN,MAXX,AVE};
enum{X,V,F,COMPUTE,FIX,VARIABLE};
enum{PERATOM,LOCAL};
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
#define INVOKED_PERATOM 8
#define INVOKED_LOCAL 16
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
ComputeReduce::ComputeReduce(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
int iarg;
if (strcmp(style,"reduce") == 0) {
- if (narg < 5) error->all("Illegal compute reduce command");
+ if (narg < 5) error->all(FLERR,"Illegal compute reduce command");
idregion = NULL;
iarg = 3;
} else if (strcmp(style,"reduce/region") == 0) {
- if (narg < 6) error->all("Illegal compute reduce/region command");
+ if (narg < 6) error->all(FLERR,"Illegal compute reduce/region command");
iregion = domain->find_region(arg[3]);
if (iregion == -1)
- error->all("Region ID for compute reduce/region does not exist");
+ error->all(FLERR,"Region ID for compute reduce/region does not exist");
int n = strlen(arg[3]) + 1;
idregion = new char[n];
strcpy(idregion,arg[3]);
iarg = 4;
}
if (strcmp(arg[iarg],"sum") == 0) mode = SUM;
else if (strcmp(arg[iarg],"min") == 0) mode = MINN;
else if (strcmp(arg[iarg],"max") == 0) mode = MAXX;
else if (strcmp(arg[iarg],"ave") == 0) mode = AVE;
- else error->all("Illegal compute reduce command");
+ else error->all(FLERR,"Illegal compute reduce command");
iarg++;
MPI_Comm_rank(world,&me);
// parse remaining values until one isn't recognized
which = new int[narg-4];
argindex = new int[narg-4];
flavor = new int[narg-4];
ids = new char*[narg-4];
value2index = new int[narg-4];
nvalues = 0;
while (iarg < narg) {
ids[nvalues] = NULL;
if (strcmp(arg[iarg],"x") == 0) {
which[nvalues] = X;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"y") == 0) {
which[nvalues] = X;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"z") == 0) {
which[nvalues] = X;
argindex[nvalues++] = 2;
} else if (strcmp(arg[iarg],"vx") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"vy") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"vz") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 2;
} else if (strcmp(arg[iarg],"fx") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"fy") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"fz") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 2;
} else if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal compute reduce command");
+ error->all(FLERR,"Illegal compute reduce command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
nvalues++;
delete [] suffix;
} else break;
iarg++;
}
// optional args
replace = new int[nvalues];
for (int i = 0; i < nvalues; i++) replace[i] = -1;
while (iarg < narg) {
if (strcmp(arg[iarg],"replace") == 0) {
- if (iarg+3 > narg) error->all("Illegal compute reduce command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal compute reduce command");
if (mode != MINN && mode != MAXX)
- error->all("Compute reduce replace requires min or max mode");
+ error->all(FLERR,"Compute reduce replace requires min or max mode");
int col1 = atoi(arg[iarg+1]) - 1;
int col2 = atoi(arg[iarg+2]) - 1;
if (col1 < 0 || col1 >= nvalues || col2 < 0 || col2 >= nvalues)
- error->all("Illegal compute reduce command");
- if (col1 == col2) error->all("Illegal compute reduce command");
+ error->all(FLERR,"Illegal compute reduce command");
+ if (col1 == col2) error->all(FLERR,"Illegal compute reduce command");
if (replace[col1] >= 0 || replace[col2] >= 0)
- error->all("Invalid replace values in compute reduce");
+ error->all(FLERR,"Invalid replace values in compute reduce");
replace[col1] = col2;
iarg += 3;
- } else error->all("Illegal compute reduce command");
+ } else error->all(FLERR,"Illegal compute reduce command");
}
// delete replace if not set
int flag = 0;
for (int i = 0; i < nvalues; i++)
if (replace[i] >= 0) flag = 1;
if (!flag) {
delete [] replace;
replace = NULL;
}
// setup and error check
for (int i = 0; i < nvalues; i++) {
if (which[i] == X || which[i] == V || which[i] == F)
flavor[i] = PERATOM;
else if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for compute reduce does not exist");
+ error->all(FLERR,"Compute ID for compute reduce does not exist");
if (modify->compute[icompute]->peratom_flag) {
flavor[i] = PERATOM;
if (argindex[i] == 0 &&
modify->compute[icompute]->size_peratom_cols != 0)
- error->all("Compute reduce compute does not "
+ error->all(FLERR,"Compute reduce compute does not "
"calculate a per-atom vector");
if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0)
- error->all("Compute reduce compute does not "
+ error->all(FLERR,"Compute reduce compute does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_peratom_cols)
- error->all("Compute reduce compute array is accessed out-of-range");
+ error->all(FLERR,"Compute reduce compute array is accessed out-of-range");
} else if (modify->compute[icompute]->local_flag) {
flavor[i] = LOCAL;
if (argindex[i] == 0 &&
modify->compute[icompute]->size_local_cols != 0)
- error->all("Compute reduce compute does not "
+ error->all(FLERR,"Compute reduce compute does not "
"calculate a local vector");
if (argindex[i] && modify->compute[icompute]->size_local_cols == 0)
- error->all("Compute reduce compute does not "
+ error->all(FLERR,"Compute reduce compute does not "
"calculate a local array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_local_cols)
- error->all("Compute reduce compute array is accessed out-of-range");
- } else error->all("Compute reduce compute calculates global values");
+ error->all(FLERR,"Compute reduce compute array is accessed out-of-range");
+ } else error->all(FLERR,"Compute reduce compute calculates global values");
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for compute reduce does not exist");
+ error->all(FLERR,"Fix ID for compute reduce does not exist");
if (modify->fix[ifix]->peratom_flag) {
flavor[i] = PERATOM;
if (argindex[i] == 0 &&
modify->fix[ifix]->size_peratom_cols != 0)
- error->all("Compute reduce fix does not "
+ error->all(FLERR,"Compute reduce fix does not "
"calculate a per-atom vector");
if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0)
- error->all("Compute reduce fix does not "
+ error->all(FLERR,"Compute reduce fix does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->fix[ifix]->size_peratom_cols)
- error->all("Compute reduce fix array is accessed out-of-range");
+ error->all(FLERR,"Compute reduce fix array is accessed out-of-range");
} else if (modify->fix[ifix]->local_flag) {
flavor[i] = LOCAL;
if (argindex[i] == 0 &&
modify->fix[ifix]->size_local_cols != 0)
- error->all("Compute reduce fix does not "
+ error->all(FLERR,"Compute reduce fix does not "
"calculate a local vector");
if (argindex[i] && modify->fix[ifix]->size_local_cols == 0)
- error->all("Compute reduce fix does not "
+ error->all(FLERR,"Compute reduce fix does not "
"calculate a local array");
if (argindex[i] &&
argindex[i] > modify->fix[ifix]->size_local_cols)
- error->all("Compute reduce fix array is accessed out-of-range");
- } else error->all("Compute reduce fix calculates global values");
+ error->all(FLERR,"Compute reduce fix array is accessed out-of-range");
+ } else error->all(FLERR,"Compute reduce fix calculates global values");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for compute reduce does not exist");
+ error->all(FLERR,"Variable name for compute reduce does not exist");
if (input->variable->atomstyle(ivariable) == 0)
- error->all("Compute reduce variable is not atom-style variable");
+ error->all(FLERR,"Compute reduce variable is not atom-style variable");
flavor[i] = PERATOM;
}
}
// this compute produces either a scalar or vector
if (nvalues == 1) {
scalar_flag = 1;
if (mode == SUM) extscalar = 1;
else extscalar = 0;
vector = onevec = NULL;
indices = owner = NULL;
} else {
vector_flag = 1;
size_vector = nvalues;
if (mode == SUM) extvector = 1;
else extvector = 0;
vector = new double[size_vector];
onevec = new double[size_vector];
indices = new int[size_vector];
owner = new int[size_vector];
}
maxatom = 0;
varatom = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeReduce::~ComputeReduce()
{
delete [] which;
delete [] argindex;
delete [] flavor;
for (int m = 0; m < nvalues; m++) delete [] ids[m];
delete [] ids;
delete [] value2index;
delete [] replace;
delete [] idregion;
delete [] vector;
delete [] onevec;
delete [] indices;
delete [] owner;
memory->destroy(varatom);
}
/* ---------------------------------------------------------------------- */
void ComputeReduce::init()
{
// set indices and check validity of all computes,fixes,variables
for (int m = 0; m < nvalues; m++) {
if (which[m] == COMPUTE) {
int icompute = modify->find_compute(ids[m]);
if (icompute < 0)
- error->all("Compute ID for compute reduce does not exist");
+ error->all(FLERR,"Compute ID for compute reduce does not exist");
value2index[m] = icompute;
} else if (which[m] == FIX) {
int ifix = modify->find_fix(ids[m]);
if (ifix < 0)
- error->all("Fix ID for compute reduce does not exist");
+ error->all(FLERR,"Fix ID for compute reduce does not exist");
value2index[m] = ifix;
} else if (which[m] == VARIABLE) {
int ivariable = input->variable->find(ids[m]);
if (ivariable < 0)
- error->all("Variable name for compute reduce does not exist");
+ error->all(FLERR,"Variable name for compute reduce does not exist");
value2index[m] = ivariable;
} else value2index[m] = -1;
}
// set index and check validity of region
if (idregion) {
iregion = domain->find_region(idregion);
if (iregion == -1)
- error->all("Region ID for compute reduce/region does not exist");
+ error->all(FLERR,"Region ID for compute reduce/region does not exist");
}
}
/* ---------------------------------------------------------------------- */
double ComputeReduce::compute_scalar()
{
invoked_scalar = update->ntimestep;
double one = compute_one(0,-1);
if (mode == SUM) {
MPI_Allreduce(&one,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
} else if (mode == MINN) {
MPI_Allreduce(&one,&scalar,1,MPI_DOUBLE,MPI_MIN,world);
} else if (mode == MAXX) {
MPI_Allreduce(&one,&scalar,1,MPI_DOUBLE,MPI_MAX,world);
} else if (mode == AVE) {
MPI_Allreduce(&one,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
bigint n = count(0);
if (n) scalar /= n;
}
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeReduce::compute_vector()
{
invoked_vector = update->ntimestep;
for (int m = 0; m < nvalues; m++)
if (!replace || replace[m] < 0) {
onevec[m] = compute_one(m,-1);
indices[m] = index;
}
if (mode == SUM) {
for (int m = 0; m < nvalues; m++)
MPI_Allreduce(&onevec[m],&vector[m],1,MPI_DOUBLE,MPI_SUM,world);
} else if (mode == MINN) {
if (!replace) {
for (int m = 0; m < nvalues; m++)
MPI_Allreduce(&onevec[m],&vector[m],1,MPI_DOUBLE,MPI_MIN,world);
} else {
for (int m = 0; m < nvalues; m++)
if (replace[m] < 0) {
pairme.value = onevec[m];
pairme.proc = me;
MPI_Allreduce(&pairme,&pairall,1,MPI_DOUBLE_INT,MPI_MINLOC,world);
vector[m] = pairall.value;
owner[m] = pairall.proc;
}
for (int m = 0; m < nvalues; m++)
if (replace[m] >= 0) {
if (me == owner[replace[m]])
vector[m] = compute_one(m,indices[replace[m]]);
MPI_Bcast(&vector[m],1,MPI_DOUBLE,owner[replace[m]],world);
}
}
} else if (mode == MAXX) {
if (!replace) {
for (int m = 0; m < nvalues; m++)
MPI_Allreduce(&onevec[m],&vector[m],1,MPI_DOUBLE,MPI_MAX,world);
} else {
for (int m = 0; m < nvalues; m++)
if (replace[m] < 0) {
pairme.value = onevec[m];
pairme.proc = me;
MPI_Allreduce(&pairme,&pairall,1,MPI_DOUBLE_INT,MPI_MAXLOC,world);
vector[m] = pairall.value;
owner[m] = pairall.proc;
}
for (int m = 0; m < nvalues; m++)
if (replace[m] >= 0) {
if (me == owner[replace[m]])
vector[m] = compute_one(m,indices[replace[m]]);
MPI_Bcast(&vector[m],1,MPI_DOUBLE,owner[replace[m]],world);
}
}
} else if (mode == AVE) {
for (int m = 0; m < nvalues; m++) {
MPI_Allreduce(&onevec[m],&vector[m],1,MPI_DOUBLE,MPI_SUM,world);
bigint n = count(m);
if (n) vector[m] /= n;
}
}
}
/* ----------------------------------------------------------------------
calculate reduced value for one input M and return it
if flag = -1:
sum/min/max/ave all values in vector
for per-atom quantities, limit to atoms in group
if mode = MIN or MAX, also set index to which vector value wins
if flag >= 0: simply return vector[flag]
------------------------------------------------------------------------- */
double ComputeReduce::compute_one(int m, int flag)
{
int i;
// invoke the appropriate attribute,compute,fix,variable
// for flag = -1, compute scalar quantity by scanning over atom properties
// only include atoms in group for atom properties and per-atom quantities
index = -1;
int vidx = value2index[m];
int aidx = argindex[m];
int *mask = atom->mask;
int nlocal = atom->nlocal;
double one;
if (mode == SUM) one = 0.0;
else if (mode == MINN) one = BIG;
else if (mode == MAXX) one = -BIG;
else if (mode == AVE) one = 0.0;
if (which[m] == X) {
double **x = atom->x;
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) combine(one,x[i][aidx],i);
} else one = x[flag][aidx];
} else if (which[m] == V) {
double **v = atom->v;
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) combine(one,v[i][aidx],i);
} else one = v[flag][aidx];
} else if (which[m] == F) {
double **f = atom->f;
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) combine(one,f[i][aidx],i);
} else one = f[flag][aidx];
// invoke compute if not previously invoked
} else if (which[m] == COMPUTE) {
Compute *compute = modify->compute[vidx];
if (flavor[m] == PERATOM) {
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
if (aidx == 0) {
double *comp_vec = compute->vector_atom;
int n = nlocal;
if (flag < 0) {
for (i = 0; i < n; i++)
if (mask[i] & groupbit) combine(one,comp_vec[i],i);
} else one = comp_vec[flag];
} else {
double **carray_atom = compute->array_atom;
int n = nlocal;
int aidxm1 = aidx - 1;
if (flag < 0) {
for (i = 0; i < n; i++)
if (mask[i] & groupbit) combine(one,carray_atom[i][aidxm1],i);
} else one = carray_atom[flag][aidxm1];
}
} else if (flavor[m] == LOCAL) {
if (!(compute->invoked_flag & INVOKED_LOCAL)) {
compute->compute_local();
compute->invoked_flag |= INVOKED_LOCAL;
}
if (aidx == 0) {
double *comp_vec = compute->vector_local;
int n = compute->size_local_rows;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,comp_vec[i],i);
else one = comp_vec[flag];
} else {
double **carray_local = compute->array_local;
int n = compute->size_local_rows;
int aidxm1 = aidx - 1;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,carray_local[i][aidxm1],i);
else one = carray_local[flag][aidxm1];
}
}
// access fix fields, check if fix frequency is a match
} else if (which[m] == FIX) {
if (update->ntimestep % modify->fix[vidx]->peratom_freq)
- error->all("Fix used in compute reduce not computed at compatible time");
+ error->all(FLERR,"Fix used in compute reduce not computed at compatible time");
Fix *fix = modify->fix[vidx];
if (flavor[m] == PERATOM) {
if (aidx == 0) {
double *fix_vector = fix->vector_atom;
int n = nlocal;
if (flag < 0) {
for (i = 0; i < n; i++)
if (mask[i] & groupbit) combine(one,fix_vector[i],i);
} else one = fix_vector[flag];
} else {
double **fix_array = fix->array_atom;
int aidxm1 = aidx - 1;
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) combine(one,fix_array[i][aidxm1],i);
} else one = fix_array[flag][aidxm1];
}
} else if (flavor[m] == LOCAL) {
if (aidx == 0) {
double *fix_vector = fix->vector_local;
int n = fix->size_local_rows;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,fix_vector[i],i);
else one = fix_vector[flag];
} else {
double **fix_array = fix->array_local;
int n = fix->size_local_rows;
int aidxm1 = aidx - 1;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,fix_array[i][aidxm1],i);
else one = fix_array[flag][aidxm1];
}
}
// evaluate atom-style variable
} else if (which[m] == VARIABLE) {
if (nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(varatom);
memory->create(varatom,maxatom,"reduce:varatom");
}
input->variable->compute_atom(vidx,igroup,varatom,1,0);
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) combine(one,varatom[i],i);
} else one = varatom[flag];
}
return one;
}
/* ---------------------------------------------------------------------- */
bigint ComputeReduce::count(int m)
{
int vidx = value2index[m];
if (which[m] == X || which[m] == V || which[m] == F)
return group->count(igroup);
else if (which[m] == COMPUTE) {
Compute *compute = modify->compute[vidx];
if (flavor[m] == PERATOM) {
return group->count(igroup);
} else if (flavor[m] == LOCAL) {
bigint ncount = compute->size_local_rows;
bigint ncountall;
MPI_Allreduce(&ncount,&ncountall,1,MPI_LMP_BIGINT,MPI_SUM,world);
return ncountall;
}
} else if (which[m] == FIX) {
Fix *fix = modify->fix[vidx];
if (flavor[m] == PERATOM) {
return group->count(igroup);
} else if (flavor[m] == LOCAL) {
bigint ncount = fix->size_local_rows;
bigint ncountall;
MPI_Allreduce(&ncount,&ncountall,1,MPI_LMP_BIGINT,MPI_SUM,world);
return ncountall;
}
} else if (which[m] == VARIABLE)
return group->count(igroup);
bigint dummy = 0;
return dummy;
}
/* ----------------------------------------------------------------------
combine two values according to reduction mode
for MIN/MAX, also update index with winner
------------------------------------------------------------------------- */
void ComputeReduce::combine(double &one, double two, int i)
{
if (mode == SUM || mode == AVE) one += two;
else if (mode == MINN) {
if (two < one) {
one = two;
index = i;
}
} else if (mode == MAXX) {
if (two > one) {
one = two;
index = i;
}
}
}
/* ----------------------------------------------------------------------
memory usage of varatom
------------------------------------------------------------------------- */
double ComputeReduce::memory_usage()
{
double bytes = maxatom * sizeof(double);
return bytes;
}
diff --git a/src/compute_reduce_region.cpp b/src/compute_reduce_region.cpp
index eff9416b1..648b90e1d 100644
--- a/src/compute_reduce_region.cpp
+++ b/src/compute_reduce_region.cpp
@@ -1,253 +1,253 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "compute_reduce_region.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "group.h"
#include "region.h"
#include "fix.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{SUM,MINN,MAXX,AVE};
enum{X,V,F,COMPUTE,FIX,VARIABLE};
enum{PERATOM,LOCAL};
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
#define INVOKED_PERATOM 8
#define INVOKED_LOCAL 16
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
ComputeReduceRegion::ComputeReduceRegion(LAMMPS *lmp, int narg, char **arg) :
ComputeReduce(lmp, narg, arg) {}
/* ----------------------------------------------------------------------
calculate reduced value for one input M and return it
if flag = -1:
sum/min/max/ave all values in vector
for per-atom quantities, limit to atoms in group and region
if mode = MIN or MAX, also set index to which vector value wins
if flag >= 0: simply return vector[flag]
------------------------------------------------------------------------- */
double ComputeReduceRegion::compute_one(int m, int flag)
{
int i;
Region *region = domain->regions[iregion];
// invoke the appropriate attribute,compute,fix,variable
// compute scalar quantity by summing over atom scalars
// only include atoms in group
index = -1;
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int n = value2index[m];
int j = argindex[m];
double one;
if (mode == SUM) one = 0.0;
else if (mode == MINN) one = BIG;
else if (mode == MAXX) one = -BIG;
else if (mode == AVE) one = 0.0;
if (which[m] == X) {
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,x[i][j],i);
} else one = x[flag][j];
} else if (which[m] == V) {
double **v = atom->v;
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,v[i][j],i);
} else one = v[flag][j];
} else if (which[m] == F) {
double **f = atom->f;
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,f[i][j],i);
} else one = f[flag][j];
// invoke compute if not previously invoked
} else if (which[m] == COMPUTE) {
Compute *compute = modify->compute[n];
if (flavor[m] == PERATOM) {
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
if (j == 0) {
double *compute_vector = compute->vector_atom;
int n = nlocal;
if (flag < 0) {
for (i = 0; i < n; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,compute_vector[i],i);
} else one = compute_vector[flag];
} else {
double **compute_array = compute->array_atom;
int n = nlocal;
int jm1 = j - 1;
if (flag < 0) {
for (i = 0; i < n; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,compute_array[i][jm1],i);
} else one = compute_array[flag][jm1];
}
} else if (flavor[m] == LOCAL) {
if (!(compute->invoked_flag & INVOKED_LOCAL)) {
compute->compute_local();
compute->invoked_flag |= INVOKED_LOCAL;
}
if (j == 0) {
double *compute_vector = compute->vector_local;
int n = compute->size_local_rows;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,compute_vector[i],i);
else one = compute_vector[flag];
} else {
double **compute_array = compute->array_local;
int n = compute->size_local_rows;
int jm1 = j - 1;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,compute_array[i][jm1],i);
else one = compute_array[flag][jm1];
}
}
// check if fix frequency is a match
} else if (which[m] == FIX) {
if (update->ntimestep % modify->fix[n]->peratom_freq)
- error->all("Fix used in compute reduce not computed at compatible time");
+ error->all(FLERR,"Fix used in compute reduce not computed at compatible time");
Fix *fix = modify->fix[n];
if (flavor[m] == PERATOM) {
if (j == 0) {
double *fix_vector = fix->vector_atom;
int n = nlocal;
if (flag < 0) {
for (i = 0; i < n; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,fix_vector[i],i);
} else one = fix_vector[flag];
} else {
double **fix_array = fix->array_atom;
int jm1 = j - 1;
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,fix_array[i][jm1],i);
} else one = fix_array[flag][jm1];
}
} else if (flavor[m] == LOCAL) {
if (j == 0) {
double *fix_vector = fix->vector_local;
int n = fix->size_local_rows;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,fix_vector[i],i);
else one = fix_vector[flag];
} else {
double **fix_array = fix->array_local;
int n = fix->size_local_rows;
int jm1 = j - 1;
if (flag < 0)
for (i = 0; i < n; i++)
combine(one,fix_array[i][jm1],i);
else one = fix_array[flag][jm1];
}
}
// evaluate atom-style variable
} else if (which[m] == VARIABLE) {
if (nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(varatom);
memory->create(varatom,maxatom,"reduce/region:varatom");
}
input->variable->compute_atom(n,igroup,varatom,1,0);
if (flag < 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
combine(one,varatom[i],i);
} else one = varatom[flag];
}
return one;
}
/* ---------------------------------------------------------------------- */
bigint ComputeReduceRegion::count(int m)
{
int n = value2index[m];
if (which[m] == X || which[m] == V || which[m] == F)
return group->count(igroup,iregion);
else if (which[m] == COMPUTE) {
Compute *compute = modify->compute[n];
if (flavor[m] == PERATOM) {
return group->count(igroup,iregion);
} else if (flavor[m] == LOCAL) {
bigint ncount = compute->size_local_rows;
bigint ncountall;
MPI_Allreduce(&ncount,&ncountall,1,MPI_DOUBLE,MPI_SUM,world);
return ncountall;
}
} else if (which[m] == FIX) {
Fix *fix = modify->fix[n];
if (flavor[m] == PERATOM) {
return group->count(igroup,iregion);
} else if (flavor[m] == LOCAL) {
bigint ncount = fix->size_local_rows;
bigint ncountall;
MPI_Allreduce(&ncount,&ncountall,1,MPI_DOUBLE,MPI_SUM,world);
return ncountall;
}
} else if (which[m] == VARIABLE)
return group->count(igroup,iregion);
bigint dummy = 0;
return dummy;
}
diff --git a/src/compute_slice.cpp b/src/compute_slice.cpp
index 51e7747e3..85e923049 100644
--- a/src/compute_slice.cpp
+++ b/src/compute_slice.cpp
@@ -1,312 +1,312 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "compute_slice.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{COMPUTE,FIX};
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
/* ---------------------------------------------------------------------- */
ComputeSlice::ComputeSlice(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal compute slice command");
+ if (narg < 7) error->all(FLERR,"Illegal compute slice command");
MPI_Comm_rank(world,&me);
nstart = atoi(arg[3]);
nstop = atoi(arg[4]);
nskip = atoi(arg[5]);
if (nstart < 1 || nstop < nstart || nskip < 1)
- error->all("Illegal compute slice command");
+ error->all(FLERR,"Illegal compute slice command");
// parse remaining values until one isn't recognized
which = new int[narg-6];
argindex = new int[narg-6];
ids = new char*[narg-6];
value2index = new int[narg-6];
nvalues = 0;
for (int iarg = 6; iarg < narg; iarg++) {
if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal compute slice command");
+ error->all(FLERR,"Illegal compute slice command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
nvalues++;
delete [] suffix;
- } else error->all("Illegal compute slice command");
+ } else error->all(FLERR,"Illegal compute slice command");
}
// setup and error check
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for compute slice does not exist");
+ error->all(FLERR,"Compute ID for compute slice does not exist");
if (modify->compute[icompute]->vector_flag) {
if (argindex[i])
- error->all("Compute slice compute does not calculate a global array");
+ error->all(FLERR,"Compute slice compute does not calculate a global array");
if (nstop > modify->compute[icompute]->size_vector)
- error->all("Compute slice compute vector is accessed out-of-range");
+ error->all(FLERR,"Compute slice compute vector is accessed out-of-range");
} else if (modify->compute[icompute]->array_flag) {
if (argindex[i] == 0)
- error->all("Compute slice compute does not calculate a global vector");
+ error->all(FLERR,"Compute slice compute does not calculate a global vector");
if (argindex[i] > modify->compute[icompute]->size_array_cols)
- error->all("Compute slice compute array is accessed out-of-range");
+ error->all(FLERR,"Compute slice compute array is accessed out-of-range");
if (nstop > modify->compute[icompute]->size_array_rows)
- error->all("Compute slice compute array is accessed out-of-range");
- } else error->all("Compute slice compute does not calculate "
+ error->all(FLERR,"Compute slice compute array is accessed out-of-range");
+ } else error->all(FLERR,"Compute slice compute does not calculate "
"global vector or array");
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for compute slice does not exist");
+ error->all(FLERR,"Fix ID for compute slice does not exist");
if (modify->fix[ifix]->vector_flag) {
if (argindex[i])
- error->all("Compute slice fix does not calculate a global array");
+ error->all(FLERR,"Compute slice fix does not calculate a global array");
if (nstop > modify->fix[ifix]->size_vector)
- error->all("Compute slice fix vector is accessed out-of-range");
+ error->all(FLERR,"Compute slice fix vector is accessed out-of-range");
} else if (modify->fix[ifix]->array_flag) {
if (argindex[i] == 0)
- error->all("Compute slice fix does not calculate a global vector");
+ error->all(FLERR,"Compute slice fix does not calculate a global vector");
if (argindex[i] > modify->fix[ifix]->size_array_cols)
- error->all("Compute slice fix array is accessed out-of-range");
+ error->all(FLERR,"Compute slice fix array is accessed out-of-range");
if (nstop > modify->fix[ifix]->size_array_rows)
- error->all("Compute slice fix array is accessed out-of-range");
- } else error->all("Compute slice fix does not calculate "
+ error->all(FLERR,"Compute slice fix array is accessed out-of-range");
+ } else error->all(FLERR,"Compute slice fix does not calculate "
"global vector or array");
}
}
// this compute produces either a vector or array
// for vector, set intensive/extensive to mirror input values
// for array, set intensive if all input values are intensive, else extensive
vector = NULL;
array = NULL;
extlist = NULL;
if (nvalues == 1) {
vector_flag = 1;
size_vector = (nstop-nstart) / nskip;
memory->create(vector,size_vector,"slice:vector");
if (which[0] == COMPUTE) {
int icompute = modify->find_compute(ids[0]);
if (argindex[0] == 0) {
extvector = modify->compute[icompute]->extvector;
if (modify->compute[icompute]->extvector == -1) {
extlist = new int[size_vector];
int j = 0;
for (int i = nstart; i < nstop; i += nskip)
extlist[j++] = modify->compute[icompute]->extlist[i-1];
}
} else extvector = modify->compute[icompute]->extarray;
} else if (which[0] == FIX) {
int ifix = modify->find_fix(ids[0]);
if (argindex[0] == 0) {
extvector = modify->fix[ifix]->extvector;
if (modify->fix[ifix]->extvector == -1) {
extlist = new int[size_vector];
int j = 0;
for (int i = nstart; i < nstop; i += nskip)
extlist[j++] = modify->fix[ifix]->extlist[i-1];
}
} else extvector = modify->fix[ifix]->extarray;
}
} else {
array_flag = 1;
size_array_rows = (nstop-nstart) / nskip;
size_array_cols = nvalues;
memory->create(array,size_array_rows,size_array_cols,"slice:array");
extarray = 0;
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (argindex[i] == 0) {
if (modify->compute[icompute]->extvector == 1) extarray = 1;
if (modify->compute[icompute]->extvector == -1) {
for (int j = 0; j < modify->compute[icompute]->size_vector; j++)
if (modify->compute[icompute]->extlist[j]) extarray = 1;
}
} else {
if (modify->compute[icompute]->extarray) extarray = 1;
}
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (argindex[i] == 0) {
if (modify->fix[ifix]->extvector == 1) extarray = 1;
if (modify->fix[ifix]->extvector == -1) {
for (int j = 0; j < modify->fix[ifix]->size_vector; j++)
if (modify->fix[ifix]->extlist[j]) extarray = 1;
}
} else {
if (modify->fix[ifix]->extarray) extarray = 1;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
ComputeSlice::~ComputeSlice()
{
delete [] which;
delete [] argindex;
for (int m = 0; m < nvalues; m++) delete [] ids[m];
delete [] ids;
delete [] value2index;
memory->destroy(vector);
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
void ComputeSlice::init()
{
// set indices and check validity of all computes,fixes
for (int m = 0; m < nvalues; m++) {
if (which[m] == COMPUTE) {
int icompute = modify->find_compute(ids[m]);
if (icompute < 0)
- error->all("Compute ID for compute slice does not exist");
+ error->all(FLERR,"Compute ID for compute slice does not exist");
value2index[m] = icompute;
} else if (which[m] == FIX) {
int ifix = modify->find_fix(ids[m]);
if (ifix < 0)
- error->all("Fix ID for compute slice does not exist");
+ error->all(FLERR,"Fix ID for compute slice does not exist");
value2index[m] = ifix;
}
}
}
/* ---------------------------------------------------------------------- */
void ComputeSlice::compute_vector()
{
invoked_vector = update->ntimestep;
extract_one(0,vector,1);
}
/* ---------------------------------------------------------------------- */
void ComputeSlice::compute_array()
{
invoked_array = update->ntimestep;
for (int m = 0; m < nvalues; m++)
extract_one(0,&array[m][0],nvalues);
}
/* ----------------------------------------------------------------------
calculate sliced value for one input M and return it in vec
vec may be array so that returned values are with stride
------------------------------------------------------------------------- */
void ComputeSlice::extract_one(int m, double *vec, int stride)
{
int i,j;
// invoke the appropriate compute if needed
if (which[m] == COMPUTE) {
Compute *compute = modify->compute[value2index[m]];
if (argindex[m] == 0) {
if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
double *cvector = compute->vector;
j = 0;
for (i = nstart; i < nstop; i += nskip) {
vec[j] = cvector[i-1];
j += stride;
}
} else {
if (!(compute->invoked_flag & INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
}
double **carray = compute->array;
int icol = argindex[m]-1;
j = 0;
for (i = nstart; i < nstop; i += nskip) {
vec[j] = carray[i-1][icol];
j += stride;
}
}
// access fix fields, check if fix frequency is a match
} else if (which[m] == FIX) {
if (update->ntimestep % modify->fix[value2index[m]]->global_freq)
- error->all("Fix used in compute slice not computed at compatible time");
+ error->all(FLERR,"Fix used in compute slice not computed at compatible time");
Fix *fix = modify->fix[value2index[m]];
if (argindex[m] == 0) {
j = 0;
for (i = nstart; i < nstop; i += nskip) {
vec[j] = fix->compute_vector(i-1);
j += stride;
}
} else {
int icol = argindex[m]-1;
j = 0;
for (i = nstart; i < nstop; i += nskip) {
vec[j] = fix->compute_array(i-1,icol);
j += stride;
}
}
}
}
diff --git a/src/compute_stress_atom.cpp b/src/compute_stress_atom.cpp
index b17d4fc6a..556022122 100644
--- a/src/compute_stress_atom.cpp
+++ b/src/compute_stress_atom.cpp
@@ -1,288 +1,288 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "compute_stress_atom.h"
#include "atom.h"
#include "update.h"
#include "comm.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "modify.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeStressAtom::ComputeStressAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal compute stress/atom command");
+ if (narg < 3) error->all(FLERR,"Illegal compute stress/atom command");
peratom_flag = 1;
size_peratom_cols = 6;
pressatomflag = 1;
timeflag = 1;
comm_reverse = 6;
if (narg == 3) {
keflag = 1;
pairflag = 1;
bondflag = angleflag = dihedralflag = improperflag = 1;
fixflag = 1;
} else {
keflag = 0;
pairflag = 0;
bondflag = angleflag = dihedralflag = improperflag = 0;
fixflag = 0;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"ke") == 0) keflag = 1;
else if (strcmp(arg[iarg],"pair") == 0) pairflag = 1;
else if (strcmp(arg[iarg],"bond") == 0) bondflag = 1;
else if (strcmp(arg[iarg],"angle") == 0) angleflag = 1;
else if (strcmp(arg[iarg],"dihedral") == 0) dihedralflag = 1;
else if (strcmp(arg[iarg],"improper") == 0) improperflag = 1;
else if (strcmp(arg[iarg],"fix") == 0) fixflag = 1;
else if (strcmp(arg[iarg],"virial") == 0) {
pairflag = 1;
bondflag = angleflag = dihedralflag = improperflag = 1;
fixflag = 1;
- } else error->all("Illegal compute stress/atom command");
+ } else error->all(FLERR,"Illegal compute stress/atom command");
iarg++;
}
}
nmax = 0;
stress = NULL;
}
/* ---------------------------------------------------------------------- */
ComputeStressAtom::~ComputeStressAtom()
{
memory->destroy(stress);
}
/* ---------------------------------------------------------------------- */
void ComputeStressAtom::compute_peratom()
{
int i,j;
double onemass;
invoked_peratom = update->ntimestep;
if (update->vflag_atom != invoked_peratom)
- error->all("Per-atom virial was not tallied on needed timestep");
+ error->all(FLERR,"Per-atom virial was not tallied on needed timestep");
// grow local stress array if necessary
// needs to be atom->nmax in length
if (atom->nmax > nmax) {
memory->destroy(stress);
nmax = atom->nmax;
memory->create(stress,nmax,6,"stress/atom:stress");
array_atom = stress;
}
// npair includes ghosts if either newton flag is set
// b/c some bonds/dihedrals call pair::ev_tally with pairwise info
// nbond includes ghosts if newton_bond is set
// ntotal includes ghosts if either newton flag is set
int nlocal = atom->nlocal;
int npair = nlocal;
int nbond = nlocal;
int ntotal = nlocal;
if (force->newton) npair += atom->nghost;
if (force->newton_bond) nbond += atom->nghost;
if (force->newton) ntotal += atom->nghost;
// clear local stress array
for (i = 0; i < ntotal; i++)
for (j = 0; j < 6; j++)
stress[i][j] = 0.0;
// add in per-atom contributions from each force
if (pairflag && force->pair) {
double **vatom = force->pair->vatom;
for (i = 0; i < npair; i++)
for (j = 0; j < 6; j++)
stress[i][j] += vatom[i][j];
}
if (bondflag && force->bond) {
double **vatom = force->bond->vatom;
for (i = 0; i < nbond; i++)
for (j = 0; j < 6; j++)
stress[i][j] += vatom[i][j];
}
if (angleflag && force->angle) {
double **vatom = force->angle->vatom;
for (i = 0; i < nbond; i++)
for (j = 0; j < 6; j++)
stress[i][j] += vatom[i][j];
}
if (dihedralflag && force->dihedral) {
double **vatom = force->dihedral->vatom;
for (i = 0; i < nbond; i++)
for (j = 0; j < 6; j++)
stress[i][j] += vatom[i][j];
}
if (improperflag && force->improper) {
double **vatom = force->improper->vatom;
for (i = 0; i < nbond; i++)
for (j = 0; j < 6; j++)
stress[i][j] += vatom[i][j];
}
// add in per-atom contributions from relevant fixes
if (fixflag) {
for (int ifix = 0; ifix < modify->nfix; ifix++)
if (modify->fix[ifix]->virial_flag) {
double **vatom = modify->fix[ifix]->vatom;
for (i = 0; i < nlocal; i++)
for (j = 0; j < 6; j++)
stress[i][j] += vatom[i][j];
}
}
// communicate ghost atom virials between neighbor procs
if (force->newton) comm->reverse_comm_compute(this);
// zero virial of atoms not in group
// only do this after comm since ghost contributions must be included
int *mask = atom->mask;
for (i = 0; i < nlocal; i++)
if (!(mask[i] & groupbit)) {
stress[i][0] = 0.0;
stress[i][1] = 0.0;
stress[i][2] = 0.0;
stress[i][3] = 0.0;
stress[i][4] = 0.0;
stress[i][5] = 0.0;
}
// include kinetic energy term for each atom in group
// mvv2e converts mv^2 to energy
if (keflag) {
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
double mvv2e = force->mvv2e;
if (rmass) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
onemass = mvv2e * rmass[i];
stress[i][0] += onemass*v[i][0]*v[i][0];
stress[i][1] += onemass*v[i][1]*v[i][1];
stress[i][2] += onemass*v[i][2]*v[i][2];
stress[i][3] += onemass*v[i][0]*v[i][1];
stress[i][4] += onemass*v[i][0]*v[i][2];
stress[i][5] += onemass*v[i][1]*v[i][2];
}
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
onemass = mvv2e * mass[type[i]];
stress[i][0] += onemass*v[i][0]*v[i][0];
stress[i][1] += onemass*v[i][1]*v[i][1];
stress[i][2] += onemass*v[i][2]*v[i][2];
stress[i][3] += onemass*v[i][0]*v[i][1];
stress[i][4] += onemass*v[i][0]*v[i][2];
stress[i][5] += onemass*v[i][1]*v[i][2];
}
}
}
// convert to stress*volume units = -pressure*volume
double nktv2p = -force->nktv2p;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
stress[i][0] *= nktv2p;
stress[i][1] *= nktv2p;
stress[i][2] *= nktv2p;
stress[i][3] *= nktv2p;
stress[i][4] *= nktv2p;
stress[i][5] *= nktv2p;
}
}
/* ---------------------------------------------------------------------- */
int ComputeStressAtom::pack_reverse_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
buf[m++] = stress[i][0];
buf[m++] = stress[i][1];
buf[m++] = stress[i][2];
buf[m++] = stress[i][3];
buf[m++] = stress[i][4];
buf[m++] = stress[i][5];
}
return 6;
}
/* ---------------------------------------------------------------------- */
void ComputeStressAtom::unpack_reverse_comm(int n, int *list, double *buf)
{
int i,j,m;
m = 0;
for (i = 0; i < n; i++) {
j = list[i];
stress[j][0] += buf[m++];
stress[j][1] += buf[m++];
stress[j][2] += buf[m++];
stress[j][3] += buf[m++];
stress[j][4] += buf[m++];
stress[j][5] += buf[m++];
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double ComputeStressAtom::memory_usage()
{
double bytes = nmax*6 * sizeof(double);
return bytes;
}
diff --git a/src/compute_temp.cpp b/src/compute_temp.cpp
index 5ba16633f..ab63a8c9f 100644
--- a/src/compute_temp.cpp
+++ b/src/compute_temp.cpp
@@ -1,136 +1,136 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_temp.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeTemp::ComputeTemp(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute temp command");
+ if (narg != 3) error->all(FLERR,"Illegal compute temp command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTemp::~ComputeTemp()
{
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTemp::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ---------------------------------------------------------------------- */
void ComputeTemp::dof_compute()
{
double natoms = group->count(igroup);
dof = domain->dimension * natoms;
dof -= extra_dof + fix_dof;
if (dof > 0.0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTemp::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
mass[type[i]];
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTemp::compute_vector()
{
int i;
invoked_vector = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * v[i][0]*v[i][0];
t[1] += massone * v[i][1]*v[i][1];
t[2] += massone * v[i][2]*v[i][2];
t[3] += massone * v[i][0]*v[i][1];
t[4] += massone * v[i][0]*v[i][2];
t[5] += massone * v[i][1]*v[i][2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
diff --git a/src/compute_temp_com.cpp b/src/compute_temp_com.cpp
index 22cfab761..d344d3d21 100644
--- a/src/compute_temp_com.cpp
+++ b/src/compute_temp_com.cpp
@@ -1,219 +1,216 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "compute_temp_com.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "domain.h"
#include "lattice.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
ComputeTempCOM::ComputeTempCOM(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute temp command");
+ if (narg != 3) error->all(FLERR,"Illegal compute temp command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempCOM::~ComputeTempCOM()
{
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempCOM::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
masstotal = group->mass(igroup);
}
/* ---------------------------------------------------------------------- */
void ComputeTempCOM::dof_compute()
{
double natoms = group->count(igroup);
int nper = domain->dimension;
dof = nper * natoms;
dof -= extra_dof + fix_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempCOM::compute_scalar()
{
double vthermal[3];
invoked_scalar = update->ntimestep;
if (dynamic) masstotal = group->mass(igroup);
group->vcm(igroup,masstotal,vbias);
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vthermal[0] = v[i][0] - vbias[0];
vthermal[1] = v[i][1] - vbias[1];
vthermal[2] = v[i][2] - vbias[2];
if (rmass)
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * rmass[i];
else
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * mass[type[i]];
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempCOM::compute_vector()
{
int i;
double vthermal[3];
invoked_vector = update->ntimestep;
if (dynamic) masstotal = group->mass(igroup);
group->vcm(igroup,masstotal,vbias);
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vthermal[0] = v[i][0] - vbias[0];
vthermal[1] = v[i][1] - vbias[1];
vthermal[2] = v[i][2] - vbias[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * vthermal[0]*vthermal[0];
t[1] += massone * vthermal[1]*vthermal[1];
t[2] += massone * vthermal[2]*vthermal[2];
t[3] += massone * vthermal[0]*vthermal[1];
t[4] += massone * vthermal[0]*vthermal[2];
t[5] += massone * vthermal[1]*vthermal[2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempCOM::remove_bias(int i, double *v)
{
v[0] -= vbias[0];
v[1] -= vbias[1];
v[2] -= vbias[2];
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempCOM::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] -= vbias[0];
v[i][1] -= vbias[1];
v[i][2] -= vbias[2];
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempCOM::restore_bias(int i, double *v)
{
v[0] += vbias[0];
v[1] += vbias[1];
v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempCOM::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] += vbias[0];
v[i][1] += vbias[1];
v[i][2] += vbias[2];
}
}
diff --git a/src/compute_temp_deform.cpp b/src/compute_temp_deform.cpp
index 665f904fd..87fcb02ea 100644
--- a/src/compute_temp_deform.cpp
+++ b/src/compute_temp_deform.cpp
@@ -1,286 +1,286 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_temp_deform.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "modify.h"
#include "fix.h"
#include "fix_deform.h"
#include "group.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp
/* ---------------------------------------------------------------------- */
ComputeTempDeform::ComputeTempDeform(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal compute temp/deform command");
+ if (narg != 3) error->all(FLERR,"Illegal compute temp/deform command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempDeform::~ComputeTempDeform()
{
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempDeform::init()
{
int i;
fix_dof = 0;
for (i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
// check fix deform remap settings
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
if (((FixDeform *) modify->fix[i])->remapflag == X_REMAP &&
comm->me == 0)
- error->warning("Using compute temp/deform with inconsistent "
+ error->warning(FLERR,"Using compute temp/deform with inconsistent "
"fix deform remap option");
break;
}
if (i == modify->nfix && comm->me == 0)
- error->warning("Using compute temp/deform with no fix deform defined");
+ error->warning(FLERR,"Using compute temp/deform with no fix deform defined");
}
/* ---------------------------------------------------------------------- */
void ComputeTempDeform::dof_compute()
{
double natoms = group->count(igroup);
dof = domain->dimension * natoms;
dof -= extra_dof + fix_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempDeform::compute_scalar()
{
double lamda[3],vstream[3],vthermal[3];
invoked_scalar = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// lamda = 0-1 triclinic lamda coords
// vstream = streaming velocity = Hrate*lamda + Hratelo
// vthermal = thermal velocity = v - vstream
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
double t = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
domain->x2lamda(x[i],lamda);
vstream[0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vstream[1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vstream[2] = h_rate[2]*lamda[2] + h_ratelo[2];
vthermal[0] = v[i][0] - vstream[0];
vthermal[1] = v[i][1] - vstream[1];
vthermal[2] = v[i][2] - vstream[2];
if (rmass)
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * rmass[i];
else
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * mass[type[i]];
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempDeform::compute_vector()
{
double lamda[3],vstream[3],vthermal[3];
invoked_vector = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
double massone,t[6];
for (int i = 0; i < 6; i++) t[i] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
domain->x2lamda(x[i],lamda);
vstream[0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vstream[1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vstream[2] = h_rate[2]*lamda[2] + h_ratelo[2];
vthermal[0] = v[i][0] - vstream[0];
vthermal[1] = v[i][1] - vstream[1];
vthermal[2] = v[i][2] - vstream[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * vthermal[0]*vthermal[0];
t[1] += massone * vthermal[1]*vthermal[1];
t[2] += massone * vthermal[2]*vthermal[2];
t[3] += massone * vthermal[0]*vthermal[1];
t[4] += massone * vthermal[0]*vthermal[2];
t[5] += massone * vthermal[1]*vthermal[2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (int i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempDeform::remove_bias(int i, double *v)
{
double lamda[3];
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
domain->x2lamda(atom->x[i],lamda);
vbias[0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vbias[1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vbias[2] = h_rate[2]*lamda[2] + h_ratelo[2];
v[0] -= vbias[0];
v[1] -= vbias[1];
v[2] -= vbias[2];
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempDeform::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/deform:vbiasall");
}
double lamda[3];
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
domain->x2lamda(atom->x[i],lamda);
vbiasall[i][0] = h_rate[0]*lamda[0] + h_rate[5]*lamda[1] +
h_rate[4]*lamda[2] + h_ratelo[0];
vbiasall[i][1] = h_rate[1]*lamda[1] + h_rate[3]*lamda[2] + h_ratelo[1];
vbiasall[i][2] = h_rate[2]*lamda[2] + h_ratelo[2];
v[i][0] -= vbiasall[i][0];
v[i][1] -= vbiasall[i][1];
v[i][2] -= vbiasall[i][2];
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempDeform::restore_bias(int i, double *v)
{
v[0] += vbias[0];
v[1] += vbias[1];
v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempDeform::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] += vbiasall[i][0];
v[i][1] += vbiasall[i][1];
v[i][2] += vbiasall[i][2];
}
}
/* ---------------------------------------------------------------------- */
double ComputeTempDeform::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/compute_temp_partial.cpp b/src/compute_temp_partial.cpp
index 96fd04037..bfb2088e5 100644
--- a/src/compute_temp_partial.cpp
+++ b/src/compute_temp_partial.cpp
@@ -1,267 +1,267 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "compute_temp_partial.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeTempPartial::ComputeTempPartial(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal compute temp/partial command");
+ if (narg != 6) error->all(FLERR,"Illegal compute temp/partial command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
xflag = atoi(arg[3]);
yflag = atoi(arg[4]);
zflag = atoi(arg[5]);
if (zflag && domain->dimension == 2)
- error->all("Compute temp/partial cannot use vz for 2d systemx");
+ error->all(FLERR,"Compute temp/partial cannot use vz for 2d systemx");
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempPartial::~ComputeTempPartial()
{
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempPartial::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ----------------------------------------------------------------------
DOF for a body of N atoms with S constraints (e.g. from SHAKE)
DOF = nper/dim (dim*N - S), where dim = dimensionality = 2 or 3
------------------------------------------------------------------------- */
void ComputeTempPartial::dof_compute()
{
double natoms = group->count(igroup);
int nper = xflag+yflag+zflag;
dof = nper * natoms;
dof -= (1.0*nper/domain->dimension)*fix_dof + extra_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
int ComputeTempPartial::dof_remove(int i)
{
int nper = xflag+yflag+zflag;
return (domain->dimension - nper);
}
/* ---------------------------------------------------------------------- */
double ComputeTempPartial::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (xflag*v[i][0]*v[i][0] + yflag*v[i][1]*v[i][1] +
zflag*v[i][2]*v[i][2]) * rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (xflag*v[i][0]*v[i][0] + yflag*v[i][1]*v[i][1] +
zflag*v[i][2]*v[i][2]) * mass[type[i]];
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempPartial::compute_vector()
{
int i;
invoked_vector = update->ntimestep;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * xflag*v[i][0]*v[i][0];
t[1] += massone * yflag*v[i][1]*v[i][1];
t[2] += massone * zflag*v[i][2]*v[i][2];
t[3] += massone * xflag*yflag*v[i][0]*v[i][1];
t[4] += massone * xflag*zflag*v[i][0]*v[i][2];
t[5] += massone * yflag*zflag*v[i][1]*v[i][2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempPartial::remove_bias(int i, double *v)
{
if (!xflag) {
vbias[0] = v[0];
v[0] = 0.0;
}
if (!yflag) {
vbias[1] = v[1];
v[1] = 0.0;
}
if (!zflag) {
vbias[2] = v[2];
v[2] = 0.0;
}
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempPartial::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/partial:vbiasall");
}
if (!xflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vbiasall[i][0] = v[i][0];
v[i][0] = 0.0;
}
}
if (!yflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vbiasall[i][1] = v[i][1];
v[i][1] = 0.0;
}
}
if (!zflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
vbiasall[i][2] = v[i][2];
v[i][2] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempPartial::restore_bias(int i, double *v)
{
if (!xflag) v[0] += vbias[0];
if (!yflag) v[1] += vbias[1];
if (!zflag) v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempPartial::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (!xflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][0] += vbiasall[i][0];
}
if (!yflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][1] += vbiasall[i][1];
}
if (!zflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][2] += vbiasall[i][2];
}
}
/* ---------------------------------------------------------------------- */
double ComputeTempPartial::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/compute_temp_profile.cpp b/src/compute_temp_profile.cpp
index 399b897df..a242aba33 100644
--- a/src/compute_temp_profile.cpp
+++ b/src/compute_temp_profile.cpp
@@ -1,476 +1,473 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "compute_temp_profile.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
ComputeTempProfile::ComputeTempProfile(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal compute temp/profile command");
+ if (narg < 7) error->all(FLERR,"Illegal compute temp/profile command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
xflag = atoi(arg[3]);
yflag = atoi(arg[4]);
zflag = atoi(arg[5]);
if (zflag && domain->dimension == 2)
- error->all("Compute temp/profile cannot use vz for 2d systemx");
+ error->all(FLERR,"Compute temp/profile cannot use vz for 2d systemx");
ncount = 0;
ivx = ivy = ivz = 0;
if (xflag) ivx = ncount++;
if (yflag) ivy = ncount++;
if (zflag) ivz = ncount++;
nbinx = nbiny = nbinz = 1;
if (strcmp(arg[6],"x") == 0) {
- if (narg != 8) error->all("Illegal compute temp/profile command");
+ if (narg != 8) error->all(FLERR,"Illegal compute temp/profile command");
nbinx = atoi(arg[7]);
} else if (strcmp(arg[6],"y") == 0) {
- if (narg != 8) error->all("Illegal compute temp/profile command");
+ if (narg != 8) error->all(FLERR,"Illegal compute temp/profile command");
nbiny = atoi(arg[7]);
} else if (strcmp(arg[6],"z") == 0) {
- if (narg != 8) error->all("Illegal compute temp/profile command");
+ if (narg != 8) error->all(FLERR,"Illegal compute temp/profile command");
if (domain->dimension == 2)
- error->all("Compute temp/profile cannot bin z for 2d systems");
+ error->all(FLERR,"Compute temp/profile cannot bin z for 2d systems");
nbinz = atoi(arg[7]);
} else if (strcmp(arg[6],"xy") == 0) {
- if (narg != 9) error->all("Illegal compute temp/profile command");
+ if (narg != 9) error->all(FLERR,"Illegal compute temp/profile command");
nbinx = atoi(arg[7]);
nbiny = atoi(arg[8]);
} else if (strcmp(arg[6],"yz") == 0) {
- if (narg != 9) error->all("Illegal compute temp/profile command");
+ if (narg != 9) error->all(FLERR,"Illegal compute temp/profile command");
if (domain->dimension == 2)
- error->all("Compute temp/profile cannot bin z for 2d systems");
+ error->all(FLERR,"Compute temp/profile cannot bin z for 2d systems");
nbiny = atoi(arg[7]);
nbinz = atoi(arg[8]);
} else if (strcmp(arg[6],"xz") == 0) {
- if (narg != 9) error->all("Illegal compute temp/profile command");
+ if (narg != 9) error->all(FLERR,"Illegal compute temp/profile command");
if (domain->dimension == 2)
- error->all("Compute temp/profile cannot bin z for 2d systems");
+ error->all(FLERR,"Compute temp/profile cannot bin z for 2d systems");
nbinx = atoi(arg[7]);
nbinz = atoi(arg[8]);
} else if (strcmp(arg[6],"xyz") == 0) {
- if (narg != 10) error->all("Illegal compute temp/profile command");
+ if (narg != 10) error->all(FLERR,"Illegal compute temp/profile command");
if (domain->dimension == 2)
- error->all("Compute temp/profile cannot bin z for 2d systems");
+ error->all(FLERR,"Compute temp/profile cannot bin z for 2d systems");
nbinx = atoi(arg[7]);
nbiny = atoi(arg[8]);
nbinz = atoi(arg[9]);
- } else error->all("Illegal compute temp/profile command");
+ } else error->all(FLERR,"Illegal compute temp/profile command");
nbins = nbinx*nbiny*nbinz;
- if (nbins <= 0) error->all("Illegal compute temp/profile command");
+ if (nbins <= 0) error->all(FLERR,"Illegal compute temp/profile command");
memory->create(vbin,nbins,ncount+1,"temp/profile:vbin");
memory->create(binave,nbins,ncount+1,"temp/profile:binave");
maxatom = 0;
bin = NULL;
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempProfile::~ComputeTempProfile()
{
memory->destroy(vbin);
memory->destroy(binave);
memory->destroy(bin);
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempProfile::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
// ptrs to domain data
box_change = domain->box_change;
triclinic = domain->triclinic;
periodicity = domain->periodicity;
if (triclinic) {
boxlo = domain->boxlo_lamda;
boxhi = domain->boxhi_lamda;
prd = domain->prd_lamda;
} else {
boxlo = domain->boxlo;
boxhi = domain->boxhi;
prd = domain->prd;
}
if (!box_change) bin_setup();
}
/* ---------------------------------------------------------------------- */
void ComputeTempProfile::dof_compute()
{
double natoms = group->count(igroup);
int nper = domain->dimension;
dof = nper * natoms;
dof -= extra_dof + fix_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempProfile::compute_scalar()
{
int ibin;
double vthermal[3];
invoked_scalar = update->ntimestep;
bin_average();
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
ibin = bin[i];
if (xflag) vthermal[0] = v[i][0] - binave[ibin][ivx];
else vthermal[0] = v[i][0];
if (yflag) vthermal[1] = v[i][1] - binave[ibin][ivy];
else vthermal[1] = v[i][1];
if (zflag) vthermal[2] = v[i][2] - binave[ibin][ivz];
else vthermal[2] = v[i][2];
if (rmass)
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * rmass[i];
else
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * mass[type[i]];
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempProfile::compute_vector()
{
int i,ibin;
double vthermal[3];
invoked_vector = update->ntimestep;
bin_average();
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
ibin = bin[i];
if (xflag) vthermal[0] = v[i][0] - binave[ibin][ivx];
else vthermal[0] = v[i][0];
if (yflag) vthermal[1] = v[i][1] - binave[ibin][ivy];
else vthermal[1] = v[i][1];
if (zflag) vthermal[2] = v[i][2] - binave[ibin][ivz];
else vthermal[2] = v[i][2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * vthermal[0]*vthermal[0];
t[1] += massone * vthermal[1]*vthermal[1];
t[2] += massone * vthermal[2]*vthermal[2];
t[3] += massone * vthermal[0]*vthermal[1];
t[4] += massone * vthermal[0]*vthermal[2];
t[5] += massone * vthermal[1]*vthermal[2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempProfile::remove_bias(int i, double *v)
{
int ibin = bin[i];
if (xflag) {
vbias[0] = binave[ibin][ivx];
v[0] -= vbias[0];
}
if (yflag) {
vbias[1] = binave[ibin][ivy];
v[1] -= vbias[1];
}
if (zflag) {
vbias[2] = binave[ibin][ivz];
v[2] -= vbias[2];
}
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempProfile::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/profile:vbiasall");
}
int ibin;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
ibin = bin[i];
if (xflag) {
vbiasall[i][0] = binave[ibin][ivx];
v[i][0] -= vbiasall[i][0];
}
if (yflag) {
vbiasall[i][1] = binave[ibin][ivy];
v[i][1] -= vbiasall[i][1];
}
if (zflag) {
vbiasall[i][2] = binave[ibin][ivz];
v[i][2] -= vbiasall[i][2];
}
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempProfile::restore_bias(int i, double *v)
{
if (xflag) v[0] += vbias[0];
if (yflag) v[1] += vbias[1];
if (zflag) v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempProfile::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (xflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][0] += vbiasall[i][0];
}
if (yflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][1] += vbiasall[i][1];
}
if (zflag) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][2] += vbiasall[i][2];
}
}
/* ----------------------------------------------------------------------
compute average velocity in each bin
------------------------------------------------------------------------- */
void ComputeTempProfile::bin_average()
{
int i,j,ibin;
if (box_change) bin_setup();
bin_assign();
// clear bins, including particle count
for (i = 0; i < nbins; i++)
for (j = 0; j <= ncount; j++)
vbin[i][j] = 0.0;
// sum each particle's velocity to appropriate bin
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
ibin = bin[i];
if (xflag) vbin[ibin][ivx] += v[i][0];
if (yflag) vbin[ibin][ivy] += v[i][1];
if (zflag) vbin[ibin][ivz] += v[i][2];
vbin[ibin][ncount] += 1.0;
}
// sum bins across processors
MPI_Allreduce(vbin[0],binave[0],nbins*(ncount+1),MPI_DOUBLE,MPI_SUM,world);
// compute ave velocity in each bin, checking for no particles
for (i = 0; i < nbins; i++)
if (binave[i][ncount] > 0.0)
for (j = 0; j < ncount; j++)
binave[i][j] /= binave[i][ncount];
}
/* ----------------------------------------------------------------------
set bin sizes, redo if box size changes
------------------------------------------------------------------------- */
void ComputeTempProfile::bin_setup()
{
invdelta[0] = nbinx / prd[0];
invdelta[1] = nbiny / prd[1];
invdelta[2] = nbinz / prd[2];
}
/* ----------------------------------------------------------------------
assign all atoms to bins
------------------------------------------------------------------------- */
void ComputeTempProfile::bin_assign()
{
// reallocate bin array if necessary
if (atom->nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(bin);
memory->create(bin,maxatom,"temp/profile:bin");
}
// assign each atom to a bin, accounting for PBC
// if triclinic, do this in lamda space
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int ibinx,ibiny,ibinz;
double coord;
if (triclinic) domain->x2lamda(nlocal);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (nbinx > 1) {
coord = x[i][0];
if (periodicity[0]) {
if (coord < boxlo[0]) coord += prd[0];
if (coord >= boxhi[0]) coord -= prd[0];
}
ibinx = static_cast<int> ((coord - boxlo[0]) * invdelta[0]);
ibinx = MAX(ibinx,0);
ibinx = MIN(ibinx,nbinx-1);
} else ibinx = 0;
if (nbiny > 1) {
coord = x[i][1];
if (periodicity[1]) {
if (coord < boxlo[1]) coord += prd[1];
if (coord >= boxhi[1]) coord -= prd[1];
}
ibiny = static_cast<int> ((coord - boxlo[1]) * invdelta[1]);
ibiny = MAX(ibiny,0);
ibiny = MIN(ibiny,nbiny-1);
} else ibiny = 0;
if (nbinz > 1) {
coord = x[i][2];
if (periodicity[2]) {
if (coord < boxlo[2]) coord += prd[2];
if (coord >= boxhi[2]) coord -= prd[2];
}
ibinz = static_cast<int> ((coord - boxlo[2]) * invdelta[2]);
ibinz = MAX(ibinz,0);
ibinz = MIN(ibinz,nbinz-1);
} else ibinz = 0;
bin[i] = nbinx*nbiny*ibinz + nbinx*ibiny + ibinx;
}
if (triclinic) domain->lamda2x(nlocal);
}
/* ---------------------------------------------------------------------- */
double ComputeTempProfile::memory_usage()
{
double bytes = maxbias * sizeof(double);
bytes += maxatom * sizeof(int);
bytes += nbins*(ncount+1) * sizeof(double);
return bytes;
}
diff --git a/src/compute_temp_ramp.cpp b/src/compute_temp_ramp.cpp
index 1690e1224..135a3eea6 100644
--- a/src/compute_temp_ramp.cpp
+++ b/src/compute_temp_ramp.cpp
@@ -1,302 +1,299 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "compute_temp_ramp.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "domain.h"
#include "lattice.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
ComputeTempRamp::ComputeTempRamp(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 9) error->all("Illegal compute temp command");
+ if (narg < 9) error->all(FLERR,"Illegal compute temp command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
// parse optional args
scaleflag = 1;
int iarg = 9;
while (iarg < narg) {
if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute temp/ramp command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/ramp command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal compute temp/ramp command");
+ else error->all(FLERR,"Illegal compute temp/ramp command");
iarg += 2;
- } else error->all("Illegal compute temp/ramp command");
+ } else error->all(FLERR,"Illegal compute temp/ramp command");
}
// setup scaling
if (scaleflag && domain->lattice == NULL)
- error->all("Use of compute temp/ramp with undefined lattice");
+ error->all(FLERR,"Use of compute temp/ramp with undefined lattice");
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// read standard args and apply scaling
if (strcmp(arg[3],"vx") == 0) v_dim = 0;
else if (strcmp(arg[3],"vy") == 0) v_dim = 1;
else if (strcmp(arg[3],"vz") == 0) v_dim = 2;
- else error->all("Illegal compute temp/ramp command");
+ else error->all(FLERR,"Illegal compute temp/ramp command");
if (v_dim == 0) {
v_lo = xscale*atof(arg[4]);
v_hi = xscale*atof(arg[5]);
} else if (v_dim == 1) {
v_lo = yscale*atof(arg[4]);
v_hi = yscale*atof(arg[5]);
} else if (v_dim == 2) {
v_lo = zscale*atof(arg[4]);
v_hi = zscale*atof(arg[5]);
}
if (strcmp(arg[6],"x") == 0) coord_dim = 0;
else if (strcmp(arg[6],"y") == 0) coord_dim = 1;
else if (strcmp(arg[6],"z") == 0) coord_dim = 2;
- else error->all("Illegal compute temp/ramp command");
+ else error->all(FLERR,"Illegal compute temp/ramp command");
if (coord_dim == 0) {
coord_lo = xscale*atof(arg[7]);
coord_hi = xscale*atof(arg[8]);
} else if (coord_dim == 1) {
coord_lo = yscale*atof(arg[7]);
coord_hi = yscale*atof(arg[8]);
} else if (coord_dim == 2) {
coord_lo = zscale*atof(arg[7]);
coord_hi = zscale*atof(arg[8]);
}
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempRamp::~ComputeTempRamp()
{
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRamp::init()
{
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ---------------------------------------------------------------------- */
void ComputeTempRamp::dof_compute()
{
double natoms = group->count(igroup);
int nper = domain->dimension;
dof = nper * natoms;
dof -= extra_dof + fix_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempRamp::compute_scalar()
{
double fraction,vramp,vthermal[3];
invoked_scalar = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double t = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
fraction = (x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
fraction = MAX(fraction,0.0);
fraction = MIN(fraction,1.0);
vramp = v_lo + fraction*(v_hi - v_lo);
vthermal[0] = v[i][0];
vthermal[1] = v[i][1];
vthermal[2] = v[i][2];
vthermal[v_dim] -= vramp;
if (rmass)
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * rmass[i];
else
t += (vthermal[0]*vthermal[0] + vthermal[1]*vthermal[1] +
vthermal[2]*vthermal[2]) * mass[type[i]];
}
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRamp::compute_vector()
{
int i;
double fraction,vramp,vthermal[3];
invoked_vector = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
fraction = (x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
fraction = MAX(fraction,0.0);
fraction = MIN(fraction,1.0);
vramp = v_lo + fraction*(v_hi - v_lo);
vthermal[0] = v[i][0];
vthermal[1] = v[i][1];
vthermal[2] = v[i][2];
vthermal[v_dim] -= vramp;
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * vthermal[0]*vthermal[0];
t[1] += massone * vthermal[1]*vthermal[1];
t[2] += massone * vthermal[2]*vthermal[2];
t[3] += massone * vthermal[0]*vthermal[1];
t[4] += massone * vthermal[0]*vthermal[2];
t[5] += massone * vthermal[1]*vthermal[2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempRamp::remove_bias(int i, double *v)
{
double fraction = (atom->x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
fraction = MAX(fraction,0.0);
fraction = MIN(fraction,1.0);
vbias[v_dim] = v_lo + fraction*(v_hi - v_lo);
v[v_dim] -= vbias[v_dim];
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempRamp::remove_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/ramp:vbiasall");
}
double fraction;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
fraction = (atom->x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
fraction = MAX(fraction,0.0);
fraction = MIN(fraction,1.0);
vbiasall[i][v_dim] = v_lo + fraction*(v_hi - v_lo);
v[i][v_dim] -= vbiasall[i][v_dim];
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempRamp::restore_bias(int i, double *v)
{
v[v_dim] += vbias[v_dim];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempRamp::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
v[i][v_dim] += vbiasall[i][v_dim];
}
/* ---------------------------------------------------------------------- */
double ComputeTempRamp::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/compute_temp_region.cpp b/src/compute_temp_region.cpp
index b43af45de..964f162d9 100644
--- a/src/compute_temp_region.cpp
+++ b/src/compute_temp_region.cpp
@@ -1,250 +1,250 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_temp_region.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "modify.h"
#include "domain.h"
#include "region.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
ComputeTempRegion::ComputeTempRegion(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal compute temp/region command");
+ if (narg != 4) error->all(FLERR,"Illegal compute temp/region command");
iregion = domain->find_region(arg[3]);
if (iregion == -1)
- error->all("Region ID for compute temp/region does not exist");
+ error->all(FLERR,"Region ID for compute temp/region does not exist");
int n = strlen(arg[3]) + 1;
idregion = new char[n];
strcpy(idregion,arg[3]);
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 1;
maxbias = 0;
vbiasall = NULL;
vector = new double[6];
}
/* ---------------------------------------------------------------------- */
ComputeTempRegion::~ComputeTempRegion()
{
delete [] idregion;
memory->destroy(vbiasall);
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRegion::init()
{
// set index and check validity of region
iregion = domain->find_region(idregion);
if (iregion == -1)
- error->all("Region ID for compute temp/region does not exist");
+ error->all(FLERR,"Region ID for compute temp/region does not exist");
dof = 0.0;
}
/* ---------------------------------------------------------------------- */
int ComputeTempRegion::dof_remove(int i)
{
double *x = atom->x[i];
if (domain->regions[iregion]->match(x[0],x[1],x[2])) return 0;
return 1;
}
/* ---------------------------------------------------------------------- */
double ComputeTempRegion::compute_scalar()
{
invoked_scalar = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
Region *region = domain->regions[iregion];
int count = 0;
double t = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
count++;
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * rmass[i];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
count++;
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
mass[type[i]];
}
}
double tarray[2],tarray_all[2];
tarray[0] = count;
tarray[1] = t;
MPI_Allreduce(tarray,tarray_all,2,MPI_DOUBLE,MPI_SUM,world);
dof = domain->dimension * tarray_all[0] - extra_dof;
if (dof > 0) scalar = force->mvv2e * tarray_all[1] / (dof * force->boltz);
else scalar = 0.0;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempRegion::compute_vector()
{
int i;
invoked_vector = update->ntimestep;
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
Region *region = domain->regions[iregion];
double massone,t[6];
for (i = 0; i < 6; i++) t[i] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
t[0] += massone * v[i][0]*v[i][0];
t[1] += massone * v[i][1]*v[i][1];
t[2] += massone * v[i][2]*v[i][2];
t[3] += massone * v[i][0]*v[i][1];
t[4] += massone * v[i][0]*v[i][2];
t[5] += massone * v[i][1]*v[i][2];
}
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempRegion::remove_bias(int i, double *v)
{
double *x = atom->x[i];
if (domain->regions[iregion]->match(x[0],x[1],x[2]))
vbias[0] = vbias[1] = vbias[2] = 0.0;
else {
vbias[0] = v[0];
vbias[1] = v[1];
vbias[2] = v[2];
v[0] = v[1] = v[2] = 0.0;
}
}
/* ----------------------------------------------------------------------
remove velocity bias from all atoms to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempRegion::remove_bias_all()
{
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxbias) {
memory->destroy(vbiasall);
maxbias = atom->nmax;
memory->create(vbiasall,maxbias,3,"temp/region:vbiasall");
}
Region *region = domain->regions[iregion];
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (region->match(x[i][0],x[i][1],x[i][2]))
vbiasall[i][0] = vbiasall[i][1] = vbiasall[i][2] = 0.0;
else {
vbiasall[i][0] = v[i][0];
vbiasall[i][1] = v[i][1];
vbiasall[i][2] = v[i][2];
v[i][0] = v[i][1] = v[i][2] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempRegion::restore_bias(int i, double *v)
{
v[0] += vbias[0];
v[1] += vbias[1];
v[2] += vbias[2];
}
/* ----------------------------------------------------------------------
add back in velocity bias to all atoms removed by remove_bias_all()
assume remove_bias_all() was previously called
------------------------------------------------------------------------- */
void ComputeTempRegion::restore_bias_all()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] += vbiasall[i][0];
v[i][1] += vbiasall[i][1];
v[i][2] += vbiasall[i][2];
}
}
/* ---------------------------------------------------------------------- */
double ComputeTempRegion::memory_usage()
{
double bytes = maxbias * sizeof(double);
return bytes;
}
diff --git a/src/compute_temp_sphere.cpp b/src/compute_temp_sphere.cpp
index 246d58bae..ed4a25008 100644
--- a/src/compute_temp_sphere.cpp
+++ b/src/compute_temp_sphere.cpp
@@ -1,321 +1,321 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_temp_sphere.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "fix.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{ROTATE,ALL};
#define INERTIA 0.4 // moment of inertia prefactor for sphere
/* ---------------------------------------------------------------------- */
ComputeTempSphere::ComputeTempSphere(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal compute temp/sphere command");
+ if (narg < 3) error->all(FLERR,"Illegal compute temp/sphere command");
scalar_flag = vector_flag = 1;
size_vector = 6;
extscalar = 0;
extvector = 1;
tempflag = 1;
tempbias = 0;
id_bias = NULL;
mode = ALL;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"bias") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute temp/sphere command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/sphere command");
tempbias = 1;
int n = strlen(arg[iarg+1]) + 1;
id_bias = new char[n];
strcpy(id_bias,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"dof") == 0) {
- if (iarg+2 > narg) error->all("Illegal compute temp/sphere command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal compute temp/sphere command");
if (strcmp(arg[iarg+1],"rotate") == 0) mode = ROTATE;
else if (strcmp(arg[iarg+1],"all") == 0) mode = ALL;
- else error->all("Illegal compute temp/sphere command");
+ else error->all(FLERR,"Illegal compute temp/sphere command");
iarg += 2;
- } else error->all("Illegal compute temp/sphere command");
+ } else error->all(FLERR,"Illegal compute temp/sphere command");
}
vector = new double[6];
// error checks
if (!atom->sphere_flag)
- error->all("Compute temp/sphere requires atom style sphere");
+ error->all(FLERR,"Compute temp/sphere requires atom style sphere");
}
/* ---------------------------------------------------------------------- */
ComputeTempSphere::~ComputeTempSphere()
{
delete [] id_bias;
delete [] vector;
}
/* ---------------------------------------------------------------------- */
void ComputeTempSphere::init()
{
if (tempbias) {
int i = modify->find_compute(id_bias);
- if (i < 0) error->all("Could not find compute ID for temperature bias");
+ if (i < 0) error->all(FLERR,"Could not find compute ID for temperature bias");
tbias = modify->compute[i];
if (tbias->tempflag == 0)
- error->all("Bias compute does not calculate temperature");
+ error->all(FLERR,"Bias compute does not calculate temperature");
if (tbias->tempbias == 0)
- error->all("Bias compute does not calculate a velocity bias");
+ error->all(FLERR,"Bias compute does not calculate a velocity bias");
if (tbias->igroup != igroup)
- error->all("Bias compute group does not match compute group");
+ error->all(FLERR,"Bias compute group does not match compute group");
tbias->init();
if (strcmp(tbias->style,"temp/region") == 0) tempbias = 2;
else tempbias = 1;
}
fix_dof = 0;
for (int i = 0; i < modify->nfix; i++)
fix_dof += modify->fix[i]->dof(igroup);
dof_compute();
}
/* ---------------------------------------------------------------------- */
void ComputeTempSphere::dof_compute()
{
int count,count_all;
// 6 or 3 dof for extended/point particles for 3d
// 3 or 2 dof for extended/point particles for 2d
// which dof are included also depends on mode
// assume full rotation of extended particles
// user should correct this via compute_modify if needed
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
count = 0;
if (domain->dimension == 3) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (radius[i] == 0.0) {
if (mode == ALL) count += 3;
} else {
if (mode == ALL) count += 6;
else count += 3;
}
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (radius[i] == 0.0) {
if (mode == ALL) count += 2;
} else {
if (mode == ALL) count += 3;
else count += 1;
}
}
}
MPI_Allreduce(&count,&count_all,1,MPI_INT,MPI_SUM,world);
dof = count_all;
// additional adjustments to dof
if (tempbias == 1) {
if (mode == ALL) {
double natoms = group->count(igroup);
dof -= tbias->dof_remove(-1) * natoms;
}
} else if (tempbias == 2) {
int *mask = atom->mask;
int nlocal = atom->nlocal;
count = 0;
if (domain->dimension == 3) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (tbias->dof_remove(i)) {
if (radius[i] == 0.0) {
if (mode == ALL) count += 3;
} else {
if (mode == ALL) count += 6;
else count += 3;
}
}
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (tbias->dof_remove(i)) {
if (radius[i] == 0.0) {
if (mode == ALL) count += 2;
} else {
if (mode == ALL) count += 3;
else count += 1;
}
}
}
}
MPI_Allreduce(&count,&count_all,1,MPI_INT,MPI_SUM,world);
dof -= count_all;
}
dof -= extra_dof + fix_dof;
if (dof > 0) tfactor = force->mvv2e / (dof * force->boltz);
else tfactor = 0.0;
}
/* ---------------------------------------------------------------------- */
double ComputeTempSphere::compute_scalar()
{
invoked_scalar = update->ntimestep;
if (tempbias) {
if (tbias->invoked_scalar != update->ntimestep) tbias->compute_scalar();
tbias->remove_bias_all();
}
double **v = atom->v;
double **omega = atom->omega;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// point particles will not contribute rotation due to radius = 0
double t = 0.0;
if (mode == ALL) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
t += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) * rmass[i];
t += (omega[i][0]*omega[i][0] + omega[i][1]*omega[i][1] +
omega[i][2]*omega[i][2]) * INERTIA*rmass[i]*radius[i]*radius[i];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
t += (omega[i][0]*omega[i][0] + omega[i][1]*omega[i][1] +
omega[i][2]*omega[i][2]) * INERTIA*rmass[i]*radius[i]*radius[i];
}
if (tempbias) tbias->restore_bias_all();
MPI_Allreduce(&t,&scalar,1,MPI_DOUBLE,MPI_SUM,world);
if (dynamic || tempbias == 2) dof_compute();
scalar *= tfactor;
return scalar;
}
/* ---------------------------------------------------------------------- */
void ComputeTempSphere::compute_vector()
{
invoked_vector = update->ntimestep;
if (tempbias) {
if (tbias->invoked_vector != update->ntimestep) tbias->compute_vector();
tbias->remove_bias_all();
}
double **v = atom->v;
double **omega = atom->omega;
double *rmass = atom->rmass;
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// point particles will not contribute rotation due to radius = 0
double massone,inertiaone,t[6];
for (int i = 0; i < 6; i++) t[i] = 0.0;
if (mode == ALL) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = rmass[i];
t[0] += massone * v[i][0]*v[i][0];
t[1] += massone * v[i][1]*v[i][1];
t[2] += massone * v[i][2]*v[i][2];
t[3] += massone * v[i][0]*v[i][1];
t[4] += massone * v[i][0]*v[i][2];
t[5] += massone * v[i][1]*v[i][2];
inertiaone = INERTIA*rmass[i]*radius[i]*radius[i];
t[0] += inertiaone * omega[i][0]*omega[i][0];
t[1] += inertiaone * omega[i][1]*omega[i][1];
t[2] += inertiaone * omega[i][2]*omega[i][2];
t[3] += inertiaone * omega[i][0]*omega[i][1];
t[4] += inertiaone * omega[i][0]*omega[i][2];
t[5] += inertiaone * omega[i][1]*omega[i][2];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
inertiaone = INERTIA*rmass[i]*radius[i]*radius[i];
t[0] += inertiaone * omega[i][0]*omega[i][0];
t[1] += inertiaone * omega[i][1]*omega[i][1];
t[2] += inertiaone * omega[i][2]*omega[i][2];
t[3] += inertiaone * omega[i][0]*omega[i][1];
t[4] += inertiaone * omega[i][0]*omega[i][2];
t[5] += inertiaone * omega[i][1]*omega[i][2];
}
}
if (tempbias) tbias->restore_bias_all();
MPI_Allreduce(t,vector,6,MPI_DOUBLE,MPI_SUM,world);
for (int i = 0; i < 6; i++) vector[i] *= force->mvv2e;
}
/* ----------------------------------------------------------------------
remove velocity bias from atom I to leave thermal velocity
------------------------------------------------------------------------- */
void ComputeTempSphere::remove_bias(int i, double *v)
{
tbias->remove_bias(i,v);
}
/* ----------------------------------------------------------------------
add back in velocity bias to atom I removed by remove_bias()
assume remove_bias() was previously called
------------------------------------------------------------------------- */
void ComputeTempSphere::restore_bias(int i, double *v)
{
tbias->restore_bias(i,v);
}
diff --git a/src/compute_ti.cpp b/src/compute_ti.cpp
index fd2a83ae0..035fb3576 100644
--- a/src/compute_ti.cpp
+++ b/src/compute_ti.cpp
@@ -1,178 +1,178 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Sai Jayaraman (University of Notre Dame)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "compute_ti.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "force.h"
#include "pair.h"
#include "kspace.h"
#include "input.h"
#include "variable.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{PAIR,TAIL,KSPACE};
/* ---------------------------------------------------------------------- */
ComputeTI::ComputeTI(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal compute ti command");
+ if (narg < 4) error->all(FLERR,"Illegal compute ti command");
peflag = 1;
scalar_flag = 1;
extscalar = 1;
timeflag = 1;
// terms come in triplets
nterms = (narg-3) / 3;
- if (narg != 3*nterms + 3) error->all("Illegal compute ti command");
+ if (narg != 3*nterms + 3) error->all(FLERR,"Illegal compute ti command");
which = new int[nterms];
ivar1 = new int[nterms];
ivar2 = new int[nterms];
var1 = new char*[nterms];
var2 = new char*[nterms];
pptr = new Pair*[nterms];
pstyle = new char*[nterms];
for (int m = 0; m < nterms; m++) pstyle[m] = NULL;
// parse keywords
nterms = 0;
int iarg = 3;
while (iarg < narg) {
- if (iarg+3 > narg) error->all("Illegal compute ti command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal compute ti command");
if (strcmp(arg[iarg],"kspace") == 0) which[nterms] = KSPACE;
else if (strcmp(arg[iarg],"tail") == 0) which[nterms] = TAIL;
else {
which[nterms] = PAIR;
int n = strlen(arg[iarg]) + 1;
pstyle[nterms] = new char[n];
strcpy(pstyle[nterms],arg[iarg]);
}
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
var1[nterms] = new char[n];
strcpy(var1[nterms],&arg[iarg+1][2]);
- } else error->all("Illegal compute ti command");
+ } else error->all(FLERR,"Illegal compute ti command");
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
var2[nterms] = new char[n];
strcpy(var2[nterms],&arg[iarg+2][2]);
- } else error->all("Illegal compute ti command");
+ } else error->all(FLERR,"Illegal compute ti command");
nterms++;
iarg += 3;
}
}
/* --------------------------------------------------------------------- */
ComputeTI::~ComputeTI()
{
for (int m = 0; m < nterms; m++) {
delete [] var1[m];
delete [] var2[m];
delete [] pstyle[m];
}
delete [] which;
delete [] ivar1;
delete [] ivar2;
delete [] var1;
delete [] var2;
delete [] pptr;
delete [] pstyle;
}
/* --------------------------------------------------------------------- */
void ComputeTI::init()
{
// setup and error checks
for (int m = 0; m < nterms; m++) {
ivar1[m] = input->variable->find(var1[m]);
ivar2[m] = input->variable->find(var2[m]);
if (ivar1[m] < 0 || ivar2 < 0)
- error->all("Variable name for compute ti does not exist");
+ error->all(FLERR,"Variable name for compute ti does not exist");
if (!input->variable->equalstyle(ivar1[m]) ||
!input->variable->equalstyle(ivar2[m]))
- error->all("Variable for compute ti is invalid style");
+ error->all(FLERR,"Variable for compute ti is invalid style");
if (which[m] == PAIR) {
pptr[m] = force->pair_match(pstyle[m],1);
- if (pptr[m] == NULL) error->all("Compute ti pair style does not exist");
+ if (pptr[m] == NULL) error->all(FLERR,"Compute ti pair style does not exist");
} else if (which[m] == TAIL) {
if (force->pair == NULL || force->pair->tail_flag == 0)
- error->all("Compute ti tail when pair style does not "
+ error->all(FLERR,"Compute ti tail when pair style does not "
"compute tail corrections");
} else if (which[m] == KSPACE) {
if (force->kspace == NULL)
- error->all("Compute ti kspace style does not exist");
+ error->all(FLERR,"Compute ti kspace style does not exist");
}
}
}
/* --------------------------------------------------------------------- */
double ComputeTI::compute_scalar()
{
double eng,engall,value1,value2;
invoked_scalar = update->ntimestep;
if (update->eflag_global != invoked_scalar)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
double dUdl = 0.0;
for (int m = 0; m < nterms; m++) {
value1 = input->variable->compute_equal(ivar1[m]);
value2 = input->variable->compute_equal(ivar2[m]);
if (value1 == 0.0) continue;
if (which[m] == PAIR) {
eng = pptr[m]->eng_vdwl + pptr[m]->eng_coul;
MPI_Allreduce(&eng,&engall,1,MPI_DOUBLE,MPI_SUM,world);
dUdl += engall/value1 * value2;
} else if (which[m] == TAIL) {
double vol = domain->xprd*domain->yprd*domain->zprd;
eng = force->pair->etail / vol;
dUdl += eng/value1 * value2;
} else if (which[m] == KSPACE) {
eng = force->kspace->energy;
dUdl += eng/value1 * value2;
}
}
scalar = dUdl;
return scalar;
}
diff --git a/src/create_atoms.cpp b/src/create_atoms.cpp
index 1f7d3ef65..c1cdc6d83 100644
--- a/src/create_atoms.cpp
+++ b/src/create_atoms.cpp
@@ -1,487 +1,484 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "create_atoms.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "modify.h"
#include "fix.h"
#include "domain.h"
#include "lattice.h"
#include "region.h"
#include "random_park.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e30
#define EPSILON 1.0e-6
enum{BOX,REGION,SINGLE,RANDOM};
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
CreateAtoms::CreateAtoms(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void CreateAtoms::command(int narg, char **arg)
{
if (domain->box_exist == 0)
- error->all("Create_atoms command before simulation box is defined");
+ error->all(FLERR,"Create_atoms command before simulation box is defined");
if (modify->nfix_restart_peratom)
- error->all("Cannot create_atoms after "
+ error->all(FLERR,"Cannot create_atoms after "
"reading restart file with per-atom info");
// parse arguments
- if (narg < 2) error->all("Illegal create_atoms command");
+ if (narg < 2) error->all(FLERR,"Illegal create_atoms command");
itype = atoi(arg[0]);
if (itype <= 0 || itype > atom->ntypes)
- error->all("Invalid atom type in create_atoms command");
+ error->all(FLERR,"Invalid atom type in create_atoms command");
int iarg;
if (strcmp(arg[1],"box") == 0) {
style = BOX;
iarg = 2;
} else if (strcmp(arg[1],"region") == 0) {
style = REGION;
- if (narg < 3) error->all("Illegal create_atoms command");
+ if (narg < 3) error->all(FLERR,"Illegal create_atoms command");
nregion = domain->find_region(arg[2]);
- if (nregion == -1) error->all("Create_atoms region ID does not exist");
+ if (nregion == -1) error->all(FLERR,"Create_atoms region ID does not exist");
iarg = 3;;
} else if (strcmp(arg[1],"single") == 0) {
style = SINGLE;
- if (narg < 5) error->all("Illegal create_atoms command");
+ if (narg < 5) error->all(FLERR,"Illegal create_atoms command");
xone[0] = atof(arg[2]);
xone[1] = atof(arg[3]);
xone[2] = atof(arg[4]);
iarg = 5;
} else if (strcmp(arg[1],"random") == 0) {
style = RANDOM;
- if (narg < 5) error->all("Illegal create_atoms command");
+ if (narg < 5) error->all(FLERR,"Illegal create_atoms command");
nrandom = atoi(arg[2]);
seed = atoi(arg[3]);
if (strcmp(arg[4],"NULL") == 0) nregion = -1;
else {
nregion = domain->find_region(arg[4]);
- if (nregion == -1) error->all("Create_atoms region ID does not exist");
+ if (nregion == -1) error->all(FLERR,"Create_atoms region ID does not exist");
}
iarg = 5;
- } else error->all("Illegal create_atoms command");
+ } else error->all(FLERR,"Illegal create_atoms command");
// process optional keywords
int scaleflag = 1;
if (domain->lattice) {
nbasis = domain->lattice->nbasis;
basistype = new int[nbasis];
for (int i = 0; i < nbasis; i++) basistype[i] = itype;
}
while (iarg < narg) {
if (strcmp(arg[iarg],"basis") == 0) {
- if (iarg+3 > narg) error->all("Illegal create_atoms command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal create_atoms command");
if (domain->lattice == NULL)
- error->all("Cannot create atoms with undefined lattice");
+ error->all(FLERR,"Cannot create atoms with undefined lattice");
int ibasis = atoi(arg[iarg+1]);
itype = atoi(arg[iarg+2]);
if (ibasis <= 0 || ibasis > nbasis ||
itype <= 0 || itype > atom->ntypes)
- error->all("Illegal create_atoms command");
+ error->all(FLERR,"Illegal create_atoms command");
basistype[ibasis-1] = itype;
iarg += 3;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal create_atoms command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal create_atoms command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal create_atoms command");
+ else error->all(FLERR,"Illegal create_atoms command");
iarg += 2;
- } else error->all("Illegal create_atoms command");
+ } else error->all(FLERR,"Illegal create_atoms command");
}
// error checks
if (style == RANDOM) {
- if (nrandom < 0) error->all("Illegal create_atoms command");
- if (seed <= 0) error->all("Illegal create_atoms command");
+ if (nrandom < 0) error->all(FLERR,"Illegal create_atoms command");
+ if (seed <= 0) error->all(FLERR,"Illegal create_atoms command");
}
// demand lattice be defined
// else setup scaling for single atom
// could use domain->lattice->lattice2box() to do conversion of
// lattice to box, but not consistent with other uses of units=lattice
// triclinic remapping occurs in add_single()
if (style == BOX || style == REGION) {
if (domain->lattice == NULL)
- error->all("Cannot create atoms with undefined lattice");
+ error->all(FLERR,"Cannot create atoms with undefined lattice");
} else if (scaleflag == 1) {
if (domain->lattice == NULL)
- error->all("Cannot create atoms with undefined lattice");
+ error->all(FLERR,"Cannot create atoms with undefined lattice");
xone[0] *= domain->lattice->xlattice;
xone[1] *= domain->lattice->ylattice;
xone[2] *= domain->lattice->zlattice;
}
// add atoms
bigint natoms_previous = atom->natoms;
int nlocal_previous = atom->nlocal;
if (style == SINGLE) add_single();
else if (style == RANDOM) add_random();
else add_lattice();
// invoke set_arrays() for fixes that need initialization of new atoms
int nlocal = atom->nlocal;
for (int m = 0; m < modify->nfix; m++) {
Fix *fix = modify->fix[m];
if (fix->create_attribute)
for (int i = nlocal_previous; i < nlocal; i++)
fix->set_arrays(i);
}
// clean up
if (domain->lattice) delete [] basistype;
// new total # of atoms
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (atom->natoms < 0 || atom->natoms > MAXBIGINT)
- error->all("Too many total atoms");
+ error->all(FLERR,"Too many total atoms");
// print status
if (comm->me == 0) {
if (screen)
fprintf(screen,"Created " BIGINT_FORMAT " atoms\n",
atom->natoms-natoms_previous);
if (logfile)
fprintf(logfile,"Created " BIGINT_FORMAT " atoms\n",
atom->natoms-natoms_previous);
}
// reset simulation now that more atoms are defined
// add tags for newly created atoms if possible
// if global map exists, reset it
// if a molecular system, set nspecial to 0 for new atoms
if (atom->natoms > MAXTAGINT) atom->tag_enable = 0;
if (atom->natoms <= MAXTAGINT) atom->tag_extend();
if (atom->map_style) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
if (atom->molecular) {
int **nspecial = atom->nspecial;
for (int i = nlocal_previous; i < atom->nlocal; i++) {
nspecial[i][0] = 0;
nspecial[i][1] = 0;
nspecial[i][2] = 0;
}
}
}
/* ----------------------------------------------------------------------
add single atom with coords at xone if it's in my sub-box
if triclinic, xone is in lamda coords
------------------------------------------------------------------------- */
void CreateAtoms::add_single()
{
double *sublo,*subhi;
// sub-domain bounding box, in lamda units if triclinic
if (domain->triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
// if triclinic, convert to lamda coords (0-1)
double lamda[3],*coord;
if (domain->triclinic) {
domain->x2lamda(xone,lamda);
coord = lamda;
} else coord = xone;
// if atom is in my subbox, create it
if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1] &&
coord[2] >= sublo[2] && coord[2] < subhi[2])
atom->avec->create_atom(itype,xone);
}
/* ----------------------------------------------------------------------
add Nrandom atoms at random locations
------------------------------------------------------------------------- */
void CreateAtoms::add_random()
{
double xlo,ylo,zlo,xhi,yhi,zhi,zmid;
double lamda[3],*coord;
double *sublo,*subhi,*boxlo,*boxhi;
// random number generator, same for all procs
RanPark *random = new RanPark(lmp,seed);
// bounding box for atom creation
// in real units, even if triclinic
// only limit bbox by region if its bboxflag is set (interior region)
if (domain->triclinic == 0) {
xlo = domain->boxlo[0]; xhi = domain->boxhi[0];
ylo = domain->boxlo[1]; yhi = domain->boxhi[1];
zlo = domain->boxlo[2]; zhi = domain->boxhi[2];
zmid = zlo + 0.5*(zhi-zlo);
} else {
xlo = domain->boxlo_bound[0]; xhi = domain->boxhi_bound[0];
ylo = domain->boxlo_bound[1]; yhi = domain->boxhi_bound[1];
zlo = domain->boxlo_bound[2]; zhi = domain->boxhi_bound[2];
zmid = zlo + 0.5*(zhi-zlo);
}
if (nregion >= 0 && domain->regions[nregion]->bboxflag) {
xlo = MAX(xlo,domain->regions[nregion]->extent_xlo);
xhi = MIN(xhi,domain->regions[nregion]->extent_xhi);
ylo = MAX(ylo,domain->regions[nregion]->extent_ylo);
yhi = MIN(yhi,domain->regions[nregion]->extent_yhi);
zlo = MAX(zlo,domain->regions[nregion]->extent_zlo);
zhi = MIN(zhi,domain->regions[nregion]->extent_zhi);
}
// sub-domain bounding box, in lamda units if triclinic
if (domain->triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
boxlo = domain->boxlo_lamda;
boxhi = domain->boxhi_lamda;
}
// generate random positions for each new atom within bounding box
// iterate until atom is within region and triclinic simulation box
// if final atom position is in my subbox, create it
int valid;
for (int i = 0; i < nrandom; i++) {
while (1) {
xone[0] = xlo + random->uniform() * (xhi-xlo);
xone[1] = ylo + random->uniform() * (yhi-ylo);
xone[2] = zlo + random->uniform() * (zhi-zlo);
if (domain->dimension == 2) xone[2] = zmid;
valid = 1;
if (nregion >= 0 &&
domain->regions[nregion]->match(xone[0],xone[1],xone[2]) == 0)
valid = 0;
if (domain->triclinic) {
domain->x2lamda(xone,lamda);
coord = lamda;
if (coord[0] < boxlo[0] || coord[0] >= boxhi[0] ||
coord[1] < boxlo[1] || coord[1] >= boxhi[1] ||
coord[2] < boxlo[2] || coord[2] >= boxhi[2]) valid = 0;
} else coord = xone;
if (valid) break;
}
// if triclinic, coord is now in lamda units
if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1] &&
coord[2] >= sublo[2] && coord[2] < subhi[2])
atom->avec->create_atom(itype,xone);
}
// clean-up
delete random;
}
/* ----------------------------------------------------------------------
add many atoms by looping over lattice
------------------------------------------------------------------------- */
void CreateAtoms::add_lattice()
{
// convert 8 corners of my subdomain from box coords to lattice coords
// for orthogonal, use corner pts of my subbox
// for triclinic, use bounding box of my subbox
// xyz min to max = bounding box around the domain corners in lattice space
int triclinic = domain->triclinic;
double bboxlo[3],bboxhi[3];
if (triclinic == 0) {
bboxlo[0] = domain->sublo[0]; bboxhi[0] = domain->subhi[0];
bboxlo[1] = domain->sublo[1]; bboxhi[1] = domain->subhi[1];
bboxlo[2] = domain->sublo[2]; bboxhi[2] = domain->subhi[2];
} else domain->bbox(domain->sublo_lamda,domain->subhi_lamda,bboxlo,bboxhi);
double xmin,ymin,zmin,xmax,ymax,zmax;
xmin = ymin = zmin = BIG;
xmax = ymax = zmax = -BIG;
domain->lattice->bbox(1,bboxlo[0],bboxlo[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxlo[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxhi[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxhi[1],bboxlo[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxlo[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxlo[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxlo[0],bboxhi[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
domain->lattice->bbox(1,bboxhi[0],bboxhi[1],bboxhi[2],
xmin,ymin,zmin,xmax,ymax,zmax);
// ilo:ihi,jlo:jhi,klo:khi = loop bounds for lattice overlap of my subbox
// overlap = any part of a unit cell (face,edge,pt) in common with my subbox
// in lattice space, subbox is a tilted box
// but bbox of subbox is aligned with lattice axes
// so ilo:khi unit cells should completely tile bounding box
// decrement lo, increment hi to avoid round-off issues in lattice->bbox(),
// which can lead to missing atoms in rare cases
// extra decrement of lo if min < 0, since static_cast(-1.5) = -1
int ilo,ihi,jlo,jhi,klo,khi;
ilo = static_cast<int> (xmin) - 1;
jlo = static_cast<int> (ymin) - 1;
klo = static_cast<int> (zmin) - 1;
ihi = static_cast<int> (xmax) + 1;
jhi = static_cast<int> (ymax) + 1;
khi = static_cast<int> (zmax) + 1;
if (xmin < 0.0) ilo--;
if (ymin < 0.0) jlo--;
if (zmin < 0.0) klo--;
// set bounds for my proc
// if periodic:
// should create exactly 1 atom when 2 images are both "on" the boundary
// either image may be slightly inside/outside true box due to round-off
// if I am lo proc, decrement lower bound by EPSILON
// this will insure lo image is created
// if I am hi proc, decrement upper bound by 2.0*EPSILON
// this will insure hi image is not created
// thus insertion box is EPSILON smaller than true box
// and is shifted away from true boundary
// which is where atoms are likely to be generated
double epsilon[3];
if (triclinic) epsilon[0] = epsilon[1] = epsilon[2] = EPSILON;
else {
epsilon[0] = domain->prd[0] * EPSILON;
epsilon[1] = domain->prd[1] * EPSILON;
epsilon[2] = domain->prd[2] * EPSILON;
}
double sublo[3],subhi[3];
if (triclinic == 0) {
sublo[0] = domain->sublo[0]; subhi[0] = domain->subhi[0];
sublo[1] = domain->sublo[1]; subhi[1] = domain->subhi[1];
sublo[2] = domain->sublo[2]; subhi[2] = domain->subhi[2];
} else {
sublo[0] = domain->sublo_lamda[0]; subhi[0] = domain->subhi_lamda[0];
sublo[1] = domain->sublo_lamda[1]; subhi[1] = domain->subhi_lamda[1];
sublo[2] = domain->sublo_lamda[2]; subhi[2] = domain->subhi_lamda[2];
}
if (domain->xperiodic) {
if (comm->myloc[0] == 0) sublo[0] -= epsilon[0];
if (comm->myloc[0] == comm->procgrid[0]-1) subhi[0] -= 2.0*epsilon[0];
}
if (domain->yperiodic) {
if (comm->myloc[1] == 0) sublo[1] -= epsilon[1];
if (comm->myloc[1] == comm->procgrid[1]-1) subhi[1] -= 2.0*epsilon[1];
}
if (domain->zperiodic) {
if (comm->myloc[2] == 0) sublo[2] -= epsilon[2];
if (comm->myloc[2] == comm->procgrid[2]-1) subhi[2] -= 2.0*epsilon[2];
}
// iterate on 3d periodic lattice of unit cells using loop bounds
// iterate on nbasis atoms in each unit cell
// convert lattice coords to box coords
// add atom if it meets all criteria
double **basis = domain->lattice->basis;
double x[3],lamda[3];
double *coord;
int i,j,k,m;
for (k = klo; k <= khi; k++)
for (j = jlo; j <= jhi; j++)
for (i = ilo; i <= ihi; i++)
for (m = 0; m < nbasis; m++) {
x[0] = i + basis[m][0];
x[1] = j + basis[m][1];
x[2] = k + basis[m][2];
// convert from lattice coords to box coords
domain->lattice->lattice2box(x[0],x[1],x[2]);
// if a region was specified, test if atom is in it
if (style == REGION)
if (!domain->regions[nregion]->match(x[0],x[1],x[2])) continue;
// test if atom is in my subbox
if (triclinic) {
domain->x2lamda(x,lamda);
coord = lamda;
} else coord = x;
if (coord[0] < sublo[0] || coord[0] >= subhi[0] ||
coord[1] < sublo[1] || coord[1] >= subhi[1] ||
coord[2] < sublo[2] || coord[2] >= subhi[2]) continue;
// add the atom to my list of atoms
atom->avec->create_atom(basistype[m],x);
}
}
diff --git a/src/create_box.cpp b/src/create_box.cpp
index cc9ad9513..7cdb03365 100644
--- a/src/create_box.cpp
+++ b/src/create_box.cpp
@@ -1,115 +1,115 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "create_box.h"
#include "atom.h"
#include "force.h"
#include "domain.h"
#include "region.h"
#include "region_prism.h"
#include "comm.h"
#include "update.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
CreateBox::CreateBox(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void CreateBox::command(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal create_box command");
+ if (narg != 2) error->all(FLERR,"Illegal create_box command");
if (domain->box_exist)
- error->all("Cannot create_box after simulation box is defined");
+ error->all(FLERR,"Cannot create_box after simulation box is defined");
if (domain->dimension == 2 && domain->zperiodic == 0)
- error->all("Cannot run 2d simulation with nonperiodic Z dimension");
+ error->all(FLERR,"Cannot run 2d simulation with nonperiodic Z dimension");
domain->box_exist = 1;
// region check
int iregion = domain->find_region(arg[1]);
- if (iregion == -1) error->all("Create_box region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Create_box region ID does not exist");
if (domain->regions[iregion]->bboxflag == 0)
- error->all("Create_box region does not support a bounding box");
+ error->all(FLERR,"Create_box region does not support a bounding box");
// if region not prism:
// setup orthogonal domain
// set simulation domain from region extent
// if region is prism:
// seutp triclinic domain
// set simulation domain params from prism params
if (strcmp(domain->regions[iregion]->style,"prism") != 0) {
domain->triclinic = 0;
domain->boxlo[0] = domain->regions[iregion]->extent_xlo;
domain->boxhi[0] = domain->regions[iregion]->extent_xhi;
domain->boxlo[1] = domain->regions[iregion]->extent_ylo;
domain->boxhi[1] = domain->regions[iregion]->extent_yhi;
domain->boxlo[2] = domain->regions[iregion]->extent_zlo;
domain->boxhi[2] = domain->regions[iregion]->extent_zhi;
} else {
domain->triclinic = 1;
RegPrism *region = (RegPrism *) domain->regions[iregion];
domain->boxlo[0] = region->xlo;
domain->boxhi[0] = region->xhi;
domain->boxlo[1] = region->ylo;
domain->boxhi[1] = region->yhi;
domain->boxlo[2] = region->zlo;
domain->boxhi[2] = region->zhi;
domain->xy = region->xy;
domain->xz = region->xz;
domain->yz = region->yz;
}
// if molecular, zero out topology info
if (atom->molecular) {
atom->bond_per_atom = 0;
atom->angle_per_atom = 0;
atom->dihedral_per_atom = 0;
atom->improper_per_atom = 0;
atom->nbonds = 0;
atom->nangles = 0;
atom->ndihedrals = 0;
atom->nimpropers = 0;
}
// set atom and topology type quantities
atom->ntypes = atoi(arg[0]);
atom->nbondtypes = 0;
atom->nangletypes = 0;
atom->ndihedraltypes = 0;
atom->nimpropertypes = 0;
// problem setup using info from header
// no call to atom->grow since create_atoms or fixes will do it
update->ntimestep = 0;
atom->allocate_type_arrays();
domain->print_box("Created ");
domain->set_initial_box();
domain->set_global_box();
comm->set_procs();
domain->set_local_box();
}
diff --git a/src/delete_atoms.cpp b/src/delete_atoms.cpp
index 3de098fda..9ed147e06 100644
--- a/src/delete_atoms.cpp
+++ b/src/delete_atoms.cpp
@@ -1,364 +1,361 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "delete_atoms.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "domain.h"
#include "force.h"
#include "group.h"
#include "region.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
DeleteAtoms::DeleteAtoms(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void DeleteAtoms::command(int narg, char **arg)
{
if (domain->box_exist == 0)
- error->all("Delete_atoms command before simulation box is defined");
- if (narg < 1) error->all("Illegal delete_atoms command");
+ error->all(FLERR,"Delete_atoms command before simulation box is defined");
+ if (narg < 1) error->all(FLERR,"Illegal delete_atoms command");
if (atom->tag_enable == 0)
- error->all("Cannot use delete_atoms unless atoms have IDs");
+ error->all(FLERR,"Cannot use delete_atoms unless atoms have IDs");
// store state before delete
bigint natoms_previous = atom->natoms;
// delete the atoms
if (strcmp(arg[0],"group") == 0) delete_group(narg,arg);
else if (strcmp(arg[0],"region") == 0) delete_region(narg,arg);
else if (strcmp(arg[0],"overlap") == 0) delete_overlap(narg,arg);
else if (strcmp(arg[0],"porosity") == 0) delete_porosity(narg,arg);
- else error->all("Illegal delete_atoms command");
+ else error->all(FLERR,"Illegal delete_atoms command");
// delete local atoms flagged in dlist
// reset nlocal
AtomVec *avec = atom->avec;
int nlocal = atom->nlocal;
int i = 0;
while (i < nlocal) {
if (dlist[i]) {
avec->copy(nlocal-1,i,1);
dlist[i] = dlist[nlocal-1];
nlocal--;
} else i++;
}
atom->nlocal = nlocal;
memory->destroy(dlist);
// if non-molecular system and compress flag set,
// reset atom tags to be contiguous
// set all atom IDs to 0, call tag_extend()
if (atom->molecular == 0 && compress_flag) {
int *tag = atom->tag;
for (i = 0; i < nlocal; i++) tag[i] = 0;
atom->tag_extend();
}
// reset atom->natoms
// reset atom->map if it exists
// set nghost to 0 so old ghosts of deleted atoms won't be mapped
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (atom->map_style) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
// print before and after atom count
bigint ndelete = natoms_previous - atom->natoms;
if (comm->me == 0) {
if (screen) fprintf(screen,"Deleted " BIGINT_FORMAT
" atoms, new total = " BIGINT_FORMAT "\n",
ndelete,atom->natoms);
if (logfile) fprintf(logfile,"Deleted " BIGINT_FORMAT
" atoms, new total = " BIGINT_FORMAT "\n",
ndelete,atom->natoms);
}
}
/* ----------------------------------------------------------------------
delete all atoms in group
group will still exist
------------------------------------------------------------------------- */
void DeleteAtoms::delete_group(int narg, char **arg)
{
- if (narg < 2) error->all("Illegal delete_atoms command");
+ if (narg < 2) error->all(FLERR,"Illegal delete_atoms command");
int igroup = group->find(arg[1]);
- if (igroup == -1) error->all("Could not find delete_atoms group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find delete_atoms group ID");
options(narg-2,&arg[2]);
// allocate and initialize deletion list
int nlocal = atom->nlocal;
memory->create(dlist,nlocal,"delete_atoms:dlist");
for (int i = 0; i < nlocal; i++) dlist[i] = 0;
int *mask = atom->mask;
int groupbit = group->bitmask[igroup];
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) dlist[i] = 1;
}
/* ----------------------------------------------------------------------
delete all atoms in region
------------------------------------------------------------------------- */
void DeleteAtoms::delete_region(int narg, char **arg)
{
- if (narg < 2) error->all("Illegal delete_atoms command");
+ if (narg < 2) error->all(FLERR,"Illegal delete_atoms command");
int iregion = domain->find_region(arg[1]);
- if (iregion == -1) error->all("Could not find delete_atoms region ID");
+ if (iregion == -1) error->all(FLERR,"Could not find delete_atoms region ID");
options(narg-2,&arg[2]);
// allocate and initialize deletion list
int nlocal = atom->nlocal;
memory->create(dlist,nlocal,"delete_atoms:dlist");
for (int i = 0; i < nlocal; i++) dlist[i] = 0;
double **x = atom->x;
for (int i = 0; i < nlocal; i++)
if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2])) dlist[i] = 1;
}
/* ----------------------------------------------------------------------
delete atoms so there are no pairs within cutoff
which atoms are deleted depends on ordering of atoms within proc
deletions can vary with processor count
no guarantee that minimium number of atoms will be deleted
------------------------------------------------------------------------- */
void DeleteAtoms::delete_overlap(int narg, char **arg)
{
- if (narg < 4) error->all("Illegal delete_atoms command");
+ if (narg < 4) error->all(FLERR,"Illegal delete_atoms command");
// read args
double cut = atof(arg[1]);
double cutsq = cut*cut;
int igroup1 = group->find(arg[2]);
int igroup2 = group->find(arg[3]);
if (igroup1 < 0 || igroup2 < 0)
- error->all("Could not find delete_atoms group ID");
+ error->all(FLERR,"Could not find delete_atoms group ID");
options(narg-4,&arg[4]);
int group1bit = group->bitmask[igroup1];
int group2bit = group->bitmask[igroup2];
if (comm->me == 0 && screen)
fprintf(screen,"System init for delete_atoms ...\n");
// request a full neighbor list for use by this command
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->command = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
neighbor->requests[irequest]->occasional = 1;
// init entire system since comm->borders and neighbor->build is done
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc
lmp->init();
// error check on cutoff
// if no pair style, neighbor list will be empty
if (force->pair == NULL)
- error->all("Delete_atoms requires a pair style be defined");
+ error->all(FLERR,"Delete_atoms requires a pair style be defined");
if (cut > neighbor->cutneighmax)
- error->all("Delete_atoms cutoff > neighbor cutoff");
+ error->all(FLERR,"Delete_atoms cutoff > neighbor cutoff");
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor list based on earlier request
if (domain->triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
comm->borders();
if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
NeighList *list = neighbor->lists[irequest];
neighbor->build_one(irequest);
// allocate and initialize deletion list
// must be after exchange potentially changes nlocal
int nlocal = atom->nlocal;
memory->create(dlist,nlocal,"delete_atoms:dlist");
for (int i = 0; i < nlocal; i++) dlist[i] = 0;
// double loop over owned atoms and their full neighbor list
// at end of loop, there are no more overlaps
// only ever delete owned atom I, never J even if owned
int *tag = atom->tag;
int *mask = atom->mask;
double **x = atom->x;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int i,j,ii,jj,inum,jnum;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *ilist,*jlist,*numneigh,**firstneigh;
double factor_lj,factor_coul;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
// if both weighting factors are 0, skip this pair
// could be 0 and still be in neigh list for long-range Coulombics
// want consistency with non-charged pairs which wouldn't be in list
if (factor_lj == 0.0 && factor_coul == 0.0) continue;
// only consider deletion if I,J distance < cutoff
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq >= cutsq) continue;
// only consider deletion if I,J are in groups 1,2 respectively
// true whether J is owned or ghost atom
if (!(mask[i] & group1bit)) continue;
if (!(mask[j] & group2bit)) continue;
// J is owned atom:
// delete atom I if atom J has not already been deleted
// J is ghost atom:
// delete atom I if J,I is not a candidate deletion pair
// due to being in groups 1,2 respectively
// if they are candidate pair, then either:
// another proc owns J and could delete J
// J is a ghost of another of my owned atoms, and I could delete J
// test on tags of I,J insures that only I or J is deleted
if (j < nlocal) {
if (dlist[j]) continue;
} else if ((mask[i] & group2bit) && (mask[j] & group1bit)) {
if (tag[i] > tag[j]) continue;
}
dlist[i] = 1;
break;
}
}
}
/* ----------------------------------------------------------------------
create porosity by deleting atoms in a specified region
------------------------------------------------------------------------- */
void DeleteAtoms::delete_porosity(int narg, char **arg)
{
- if (narg < 4) error->all("Illegal delete_atoms command");
+ if (narg < 4) error->all(FLERR,"Illegal delete_atoms command");
int iregion = domain->find_region(arg[1]);
- if (iregion == -1) error->all("Could not find delete_atoms region ID");
+ if (iregion == -1) error->all(FLERR,"Could not find delete_atoms region ID");
double porosity_fraction = atof(arg[2]);
int seed = atoi(arg[3]);
options(narg-4,&arg[4]);
RanMars *random = new RanMars(lmp,seed + comm->me);
// allocate and initialize deletion list
int nlocal = atom->nlocal;
memory->create(dlist,nlocal,"delete_atoms:dlist");
for (int i = 0; i < nlocal; i++) dlist[i] = 0;
double **x = atom->x;
for (int i = 0; i < nlocal; i++)
if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
if (random->uniform() <= porosity_fraction) dlist[i] = 1;
}
/* ----------------------------------------------------------------------
process command options
------------------------------------------------------------------------- */
void DeleteAtoms::options(int narg, char **arg)
{
compress_flag = 1;
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"compress") == 0) {
- if (iarg+2 > narg) error->all("Illegal delete_bonds command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal delete_bonds command");
if (strcmp(arg[iarg+1],"yes") == 0) compress_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) compress_flag = 0;
- else error->all("Illegal delete_bonds command");
+ else error->all(FLERR,"Illegal delete_bonds command");
iarg += 2;
- } else error->all("Illegal delete_bonds command");
+ } else error->all(FLERR,"Illegal delete_bonds command");
}
}
diff --git a/src/delete_bonds.cpp b/src/delete_bonds.cpp
index 5bf219d97..01e1e3d14 100644
--- a/src/delete_bonds.cpp
+++ b/src/delete_bonds.cpp
@@ -1,500 +1,500 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "delete_bonds.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "neighbor.h"
#include "comm.h"
#include "force.h"
#include "group.h"
#include "special.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{MULTI,ATOM,BOND,ANGLE,DIHEDRAL,IMPROPER,STATS};
/* ---------------------------------------------------------------------- */
DeleteBonds::DeleteBonds(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void DeleteBonds::command(int narg, char **arg)
{
if (domain->box_exist == 0)
- error->all("Delete_bonds command before simulation box is defined");
+ error->all(FLERR,"Delete_bonds command before simulation box is defined");
if (atom->natoms == 0)
- error->all("Delete_bonds command with no atoms existing");
+ error->all(FLERR,"Delete_bonds command with no atoms existing");
if (atom->molecular == 0)
- error->all("Cannot use delete_bonds with non-molecular system");
- if (narg < 2) error->all("Illegal delete_bonds command");
+ error->all(FLERR,"Cannot use delete_bonds with non-molecular system");
+ if (narg < 2) error->all(FLERR,"Illegal delete_bonds command");
// init entire system since comm->borders is done
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc
if (comm->me == 0 && screen)
fprintf(screen,"System init for delete_bonds ...\n");
lmp->init();
if (comm->me == 0 && screen) fprintf(screen,"Deleting bonds ...\n");
// identify group
int igroup = group->find(arg[0]);
- if (igroup == -1) error->all("Cannot find delete_bonds group ID");
+ if (igroup == -1) error->all(FLERR,"Cannot find delete_bonds group ID");
int groupbit = group->bitmask[igroup];
// set style and which = type value
int style;
if (strcmp(arg[1],"multi") == 0) style = MULTI;
else if (strcmp(arg[1],"atom") == 0) style = ATOM;
else if (strcmp(arg[1],"bond") == 0) style = BOND;
else if (strcmp(arg[1],"angle") == 0) style = ANGLE;
else if (strcmp(arg[1],"dihedral") == 0) style = DIHEDRAL;
else if (strcmp(arg[1],"improper") == 0) style = IMPROPER;
else if (strcmp(arg[1],"stats") == 0) style = STATS;
- else error->all("Illegal delete_bonds command");
+ else error->all(FLERR,"Illegal delete_bonds command");
int iarg = 2;
int which;
if (style != MULTI && style != STATS) {
- if (narg < 3) error->all("Illegal delete_bonds command");
+ if (narg < 3) error->all(FLERR,"Illegal delete_bonds command");
which = atoi(arg[2]);
iarg++;
}
// grab optional keywords
int undo_flag = 0;
int remove_flag = 0;
int special_flag = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"undo") == 0) undo_flag = 1;
else if (strcmp(arg[iarg],"remove") == 0) remove_flag = 1;
else if (strcmp(arg[iarg],"special") == 0) special_flag = 1;
- else error->all("Illegal delete_bonds command");
+ else error->all(FLERR,"Illegal delete_bonds command");
iarg++;
}
// border swap to insure type and mask is current for off-proc atoms
// enforce PBC before in case atoms are outside box
if (domain->triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
comm->exchange();
comm->borders();
if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
// set topology interactions either off or on
// criteria for an interaction to potentially be changed (set flag = 1)
// all atoms in interaction must be in group
// for style = MULTI, no other criteria
// for style = ATOM, at least one atom is specified type
// for style = BOND/ANGLE/DIHEDRAL/IMPROPER, interaction is specified type
// for style = STATS only compute stats, flag is always 0
// if flag = 1
// set interaction type negative if undo_flag = 0
// set interaction type positive if undo_flag = 1
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
int i,m,n,flag;
int atom1,atom2,atom3,atom4;
if (atom->avec->bonds_allow) {
int *num_bond = atom->num_bond;
int **bond_type = atom->bond_type;
for (i = 0; i < nlocal; i++) {
for (m = 0; m < num_bond[i]; m++) {
atom1 = atom->map(atom->bond_atom[i][m]);
- if (atom1 == -1) error->one("Bond atom missing in delete_bonds");
+ if (atom1 == -1) error->one(FLERR,"Bond atom missing in delete_bonds");
if (mask[i] & groupbit && mask[atom1] & groupbit) {
flag = 0;
if (style == MULTI) flag = 1;
if (style == ATOM &&
(type[i] == which || type[atom1] == which)) flag = 1;
if (style == BOND && (bond_type[i][m] == which)) flag = 1;
if (flag) {
if (undo_flag == 0 && bond_type[i][m] > 0)
bond_type[i][m] = -bond_type[i][m];
if (undo_flag == 1 && bond_type[i][m] < 0)
bond_type[i][m] = -bond_type[i][m];
}
}
}
}
}
if (atom->avec->angles_allow) {
int *num_angle = atom->num_angle;
int **angle_type = atom->angle_type;
for (i = 0; i < nlocal; i++) {
for (m = 0; m < num_angle[i]; m++) {
atom1 = atom->map(atom->angle_atom1[i][m]);
atom2 = atom->map(atom->angle_atom2[i][m]);
atom3 = atom->map(atom->angle_atom3[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1)
- error->one("Angle atom missing in delete_bonds");
+ error->one(FLERR,"Angle atom missing in delete_bonds");
if (mask[atom1] & groupbit && mask[atom2] & groupbit &&
mask[atom3] & groupbit) {
flag = 0;
if (style == MULTI) flag = 1;
if (style == ATOM &&
(type[atom1] == which || type[atom2] == which ||
type[atom3] == which)) flag = 1;
if (style == ANGLE && (angle_type[i][m] == which)) flag = 1;
if (flag) {
if (undo_flag == 0 && angle_type[i][m] > 0)
angle_type[i][m] = -angle_type[i][m];
if (undo_flag == 1 && angle_type[i][m] < 0)
angle_type[i][m] = -angle_type[i][m];
}
}
}
}
}
if (atom->avec->dihedrals_allow) {
int *num_dihedral = atom->num_dihedral;
int **dihedral_type = atom->dihedral_type;
for (i = 0; i < nlocal; i++) {
for (m = 0; m < num_dihedral[i]; m++) {
atom1 = atom->map(atom->dihedral_atom1[i][m]);
atom2 = atom->map(atom->dihedral_atom2[i][m]);
atom3 = atom->map(atom->dihedral_atom3[i][m]);
atom4 = atom->map(atom->dihedral_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1)
- error->one("Dihedral atom missing in delete_bonds");
+ error->one(FLERR,"Dihedral atom missing in delete_bonds");
if (mask[atom1] & groupbit && mask[atom2] & groupbit &&
mask[atom3] & groupbit && mask[atom4] & groupbit) {
flag = 0;
if (style == MULTI) flag = 1;
if (style == ATOM &&
(type[atom1] == which || type[atom2] == which ||
type[atom3] == which || type[atom4] == which)) flag = 1;
if (style == DIHEDRAL && (dihedral_type[i][m] == which)) flag = 1;
if (flag) {
if (undo_flag == 0 && dihedral_type[i][m] > 0)
dihedral_type[i][m] = -dihedral_type[i][m];
if (undo_flag == 1 && dihedral_type[i][m] < 0)
dihedral_type[i][m] = -dihedral_type[i][m];
}
}
}
}
}
if (atom->avec->impropers_allow) {
int *num_improper = atom->num_improper;
int **improper_type = atom->improper_type;
for (i = 0; i < nlocal; i++) {
for (m = 0; m < num_improper[i]; m++) {
atom1 = atom->map(atom->improper_atom1[i][m]);
atom2 = atom->map(atom->improper_atom2[i][m]);
atom3 = atom->map(atom->improper_atom3[i][m]);
atom4 = atom->map(atom->improper_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1)
- error->one("Improper atom missing in delete_bonds");
+ error->one(FLERR,"Improper atom missing in delete_bonds");
if (mask[atom1] & groupbit && mask[atom2] & groupbit &&
mask[atom3] & groupbit && mask[atom4] & groupbit) {
flag = 0;
if (style == MULTI) flag = 1;
if (style == ATOM &&
(type[atom1] == which || type[atom2] == which ||
type[atom3] == which || type[atom4] == which)) flag = 1;
if (style == IMPROPER && (improper_type[i][m] == which)) flag = 1;
if (flag) {
if (undo_flag == 0 && improper_type[i][m] > 0)
improper_type[i][m] = -improper_type[i][m];
if (undo_flag == 1 && improper_type[i][m] < 0)
improper_type[i][m] = -improper_type[i][m];
}
}
}
}
}
// remove interactions if requested
// only if all atoms in bond, angle, etc are in the delete_bonds group
if (remove_flag) {
if (atom->avec->bonds_allow) {
for (i = 0; i < nlocal; i++) {
m = 0;
while (m < atom->num_bond[i]) {
if (atom->bond_type[i][m] <= 0) {
atom1 = atom->map(atom->bond_atom[i][m]);
if (mask[i] & groupbit && mask[atom1] & groupbit) {
n = atom->num_bond[i];
atom->bond_type[i][m] = atom->bond_type[i][n-1];
atom->bond_atom[i][m] = atom->bond_atom[i][n-1];
atom->num_bond[i]--;
} else m++;
} else m++;
}
}
}
if (atom->avec->angles_allow) {
for (i = 0; i < nlocal; i++) {
m = 0;
while (m < atom->num_angle[i]) {
if (atom->angle_type[i][m] <= 0) {
atom1 = atom->map(atom->angle_atom1[i][m]);
atom2 = atom->map(atom->angle_atom2[i][m]);
atom3 = atom->map(atom->angle_atom3[i][m]);
if (mask[atom1] & groupbit && mask[atom2] & groupbit &&
mask[atom3] & groupbit) {
n = atom->num_angle[i];
atom->angle_type[i][m] = atom->angle_type[i][n-1];
atom->angle_atom1[i][m] = atom->angle_atom1[i][n-1];
atom->angle_atom2[i][m] = atom->angle_atom2[i][n-1];
atom->angle_atom3[i][m] = atom->angle_atom3[i][n-1];
atom->num_angle[i]--;
} else m++;
} else m++;
}
}
}
if (atom->avec->dihedrals_allow) {
for (i = 0; i < nlocal; i++) {
m = 0;
while (m < atom->num_dihedral[i]) {
if (atom->dihedral_type[i][m] <= 0) {
atom1 = atom->map(atom->dihedral_atom1[i][m]);
atom2 = atom->map(atom->dihedral_atom2[i][m]);
atom3 = atom->map(atom->dihedral_atom3[i][m]);
atom4 = atom->map(atom->dihedral_atom4[i][m]);
if (mask[atom1] & groupbit && mask[atom2] & groupbit &&
mask[atom3] & groupbit && mask[atom4] & groupbit) {
n = atom->num_dihedral[i];
atom->dihedral_type[i][m] = atom->dihedral_type[i][n-1];
atom->dihedral_atom1[i][m] = atom->dihedral_atom1[i][n-1];
atom->dihedral_atom2[i][m] = atom->dihedral_atom2[i][n-1];
atom->dihedral_atom3[i][m] = atom->dihedral_atom3[i][n-1];
atom->dihedral_atom4[i][m] = atom->dihedral_atom4[i][n-1];
atom->num_dihedral[i]--;
} else m++;
} else m++;
}
}
}
if (atom->avec->impropers_allow) {
for (i = 0; i < nlocal; i++) {
m = 0;
while (m < atom->num_improper[i]) {
if (atom->improper_type[i][m] <= 0) {
atom1 = atom->map(atom->improper_atom1[i][m]);
atom2 = atom->map(atom->improper_atom2[i][m]);
atom3 = atom->map(atom->improper_atom3[i][m]);
atom4 = atom->map(atom->improper_atom4[i][m]);
if (mask[atom1] & groupbit && mask[atom2] & groupbit &&
mask[atom3] & groupbit && mask[atom4] & groupbit) {
n = atom->num_improper[i];
atom->improper_type[i][m] = atom->improper_type[i][n-1];
atom->improper_atom1[i][m] = atom->improper_atom1[i][n-1];
atom->improper_atom2[i][m] = atom->improper_atom2[i][n-1];
atom->improper_atom3[i][m] = atom->improper_atom3[i][n-1];
atom->improper_atom4[i][m] = atom->improper_atom4[i][n-1];
atom->num_improper[i]--;
} else m++;
} else m++;
}
}
}
}
// if interactions were removed, recompute global counts
if (remove_flag) {
if (atom->avec->bonds_allow) {
bigint nbonds = 0;
for (i = 0; i < nlocal; i++) nbonds += atom->num_bond[i];
MPI_Allreduce(&nbonds,&atom->nbonds,1,MPI_LMP_BIGINT,
MPI_SUM,world);
if (force->newton_bond == 0) atom->nbonds /= 2;
}
if (atom->avec->angles_allow) {
bigint nangles = 0;
for (i = 0; i < nlocal; i++) nangles += atom->num_angle[i];
MPI_Allreduce(&nangles,&atom->nangles,1,MPI_LMP_BIGINT,
MPI_SUM,world);
if (force->newton_bond == 0) atom->nangles /= 3;
}
if (atom->avec->dihedrals_allow) {
bigint ndihedrals = 0;
for (i = 0; i < nlocal; i++) ndihedrals += atom->num_dihedral[i];
MPI_Allreduce(&ndihedrals,&atom->ndihedrals,
1,MPI_LMP_BIGINT,MPI_SUM,world);
if (force->newton_bond == 0) atom->ndihedrals /= 4;
}
if (atom->avec->impropers_allow) {
bigint nimpropers = 0;
for (i = 0; i < nlocal; i++) nimpropers += atom->num_improper[i];
MPI_Allreduce(&nimpropers,&atom->nimpropers,
1,MPI_LMP_BIGINT,MPI_SUM,world);
if (force->newton_bond == 0) atom->nimpropers /= 4;
}
}
// compute and print stats
bigint tmp;
bigint bond_on,bond_off;
bigint angle_on,angle_off;
bigint dihedral_on,dihedral_off;
bigint improper_on,improper_off;
if (atom->avec->bonds_allow) {
bond_on = bond_off = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_bond[i]; m++)
if (atom->bond_type[i][m] > 0) bond_on++;
else bond_off++;
MPI_Allreduce(&bond_on,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
bond_on = tmp;
MPI_Allreduce(&bond_off,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
bond_off = tmp;
if (force->newton_bond == 0) {
bond_on /= 2;
bond_off /= 2;
}
}
if (atom->avec->angles_allow) {
angle_on = angle_off = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_angle[i]; m++)
if (atom->angle_type[i][m] > 0) angle_on++;
else angle_off++;
MPI_Allreduce(&angle_on,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
angle_on = tmp;
MPI_Allreduce(&angle_off,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
angle_off = tmp;
if (force->newton_bond == 0) {
angle_on /= 3;
angle_off /= 3;
}
}
if (atom->avec->dihedrals_allow) {
dihedral_on = dihedral_off = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_dihedral[i]; m++)
if (atom->dihedral_type[i][m] > 0) dihedral_on++;
else dihedral_off++;
MPI_Allreduce(&dihedral_on,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
dihedral_on = tmp;
MPI_Allreduce(&dihedral_off,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
dihedral_off = tmp;
if (force->newton_bond == 0) {
dihedral_on /= 4;
dihedral_off /= 4;
}
}
if (atom->avec->impropers_allow) {
improper_on = improper_off = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_improper[i]; m++)
if (atom->improper_type[i][m] > 0) improper_on++;
else improper_off++;
MPI_Allreduce(&improper_on,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
improper_on = tmp;
MPI_Allreduce(&improper_off,&tmp,1,MPI_LMP_BIGINT,MPI_SUM,world);
improper_off = tmp;
if (force->newton_bond == 0) {
improper_on /= 4;
improper_off /= 4;
}
}
if (comm->me == 0) {
if (atom->avec->bonds_allow) {
if (screen) fprintf(screen,
" " BIGINT_FORMAT " total bonds, " BIGINT_FORMAT
" turned on, " BIGINT_FORMAT " turned off\n",
atom->nbonds,bond_on,bond_off);
if (logfile) fprintf(logfile,
" " BIGINT_FORMAT " total bonds, " BIGINT_FORMAT
" turned on, " BIGINT_FORMAT " turned off\n",
atom->nbonds,bond_on,bond_off);
}
if (atom->avec->angles_allow) {
if (screen) fprintf(screen,
" " BIGINT_FORMAT " total angles, " BIGINT_FORMAT
" turned on, " BIGINT_FORMAT " turned off\n",
atom->nangles,angle_on,angle_off);
if (logfile) fprintf(logfile,
" " BIGINT_FORMAT " total angles, " BIGINT_FORMAT
" turned on, " BIGINT_FORMAT " turned off\n",
atom->nangles,angle_on,angle_off);
}
if (atom->avec->dihedrals_allow) {
if (screen) fprintf(screen,
" " BIGINT_FORMAT " total dihedrals, "
BIGINT_FORMAT " turned on, " BIGINT_FORMAT
" turned off\n",
atom->ndihedrals,dihedral_on,dihedral_off);
if (logfile) fprintf(logfile,
" " BIGINT_FORMAT " total dihedrals, "
BIGINT_FORMAT " turned on, " BIGINT_FORMAT
" turned off\n",
atom->ndihedrals,dihedral_on,dihedral_off);
}
if (atom->avec->impropers_allow) {
if (screen) fprintf(screen,
" " BIGINT_FORMAT " total impropers, "
BIGINT_FORMAT " turned on, " BIGINT_FORMAT
" turned off\n",
atom->nimpropers,improper_on,improper_off);
if (logfile) fprintf(logfile,
" " BIGINT_FORMAT " total impropers, "
BIGINT_FORMAT " turned on, " BIGINT_FORMAT
" turned off\n",
atom->nimpropers,improper_on,improper_off);
}
}
// re-compute special list if requested
if (special_flag) {
Special special(lmp);
special.build();
}
}
diff --git a/src/dihedral.cpp b/src/dihedral.cpp
index 1a3f6f5a4..a3edadc0c 100644
--- a/src/dihedral.cpp
+++ b/src/dihedral.cpp
@@ -1,249 +1,249 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "dihedral.h"
#include "atom.h"
#include "atom.h"
#include "force.h"
#include "pair.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
set dihedral contribution to Vdwl and Coulombic energy to 0.0
DihedralCharmm will override this
------------------------------------------------------------------------- */
Dihedral::Dihedral(LAMMPS *lmp) : Pointers(lmp)
{
energy = 0.0;
allocated = 0;
PI = 4.0*atan(1.0);
maxeatom = maxvatom = 0;
eatom = NULL;
vatom = NULL;
}
/* ---------------------------------------------------------------------- */
Dihedral::~Dihedral()
{
memory->destroy(eatom);
memory->destroy(vatom);
}
/* ----------------------------------------------------------------------
check if all coeffs are set
------------------------------------------------------------------------- */
void Dihedral::init()
{
- if (!allocated) error->all("Dihedral coeffs are not set");
+ if (!allocated) error->all(FLERR,"Dihedral coeffs are not set");
for (int i = 1; i <= atom->ndihedraltypes; i++)
- if (setflag[i] == 0) error->all("All dihedral coeffs are not set");
+ if (setflag[i] == 0) error->all(FLERR,"All dihedral coeffs are not set");
init_style();
}
/* ----------------------------------------------------------------------
setup for energy, virial computation
see integrate::ev_set() for values of eflag (0-3) and vflag (0-6)
------------------------------------------------------------------------- */
void Dihedral::ev_setup(int eflag, int vflag)
{
int i,n;
evflag = 1;
eflag_either = eflag;
eflag_global = eflag % 2;
eflag_atom = eflag / 2;
vflag_either = vflag;
vflag_global = vflag % 4;
vflag_atom = vflag / 4;
// reallocate per-atom arrays if necessary
if (eflag_atom && atom->nmax > maxeatom) {
maxeatom = atom->nmax;
memory->destroy(eatom);
memory->create(eatom,maxeatom,"bond:eatom");
}
if (vflag_atom && atom->nmax > maxvatom) {
maxvatom = atom->nmax;
memory->destroy(vatom);
memory->create(vatom,maxvatom,6,"bond:vatom");
}
// zero accumulators
if (eflag_global) energy = 0.0;
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) eatom[i] = 0.0;
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) {
vatom[i][0] = 0.0;
vatom[i][1] = 0.0;
vatom[i][2] = 0.0;
vatom[i][3] = 0.0;
vatom[i][4] = 0.0;
vatom[i][5] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
tally energy and virial into global and per-atom accumulators
virial = r1F1 + r2F2 + r3F3 + r4F4 = (r1-r2) F1 + (r3-r2) F3 + (r4-r2) F4
= (r1-r2) F1 + (r3-r2) F3 + (r4-r3 + r3-r2) F4
= vb1*f1 + vb2*f3 + (vb3+vb2)*f4
------------------------------------------------------------------------- */
void Dihedral::ev_tally(int i1, int i2, int i3, int i4,
int nlocal, int newton_bond,
double edihedral, double *f1, double *f3, double *f4,
double vb1x, double vb1y, double vb1z,
double vb2x, double vb2y, double vb2z,
double vb3x, double vb3y, double vb3z)
{
double edihedralquarter,v[6];
if (eflag_either) {
if (eflag_global) {
if (newton_bond) energy += edihedral;
else {
edihedralquarter = 0.25*edihedral;
if (i1 < nlocal) energy += edihedralquarter;
if (i2 < nlocal) energy += edihedralquarter;
if (i3 < nlocal) energy += edihedralquarter;
if (i4 < nlocal) energy += edihedralquarter;
}
}
if (eflag_atom) {
edihedralquarter = 0.25*edihedral;
if (newton_bond || i1 < nlocal) eatom[i1] += edihedralquarter;
if (newton_bond || i2 < nlocal) eatom[i2] += edihedralquarter;
if (newton_bond || i3 < nlocal) eatom[i3] += edihedralquarter;
if (newton_bond || i4 < nlocal) eatom[i4] += edihedralquarter;
}
}
if (vflag_either) {
v[0] = vb1x*f1[0] + vb2x*f3[0] + (vb3x+vb2x)*f4[0];
v[1] = vb1y*f1[1] + vb2y*f3[1] + (vb3y+vb2y)*f4[1];
v[2] = vb1z*f1[2] + vb2z*f3[2] + (vb3z+vb2z)*f4[2];
v[3] = vb1x*f1[1] + vb2x*f3[1] + (vb3x+vb2x)*f4[1];
v[4] = vb1x*f1[2] + vb2x*f3[2] + (vb3x+vb2x)*f4[2];
v[5] = vb1y*f1[2] + vb2y*f3[2] + (vb3y+vb2y)*f4[2];
if (vflag_global) {
if (newton_bond) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i1 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
if (i2 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
if (i3 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
if (i4 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
}
}
if (vflag_atom) {
if (newton_bond || i1 < nlocal) {
vatom[i1][0] += 0.25*v[0];
vatom[i1][1] += 0.25*v[1];
vatom[i1][2] += 0.25*v[2];
vatom[i1][3] += 0.25*v[3];
vatom[i1][4] += 0.25*v[4];
vatom[i1][5] += 0.25*v[5];
}
if (newton_bond || i2 < nlocal) {
vatom[i2][0] += 0.25*v[0];
vatom[i2][1] += 0.25*v[1];
vatom[i2][2] += 0.25*v[2];
vatom[i2][3] += 0.25*v[3];
vatom[i2][4] += 0.25*v[4];
vatom[i2][5] += 0.25*v[5];
}
if (newton_bond || i3 < nlocal) {
vatom[i3][0] += 0.25*v[0];
vatom[i3][1] += 0.25*v[1];
vatom[i3][2] += 0.25*v[2];
vatom[i3][3] += 0.25*v[3];
vatom[i3][4] += 0.25*v[4];
vatom[i3][5] += 0.25*v[5];
}
if (newton_bond || i4 < nlocal) {
vatom[i4][0] += 0.25*v[0];
vatom[i4][1] += 0.25*v[1];
vatom[i4][2] += 0.25*v[2];
vatom[i4][3] += 0.25*v[3];
vatom[i4][4] += 0.25*v[4];
vatom[i4][5] += 0.25*v[5];
}
}
}
}
/* ---------------------------------------------------------------------- */
double Dihedral::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
return bytes;
}
diff --git a/src/displace_atoms.cpp b/src/displace_atoms.cpp
index f433541d9..1793a5e19 100644
--- a/src/displace_atoms.cpp
+++ b/src/displace_atoms.cpp
@@ -1,243 +1,240 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "displace_atoms.h"
#include "atom.h"
#include "modify.h"
#include "domain.h"
#include "lattice.h"
#include "comm.h"
#include "irregular.h"
#include "group.h"
#include "random_park.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{MOVE,RAMP,RANDOM};
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
DisplaceAtoms::DisplaceAtoms(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void DisplaceAtoms::command(int narg, char **arg)
{
int i;
if (domain->box_exist == 0)
- error->all("Displace_atoms command before simulation box is defined");
- if (narg < 2) error->all("Illegal displace_atoms command");
+ error->all(FLERR,"Displace_atoms command before simulation box is defined");
+ if (narg < 2) error->all(FLERR,"Illegal displace_atoms command");
if (modify->nfix_restart_peratom)
- error->all("Cannot displace_atoms after "
+ error->all(FLERR,"Cannot displace_atoms after "
"reading restart file with per-atom info");
if (comm->me == 0 && screen) fprintf(screen,"Displacing atoms ...\n");
// group and style
int igroup = group->find(arg[0]);
- if (igroup == -1) error->all("Could not find displace_atoms group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find displace_atoms group ID");
int groupbit = group->bitmask[igroup];
int style;
if (strcmp(arg[1],"move") == 0) style = MOVE;
else if (strcmp(arg[1],"ramp") == 0) style = RAMP;
else if (strcmp(arg[1],"random") == 0) style = RANDOM;
- else error->all("Illegal displace_atoms command");
+ else error->all(FLERR,"Illegal displace_atoms command");
// set option defaults
scaleflag = 1;
// read options from end of input line
if (style == MOVE) options(narg-5,&arg[5]);
else if (style == RAMP) options(narg-8,&arg[8]);
else if (style == RANDOM) options(narg-6,&arg[6]);
// setup scaling
if (scaleflag && domain->lattice == NULL)
- error->all("Use of displace_atoms with undefined lattice");
+ error->all(FLERR,"Use of displace_atoms with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// move atoms by 3-vector
if (style == MOVE) {
double delx = xscale*atof(arg[2]);
double dely = yscale*atof(arg[3]);
double delz = zscale*atof(arg[4]);
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
x[i][0] += delx;
x[i][1] += dely;
x[i][2] += delz;
}
}
}
// move atoms in ramped fashion
if (style == RAMP) {
int d_dim;
if (strcmp(arg[2],"x") == 0) d_dim = 0;
else if (strcmp(arg[2],"y") == 0) d_dim = 1;
else if (strcmp(arg[2],"z") == 0) d_dim = 2;
- else error->all("Illegal displace_atoms ramp command");
+ else error->all(FLERR,"Illegal displace_atoms ramp command");
double d_lo,d_hi;
if (d_dim == 0) {
d_lo = xscale*atof(arg[3]);
d_hi = xscale*atof(arg[4]);
} else if (d_dim == 1) {
d_lo = yscale*atof(arg[3]);
d_hi = yscale*atof(arg[4]);
} else if (d_dim == 2) {
d_lo = zscale*atof(arg[3]);
d_hi = zscale*atof(arg[4]);
}
int coord_dim;
if (strcmp(arg[5],"x") == 0) coord_dim = 0;
else if (strcmp(arg[5],"y") == 0) coord_dim = 1;
else if (strcmp(arg[5],"z") == 0) coord_dim = 2;
- else error->all("Illegal displace_atoms ramp command");
+ else error->all(FLERR,"Illegal displace_atoms ramp command");
double coord_lo,coord_hi;
if (coord_dim == 0) {
coord_lo = xscale*atof(arg[6]);
coord_hi = xscale*atof(arg[7]);
} else if (coord_dim == 1) {
coord_lo = yscale*atof(arg[6]);
coord_hi = yscale*atof(arg[7]);
} else if (coord_dim == 2) {
coord_lo = zscale*atof(arg[6]);
coord_hi = zscale*atof(arg[7]);
}
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double fraction,dramp;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
fraction = (x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
fraction = MAX(fraction,0.0);
fraction = MIN(fraction,1.0);
dramp = d_lo + fraction*(d_hi - d_lo);
x[i][d_dim] += dramp;
}
}
}
// move atoms randomly
// makes atom result independent of what proc owns it via random->reset()
if (style == RANDOM) {
RanPark *random = new RanPark(lmp,1);
double dx = xscale*atof(arg[2]);
double dy = yscale*atof(arg[3]);
double dz = zscale*atof(arg[4]);
int seed = atoi(arg[5]);
- if (seed <= 0) error->all("Illegal displace_atoms random command");
+ if (seed <= 0) error->all(FLERR,"Illegal displace_atoms random command");
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
random->reset(seed,x[i]);
x[i][0] += dx * 2.0*(random->uniform()-0.5);
x[i][1] += dy * 2.0*(random->uniform()-0.5);
x[i][2] += dz * 2.0*(random->uniform()-0.5);
}
}
delete random;
}
// move atoms back inside simulation box and to new processors
// use remap() instead of pbc() in case atoms moved a long distance
// use irregular() in case atoms moved a long distance
double **x = atom->x;
int *image = atom->image;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);
if (domain->triclinic) domain->x2lamda(atom->nlocal);
domain->reset_box();
Irregular *irregular = new Irregular(lmp);
irregular->migrate_atoms();
delete irregular;
if (domain->triclinic) domain->lamda2x(atom->nlocal);
// check if any atoms were lost
bigint natoms;
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (natoms != atom->natoms) {
char str[128];
sprintf(str,"Lost atoms via displace_atoms: original " BIGINT_FORMAT
" current " BIGINT_FORMAT,atom->natoms,natoms);
- error->all(str);
+ error->all(FLERR,str);
}
}
/* ----------------------------------------------------------------------
parse optional parameters at end of displace_atoms input line
------------------------------------------------------------------------- */
void DisplaceAtoms::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal displace_atoms command");
+ if (narg < 0) error->all(FLERR,"Illegal displace_atoms command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal displace_atoms command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal displace_atoms command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal displace_atoms command");
+ else error->all(FLERR,"Illegal displace_atoms command");
iarg += 2;
- } else error->all("Illegal displace_atoms command");
+ } else error->all(FLERR,"Illegal displace_atoms command");
}
}
diff --git a/src/displace_box.cpp b/src/displace_box.cpp
index f2e3363a6..79f886578 100644
--- a/src/displace_box.cpp
+++ b/src/displace_box.cpp
@@ -1,418 +1,418 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "displace_box.h"
#include "atom.h"
#include "modify.h"
#include "domain.h"
#include "lattice.h"
#include "comm.h"
#include "irregular.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NONE,FINAL,DELTA,SCALE,VOLUME};
enum{ONE_FROM_ONE,ONE_FROM_TWO,TWO_FROM_ONE};
enum{NO_REMAP,X_REMAP};
/* ---------------------------------------------------------------------- */
DisplaceBox::DisplaceBox(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void DisplaceBox::command(int narg, char **arg)
{
int i;
if (domain->box_exist == 0)
- error->all("Displace_box command before simulation box is defined");
- if (narg < 2) error->all("Illegal displace_box command");
+ error->all(FLERR,"Displace_box command before simulation box is defined");
+ if (narg < 2) error->all(FLERR,"Illegal displace_box command");
if (modify->nfix_restart_peratom)
- error->all("Cannot displace_box after "
+ error->all(FLERR,"Cannot displace_box after "
"reading restart file with per-atom info");
if (comm->me == 0 && screen) fprintf(screen,"Displacing box ...\n");
// group
int igroup = group->find(arg[0]);
- if (igroup == -1) error->all("Could not find displace_box group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find displace_box group ID");
int groupbit = group->bitmask[igroup];
// set defaults
set = new Set[6];
set[0].style = set[1].style = set[2].style =
set[3].style = set[4].style = set[5].style = NONE;
// parse arguments
int triclinic = domain->triclinic;
int index;
int iarg = 1;
while (iarg < narg) {
if (strcmp(arg[iarg],"x") == 0 || strcmp(arg[iarg],"y") == 0 ||
strcmp(arg[iarg],"z") == 0) {
if (strcmp(arg[iarg],"x") == 0) index = 0;
else if (strcmp(arg[iarg],"y") == 0) index = 1;
else if (strcmp(arg[iarg],"z") == 0) index = 2;
- if (iarg+2 > narg) error->all("Illegal displace_box command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal displace_box command");
if (strcmp(arg[iarg+1],"final") == 0) {
- if (iarg+4 > narg) error->all("Illegal displace_box command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal displace_box command");
set[index].style = FINAL;
set[index].flo = atof(arg[iarg+2]);
set[index].fhi = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg+1],"delta") == 0) {
- if (iarg+4 > narg) error->all("Illegal displace_box command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal displace_box command");
set[index].style = DELTA;
set[index].dlo = atof(arg[iarg+2]);
set[index].dhi = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg+1],"scale") == 0) {
- if (iarg+3 > narg) error->all("Illegal displace_box command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal displace_box command");
set[index].style = SCALE;
set[index].scale = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"volume") == 0) {
set[index].style = VOLUME;
iarg += 2;
- } else error->all("Illegal displace_box command");
+ } else error->all(FLERR,"Illegal displace_box command");
} else if (strcmp(arg[iarg],"xy") == 0 || strcmp(arg[iarg],"xz") == 0 ||
strcmp(arg[iarg],"yz") == 0) {
if (triclinic == 0)
- error->all("Displace_box tilt factors require triclinic box");
+ error->all(FLERR,"Displace_box tilt factors require triclinic box");
if (strcmp(arg[iarg],"xy") == 0) index = 5;
else if (strcmp(arg[iarg],"xz") == 0) index = 4;
else if (strcmp(arg[iarg],"yz") == 0) index = 3;
- if (iarg+2 > narg) error->all("Illegal displace_box command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal displace_box command");
if (strcmp(arg[iarg+1],"final") == 0) {
- if (iarg+3 > narg) error->all("Illegal displace_box command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal displace_box command");
set[index].style = FINAL;
set[index].ftilt = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"delta") == 0) {
- if (iarg+3 > narg) error->all("Illegal displace_box command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal displace_box command");
set[index].style = DELTA;
set[index].dtilt = atof(arg[iarg+2]);
iarg += 3;
- } else error->all("Illegal displace_box command");
+ } else error->all(FLERR,"Illegal displace_box command");
} else break;
}
// read options from end of input line
options(narg-iarg,&arg[iarg]);
// check periodicity
if ((set[0].style && domain->xperiodic == 0) ||
(set[1].style && domain->yperiodic == 0) ||
(set[2].style && domain->zperiodic == 0))
- error->all("Cannot displace_box on a non-periodic boundary");
+ error->all(FLERR,"Cannot displace_box on a non-periodic boundary");
if (set[3].style && (domain->yperiodic == 0 || domain->zperiodic == 0))
- error->all("Cannot displace_box on a non-periodic boundary");
+ error->all(FLERR,"Cannot displace_box on a non-periodic boundary");
if (set[4].style && (domain->xperiodic == 0 || domain->zperiodic == 0))
- error->all("Cannot displace_box on a non-periodic boundary");
+ error->all(FLERR,"Cannot displace_box on a non-periodic boundary");
if (set[5].style && (domain->xperiodic == 0 || domain->yperiodic == 0))
- error->all("Cannot displace_box on a non-periodic boundary");
+ error->all(FLERR,"Cannot displace_box on a non-periodic boundary");
// apply scaling to FINAL,DELTA since they have distance units
int flag = 0;
for (int i = 0; i < 6; i++)
if (set[i].style == FINAL || set[i].style == DELTA) flag = 1;
if (flag && scaleflag && domain->lattice == NULL)
- error->all("Use of displace_box with undefined lattice");
+ error->all(FLERR,"Use of displace_box with undefined lattice");
double xscale,yscale,zscale;
if (flag && scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// for 3,4,5 scaling is in 1st dimension, e.g. x for xz
double map[6];
map[0] = xscale; map[1] = yscale; map[2] = zscale;
map[3] = yscale; map[4] = xscale; map[5] = xscale;
for (int i = 0; i < 3; i++) {
if (set[i].style == FINAL) {
set[i].flo *= map[i];
set[i].fhi *= map[i];
} else if (set[i].style == DELTA) {
set[i].dlo *= map[i];
set[i].dhi *= map[i];
}
}
for (int i = 3; i < 6; i++) {
if (set[i].style == FINAL) set[i].ftilt *= map[i];
else if (set[i].style == DELTA) set[i].dtilt *= map[i];
}
// set initial/final values for box size and shape
// final = initial if no setting
for (int i = 0; i < 3; i++) {
set[i].lo_stop = set[i].lo_start = domain->boxlo[i];
set[i].hi_stop = set[i].hi_start = domain->boxhi[i];
if (set[i].style == FINAL) {
set[i].lo_stop = set[i].flo;
set[i].hi_stop = set[i].fhi;
} else if (set[i].style == DELTA) {
set[i].lo_stop = set[i].lo_start + set[i].dlo;
set[i].hi_stop = set[i].hi_start + set[i].dhi;
} else if (set[i].style == SCALE) {
set[i].lo_stop = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*set[i].scale*(set[i].hi_start-set[i].lo_start);
set[i].hi_stop = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*set[i].scale*(set[i].hi_start-set[i].lo_start);
}
}
for (int i = 3; i < 6; i++) {
if (i == 5) set[i].tilt_start = domain->xy;
else if (i == 4) set[i].tilt_start = domain->xz;
else if (i == 3) set[i].tilt_start = domain->yz;
set[i].tilt_stop = set[i].tilt_start;
if (set[i].style == FINAL) {
set[i].tilt_stop = set[i].ftilt;
} else if (set[i].style == DELTA) {
set[i].tilt_stop = set[i].tilt_start + set[i].dtilt;
}
}
// for VOLUME, setup links to other dims
// fixed, dynamic1,2, vol_start
for (int i = 0; i < 3; i++) {
set[i].vol_start = domain->xprd * domain->yprd * domain->zprd;
if (set[i].style != VOLUME) continue;
int other1 = (i+1) % 3;
int other2 = (i+2) % 3;
if (set[other1].style == NONE) {
if (set[other2].style == NONE || set[other2].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = ONE_FROM_ONE;
set[i].fixed = other1;
set[i].dynamic1 = other2;
} else if (set[other2].style == NONE) {
if (set[other1].style == NONE || set[other1].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = ONE_FROM_ONE;
set[i].fixed = other2;
set[i].dynamic1 = other1;
} else if (set[other1].style == VOLUME) {
if (set[other2].style == NONE || set[other2].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = TWO_FROM_ONE;
set[i].fixed = other1;
set[i].dynamic1 = other2;
} else if (set[other2].style == VOLUME) {
if (set[other1].style == NONE || set[other1].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = TWO_FROM_ONE;
set[i].fixed = other2;
set[i].dynamic1 = other1;
} else {
set[i].substyle = ONE_FROM_TWO;
set[i].dynamic2 = other1;
set[i].dynamic2 = other2;
}
}
// set new box size for VOLUME dims that are linked to other dims
for (int i = 0; i < 3; i++) {
if (set[i].style != VOLUME) continue;
if (set[i].substyle == ONE_FROM_ONE) {
set[i].lo_stop = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_stop -
set[set[i].dynamic1].lo_stop) /
(set[set[i].fixed].hi_start-set[set[i].fixed].lo_start));
set[i].hi_stop = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_stop -
set[set[i].dynamic1].lo_stop) /
(set[set[i].fixed].hi_start-set[set[i].fixed].lo_start));
} else if (set[i].substyle == ONE_FROM_TWO) {
set[i].lo_stop = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_stop -
set[set[i].dynamic1].lo_stop) /
(set[set[i].dynamic2].hi_stop -
set[set[i].dynamic2].lo_stop));
set[i].hi_stop = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_stop -
set[set[i].dynamic1].lo_stop) /
(set[set[i].dynamic2].hi_stop -
set[set[i].dynamic2].lo_stop));
} else if (set[i].substyle == TWO_FROM_ONE) {
set[i].lo_stop = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*sqrt(set[i].vol_start /
(set[set[i].dynamic1].hi_stop -
set[set[i].dynamic1].lo_stop) /
(set[set[i].fixed].hi_start -
set[set[i].fixed].lo_start) *
(set[i].hi_start - set[i].lo_start));
set[i].hi_stop = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*sqrt(set[i].vol_start /
(set[set[i].dynamic1].hi_stop -
set[set[i].dynamic1].lo_stop) /
(set[set[i].fixed].hi_start -
set[set[i].fixed].lo_start) *
(set[i].hi_start - set[i].lo_start));
}
}
// check that final tilt is not illegal value
double xprd_stop = set[0].hi_stop - set[0].lo_stop;
double yprd_stop = set[0].hi_stop - set[0].lo_stop;
if (set[3].tilt_stop < -0.5*yprd_stop || set[3].tilt_stop > 0.5*yprd_stop ||
set[4].tilt_stop < -0.5*xprd_stop || set[4].tilt_stop > 0.5*xprd_stop ||
set[5].tilt_stop < -0.5*xprd_stop || set[5].tilt_stop > 0.5*xprd_stop)
- error->all("Induced tilt by displace_box is too large");
+ error->all(FLERR,"Induced tilt by displace_box is too large");
// convert atoms to lamda coords
if (remapflag == X_REMAP) {
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->x2lamda(x[i],x[i]);
}
// reset global and local box to new size/shape
domain->boxlo[0] = set[0].lo_stop;
domain->boxlo[1] = set[1].lo_stop;
domain->boxlo[2] = set[2].lo_stop;
domain->boxhi[0] = set[0].hi_stop;
domain->boxhi[1] = set[1].hi_stop;
domain->boxhi[2] = set[2].hi_stop;
if (triclinic) {
domain->yz = set[3].tilt_stop;
domain->xz = set[4].tilt_stop;
domain->xy = set[5].tilt_stop;
}
domain->set_global_box();
domain->set_local_box();
// convert atoms back to box coords
if (remapflag == X_REMAP) {
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->lamda2x(x[i],x[i]);
}
// move atoms back inside simulation box and to new processors
// use remap() instead of pbc()
// in case box moved a long distance relative to atoms
// use irregular() in case box moved a long distance relative to atoms
double **x = atom->x;
int *image = atom->image;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);
if (domain->triclinic) domain->x2lamda(atom->nlocal);
domain->reset_box();
Irregular *irregular = new Irregular(lmp);
irregular->migrate_atoms();
delete irregular;
if (domain->triclinic) domain->lamda2x(atom->nlocal);
// clean up
delete [] set;
// check if any atoms were lost
bigint natoms;
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (natoms != atom->natoms) {
char str[128];
sprintf(str,"Lost atoms via displace_box: original " BIGINT_FORMAT
" current " BIGINT_FORMAT,atom->natoms,natoms);
- error->all(str);
+ error->all(FLERR,str);
}
}
/* ----------------------------------------------------------------------
parse optional parameters at end of displace_box input line
------------------------------------------------------------------------- */
void DisplaceBox::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal displace_box command");
+ if (narg < 0) error->all(FLERR,"Illegal displace_box command");
remapflag = X_REMAP;
scaleflag = 1;
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"remap") == 0) {
- if (iarg+2 > narg) error->all("Illegal displace_box command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal displace_box command");
if (strcmp(arg[iarg+1],"x") == 0) remapflag = X_REMAP;
else if (strcmp(arg[iarg+1],"none") == 0) remapflag = NO_REMAP;
- else error->all("Illegal displace_box command");
+ else error->all(FLERR,"Illegal displace_box command");
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal displace_box command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal displace_box command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal displace_box command");
+ else error->all(FLERR,"Illegal displace_box command");
iarg += 2;
- } else error->all("Illegal displace_box command");
+ } else error->all(FLERR,"Illegal displace_box command");
}
}
diff --git a/src/domain.cpp b/src/domain.cpp
index 4688a733f..a1a0045fa 100644
--- a/src/domain.cpp
+++ b/src/domain.cpp
@@ -1,1290 +1,1288 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author (triclinic) : Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "math.h"
#include "domain.h"
#include "style_region.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "fix_deform.h"
#include "region.h"
#include "lattice.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
#define SMALL 1.0e-4
#define DELTA 1
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp
/* ----------------------------------------------------------------------
default is periodic
------------------------------------------------------------------------- */
Domain::Domain(LAMMPS *lmp) : Pointers(lmp)
{
box_exist = 0;
dimension = 3;
nonperiodic = 0;
xperiodic = yperiodic = zperiodic = 1;
periodicity[0] = xperiodic;
periodicity[1] = yperiodic;
periodicity[2] = zperiodic;
boundary[0][0] = boundary[0][1] = 0;
boundary[1][0] = boundary[1][1] = 0;
boundary[2][0] = boundary[2][1] = 0;
triclinic = 0;
boxlo[0] = boxlo[1] = boxlo[2] = -0.5;
boxhi[0] = boxhi[1] = boxhi[2] = 0.5;
xy = xz = yz = 0.0;
h[3] = h[4] = h[5] = 0.0;
h_inv[3] = h_inv[4] = h_inv[5] = 0.0;
h_rate[0] = h_rate[1] = h_rate[2] =
h_rate[3] = h_rate[4] = h_rate[5] = 0.0;
h_ratelo[0] = h_ratelo[1] = h_ratelo[2] = 0.0;
prd_lamda[0] = prd_lamda[1] = prd_lamda[2] = 1.0;
prd_half_lamda[0] = prd_half_lamda[1] = prd_half_lamda[2] = 0.5;
boxlo_lamda[0] = boxlo_lamda[1] = boxlo_lamda[2] = 0.0;
boxhi_lamda[0] = boxhi_lamda[1] = boxhi_lamda[2] = 1.0;
lattice = NULL;
nregion = maxregion = 0;
regions = NULL;
}
/* ---------------------------------------------------------------------- */
Domain::~Domain()
{
delete lattice;
for (int i = 0; i < nregion; i++) delete regions[i];
memory->sfree(regions);
}
/* ---------------------------------------------------------------------- */
void Domain::init()
{
// set box_change if box dimensions/shape ever changes
// due to shrink-wrapping, fixes that change volume (npt, vol/rescale, etc)
box_change = 0;
if (nonperiodic == 2) box_change = 1;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->box_change) box_change = 1;
// check for fix deform
deform_flag = deform_vremap = deform_groupbit = 0;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
deform_flag = 1;
if (((FixDeform *) modify->fix[i])->remapflag == V_REMAP) {
deform_vremap = 1;
deform_groupbit = modify->fix[i]->groupbit;
}
}
// region inits
for (int i = 0; i < nregion; i++) regions[i]->init();
}
/* ----------------------------------------------------------------------
set initial global box
assumes boxlo/hi and triclinic tilts are already set
------------------------------------------------------------------------- */
void Domain::set_initial_box()
{
// error checks for orthogonal and triclinic domains
if (boxlo[0] >= boxhi[0] || boxlo[1] >= boxhi[1] || boxlo[2] >= boxhi[2])
- error->one("Box bounds are invalid");
+ error->one(FLERR,"Box bounds are invalid");
if (triclinic) {
if (domain->dimension == 2 && (xz != 0.0 || yz != 0.0))
- error->all("Cannot skew triclinic box in z for 2d simulation");
+ error->all(FLERR,"Cannot skew triclinic box in z for 2d simulation");
if (xy != 0.0 && (!xperiodic || !yperiodic))
- error->all("Triclinic box must be periodic in skewed dimensions");
+ error->all(FLERR,"Triclinic box must be periodic in skewed dimensions");
if (xz != 0.0 && (!xperiodic || !zperiodic))
- error->all("Triclinic box must be periodic in skewed dimensions");
+ error->all(FLERR,"Triclinic box must be periodic in skewed dimensions");
if (yz != 0.0 && (!yperiodic || !zperiodic))
- error->all("Triclinic box must be periodic in skewed dimensions");
+ error->all(FLERR,"Triclinic box must be periodic in skewed dimensions");
if (fabs(xy/(boxhi[0]-boxlo[0])) > 0.5)
- error->all("Triclinic box skew is too large");
+ error->all(FLERR,"Triclinic box skew is too large");
if (fabs(xz/(boxhi[0]-boxlo[0])) > 0.5)
- error->all("Triclinic box skew is too large");
+ error->all(FLERR,"Triclinic box skew is too large");
if (fabs(yz/(boxhi[1]-boxlo[1])) > 0.5)
- error->all("Triclinic box skew is too large");
+ error->all(FLERR,"Triclinic box skew is too large");
}
// adjust box lo/hi for shrink-wrapped dims
if (boundary[0][0] == 2) boxlo[0] -= SMALL;
else if (boundary[0][0] == 3) minxlo = boxlo[0];
if (boundary[0][1] == 2) boxhi[0] += SMALL;
else if (boundary[0][1] == 3) minxhi = boxhi[0];
if (boundary[1][0] == 2) boxlo[1] -= SMALL;
else if (boundary[1][0] == 3) minylo = boxlo[1];
if (boundary[1][1] == 2) boxhi[1] += SMALL;
else if (boundary[1][1] == 3) minyhi = boxhi[1];
if (boundary[2][0] == 2) boxlo[2] -= SMALL;
else if (boundary[2][0] == 3) minzlo = boxlo[2];
if (boundary[2][1] == 2) boxhi[2] += SMALL;
else if (boundary[2][1] == 3) minzhi = boxhi[2];
}
/* ----------------------------------------------------------------------
set global box params
assumes boxlo/hi and triclinic tilts are already set
------------------------------------------------------------------------- */
void Domain::set_global_box()
{
prd[0] = xprd = boxhi[0] - boxlo[0];
prd[1] = yprd = boxhi[1] - boxlo[1];
prd[2] = zprd = boxhi[2] - boxlo[2];
h[0] = xprd;
h[1] = yprd;
h[2] = zprd;
h_inv[0] = 1.0/h[0];
h_inv[1] = 1.0/h[1];
h_inv[2] = 1.0/h[2];
prd_half[0] = xprd_half = 0.5*xprd;
prd_half[1] = yprd_half = 0.5*yprd;
prd_half[2] = zprd_half = 0.5*zprd;
if (triclinic) {
h[3] = yz;
h[4] = xz;
h[5] = xy;
h_inv[3] = -h[3] / (h[1]*h[2]);
h_inv[4] = (h[3]*h[5] - h[1]*h[4]) / (h[0]*h[1]*h[2]);
h_inv[5] = -h[5] / (h[0]*h[1]);
boxlo_bound[0] = MIN(boxlo[0],boxlo[0]+xy);
boxlo_bound[0] = MIN(boxlo_bound[0],boxlo_bound[0]+xz);
boxlo_bound[1] = MIN(boxlo[1],boxlo[1]+yz);
boxlo_bound[2] = boxlo[2];
boxhi_bound[0] = MAX(boxhi[0],boxhi[0]+xy);
boxhi_bound[0] = MAX(boxhi_bound[0],boxhi_bound[0]+xz);
boxhi_bound[1] = MAX(boxhi[1],boxhi[1]+yz);
boxhi_bound[2] = boxhi[2];
}
}
/* ----------------------------------------------------------------------
set lamda box params, only need be done one time
assumes global box is defined and proc assignment has been made by comm
for uppermost proc, insure subhi = 1.0 (in case round-off occurs)
------------------------------------------------------------------------- */
void Domain::set_lamda_box()
{
int *myloc = comm->myloc;
int *procgrid = comm->procgrid;
sublo_lamda[0] = 1.0*myloc[0] / procgrid[0];
sublo_lamda[1] = 1.0*myloc[1] / procgrid[1];
sublo_lamda[2] = 1.0*myloc[2] / procgrid[2];
if (myloc[0] < procgrid[0]-1)
subhi_lamda[0] = 1.0*(myloc[0]+1) / procgrid[0];
else subhi_lamda[0] = 1.0;
if (myloc[1] < procgrid[1]-1)
subhi_lamda[1] = 1.0*(myloc[1]+1) / procgrid[1];
else subhi_lamda[1] = 1.0;
if (myloc[2] < procgrid[2]-1)
subhi_lamda[2] = 1.0*(myloc[2]+1) / procgrid[2];
else subhi_lamda[2] = 1.0;
}
/* ----------------------------------------------------------------------
set local subbox params
assumes global box is defined and proc assignment has been made
for uppermost proc, insure subhi = boxhi (in case round-off occurs)
------------------------------------------------------------------------- */
void Domain::set_local_box()
{
int *myloc = comm->myloc;
int *procgrid = comm->procgrid;
if (triclinic == 0) {
sublo[0] = boxlo[0] + myloc[0] * xprd / procgrid[0];
if (myloc[0] < procgrid[0]-1)
subhi[0] = boxlo[0] + (myloc[0]+1) * xprd / procgrid[0];
else subhi[0] = boxhi[0];
sublo[1] = boxlo[1] + myloc[1] * yprd / procgrid[1];
if (myloc[1] < procgrid[1]-1)
subhi[1] = boxlo[1] + (myloc[1]+1) * yprd / procgrid[1];
else subhi[1] = boxhi[1];
sublo[2] = boxlo[2] + myloc[2] * zprd / procgrid[2];
if (myloc[2] < procgrid[2]-1)
subhi[2] = boxlo[2] + (myloc[2]+1) * zprd / procgrid[2];
else subhi[2] = boxhi[2];
}
}
/* ----------------------------------------------------------------------
reset global & local boxes due to global box boundary changes
if shrink-wrapped, determine atom extent and reset boxlo/hi
if shrink-wrapped and triclinic, perform shrink-wrap in box coords
------------------------------------------------------------------------- */
void Domain::reset_box()
{
if (nonperiodic == 2) {
// convert back to box coords for shrink-wrap operation
if (triclinic) lamda2x(atom->nlocal);
// compute extent of atoms on this proc
double extent[3][2],all[3][2];
extent[2][0] = extent[1][0] = extent[0][0] = BIG;
extent[2][1] = extent[1][1] = extent[0][1] = -BIG;
double **x = atom->x;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
extent[0][0] = MIN(extent[0][0],x[i][0]);
extent[0][1] = MAX(extent[0][1],x[i][0]);
extent[1][0] = MIN(extent[1][0],x[i][1]);
extent[1][1] = MAX(extent[1][1],x[i][1]);
extent[2][0] = MIN(extent[2][0],x[i][2]);
extent[2][1] = MAX(extent[2][1],x[i][2]);
}
// compute extent across all procs
// flip sign of MIN to do it in one Allreduce MAX
extent[0][0] = -extent[0][0];
extent[1][0] = -extent[1][0];
extent[2][0] = -extent[2][0];
MPI_Allreduce(extent,all,6,MPI_DOUBLE,MPI_MAX,world);
// in shrink-wrapped dims, set box by atom extent
// if minimum set, enforce min box size settings
if (xperiodic == 0) {
if (boundary[0][0] == 2) boxlo[0] = -all[0][0] - SMALL;
else if (boundary[0][0] == 3) boxlo[0] = MIN(-all[0][0]-SMALL,minxlo);
if (boundary[0][1] == 2) boxhi[0] = all[0][1] + SMALL;
else if (boundary[0][1] == 3) boxhi[0] = MAX(all[0][1]+SMALL,minxhi);
- if (boxlo[0] > boxhi[0]) error->all("Illegal simulation box");
+ if (boxlo[0] > boxhi[0]) error->all(FLERR,"Illegal simulation box");
}
if (yperiodic == 0) {
if (boundary[1][0] == 2) boxlo[1] = -all[1][0] - SMALL;
else if (boundary[1][0] == 3) boxlo[1] = MIN(-all[1][0]-SMALL,minylo);
if (boundary[1][1] == 2) boxhi[1] = all[1][1] + SMALL;
else if (boundary[1][1] == 3) boxhi[1] = MAX(all[1][1]+SMALL,minyhi);
- if (boxlo[1] > boxhi[1]) error->all("Illegal simulation box");
+ if (boxlo[1] > boxhi[1]) error->all(FLERR,"Illegal simulation box");
}
if (zperiodic == 0) {
if (boundary[2][0] == 2) boxlo[2] = -all[2][0] - SMALL;
else if (boundary[2][0] == 3) boxlo[2] = MIN(-all[2][0]-SMALL,minzlo);
if (boundary[2][1] == 2) boxhi[2] = all[2][1] + SMALL;
else if (boundary[2][1] == 3) boxhi[2] = MAX(all[2][1]+SMALL,minzhi);
- if (boxlo[2] > boxhi[2]) error->all("Illegal simulation box");
+ if (boxlo[2] > boxhi[2]) error->all(FLERR,"Illegal simulation box");
}
}
set_global_box();
set_local_box();
// if shrink-wrapped, convert to lamda coords for new box
// must re-invoke pbc() b/c x2lamda result can be outside 0,1 due to roundoff
if (nonperiodic == 2 && triclinic) {
x2lamda(atom->nlocal);
pbc();
}
}
/* ----------------------------------------------------------------------
enforce PBC and modify box image flags for each atom
called every reneighboring and by other commands that change atoms
resulting coord must satisfy lo <= coord < hi
MAX is important since coord - prd < lo can happen when coord = hi
if fix deform, remap velocity of fix group atoms by box edge velocities
for triclinic, atoms must be in lamda coords (0-1) before pbc is called
image = 10 bits for each dimension
increment/decrement in wrap-around fashion
------------------------------------------------------------------------- */
void Domain::pbc()
{
int i,idim,otherdims;
double *lo,*hi,*period;
int nlocal = atom->nlocal;
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int *image = atom->image;
if (triclinic == 0) {
lo = boxlo;
hi = boxhi;
period = prd;
} else {
lo = boxlo_lamda;
hi = boxhi_lamda;
period = prd_lamda;
}
for (i = 0; i < nlocal; i++) {
if (xperiodic) {
if (x[i][0] < lo[0]) {
x[i][0] += period[0];
if (deform_vremap && mask[i] & deform_groupbit) v[i][0] += h_rate[0];
idim = image[i] & 1023;
otherdims = image[i] ^ idim;
idim--;
idim &= 1023;
image[i] = otherdims | idim;
}
if (x[i][0] >= hi[0]) {
x[i][0] -= period[0];
x[i][0] = MAX(x[i][0],lo[0]);
if (deform_vremap && mask[i] & deform_groupbit) v[i][0] -= h_rate[0];
idim = image[i] & 1023;
otherdims = image[i] ^ idim;
idim++;
idim &= 1023;
image[i] = otherdims | idim;
}
}
if (yperiodic) {
if (x[i][1] < lo[1]) {
x[i][1] += period[1];
if (deform_vremap && mask[i] & deform_groupbit) {
v[i][0] += h_rate[5];
v[i][1] += h_rate[1];
}
idim = (image[i] >> 10) & 1023;
otherdims = image[i] ^ (idim << 10);
idim--;
idim &= 1023;
image[i] = otherdims | (idim << 10);
}
if (x[i][1] >= hi[1]) {
x[i][1] -= period[1];
x[i][1] = MAX(x[i][1],lo[1]);
if (deform_vremap && mask[i] & deform_groupbit) {
v[i][0] -= h_rate[5];
v[i][1] -= h_rate[1];
}
idim = (image[i] >> 10) & 1023;
otherdims = image[i] ^ (idim << 10);
idim++;
idim &= 1023;
image[i] = otherdims | (idim << 10);
}
}
if (zperiodic) {
if (x[i][2] < lo[2]) {
x[i][2] += period[2];
if (deform_vremap && mask[i] & deform_groupbit) {
v[i][0] += h_rate[4];
v[i][1] += h_rate[3];
v[i][2] += h_rate[2];
}
idim = image[i] >> 20;
otherdims = image[i] ^ (idim << 20);
idim--;
idim &= 1023;
image[i] = otherdims | (idim << 20);
}
if (x[i][2] >= hi[2]) {
x[i][2] -= period[2];
x[i][2] = MAX(x[i][2],lo[2]);
if (deform_vremap && mask[i] & deform_groupbit) {
v[i][0] -= h_rate[4];
v[i][1] -= h_rate[3];
v[i][2] -= h_rate[2];
}
idim = image[i] >> 20;
otherdims = image[i] ^ (idim << 20);
idim++;
idim &= 1023;
image[i] = otherdims | (idim << 20);
}
}
}
}
/* ----------------------------------------------------------------------
minimum image convention check
return 1 if any distance > 1/2 of box size
------------------------------------------------------------------------- */
int Domain::minimum_image_check(double dx, double dy, double dz)
{
if (xperiodic && fabs(dx) > xprd_half) return 1;
if (yperiodic && fabs(dy) > yprd_half) return 1;
if (zperiodic && fabs(dz) > zprd_half) return 1;
return 0;
}
/* ----------------------------------------------------------------------
minimum image convention
use 1/2 of box size as test
for triclinic, also add/subtract tilt factors in other dims as needed
------------------------------------------------------------------------- */
void Domain::minimum_image(double &dx, double &dy, double &dz)
{
if (triclinic == 0) {
if (xperiodic) {
if (fabs(dx) > xprd_half) {
if (dx < 0.0) dx += xprd;
else dx -= xprd;
}
}
if (yperiodic) {
if (fabs(dy) > yprd_half) {
if (dy < 0.0) dy += yprd;
else dy -= yprd;
}
}
if (zperiodic) {
if (fabs(dz) > zprd_half) {
if (dz < 0.0) dz += zprd;
else dz -= zprd;
}
}
} else {
if (zperiodic) {
if (fabs(dz) > zprd_half) {
if (dz < 0.0) {
dz += zprd;
dy += yz;
dx += xz;
} else {
dz -= zprd;
dy -= yz;
dx -= xz;
}
}
}
if (yperiodic) {
if (fabs(dy) > yprd_half) {
if (dy < 0.0) {
dy += yprd;
dx += xy;
} else {
dy -= yprd;
dx -= xy;
}
}
}
if (xperiodic) {
if (fabs(dx) > xprd_half) {
if (dx < 0.0) dx += xprd;
else dx -= xprd;
}
}
}
}
/* ----------------------------------------------------------------------
minimum image convention
use 1/2 of box size as test
for triclinic, also add/subtract tilt factors in other dims as needed
------------------------------------------------------------------------- */
void Domain::minimum_image(double *delta)
{
if (triclinic == 0) {
if (xperiodic) {
if (fabs(delta[0]) > xprd_half) {
if (delta[0] < 0.0) delta[0] += xprd;
else delta[0] -= xprd;
}
}
if (yperiodic) {
if (fabs(delta[1]) > yprd_half) {
if (delta[1] < 0.0) delta[1] += yprd;
else delta[1] -= yprd;
}
}
if (zperiodic) {
if (fabs(delta[2]) > zprd_half) {
if (delta[2] < 0.0) delta[2] += zprd;
else delta[2] -= zprd;
}
}
} else {
if (zperiodic) {
if (fabs(delta[2]) > zprd_half) {
if (delta[2] < 0.0) {
delta[2] += zprd;
delta[1] += yz;
delta[0] += xz;
} else {
delta[2] -= zprd;
delta[1] -= yz;
delta[0] -= xz;
}
}
}
if (yperiodic) {
if (fabs(delta[1]) > yprd_half) {
if (delta[1] < 0.0) {
delta[1] += yprd;
delta[0] += xy;
} else {
delta[1] -= yprd;
delta[0] -= xy;
}
}
}
if (xperiodic) {
if (fabs(delta[0]) > xprd_half) {
if (delta[0] < 0.0) delta[0] += xprd;
else delta[0] -= xprd;
}
}
}
}
/* ----------------------------------------------------------------------
find Xj image = periodic image of Xj that is closest to Xi
for triclinic, also add/subtract tilt factors in other dims as needed
------------------------------------------------------------------------- */
void Domain::closest_image(double *xi, double *xj, double *xjimage)
{
double dx,dy,dz;
if (triclinic == 0) {
if (xperiodic) {
dx = xj[0] - xi[0];
if (dx < 0.0) {
while (dx < 0.0) dx += xprd;
if (dx > xprd_half) dx -= xprd;
} else {
while (dx > 0.0) dx -= xprd;
if (dx < -xprd_half) dx += xprd;
}
xjimage[0] = xi[0] + dx;
}
if (yperiodic) {
dy = xj[1] - xi[1];
if (dy < 0.0) {
while (dy < 0.0) dy += yprd;
if (dy > yprd_half) dy -= yprd;
} else {
while (dy > 0.0) dy -= yprd;
if (dy < -yprd_half) dy += yprd;
}
xjimage[1] = xi[1] + dy;
}
if (zperiodic) {
dz = xj[2] - xi[2];
if (dz < 0.0) {
while (dz < 0.0) dz += zprd;
if (dz > zprd_half) dz -= zprd;
} else {
while (dz > 0.0) dz -= zprd;
if (dz < -zprd_half) dz += zprd;
}
xjimage[2] = xi[2] + dz;
}
} else {
dx = xj[0] - xi[0];
dy = xj[1] - xi[1];
dz = xj[2] - xi[2];
if (zperiodic) {
if (dz < 0.0) {
while (dz < 0.0) {
dz += zprd;
dy += yz;
dx += xz;
}
if (dz > zprd_half) {
dz -= zprd;
dy -= yz;
dx -= xz;
}
} else {
while (dz > 0.0) {
dz -= zprd;
dy -= yz;
dx -= xz;
}
if (dz < -zprd_half) {
dz += zprd;
dy += yz;
dx += xz;
}
}
}
if (yperiodic) {
if (dy < 0.0) {
while (dy < 0.0) {
dy += yprd;
dx += xy;
}
if (dy > yprd_half) {
dy -= yprd;
dx -= xy;
}
} else {
while (dy > 0.0) {
dy -= yprd;
dx -= xy;
}
if (dy < -yprd_half) {
dy += yprd;
dx += xy;
}
}
}
if (xperiodic) {
if (dx < 0.0) {
while (dx < 0.0) dx += xprd;
if (dx > xprd_half) dx -= xprd;
} else {
while (dx > 0.0) dx -= xprd;
if (dx < -xprd_half) dx += xprd;
}
}
xjimage[0] = xi[0] + dx;
xjimage[1] = xi[1] + dy;
xjimage[2] = xi[2] + dz;
}
}
/* ----------------------------------------------------------------------
remap the point into the periodic box no matter how far away
adjust image accordingly
resulting coord must satisfy lo <= coord < hi
MAX is important since coord - prd < lo can happen when coord = hi
for triclinic, point is converted to lamda coords (0-1) before doing remap
image = 10 bits for each dimension
increment/decrement in wrap-around fashion
------------------------------------------------------------------------- */
void Domain::remap(double *x, int &image)
{
double *lo,*hi,*period,*coord;
double lamda[3];
if (triclinic == 0) {
lo = boxlo;
hi = boxhi;
period = prd;
coord = x;
} else {
lo = boxlo_lamda;
hi = boxhi_lamda;
period = prd_lamda;
x2lamda(x,lamda);
coord = lamda;
}
if (xperiodic) {
while (coord[0] < lo[0]) {
coord[0] += period[0];
int idim = image & 1023;
int otherdims = image ^ idim;
idim--;
idim &= 1023;
image = otherdims | idim;
}
while (coord[0] >= hi[0]) {
coord[0] -= period[0];
int idim = image & 1023;
int otherdims = image ^ idim;
idim++;
idim &= 1023;
image = otherdims | idim;
}
coord[0] = MAX(coord[0],lo[0]);
}
if (yperiodic) {
while (coord[1] < lo[1]) {
coord[1] += period[1];
int idim = (image >> 10) & 1023;
int otherdims = image ^ (idim << 10);
idim--;
idim &= 1023;
image = otherdims | (idim << 10);
}
while (coord[1] >= hi[1]) {
coord[1] -= period[1];
int idim = (image >> 10) & 1023;
int otherdims = image ^ (idim << 10);
idim++;
idim &= 1023;
image = otherdims | (idim << 10);
}
coord[1] = MAX(coord[1],lo[1]);
}
if (zperiodic) {
while (coord[2] < lo[2]) {
coord[2] += period[2];
int idim = image >> 20;
int otherdims = image ^ (idim << 20);
idim--;
idim &= 1023;
image = otherdims | (idim << 20);
}
while (coord[2] >= hi[2]) {
coord[2] -= period[2];
int idim = image >> 20;
int otherdims = image ^ (idim << 20);
idim++;
idim &= 1023;
image = otherdims | (idim << 20);
}
coord[2] = MAX(coord[2],lo[2]);
}
if (triclinic) lamda2x(coord,x);
}
/* ----------------------------------------------------------------------
remap the point into the periodic box no matter how far away
resulting coord must satisfy lo <= coord < hi
MAX is important since coord - prd < lo can happen when coord = hi
for triclinic, point is converted to lamda coords (0-1) before remap
------------------------------------------------------------------------- */
void Domain::remap(double *x)
{
double *lo,*hi,*period,*coord;
double lamda[3];
if (triclinic == 0) {
lo = boxlo;
hi = boxhi;
period = prd;
coord = x;
} else {
lo = boxlo_lamda;
hi = boxhi_lamda;
period = prd_lamda;
x2lamda(x,lamda);
coord = lamda;
}
if (xperiodic) {
while (coord[0] < lo[0]) coord[0] += period[0];
while (coord[0] >= hi[0]) coord[0] -= period[0];
coord[0] = MAX(coord[0],lo[0]);
}
if (yperiodic) {
while (coord[1] < lo[1]) coord[1] += period[1];
while (coord[1] >= hi[1]) coord[1] -= period[1];
coord[1] = MAX(coord[1],lo[1]);
}
if (zperiodic) {
while (coord[2] < lo[2]) coord[2] += period[2];
while (coord[2] >= hi[2]) coord[2] -= period[2];
coord[2] = MAX(coord[2],lo[2]);
}
if (triclinic) lamda2x(coord,x);
}
/* ----------------------------------------------------------------------
remap xnew to be within half box length of xold
do it directly, not iteratively, in case is far away
for triclinic, both points are converted to lamda coords (0-1) before remap
------------------------------------------------------------------------- */
void Domain::remap_near(double *xnew, double *xold)
{
int n;
double *coordnew,*coordold,*period,*half;
double lamdanew[3],lamdaold[3];
if (triclinic == 0) {
period = prd;
half = prd_half;
coordnew = xnew;
coordold = xold;
} else {
period = prd_lamda;
half = prd_half_lamda;
x2lamda(xnew,lamdanew);
coordnew = lamdanew;
x2lamda(xold,lamdaold);
coordold = lamdaold;
}
// iterative form
// if (xperiodic) {
// while (xnew[0]-xold[0] > half[0]) xnew[0] -= period[0];
// while (xold[0]-xnew[0] > half[0]) xnew[0] += period[0];
// }
if (xperiodic) {
if (coordnew[0]-coordold[0] > period[0]) {
n = static_cast<int> ((coordnew[0]-coordold[0])/period[0]);
xnew[0] -= n*period[0];
}
while (xnew[0]-xold[0] > half[0]) xnew[0] -= period[0];
if (xold[0]-xnew[0] > period[0]) {
n = static_cast<int> ((xold[0]-xnew[0])/period[0]);
xnew[0] += n*period[0];
}
while (xold[0]-xnew[0] > half[0]) xnew[0] += period[0];
}
if (yperiodic) {
if (coordnew[1]-coordold[1] > period[1]) {
n = static_cast<int> ((coordnew[1]-coordold[1])/period[1]);
xnew[1] -= n*period[1];
}
while (xnew[1]-xold[1] > half[1]) xnew[1] -= period[1];
if (xold[1]-xnew[1] > period[1]) {
n = static_cast<int> ((xold[1]-xnew[1])/period[1]);
xnew[1] += n*period[1];
}
while (xold[1]-xnew[1] > half[1]) xnew[1] += period[1];
}
if (zperiodic) {
if (coordnew[2]-coordold[2] > period[2]) {
n = static_cast<int> ((coordnew[2]-coordold[2])/period[2]);
xnew[2] -= n*period[2];
}
while (xnew[2]-xold[2] > half[2]) xnew[2] -= period[2];
if (xold[2]-xnew[2] > period[2]) {
n = static_cast<int> ((xold[2]-xnew[2])/period[2]);
xnew[2] += n*period[2];
}
while (xold[2]-xnew[2] > half[2]) xnew[2] += period[2];
}
if (triclinic) {
lamda2x(coordnew,xnew);
lamda2x(coordold,xold);
}
}
/* ----------------------------------------------------------------------
unmap the point via image flags
x overwritten with result, don't reset image flag
for triclinic, use h[] to add in tilt factors in other dims as needed
------------------------------------------------------------------------- */
void Domain::unmap(double *x, int image)
{
int xbox = (image & 1023) - 512;
int ybox = (image >> 10 & 1023) - 512;
int zbox = (image >> 20) - 512;
if (triclinic == 0) {
x[0] += xbox*xprd;
x[1] += ybox*yprd;
x[2] += zbox*zprd;
} else {
x[0] += h[0]*xbox + h[5]*ybox + h[4]*zbox;
x[1] += h[1]*ybox + h[3]*zbox;
x[2] += h[2]*zbox;
}
}
/* ----------------------------------------------------------------------
unmap the point via image flags
result returned in y, don't reset image flag
for triclinic, use h[] to add in tilt factors in other dims as needed
------------------------------------------------------------------------- */
void Domain::unmap(double *x, int image, double *y)
{
int xbox = (image & 1023) - 512;
int ybox = (image >> 10 & 1023) - 512;
int zbox = (image >> 20) - 512;
if (triclinic == 0) {
y[0] = x[0] + xbox*xprd;
y[1] = x[1] + ybox*yprd;
y[2] = x[2] + zbox*zprd;
} else {
y[0] = x[0] + h[0]*xbox + h[5]*ybox + h[4]*zbox;
y[1] = x[1] + h[1]*ybox + h[3]*zbox;
y[2] = x[2] + h[2]*zbox;
}
}
/* ----------------------------------------------------------------------
create a lattice
delete it if style = none
------------------------------------------------------------------------- */
void Domain::set_lattice(int narg, char **arg)
{
if (lattice) delete lattice;
lattice = new Lattice(lmp,narg,arg);
if (lattice->style == 0) {
delete lattice;
lattice = NULL;
}
}
/* ----------------------------------------------------------------------
create a new region
------------------------------------------------------------------------- */
void Domain::add_region(int narg, char **arg)
{
- if (narg < 2) error->all("Illegal region command");
+ if (narg < 2) error->all(FLERR,"Illegal region command");
if (strcmp(arg[1],"delete") == 0) {
delete_region(narg,arg);
return;
}
- if (find_region(arg[0]) >= 0) error->all("Reuse of region ID");
+ if (find_region(arg[0]) >= 0) error->all(FLERR,"Reuse of region ID");
// extend Region list if necessary
if (nregion == maxregion) {
maxregion += DELTA;
regions = (Region **)
memory->srealloc(regions,maxregion*sizeof(Region *),"domain:regions");
}
// create the Region
- if (strcmp(arg[1],"none") == 0) error->all("Invalid region style");
+ if (strcmp(arg[1],"none") == 0) error->all(FLERR,"Invalid region style");
#define REGION_CLASS
#define RegionStyle(key,Class) \
else if (strcmp(arg[1],#key) == 0) \
regions[nregion] = new Class(lmp,narg,arg);
#include "style_region.h"
#undef REGION_CLASS
- else error->all("Invalid region style");
+ else error->all(FLERR,"Invalid region style");
nregion++;
}
/* ----------------------------------------------------------------------
delete a region
------------------------------------------------------------------------- */
void Domain::delete_region(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal region command");
+ if (narg != 2) error->all(FLERR,"Illegal region command");
int iregion = find_region(arg[0]);
- if (iregion == -1) error->all("Delete region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Delete region ID does not exist");
delete regions[iregion];
regions[iregion] = regions[nregion-1];
nregion--;
}
/* ----------------------------------------------------------------------
return region index if name matches existing region ID
return -1 if no such region
------------------------------------------------------------------------- */
int Domain::find_region(char *name)
{
for (int iregion = 0; iregion < nregion; iregion++)
if (strcmp(name,regions[iregion]->id) == 0) return iregion;
return -1;
}
/* ----------------------------------------------------------------------
boundary settings from the input script
------------------------------------------------------------------------- */
void Domain::set_boundary(int narg, char **arg)
{
- if (narg != 3) error->all("Illegal boundary command");
+ if (narg != 3) error->all(FLERR,"Illegal boundary command");
char c;
for (int idim = 0; idim < 3; idim++)
for (int iside = 0; iside < 2; iside++) {
if (iside == 0) c = arg[idim][0];
else if (iside == 1 && strlen(arg[idim]) == 1) c = arg[idim][0];
else c = arg[idim][1];
if (c == 'p') boundary[idim][iside] = 0;
else if (c == 'f') boundary[idim][iside] = 1;
else if (c == 's') boundary[idim][iside] = 2;
else if (c == 'm') boundary[idim][iside] = 3;
- else error->all("Illegal boundary command");
+ else error->all(FLERR,"Illegal boundary command");
}
for (int idim = 0; idim < 3; idim++)
if ((boundary[idim][0] == 0 && boundary[idim][1]) ||
(boundary[idim][0] && boundary[idim][1] == 0))
- error->all("Both sides of boundary must be periodic");
+ error->all(FLERR,"Both sides of boundary must be periodic");
if (boundary[0][0] == 0) xperiodic = 1;
else xperiodic = 0;
if (boundary[1][0] == 0) yperiodic = 1;
else yperiodic = 0;
if (boundary[2][0] == 0) zperiodic = 1;
else zperiodic = 0;
periodicity[0] = xperiodic;
periodicity[1] = yperiodic;
periodicity[2] = zperiodic;
nonperiodic = 0;
if (xperiodic == 0 || yperiodic == 0 || zperiodic == 0) {
nonperiodic = 1;
if (boundary[0][0] >= 2 || boundary[0][1] >= 2 ||
boundary[1][0] >= 2 || boundary[1][1] >= 2 ||
boundary[2][0] >= 2 || boundary[2][1] >= 2) nonperiodic = 2;
}
}
/* ----------------------------------------------------------------------
print box info, orthogonal or triclinic
------------------------------------------------------------------------- */
void Domain::print_box(const char *str)
{
if (comm->me == 0) {
if (screen) {
if (triclinic == 0)
fprintf(screen,"%sorthogonal box = (%g %g %g) to (%g %g %g)\n",
str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2]);
else {
char *format = (char *)
"%striclinic box = (%g %g %g) to (%g %g %g) with tilt (%g %g %g)\n";
fprintf(screen,format,
str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2],
xy,xz,yz);
}
}
if (logfile) {
if (triclinic == 0)
fprintf(logfile,"%sorthogonal box = (%g %g %g) to (%g %g %g)\n",
str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2]);
else {
char *format = (char *)
"%striclinic box = (%g %g %g) to (%g %g %g) with tilt (%g %g %g)\n";
fprintf(logfile,format,
str,boxlo[0],boxlo[1],boxlo[2],boxhi[0],boxhi[1],boxhi[2],
xy,xz,yz);
}
}
}
}
/* ----------------------------------------------------------------------
convert triclinic 0-1 lamda coords to box coords for all N atoms
x = H lamda + x0;
------------------------------------------------------------------------- */
void Domain::lamda2x(int n)
{
double **x = atom->x;
for (int i = 0; i < n; i++) {
x[i][0] = h[0]*x[i][0] + h[5]*x[i][1] + h[4]*x[i][2] + boxlo[0];
x[i][1] = h[1]*x[i][1] + h[3]*x[i][2] + boxlo[1];
x[i][2] = h[2]*x[i][2] + boxlo[2];
}
}
/* ----------------------------------------------------------------------
convert box coords to triclinic 0-1 lamda coords for all N atoms
lamda = H^-1 (x - x0)
------------------------------------------------------------------------- */
void Domain::x2lamda(int n)
{
double delta[3];
double **x = atom->x;
for (int i = 0; i < n; i++) {
delta[0] = x[i][0] - boxlo[0];
delta[1] = x[i][1] - boxlo[1];
delta[2] = x[i][2] - boxlo[2];
x[i][0] = h_inv[0]*delta[0] + h_inv[5]*delta[1] + h_inv[4]*delta[2];
x[i][1] = h_inv[1]*delta[1] + h_inv[3]*delta[2];
x[i][2] = h_inv[2]*delta[2];
}
}
/* ----------------------------------------------------------------------
convert triclinic 0-1 lamda coords to box coords for one atom
x = H lamda + x0;
lamda and x can point to same 3-vector
------------------------------------------------------------------------- */
void Domain::lamda2x(double *lamda, double *x)
{
x[0] = h[0]*lamda[0] + h[5]*lamda[1] + h[4]*lamda[2] + boxlo[0];
x[1] = h[1]*lamda[1] + h[3]*lamda[2] + boxlo[1];
x[2] = h[2]*lamda[2] + boxlo[2];
}
/* ----------------------------------------------------------------------
convert box coords to triclinic 0-1 lamda coords for one atom
lamda = H^-1 (x - x0)
x and lamda can point to same 3-vector
------------------------------------------------------------------------- */
void Domain::x2lamda(double *x, double *lamda)
{
double delta[3];
delta[0] = x[0] - boxlo[0];
delta[1] = x[1] - boxlo[1];
delta[2] = x[2] - boxlo[2];
lamda[0] = h_inv[0]*delta[0] + h_inv[5]*delta[1] + h_inv[4]*delta[2];
lamda[1] = h_inv[1]*delta[1] + h_inv[3]*delta[2];
lamda[2] = h_inv[2]*delta[2];
}
/* ----------------------------------------------------------------------
convert 8 lamda corner pts of lo/hi box to box coords
return bboxlo/hi = bounding box around 8 corner pts in box coords
------------------------------------------------------------------------- */
void Domain::bbox(double *lo, double *hi, double *bboxlo, double *bboxhi)
{
double x[3];
bboxlo[0] = bboxlo[1] = bboxlo[2] = BIG;
bboxhi[0] = bboxhi[1] = bboxhi[2] = -BIG;
x[0] = lo[0]; x[1] = lo[1]; x[2] = lo[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
x[0] = hi[0]; x[1] = lo[1]; x[2] = lo[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
x[0] = lo[0]; x[1] = hi[1]; x[2] = lo[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
x[0] = hi[0]; x[1] = hi[1]; x[2] = lo[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
x[0] = lo[0]; x[1] = lo[1]; x[2] = hi[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
x[0] = hi[0]; x[1] = lo[1]; x[2] = hi[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
x[0] = lo[0]; x[1] = hi[1]; x[2] = hi[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
x[0] = hi[0]; x[1] = hi[1]; x[2] = hi[2];
lamda2x(x,x);
bboxlo[0] = MIN(bboxlo[0],x[0]); bboxhi[0] = MAX(bboxhi[0],x[0]);
bboxlo[1] = MIN(bboxlo[1],x[1]); bboxhi[1] = MAX(bboxhi[1],x[1]);
bboxlo[2] = MIN(bboxlo[2],x[2]); bboxhi[2] = MAX(bboxhi[2],x[2]);
}
/* ----------------------------------------------------------------------
compute 8 corner pts of triclinic box
8 are ordered with x changing fastest, then y, finally z
could be more efficient if just coded with xy,yz,xz explicitly
------------------------------------------------------------------------- */
void Domain::box_corners()
{
corners[0][0] = 0.0; corners[0][1] = 0.0; corners[0][2] = 0.0;
lamda2x(corners[0],corners[0]);
corners[1][0] = 1.0; corners[1][1] = 0.0; corners[1][2] = 0.0;
lamda2x(corners[1],corners[1]);
corners[2][0] = 0.0; corners[2][1] = 1.0; corners[2][2] = 0.0;
lamda2x(corners[2],corners[2]);
corners[3][0] = 1.0; corners[3][1] = 1.0; corners[3][2] = 0.0;
lamda2x(corners[3],corners[3]);
corners[4][0] = 0.0; corners[4][1] = 0.0; corners[4][2] = 1.0;
lamda2x(corners[4],corners[4]);
corners[5][0] = 1.0; corners[5][1] = 0.0; corners[5][2] = 1.0;
lamda2x(corners[5],corners[5]);
corners[6][0] = 0.0; corners[6][1] = 1.0; corners[6][2] = 1.0;
lamda2x(corners[6],corners[6]);
corners[7][0] = 1.0; corners[7][1] = 1.0; corners[7][2] = 1.0;
lamda2x(corners[7],corners[7]);
}
diff --git a/src/dump.cpp b/src/dump.cpp
index 2dd5106bf..feda8ea15 100644
--- a/src/dump.cpp
+++ b/src/dump.cpp
@@ -1,723 +1,720 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "dump.h"
#include "atom.h"
#include "irregular.h"
#include "update.h"
#include "domain.h"
#include "group.h"
#include "output.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
// allocate space for static class variable
Dump *Dump::dumpptr;
#define BIG 1.0e20
#define IBIG 2147483647
#define EPSILON 1.0e-6
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
enum{ASCEND,DESCEND};
/* ---------------------------------------------------------------------- */
Dump::Dump(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
int n = strlen(arg[0]) + 1;
id = new char[n];
strcpy(id,arg[0]);
igroup = group->find(arg[1]);
groupbit = group->bitmask[igroup];
n = strlen(arg[2]) + 1;
style = new char[n];
strcpy(style,arg[2]);
n = strlen(arg[4]) + 1;
filename = new char[n];
strcpy(filename,arg[4]);
comm_forward = comm_reverse = 0;
first_flag = 0;
flush_flag = 1;
format = NULL;
format_user = NULL;
clearstep = 0;
sort_flag = 0;
append_flag = 0;
padflag = 0;
maxbuf = maxids = maxsort = maxproc = 0;
buf = bufsort = NULL;
ids = idsort = index = proclist = NULL;
irregular = NULL;
// parse filename for special syntax
// if contains '%', write one file per proc and replace % with proc-ID
// if contains '*', write one file per timestep and replace * with timestep
// check file suffixes
// if ends in .bin = binary file
// else if ends in .gz = gzipped text file
// else ASCII text file
fp = NULL;
singlefile_opened = 0;
compressed = 0;
binary = 0;
multifile = 0;
multiproc = 0;
char *ptr;
if (ptr = strchr(filename,'%')) {
multiproc = 1;
char *extend = new char[strlen(filename) + 16];
*ptr = '\0';
sprintf(extend,"%s%d%s",filename,me,ptr+1);
delete [] filename;
n = strlen(extend) + 1;
filename = new char[n];
strcpy(filename,extend);
delete [] extend;
}
if (strchr(filename,'*')) multifile = 1;
char *suffix = filename + strlen(filename) - strlen(".bin");
if (suffix > filename && strcmp(suffix,".bin") == 0) binary = 1;
suffix = filename + strlen(filename) - strlen(".gz");
if (suffix > filename && strcmp(suffix,".gz") == 0) compressed = 1;
}
/* ---------------------------------------------------------------------- */
Dump::~Dump()
{
delete [] id;
delete [] style;
delete [] filename;
delete [] format;
delete [] format_default;
delete [] format_user;
memory->destroy(buf);
memory->destroy(bufsort);
memory->destroy(ids);
memory->destroy(idsort);
memory->destroy(index);
memory->destroy(proclist);
delete irregular;
// XTC style sets fp to NULL since it closes file in its destructor
if (multifile == 0 && fp != NULL) {
if (compressed) {
if (multiproc) pclose(fp);
else if (me == 0) pclose(fp);
} else {
if (multiproc) fclose(fp);
else if (me == 0) fclose(fp);
}
}
}
/* ---------------------------------------------------------------------- */
void Dump::init()
{
init_style();
if (!sort_flag) {
memory->destroy(bufsort);
memory->destroy(ids);
memory->destroy(idsort);
memory->destroy(index);
memory->destroy(proclist);
delete irregular;
maxids = maxsort = maxproc = 0;
bufsort = NULL;
ids = idsort = index = proclist = NULL;
irregular = NULL;
}
if (sort_flag) {
if (sortcol == 0 && atom->tag_enable == 0)
- error->all("Cannot dump sort on atom IDs with no atom IDs defined");
+ error->all(FLERR,"Cannot dump sort on atom IDs with no atom IDs defined");
if (sortcol && sortcol > size_one)
- error->all("Dump sort column is invalid");
+ error->all(FLERR,"Dump sort column is invalid");
if (nprocs > 1 && irregular == NULL)
irregular = new Irregular(lmp);
bigint size = group->count(igroup);
- if (size > MAXSMALLINT) error->all("Too many atoms to dump sort");
+ if (size > MAXSMALLINT) error->all(FLERR,"Too many atoms to dump sort");
// set reorderflag = 1 if can simply reorder local atoms rather than sort
// criteria: sorting by ID, atom IDs are consecutive from 1 to Natoms
// min/max IDs of group match size of group
// compute ntotal_reorder, nme_reorder, idlo/idhi to test against later
reorderflag = 0;
if (sortcol == 0 && atom->tag_consecutive()) {
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int min = IBIG;
int max = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
min = MIN(min,tag[i]);
max = MAX(max,tag[i]);
}
int minall,maxall;
MPI_Allreduce(&min,&minall,1,MPI_INT,MPI_MIN,world);
MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
int isize = static_cast<int> (size);
if (maxall-minall+1 == isize) {
reorderflag = 1;
double range = maxall-minall + EPSILON;
idlo = static_cast<int> (range*me/nprocs + minall);
int idhi = static_cast<int> (range*(me+1)/nprocs + minall);
int lom1 = static_cast<int> ((idlo-1-minall)/range * nprocs);
int lo = static_cast<int> ((idlo-minall)/range * nprocs);
int him1 = static_cast<int> ((idhi-1-minall)/range * nprocs);
int hi = static_cast<int> ((idhi-minall)/range * nprocs);
if (me && me == lom1) idlo--;
else if (me && me != lo) idlo++;
if (me+1 == him1) idhi--;
else if (me+1 != hi) idhi++;
nme_reorder = idhi-idlo;
ntotal_reorder = isize;
}
}
}
}
/* ---------------------------------------------------------------------- */
void Dump::write()
{
// if file per timestep, open new file
if (multifile) openfile();
// simulation box bounds
if (domain->triclinic == 0) {
boxxlo = domain->boxlo[0];
boxxhi = domain->boxhi[0];
boxylo = domain->boxlo[1];
boxyhi = domain->boxhi[1];
boxzlo = domain->boxlo[2];
boxzhi = domain->boxhi[2];
} else {
boxxlo = domain->boxlo_bound[0];
boxxhi = domain->boxhi_bound[0];
boxylo = domain->boxlo_bound[1];
boxyhi = domain->boxhi_bound[1];
boxzlo = domain->boxlo_bound[2];
boxzhi = domain->boxhi_bound[2];
boxxy = domain->xy;
boxxz = domain->xz;
boxyz = domain->yz;
}
// nme = # of dump lines this proc will contribute to dump
nme = count();
bigint bnme = nme;
// ntotal = total # of dump lines
// nmax = max # of dump lines on any proc
int nmax;
if (multiproc) nmax = nme;
else {
MPI_Allreduce(&bnme,&ntotal,1,MPI_LMP_BIGINT,MPI_SUM,world);
MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world);
}
// write timestep header
if (multiproc) write_header(bnme);
else write_header(ntotal);
// insure proc 0 can receive everyone's info
// limit nmax*size_one to int since used as arg in MPI_Rsend() below
// pack my data into buf
// if sorting on IDs also request ID list from pack()
// sort buf as needed
if (nmax > maxbuf) {
if ((bigint) nmax * size_one > MAXSMALLINT)
- error->all("Too much per-proc info for dump");
+ error->all(FLERR,"Too much per-proc info for dump");
maxbuf = nmax;
memory->destroy(buf);
memory->create(buf,maxbuf*size_one,"dump:buf");
}
if (sort_flag && sortcol == 0 && nmax > maxids) {
maxids = nmax;
memory->destroy(ids);
memory->create(ids,maxids,"dump:ids");
}
if (sort_flag && sortcol == 0) pack(ids);
else pack(NULL);
if (sort_flag) sort();
// multiproc = 1 = each proc writes own data to own file
// multiproc = 0 = all procs write to one file thru proc 0
// proc 0 pings each proc, receives it's data, writes to file
// all other procs wait for ping, send their data to proc 0
if (multiproc) write_data(nme,buf);
else {
int tmp,nlines;
MPI_Status status;
MPI_Request request;
if (me == 0) {
for (int iproc = 0; iproc < nprocs; iproc++) {
if (iproc) {
MPI_Irecv(buf,maxbuf*size_one,MPI_DOUBLE,iproc,0,world,&request);
MPI_Send(&tmp,0,MPI_INT,iproc,0,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_DOUBLE,&nlines);
nlines /= size_one;
} else nlines = nme;
write_data(nlines,buf);
}
if (flush_flag) fflush(fp);
} else {
MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status);
MPI_Rsend(buf,nme*size_one,MPI_DOUBLE,0,0,world);
}
}
// if file per timestep, close file
if (multifile) {
if (compressed) {
if (multiproc) pclose(fp);
else if (me == 0) pclose(fp);
} else {
if (multiproc) fclose(fp);
else if (me == 0) fclose(fp);
}
}
}
/* ----------------------------------------------------------------------
generic opening of a dump file
ASCII or binary or gzipped
some derived classes override this function
------------------------------------------------------------------------- */
void Dump::openfile()
{
// single file, already opened, so just return
if (singlefile_opened) return;
if (multifile == 0) singlefile_opened = 1;
// if one file per timestep, replace '*' with current timestep
char *filecurrent;
if (multifile == 0) filecurrent = filename;
else {
filecurrent = new char[strlen(filename) + 16];
char *ptr = strchr(filename,'*');
*ptr = '\0';
if (padflag == 0)
sprintf(filecurrent,"%s" BIGINT_FORMAT "%s",
filename,update->ntimestep,ptr+1);
else {
char bif[8],pad[16];
strcpy(bif,BIGINT_FORMAT);
sprintf(pad,"%%s%%0%d%s%%s",padflag,&bif[1]);
sprintf(filecurrent,pad,filename,update->ntimestep,ptr+1);
}
*ptr = '*';
}
// open one file on proc 0 or file on every proc
if (me == 0 || multiproc) {
if (compressed) {
#ifdef LAMMPS_GZIP
char gzip[128];
sprintf(gzip,"gzip -6 > %s",filecurrent);
fp = popen(gzip,"w");
#else
- error->one("Cannot open gzipped file");
+ error->one(FLERR,"Cannot open gzipped file");
#endif
} else if (binary) {
fp = fopen(filecurrent,"wb");
} else if (append_flag) {
fp = fopen(filecurrent,"a");
} else {
fp = fopen(filecurrent,"w");
}
- if (fp == NULL) error->one("Cannot open dump file");
+ if (fp == NULL) error->one(FLERR,"Cannot open dump file");
} else fp = NULL;
// delete string with timestep replaced
if (multifile) delete [] filecurrent;
}
/* ----------------------------------------------------------------------
parallel sort of buf across all procs
changes nme, reorders datums in buf, grows buf if necessary
------------------------------------------------------------------------- */
void Dump::sort()
{
int i,iproc;
double value;
// if single proc, swap ptrs to buf,ids <-> bufsort,idsort
if (nprocs == 1) {
if (nme > maxsort) {
maxsort = nme;
memory->destroy(bufsort);
memory->create(bufsort,maxsort*size_one,"dump:bufsort");
memory->destroy(index);
memory->create(index,maxsort,"dump:index");
if (sortcol == 0) {
memory->destroy(idsort);
memory->create(idsort,maxsort,"dump:idsort");
}
}
double *dptr = buf;
buf = bufsort;
bufsort = dptr;
if (sortcol == 0) {
int *iptr = ids;
ids = idsort;
idsort = iptr;
}
// if multiple procs, exchange datums between procs via irregular
} else {
// grow proclist if necessary
if (nme > maxproc) {
maxproc = nme;
memory->destroy(proclist);
memory->create(proclist,maxproc,"dump:proclist");
}
// proclist[i] = which proc Ith datum will be sent to
if (sortcol == 0) {
int min = IBIG;
int max = 0;
for (i = 0; i < nme; i++) {
min = MIN(min,ids[i]);
max = MAX(max,ids[i]);
}
int minall,maxall;
MPI_Allreduce(&min,&minall,1,MPI_INT,MPI_MIN,world);
MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
double range = maxall-minall + EPSILON;
for (i = 0; i < nme; i++) {
iproc = static_cast<int> ((ids[i]-minall)/range * nprocs);
proclist[i] = iproc;
}
} else {
double min = BIG;
double max = -BIG;
for (i = 0; i < nme; i++) {
value = buf[i*size_one + sortcolm1];
min = MIN(min,value);
max = MAX(max,value);
}
double minall,maxall;
MPI_Allreduce(&min,&minall,1,MPI_DOUBLE,MPI_MIN,world);
MPI_Allreduce(&max,&maxall,1,MPI_DOUBLE,MPI_MAX,world);
double range = maxall-minall + EPSILON*(maxall-minall);
if (range == 0.0) range = EPSILON;
for (i = 0; i < nme; i++) {
value = buf[i*size_one + sortcolm1];
iproc = static_cast<int> ((value-minall)/range * nprocs);
proclist[i] = iproc;
}
}
// create comm plan, grow recv bufs if necessary,
// exchange datums, destroy plan
// if sorting on atom IDs, exchange IDs also
nme = irregular->create_data(nme,proclist);
if (nme > maxsort) {
maxsort = nme;
memory->destroy(bufsort);
memory->create(bufsort,maxsort*size_one,"dump:bufsort");
memory->destroy(index);
memory->create(index,maxsort,"dump:index");
if (sortcol == 0) {
memory->destroy(idsort);
memory->create(idsort,maxsort,"dump:idsort");
}
}
irregular->exchange_data((char *) buf,size_one*sizeof(double),
(char *) bufsort);
if (sortcol == 0)
irregular->exchange_data((char *) ids,sizeof(int),(char *) idsort);
irregular->destroy_data();
}
// if reorder flag is set & total/per-proc counts match pre-computed values,
// then create index directly from idsort
// else quicksort of index using IDs or buf column as comparator
if (reorderflag) {
if (ntotal != ntotal_reorder) reorderflag = 0;
int flag = 0;
if (nme != nme_reorder) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall) reorderflag = 0;
if (reorderflag)
for (i = 0; i < nme; i++)
index[idsort[i]-idlo] = i;
}
if (!reorderflag) {
dumpptr = this;
for (i = 0; i < nme; i++) index[i] = i;
if (sortcol == 0) qsort(index,nme,sizeof(int),idcompare);
else if (sortorder == ASCEND) qsort(index,nme,sizeof(int),bufcompare);
else qsort(index,nme,sizeof(int),bufcompare_reverse);
}
// reset buf size and maxbuf to largest of any post-sort nme values
// this insures proc 0 can receive everyone's info
int nmax;
if (multiproc) nmax = nme;
else MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world);
if (nmax > maxbuf) {
maxbuf = nmax;
memory->destroy(buf);
memory->create(buf,maxbuf*size_one,"dump:buf");
}
// copy data from bufsort to buf using index
int nbytes = size_one*sizeof(double);
for (i = 0; i < nme; i++)
memcpy(&buf[i*size_one],&bufsort[index[i]*size_one],nbytes);
}
/* ----------------------------------------------------------------------
compare two atom IDs
called via qsort() in sort() method
is a static method so access data via dumpptr
------------------------------------------------------------------------- */
int Dump::idcompare(const void *pi, const void *pj)
{
int *idsort = dumpptr->idsort;
int i = *((int *) pi);
int j = *((int *) pj);
if (idsort[i] < idsort[j]) return -1;
if (idsort[i] > idsort[j]) return 1;
return 0;
}
/* ----------------------------------------------------------------------
compare two buffer values with size_one stride
called via qsort() in sort() method
is a static method so access data via dumpptr
sort in ASCENDing order
------------------------------------------------------------------------- */
int Dump::bufcompare(const void *pi, const void *pj)
{
double *bufsort = dumpptr->bufsort;
int size_one = dumpptr->size_one;
int sortcolm1 = dumpptr->sortcolm1;
int i = *((int *) pi)*size_one + sortcolm1;
int j = *((int *) pj)*size_one + sortcolm1;
if (bufsort[i] < bufsort[j]) return -1;
if (bufsort[i] > bufsort[j]) return 1;
return 0;
}
/* ----------------------------------------------------------------------
compare two buffer values with size_one stride
called via qsort() in sort() method
is a static method so access data via dumpptr
sort in DESCENDing order
------------------------------------------------------------------------- */
int Dump::bufcompare_reverse(const void *pi, const void *pj)
{
double *bufsort = dumpptr->bufsort;
int size_one = dumpptr->size_one;
int sortcolm1 = dumpptr->sortcolm1;
int i = *((int *) pi)*size_one + sortcolm1;
int j = *((int *) pj)*size_one + sortcolm1;
if (bufsort[i] > bufsort[j]) return -1;
if (bufsort[i] < bufsort[j]) return 1;
return 0;
}
/* ----------------------------------------------------------------------
process params common to all dumps here
if unknown param, call modify_param specific to the dump
------------------------------------------------------------------------- */
void Dump::modify_params(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal dump_modify command");
+ if (narg == 0) error->all(FLERR,"Illegal dump_modify command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"append") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) append_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) append_flag = 0;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"every") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
int n;
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
delete [] output->var_dump[idump];
n = strlen(&arg[iarg+1][2]) + 1;
output->var_dump[idump] = new char[n];
strcpy(output->var_dump[idump],&arg[iarg+1][2]);
n = 0;
} else {
n = atoi(arg[iarg+1]);
- if (n <= 0) error->all("Illegal dump_modify command");
+ if (n <= 0) error->all(FLERR,"Illegal dump_modify command");
}
output->every_dump[idump] = n;
iarg += 2;
} else if (strcmp(arg[iarg],"first") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) first_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) first_flag = 0;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"flush") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) flush_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) flush_flag = 0;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"format") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
delete [] format_user;
format_user = NULL;
if (strcmp(arg[iarg+1],"none")) {
int n = strlen(arg[iarg+1]) + 1;
format_user = new char[n];
strcpy(format_user,arg[iarg+1]);
}
iarg += 2;
} else if (strcmp(arg[iarg],"pad") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
padflag = atoi(arg[iarg+1]);
- if (padflag < 0) error->all("Illegal dump_modify command");
+ if (padflag < 0) error->all(FLERR,"Illegal dump_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"sort") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[iarg+1],"off") == 0) sort_flag = 0;
else if (strcmp(arg[iarg+1],"id") == 0) {
sort_flag = 1;
sortcol = 0;
sortorder = ASCEND;
} else {
sort_flag = 1;
sortcol = atoi(arg[iarg+1]);
sortorder = ASCEND;
- if (sortcol == 0) error->all("Illegal dump_modify command");
+ if (sortcol == 0) error->all(FLERR,"Illegal dump_modify command");
if (sortcol < 0) {
sortorder = DESCEND;
sortcol = -sortcol;
}
sortcolm1 = sortcol - 1;
}
iarg += 2;
} else {
int n = modify_param(narg-iarg,&arg[iarg]);
- if (n == 0) error->all("Illegal dump_modify command");
+ if (n == 0) error->all(FLERR,"Illegal dump_modify command");
iarg += n;
}
}
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint Dump::memory_usage()
{
bigint bytes = memory->usage(buf,size_one*maxbuf);
if (sort_flag) {
if (sortcol == 0) bytes += memory->usage(ids,maxids);
bytes += memory->usage(bufsort,size_one*maxsort);
if (sortcol == 0) bytes += memory->usage(idsort,maxsort);
bytes += memory->usage(index,maxsort);
bytes += memory->usage(proclist,maxproc);
if (irregular) bytes += irregular->memory_usage();
}
return bytes;
}
diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp
index 513e6baef..2365fb3e2 100644
--- a/src/dump_atom.cpp
+++ b/src/dump_atom.cpp
@@ -1,454 +1,454 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "dump_atom.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
DumpAtom::DumpAtom(LAMMPS *lmp, int narg, char **arg) : Dump(lmp, narg, arg)
{
- if (narg != 5) error->all("Illegal dump atom command");
+ if (narg != 5) error->all(FLERR,"Illegal dump atom command");
scale_flag = 1;
image_flag = 0;
format_default = NULL;
}
/* ---------------------------------------------------------------------- */
void DumpAtom::init_style()
{
if (image_flag == 0) size_one = 5;
else size_one = 8;
// default format depends on image flags
delete [] format;
if (format_user) {
int n = strlen(format_user) + 2;
format = new char[n];
strcpy(format,format_user);
strcat(format,"\n");
} else {
char *str;
if (image_flag == 0) str = (char *) "%d %d %g %g %g";
else str = (char *) "%d %d %g %g %g %d %d %d";
int n = strlen(str) + 2;
format = new char[n];
strcpy(format,str);
strcat(format,"\n");
}
// setup boundary string
int m = 0;
for (int idim = 0; idim < 3; idim++) {
for (int iside = 0; iside < 2; iside++) {
if (domain->boundary[idim][iside] == 0) boundstr[m++] = 'p';
else if (domain->boundary[idim][iside] == 1) boundstr[m++] = 'f';
else if (domain->boundary[idim][iside] == 2) boundstr[m++] = 's';
else if (domain->boundary[idim][iside] == 3) boundstr[m++] = 'm';
}
boundstr[m++] = ' ';
}
boundstr[8] = '\0';
// setup column string
if (scale_flag == 0 && image_flag == 0)
columns = "id type x y z";
else if (scale_flag == 0 && image_flag == 1)
columns = "id type x y z ix iy iz";
else if (scale_flag == 1 && image_flag == 0)
columns = "id type xs ys zs";
else if (scale_flag == 1 && image_flag == 1)
columns = "id type xs ys zs ix iy iz";
// setup function ptrs
if (binary && domain->triclinic == 0)
header_choice = &DumpAtom::header_binary;
else if (binary && domain->triclinic == 1)
header_choice = &DumpAtom::header_binary_triclinic;
else if (!binary && domain->triclinic == 0)
header_choice = &DumpAtom::header_item;
else if (!binary && domain->triclinic == 1)
header_choice = &DumpAtom::header_item_triclinic;
if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 0)
pack_choice = &DumpAtom::pack_scale_noimage;
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 0)
pack_choice = &DumpAtom::pack_scale_image;
else if (scale_flag == 1 && image_flag == 0 && domain->triclinic == 1)
pack_choice = &DumpAtom::pack_scale_noimage_triclinic;
else if (scale_flag == 1 && image_flag == 1 && domain->triclinic == 1)
pack_choice = &DumpAtom::pack_scale_image_triclinic;
else if (scale_flag == 0 && image_flag == 0)
pack_choice = &DumpAtom::pack_noscale_noimage;
else if (scale_flag == 0 && image_flag == 1)
pack_choice = &DumpAtom::pack_noscale_image;
if (binary) write_choice = &DumpAtom::write_binary;
else if (image_flag == 0) write_choice = &DumpAtom::write_noimage;
else if (image_flag == 1) write_choice = &DumpAtom::write_image;
// open single file, one time only
if (multifile == 0) openfile();
}
/* ---------------------------------------------------------------------- */
int DumpAtom::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"scale") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"yes") == 0) scale_flag = 1;
else if (strcmp(arg[1],"no") == 0) scale_flag = 0;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
return 2;
} else if (strcmp(arg[0],"image") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"yes") == 0) image_flag = 1;
else if (strcmp(arg[1],"no") == 0) image_flag = 0;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void DumpAtom::write_header(bigint ndump)
{
if (multiproc) (this->*header_choice)(ndump);
else if (me == 0) (this->*header_choice)(ndump);
}
/* ---------------------------------------------------------------------- */
int DumpAtom::count()
{
if (igroup == 0) return atom->nlocal;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) m++;
return m;
}
/* ---------------------------------------------------------------------- */
void DumpAtom::pack(int *ids)
{
(this->*pack_choice)(ids);
}
/* ---------------------------------------------------------------------- */
void DumpAtom::write_data(int n, double *mybuf)
{
(this->*write_choice)(n,mybuf);
}
/* ---------------------------------------------------------------------- */
void DumpAtom::header_binary(bigint ndump)
{
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
fwrite(&ndump,sizeof(bigint),1,fp);
fwrite(&domain->triclinic,sizeof(int),1,fp);
fwrite(&domain->boundary[0][0],6*sizeof(int),1,fp);
fwrite(&boxxlo,sizeof(double),1,fp);
fwrite(&boxxhi,sizeof(double),1,fp);
fwrite(&boxylo,sizeof(double),1,fp);
fwrite(&boxyhi,sizeof(double),1,fp);
fwrite(&boxzlo,sizeof(double),1,fp);
fwrite(&boxzhi,sizeof(double),1,fp);
fwrite(&size_one,sizeof(int),1,fp);
if (multiproc) {
int one = 1;
fwrite(&one,sizeof(int),1,fp);
} else fwrite(&nprocs,sizeof(int),1,fp);
}
/* ---------------------------------------------------------------------- */
void DumpAtom::header_binary_triclinic(bigint ndump)
{
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
fwrite(&ndump,sizeof(bigint),1,fp);
fwrite(&domain->triclinic,sizeof(int),1,fp);
fwrite(&domain->boundary[0][0],6*sizeof(int),1,fp);
fwrite(&boxxlo,sizeof(double),1,fp);
fwrite(&boxxhi,sizeof(double),1,fp);
fwrite(&boxylo,sizeof(double),1,fp);
fwrite(&boxyhi,sizeof(double),1,fp);
fwrite(&boxzlo,sizeof(double),1,fp);
fwrite(&boxzhi,sizeof(double),1,fp);
fwrite(&boxxy,sizeof(double),1,fp);
fwrite(&boxxz,sizeof(double),1,fp);
fwrite(&boxyz,sizeof(double),1,fp);
fwrite(&size_one,sizeof(int),1,fp);
if (multiproc) {
int one = 1;
fwrite(&one,sizeof(int),1,fp);
} else fwrite(&nprocs,sizeof(int),1,fp);
}
/* ---------------------------------------------------------------------- */
void DumpAtom::header_item(bigint ndump)
{
fprintf(fp,"ITEM: TIMESTEP\n");
fprintf(fp,BIGINT_FORMAT "\n",update->ntimestep);
fprintf(fp,"ITEM: NUMBER OF ATOMS\n");
fprintf(fp,BIGINT_FORMAT "\n",ndump);
fprintf(fp,"ITEM: BOX BOUNDS %s\n",boundstr);
fprintf(fp,"%g %g\n",boxxlo,boxxhi);
fprintf(fp,"%g %g\n",boxylo,boxyhi);
fprintf(fp,"%g %g\n",boxzlo,boxzhi);
fprintf(fp,"ITEM: ATOMS %s\n",columns);
}
/* ---------------------------------------------------------------------- */
void DumpAtom::header_item_triclinic(bigint ndump)
{
fprintf(fp,"ITEM: TIMESTEP\n");
fprintf(fp,BIGINT_FORMAT "\n",update->ntimestep);
fprintf(fp,"ITEM: NUMBER OF ATOMS\n");
fprintf(fp,BIGINT_FORMAT "\n",ndump);
fprintf(fp,"ITEM: BOX BOUNDS xy xz yz %s\n",boundstr);
fprintf(fp,"%g %g %g\n",boxxlo,boxxhi,boxxy);
fprintf(fp,"%g %g %g\n",boxylo,boxyhi,boxxz);
fprintf(fp,"%g %g %g\n",boxzlo,boxzhi,boxyz);
fprintf(fp,"ITEM: ATOMS %s\n",columns);
}
/* ---------------------------------------------------------------------- */
void DumpAtom::pack_scale_image(int *ids)
{
int m,n;
int *tag = atom->tag;
int *type = atom->type;
int *image = atom->image;
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
double invxprd = 1.0/domain->xprd;
double invyprd = 1.0/domain->yprd;
double invzprd = 1.0/domain->zprd;
m = n = 00;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = (x[i][0] - boxxlo) * invxprd;
buf[m++] = (x[i][1] - boxylo) * invyprd;
buf[m++] = (x[i][2] - boxzlo) * invzprd;
buf[m++] = (image[i] & 1023) - 512;
buf[m++] = (image[i] >> 10 & 1023) - 512;
buf[m++] = (image[i] >> 20) - 512;
if (ids) ids[n++] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void DumpAtom::pack_scale_noimage(int *ids)
{
int m,n;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
double invxprd = 1.0/domain->xprd;
double invyprd = 1.0/domain->yprd;
double invzprd = 1.0/domain->zprd;
m = n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = (x[i][0] - boxxlo) * invxprd;
buf[m++] = (x[i][1] - boxylo) * invyprd;
buf[m++] = (x[i][2] - boxzlo) * invzprd;
if (ids) ids[n++] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void DumpAtom::pack_scale_image_triclinic(int *ids)
{
int m,n;
int *tag = atom->tag;
int *type = atom->type;
int *image = atom->image;
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
double lamda[3];
m = n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = tag[i];
buf[m++] = type[i];
domain->x2lamda(x[i],lamda);
buf[m++] = lamda[0];
buf[m++] = lamda[1];
buf[m++] = lamda[2];
buf[m++] = (image[i] & 1023) - 512;
buf[m++] = (image[i] >> 10 & 1023) - 512;
buf[m++] = (image[i] >> 20) - 512;
if (ids) ids[n++] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void DumpAtom::pack_scale_noimage_triclinic(int *ids)
{
int m,n;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
double lamda[3];
m = n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = tag[i];
buf[m++] = type[i];
domain->x2lamda(x[i],lamda);
buf[m++] = lamda[0];
buf[m++] = lamda[1];
buf[m++] = lamda[2];
if (ids) ids[n++] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void DumpAtom::pack_noscale_image(int *ids)
{
int m,n;
int *tag = atom->tag;
int *type = atom->type;
int *image = atom->image;
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
m = n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
buf[m++] = (image[i] & 1023) - 512;
buf[m++] = (image[i] >> 10 & 1023) - 512;
buf[m++] = (image[i] >> 20) - 512;
if (ids) ids[n++] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void DumpAtom::pack_noscale_noimage(int *ids)
{
int m,n;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
m = n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
if (ids) ids[n++] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void DumpAtom::write_binary(int n, double *mybuf)
{
n *= size_one;
fwrite(&n,sizeof(int),1,fp);
fwrite(mybuf,sizeof(double),n,fp);
}
/* ---------------------------------------------------------------------- */
void DumpAtom::write_image(int n, double *mybuf)
{
int m = 0;
for (int i = 0; i < n; i++) {
fprintf(fp,format,
static_cast<int> (mybuf[m]), static_cast<int> (mybuf[m+1]),
mybuf[m+2],mybuf[m+3],mybuf[m+4], static_cast<int> (mybuf[m+5]),
static_cast<int> (mybuf[m+6]), static_cast<int> (mybuf[m+7]));
m += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpAtom::write_noimage(int n, double *mybuf)
{
int m = 0;
for (int i = 0; i < n; i++) {
fprintf(fp,format,
static_cast<int> (mybuf[m]), static_cast<int> (mybuf[m+1]),
mybuf[m+2],mybuf[m+3],mybuf[m+4]);
m += size_one;
}
}
diff --git a/src/dump_cfg.cpp b/src/dump_cfg.cpp
index 3e7d83eff..940e34549 100755
--- a/src/dump_cfg.cpp
+++ b/src/dump_cfg.cpp
@@ -1,245 +1,245 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Liang Wan (Chinese Academy of Sciences)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "dump_cfg.h"
#include "atom.h"
#include "domain.h"
#include "comm.h"
#include "modify.h"
#include "compute.h"
#include "input.h"
#include "fix.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
#define UNWRAPEXPAND 10.0
using namespace LAMMPS_NS;
enum{INT,DOUBLE}; // same as in dump_custom.cpp
/* ---------------------------------------------------------------------- */
DumpCFG::DumpCFG(LAMMPS *lmp, int narg, char **arg) :
DumpCustom(lmp, narg, arg)
{
if (narg < 10 ||
strcmp(arg[5],"id") != 0 || strcmp(arg[6],"type") != 0 ||
(strcmp(arg[7],"xs") != 0 && strcmp(arg[7],"xsu") != 0) ||
(strcmp(arg[8],"ys") != 0 && strcmp(arg[8],"ysu") != 0) ||
(strcmp(arg[9],"zs") != 0 && strcmp(arg[9],"zsu") != 0))
- error->all("Dump cfg arguments must start with "
+ error->all(FLERR,"Dump cfg arguments must start with "
"'id type xs ys zs' or 'id type xsu ysu zsu'");
if (strcmp(arg[7],"xs") == 0)
if (strcmp(arg[8],"ysu") == 0 || strcmp(arg[9],"zsu") == 0)
- error->all("Dump cfg arguments can not mix xs|ys|zs with xsu|ysu|zsu");
+ error->all(FLERR,"Dump cfg arguments can not mix xs|ys|zs with xsu|ysu|zsu");
else unwrapflag = 0;
else if (strcmp(arg[8],"ys") == 0 || strcmp(arg[9],"zs") == 0)
- error->all("Dump cfg arguments can not mix xs|ys|zs with xsu|ysu|zsu");
+ error->all(FLERR,"Dump cfg arguments can not mix xs|ys|zs with xsu|ysu|zsu");
else unwrapflag = 1;
// arrays for data rearrangement
rbuf = NULL;
nchosen = nlines = 0;
// setup auxiliary property name strings
// convert 'X_ID[m]' (X=c,f,v) to 'ID_m'
if (narg > 10) auxname = new char*[narg-10];
else auxname = NULL;
int i = 0;
for (int iarg = 10; iarg < narg; iarg++, i++) {
if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Invalid keyword in dump cfg command");
+ error->all(FLERR,"Invalid keyword in dump cfg command");
*ptr = '\0';
*(ptr+2) = '\0';
auxname[i] = new char[strlen(suffix) + 3];
strcpy(auxname[i],suffix);
strcat(auxname[i],"_");
strcat(auxname[i],ptr+1);
} else {
auxname[i] = new char[strlen(suffix) + 1];
strcpy(auxname[i],suffix);
}
delete [] suffix;
} else {
auxname[i] = new char[strlen(arg[iarg]) + 1];
strcpy(auxname[i],arg[iarg]);
}
}
}
/* ---------------------------------------------------------------------- */
DumpCFG::~DumpCFG()
{
if (rbuf) memory->destroy(rbuf);
if (auxname) {
for (int i = 0; i < nfield-5; i++) delete [] auxname[i];
delete [] auxname;
}
}
/* ---------------------------------------------------------------------- */
void DumpCFG::init_style()
{
- if (multifile == 0) error->all("Dump cfg requires one snapshot per file");
+ if (multifile == 0) error->all(FLERR,"Dump cfg requires one snapshot per file");
DumpCustom::init_style();
}
/* ---------------------------------------------------------------------- */
void DumpCFG::write_header(bigint n)
{
// special handling for atom style peri
// use average volume of particles to scale particles to mimic C atoms
// scale box dimension to sc lattice for C with sigma = 1.44 Angstroms
// special handling for unwrapped coordinates
double scale;
if (atom->peri_flag) {
int nlocal = atom->nlocal;
double vone = 0.0;
for (int i = 0; i < nlocal; i++) vone += atom->vfrac[i];
double vave;
MPI_Allreduce(&vone,&vave,1,MPI_DOUBLE,MPI_SUM,world);
if (atom->natoms) vave /= atom->natoms;
if (vave > 0.0) scale = 1.44 / pow(vave,1.0/3.0);
} else if (unwrapflag == 1) scale = UNWRAPEXPAND;
else scale = 1.0;
if (me == 0 || multiproc) {
char str[64];
sprintf(str,"Number of particles = %s\n",BIGINT_FORMAT);
fprintf(fp,str,n);
fprintf(fp,"A = %g Angstrom (basic length-scale)\n",scale);
fprintf(fp,"H0(1,1) = %g A\n",domain->xprd);
fprintf(fp,"H0(1,2) = 0 A \n");
fprintf(fp,"H0(1,3) = 0 A \n");
fprintf(fp,"H0(2,1) = %g A \n",domain->xy);
fprintf(fp,"H0(2,2) = %g A\n",domain->yprd);
fprintf(fp,"H0(2,3) = 0 A \n");
fprintf(fp,"H0(3,1) = %g A \n",domain->xz);
fprintf(fp,"H0(3,2) = %g A \n",domain->yz);
fprintf(fp,"H0(3,3) = %g A\n",domain->zprd);
fprintf(fp,".NO_VELOCITY.\n");
fprintf(fp,"entry_count = %d\n",nfield-2);
for (int i = 0; i < nfield-5; i++)
fprintf(fp,"auxiliary[%d] = %s\n",i,auxname[i]);
}
// calculate total # of data lines to be written on a writing proc
if (multiproc) nchosen = nme;
else MPI_Reduce(&nme,&nchosen,1,MPI_INT,MPI_SUM,0,world);
// allocate memory needed for data rearrangement on writing proc(s)
if (multiproc || me == 0) {
if (rbuf) memory->destroy(rbuf);
memory->create(rbuf,nchosen,size_one,"dump:rbuf");
}
}
/* ----------------------------------------------------------------------
write data lines to file in a block-by-block style
write head of block (mass & element name) only if has atoms of the type
------------------------------------------------------------------------- */
void DumpCFG::write_data(int n, double *mybuf)
{
int i,j,m,itype;
double *rmass = atom->rmass;
double *mass = atom->mass;
// transfer data from buf to rbuf
// if write by proc 0, transfer chunk by chunk
for (i = 0, m = 0; i < n; i++) {
for (j = 0; j < size_one; j++)
rbuf[nlines][j] = mybuf[m++];
nlines++;
}
// write data lines in rbuf to file after transfer is done
double unwrap_coord;
if (nlines == nchosen) {
for (itype = 1; itype <= ntypes; itype++) {
for (i = 0; i < nchosen; i++)
if (rbuf[i][1] == itype) break;
if (i < nchosen) {
if (rmass) fprintf(fp,"%g\n",rmass[i]);
else fprintf(fp,"%g\n",mass[itype]);
fprintf(fp,"%s\n",typenames[itype]);
for (; i < nchosen; i++) {
if (rbuf[i][1] == itype) {
if (unwrapflag == 0)
for (j = 2; j < size_one; j++) {
if (vtype[j] == INT)
fprintf(fp,vformat[j],static_cast<int> (rbuf[i][j]));
else fprintf(fp,vformat[j],rbuf[i][j]);
}
- else
+ else {
// Unwrapped scaled coordinates are shifted to
// center of expanded box, to prevent
// rewrapping by AtomEye. Dividing by
// expansion factor restores correct
// interatomic distances.
for (j = 2; j < 5; j++) {
unwrap_coord = (rbuf[i][j] - 0.5)/UNWRAPEXPAND + 0.5;
fprintf(fp,vformat[j],unwrap_coord);
}
for (j = 5; j < size_one; j++) {
if (vtype[j] == INT)
fprintf(fp,vformat[j],static_cast<int> (rbuf[i][j]));
else fprintf(fp,vformat[j],rbuf[i][j]);
}
-
+ }
fprintf(fp,"\n");
}
}
}
}
nlines = 0;
}
}
diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp
index 5a3a46b96..7382ec084 100644
--- a/src/dump_custom.cpp
+++ b/src/dump_custom.cpp
@@ -1,2394 +1,2394 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "dump_custom.h"
#include "atom.h"
#include "force.h"
#include "domain.h"
#include "region.h"
#include "group.h"
#include "input.h"
#include "variable.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "fix.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
// customize by adding keyword
// also customize compute_atom_property.cpp
enum{ID,MOL,TYPE,ELEMENT,MASS,
X,Y,Z,XS,YS,ZS,XSTRI,YSTRI,ZSTRI,XU,YU,ZU,XUTRI,YUTRI,ZUTRI,
XSU,YSU,ZSU,XSUTRI,YSUTRI,ZSUTRI,
IX,IY,IZ,
VX,VY,VZ,FX,FY,FZ,
Q,MUX,MUY,MUZ,MU,RADIUS,DIAMETER,
OMEGAX,OMEGAY,OMEGAZ,ANGMOMX,ANGMOMY,ANGMOMZ,
TQX,TQY,TQZ,SPIN,ERADIUS,ERVEL,ERFORCE,
COMPUTE,FIX,VARIABLE};
enum{LT,LE,GT,GE,EQ,NEQ};
enum{INT,DOUBLE,STRING};
#define INVOKED_PERATOM 8
/* ---------------------------------------------------------------------- */
DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) :
Dump(lmp, narg, arg)
{
- if (narg == 5) error->all("No dump custom arguments specified");
+ if (narg == 5) error->all(FLERR,"No dump custom arguments specified");
clearstep = 1;
nevery = atoi(arg[3]);
// size_one may be shrunk below if additional optional args exist
size_one = nfield = narg - 5;
pack_choice = new FnPtrPack[nfield];
vtype = new int[nfield];
iregion = -1;
idregion = NULL;
nthresh = 0;
thresh_array = NULL;
thresh_op = NULL;
thresh_value = NULL;
// computes, fixes, variables which the dump accesses
memory->create(field2index,nfield,"dump:field2index");
memory->create(argindex,nfield,"dump:argindex");
ncompute = 0;
id_compute = NULL;
compute = NULL;
nfix = 0;
id_fix = NULL;
fix = NULL;
nvariable = 0;
id_variable = NULL;
variable = NULL;
vbuf = NULL;
// process attributes
// ioptional = start of additional optional args
// only dump image style processes optional args
ioptional = parse_fields(narg,arg);
if (ioptional < narg && strcmp(style,"image") != 0)
- error->all("Invalid attribute in dump custom command");
+ error->all(FLERR,"Invalid attribute in dump custom command");
size_one = nfield = ioptional - 5;
// atom selection arrays
maxlocal = 0;
choose = NULL;
dchoose = NULL;
clist = NULL;
// element names
ntypes = atom->ntypes;
typenames = NULL;
// setup format strings
vformat = new char*[size_one];
format_default = new char[3*size_one+1];
format_default[0] = '\0';
for (int i = 0; i < size_one; i++) {
if (vtype[i] == INT) format_default = strcat(format_default,"%d ");
else if (vtype[i] == DOUBLE) format_default = strcat(format_default,"%g ");
else if (vtype[i] == STRING) strcat(format_default,"%s ");
vformat[i] = NULL;
}
// setup column string
int n = 0;
for (int iarg = 5; iarg < narg; iarg++) n += strlen(arg[iarg]) + 2;
columns = new char[n];
columns[0] = '\0';
for (int iarg = 5; iarg < narg; iarg++) {
strcat(columns,arg[iarg]);
strcat(columns," ");
}
}
/* ---------------------------------------------------------------------- */
DumpCustom::~DumpCustom()
{
delete [] pack_choice;
delete [] vtype;
memory->destroy(field2index);
memory->destroy(argindex);
delete [] idregion;
memory->destroy(thresh_array);
memory->destroy(thresh_op);
memory->destroy(thresh_value);
for (int i = 0; i < ncompute; i++) delete [] id_compute[i];
memory->sfree(id_compute);
delete [] compute;
for (int i = 0; i < nfix; i++) delete [] id_fix[i];
memory->sfree(id_fix);
delete [] fix;
for (int i = 0; i < nvariable; i++) delete [] id_variable[i];
memory->sfree(id_variable);
delete [] variable;
for (int i = 0; i < nvariable; i++) memory->destroy(vbuf[i]);
delete [] vbuf;
memory->destroy(choose);
memory->destroy(dchoose);
memory->destroy(clist);
if (typenames) {
for (int i = 1; i <= ntypes; i++) delete [] typenames[i];
delete [] typenames;
}
for (int i = 0; i < size_one; i++) delete [] vformat[i];
delete [] vformat;
delete [] columns;
}
/* ---------------------------------------------------------------------- */
void DumpCustom::init_style()
{
delete [] format;
char *str;
if (format_user) str = format_user;
else str = format_default;
int n = strlen(str) + 1;
format = new char[n];
strcpy(format,str);
// default for element names = C
if (typenames == NULL) {
typenames = new char*[ntypes+1];
for (int itype = 1; itype <= ntypes; itype++) {
typenames[itype] = new char[2];
strcpy(typenames[itype],"C");
}
}
// tokenize the format string and add space at end of each format element
char *ptr;
for (int i = 0; i < size_one; i++) {
if (i == 0) ptr = strtok(format," \0");
else ptr = strtok(NULL," \0");
delete [] vformat[i];
vformat[i] = new char[strlen(ptr) + 2];
strcpy(vformat[i],ptr);
vformat[i] = strcat(vformat[i]," ");
}
// setup boundary string
int m = 0;
for (int idim = 0; idim < 3; idim++) {
for (int iside = 0; iside < 2; iside++) {
if (domain->boundary[idim][iside] == 0) boundstr[m++] = 'p';
else if (domain->boundary[idim][iside] == 1) boundstr[m++] = 'f';
else if (domain->boundary[idim][iside] == 2) boundstr[m++] = 's';
else if (domain->boundary[idim][iside] == 3) boundstr[m++] = 'm';
}
boundstr[m++] = ' ';
}
boundstr[8] = '\0';
// setup function ptrs
if (binary && domain->triclinic == 0)
header_choice = &DumpCustom::header_binary;
else if (binary && domain->triclinic == 1)
header_choice = &DumpCustom::header_binary_triclinic;
else if (!binary && domain->triclinic == 0)
header_choice = &DumpCustom::header_item;
else if (!binary && domain->triclinic == 1)
header_choice = &DumpCustom::header_item_triclinic;
if (binary) write_choice = &DumpCustom::write_binary;
else write_choice = &DumpCustom::write_text;
// find current ptr for each compute,fix,variable
// check that fix frequency is acceptable
int icompute;
for (int i = 0; i < ncompute; i++) {
icompute = modify->find_compute(id_compute[i]);
- if (icompute < 0) error->all("Could not find dump custom compute ID");
+ if (icompute < 0) error->all(FLERR,"Could not find dump custom compute ID");
compute[i] = modify->compute[icompute];
}
int ifix;
for (int i = 0; i < nfix; i++) {
ifix = modify->find_fix(id_fix[i]);
- if (ifix < 0) error->all("Could not find dump custom fix ID");
+ if (ifix < 0) error->all(FLERR,"Could not find dump custom fix ID");
fix[i] = modify->fix[ifix];
if (nevery % modify->fix[ifix]->peratom_freq)
- error->all("Dump custom and fix not computed at compatible times");
+ error->all(FLERR,"Dump custom and fix not computed at compatible times");
}
int ivariable;
for (int i = 0; i < nvariable; i++) {
ivariable = input->variable->find(id_variable[i]);
- if (ivariable < 0) error->all("Could not find dump custom variable name");
+ if (ivariable < 0) error->all(FLERR,"Could not find dump custom variable name");
variable[i] = ivariable;
}
// set index and check validity of region
if (iregion >= 0) {
iregion = domain->find_region(idregion);
- if (iregion == -1) error->all("Region ID for dump custom does not exist");
+ if (iregion == -1) error->all(FLERR,"Region ID for dump custom does not exist");
}
// open single file, one time only
if (multifile == 0) openfile();
}
/* ---------------------------------------------------------------------- */
void DumpCustom::write_header(bigint ndump)
{
if (multiproc) (this->*header_choice)(ndump);
else if (me == 0) (this->*header_choice)(ndump);
}
/* ---------------------------------------------------------------------- */
void DumpCustom::header_binary(bigint ndump)
{
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
fwrite(&ndump,sizeof(bigint),1,fp);
fwrite(&domain->triclinic,sizeof(int),1,fp);
fwrite(&domain->boundary[0][0],6*sizeof(int),1,fp);
fwrite(&boxxlo,sizeof(double),1,fp);
fwrite(&boxxhi,sizeof(double),1,fp);
fwrite(&boxylo,sizeof(double),1,fp);
fwrite(&boxyhi,sizeof(double),1,fp);
fwrite(&boxzlo,sizeof(double),1,fp);
fwrite(&boxzhi,sizeof(double),1,fp);
fwrite(&size_one,sizeof(int),1,fp);
if (multiproc) {
int one = 1;
fwrite(&one,sizeof(int),1,fp);
} else fwrite(&nprocs,sizeof(int),1,fp);
}
/* ---------------------------------------------------------------------- */
void DumpCustom::header_binary_triclinic(bigint ndump)
{
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
fwrite(&ndump,sizeof(bigint),1,fp);
fwrite(&domain->triclinic,sizeof(int),1,fp);
fwrite(&domain->boundary[0][0],6*sizeof(int),1,fp);
fwrite(&boxxlo,sizeof(double),1,fp);
fwrite(&boxxhi,sizeof(double),1,fp);
fwrite(&boxylo,sizeof(double),1,fp);
fwrite(&boxyhi,sizeof(double),1,fp);
fwrite(&boxzlo,sizeof(double),1,fp);
fwrite(&boxzhi,sizeof(double),1,fp);
fwrite(&boxxy,sizeof(double),1,fp);
fwrite(&boxxz,sizeof(double),1,fp);
fwrite(&boxyz,sizeof(double),1,fp);
fwrite(&size_one,sizeof(int),1,fp);
if (multiproc) {
int one = 1;
fwrite(&one,sizeof(int),1,fp);
} else fwrite(&nprocs,sizeof(int),1,fp);
}
/* ---------------------------------------------------------------------- */
void DumpCustom::header_item(bigint ndump)
{
fprintf(fp,"ITEM: TIMESTEP\n");
fprintf(fp,BIGINT_FORMAT "\n",update->ntimestep);
fprintf(fp,"ITEM: NUMBER OF ATOMS\n");
fprintf(fp,BIGINT_FORMAT "\n",ndump);
fprintf(fp,"ITEM: BOX BOUNDS %s\n",boundstr);
fprintf(fp,"%g %g\n",boxxlo,boxxhi);
fprintf(fp,"%g %g\n",boxylo,boxyhi);
fprintf(fp,"%g %g\n",boxzlo,boxzhi);
fprintf(fp,"ITEM: ATOMS %s\n",columns);
}
/* ---------------------------------------------------------------------- */
void DumpCustom::header_item_triclinic(bigint ndump)
{
fprintf(fp,"ITEM: TIMESTEP\n");
fprintf(fp,BIGINT_FORMAT "\n",update->ntimestep);
fprintf(fp,"ITEM: NUMBER OF ATOMS\n");
fprintf(fp,BIGINT_FORMAT "\n",ndump);
fprintf(fp,"ITEM: BOX BOUNDS xy xz yz %s\n",boundstr);
fprintf(fp,"%g %g %g\n",boxxlo,boxxhi,boxxy);
fprintf(fp,"%g %g %g\n",boxylo,boxyhi,boxxz);
fprintf(fp,"%g %g %g\n",boxzlo,boxzhi,boxyz);
fprintf(fp,"ITEM: ATOMS %s\n",columns);
}
/* ---------------------------------------------------------------------- */
int DumpCustom::count()
{
int i;
// grow choose and variable vbuf arrays if needed
int nlocal = atom->nlocal;
if (nlocal > maxlocal) {
maxlocal = atom->nmax;
memory->destroy(choose);
memory->destroy(dchoose);
memory->destroy(clist);
memory->create(choose,maxlocal,"dump:choose");
memory->create(dchoose,maxlocal,"dump:dchoose");
memory->create(clist,maxlocal,"dump:clist");
for (i = 0; i < nvariable; i++) {
memory->destroy(vbuf[i]);
memory->create(vbuf[i],maxlocal,"dump:vbuf");
}
}
// invoke Computes for per-atom quantities
if (ncompute) {
for (i = 0; i < ncompute; i++)
if (!(compute[i]->invoked_flag & INVOKED_PERATOM)) {
compute[i]->compute_peratom();
compute[i]->invoked_flag |= INVOKED_PERATOM;
}
}
// evaluate atom-style Variables for per-atom quantities
if (nvariable)
for (i = 0; i < nvariable; i++)
input->variable->compute_atom(variable[i],igroup,vbuf[i],1,0);
// choose all local atoms for output
for (i = 0; i < nlocal; i++) choose[i] = 1;
// un-choose if not in group
if (igroup) {
int *mask = atom->mask;
for (i = 0; i < nlocal; i++)
if (!(mask[i] & groupbit))
choose[i] = 0;
}
// un-choose if not in region
if (iregion >= 0) {
Region *region = domain->regions[iregion];
double **x = atom->x;
for (i = 0; i < nlocal; i++)
if (choose[i] && region->match(x[i][0],x[i][1],x[i][2]) == 0)
choose[i] = 0;
}
// un-choose if any threshhold criterion isn't met
if (nthresh) {
double *ptr;
double value;
int nstride;
int nlocal = atom->nlocal;
for (int ithresh = 0; ithresh < nthresh; ithresh++) {
// customize by adding to if statement
if (thresh_array[ithresh] == ID) {
int *tag = atom->tag;
for (i = 0; i < nlocal; i++) dchoose[i] = tag[i];
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == MOL) {
if (!atom->molecule_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
int *molecule = atom->molecule;
for (i = 0; i < nlocal; i++) dchoose[i] = molecule[i];
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == TYPE) {
int *type = atom->type;
for (i = 0; i < nlocal; i++) dchoose[i] = type[i];
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ELEMENT) {
int *type = atom->type;
for (i = 0; i < nlocal; i++) dchoose[i] = type[i];
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == MASS) {
if (atom->rmass) {
ptr = atom->rmass;
nstride = 1;
} else {
double *mass = atom->mass;
int *type = atom->type;
for (i = 0; i < nlocal; i++) dchoose[i] = mass[type[i]];
ptr = dchoose;
nstride = 1;
}
} else if (thresh_array[ithresh] == X) {
ptr = &atom->x[0][0];
nstride = 3;
} else if (thresh_array[ithresh] == Y) {
ptr = &atom->x[0][1];
nstride = 3;
} else if (thresh_array[ithresh] == Z) {
ptr = &atom->x[0][2];
nstride = 3;
} else if (thresh_array[ithresh] == XS) {
double **x = atom->x;
double boxxlo = domain->boxlo[0];
double invxprd = 1.0/domain->xprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = (x[i][0] - boxxlo) * invxprd;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == YS) {
double **x = atom->x;
double boxylo = domain->boxlo[1];
double invyprd = 1.0/domain->yprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = (x[i][1] - boxylo) * invyprd;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ZS) {
double **x = atom->x;
double boxzlo = domain->boxlo[2];
double invzprd = 1.0/domain->zprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = (x[i][2] - boxzlo) * invzprd;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == XSTRI) {
double **x = atom->x;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (i = 0; i < nlocal; i++)
dchoose[i] = h_inv[0]*(x[i][0]-boxlo[0]) +
h_inv[5]*(x[i][1]-boxlo[1]) + h_inv[4]*(x[i][2]-boxlo[2]);
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == YSTRI) {
double **x = atom->x;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (i = 0; i < nlocal; i++)
dchoose[i] = h_inv[1]*(x[i][1]-boxlo[1]) +
h_inv[3]*(x[i][2]-boxlo[2]);
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ZSTRI) {
double **x = atom->x;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (i = 0; i < nlocal; i++)
dchoose[i] = h_inv[2]*(x[i][2]-boxlo[2]);
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == XU) {
double **x = atom->x;
int *image = atom->image;
double xprd = domain->xprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = x[i][0] + ((image[i] & 1023) - 512) * xprd;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == YU) {
double **x = atom->x;
int *image = atom->image;
double yprd = domain->yprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = x[i][1] + ((image[i] >> 10 & 1023) - 512) * yprd;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ZU) {
double **x = atom->x;
int *image = atom->image;
double zprd = domain->zprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = x[i][2] + ((image[i] >> 20) - 512) * zprd;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == XUTRI) {
double **x = atom->x;
int *image = atom->image;
double *h = domain->h;
int xbox,ybox,zbox;
for (i = 0; i < nlocal; i++) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dchoose[i] = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox;
}
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == YUTRI) {
double **x = atom->x;
int *image = atom->image;
double *h = domain->h;
int ybox,zbox;
for (i = 0; i < nlocal; i++) {
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dchoose[i] = x[i][1] + h[1]*ybox + h[3]*zbox;
}
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ZUTRI) {
double **x = atom->x;
int *image = atom->image;
double *h = domain->h;
int zbox;
for (i = 0; i < nlocal; i++) {
zbox = (image[i] >> 20) - 512;
dchoose[i] = x[i][2] + h[2]*zbox;
}
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == XSU) {
double **x = atom->x;
int *image = atom->image;
double boxxlo = domain->boxlo[0];
double invxprd = 1.0/domain->xprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = (x[i][0] - boxxlo) * invxprd + (image[i] & 1023) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == YSU) {
double **x = atom->x;
int *image = atom->image;
double boxylo = domain->boxlo[1];
double invyprd = 1.0/domain->yprd;
for (i = 0; i < nlocal; i++)
dchoose[i] =
(x[i][1] - boxylo) * invyprd + (image[i] >> 10 & 1023) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ZSU) {
double **x = atom->x;
int *image = atom->image;
double boxzlo = domain->boxlo[2];
double invzprd = 1.0/domain->zprd;
for (i = 0; i < nlocal; i++)
dchoose[i] = (x[i][2] - boxzlo) * invzprd + (image[i] >> 20) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == XSUTRI) {
double **x = atom->x;
int *image = atom->image;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (i = 0; i < nlocal; i++)
dchoose[i] = h_inv[0]*(x[i][0]-boxlo[0]) +
h_inv[5]*(x[i][1]-boxlo[1]) +
h_inv[4]*(x[i][2]-boxlo[2]) +
(image[i] & 1023) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == YSUTRI) {
double **x = atom->x;
int *image = atom->image;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (i = 0; i < nlocal; i++)
dchoose[i] = h_inv[1]*(x[i][1]-boxlo[1]) +
h_inv[3]*(x[i][2]-boxlo[2]) +
(image[i] >> 10 & 1023) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ZSUTRI) {
double **x = atom->x;
int *image = atom->image;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (i = 0; i < nlocal; i++)
dchoose[i] = h_inv[2]*(x[i][2]-boxlo[2]) +
(image[i] >> 20) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == IX) {
int *image = atom->image;
for (i = 0; i < nlocal; i++)
dchoose[i] = (image[i] & 1023) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == IY) {
int *image = atom->image;
for (i = 0; i < nlocal; i++)
dchoose[i] = (image[i] >> 10 & 1023) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == IZ) {
int *image = atom->image;
for (i = 0; i < nlocal; i++)
dchoose[i] = (image[i] >> 20) - 512;
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == VX) {
ptr = &atom->v[0][0];
nstride = 3;
} else if (thresh_array[ithresh] == VY) {
ptr = &atom->v[0][1];
nstride = 3;
} else if (thresh_array[ithresh] == VZ) {
ptr = &atom->v[0][2];
nstride = 3;
} else if (thresh_array[ithresh] == FX) {
ptr = &atom->f[0][0];
nstride = 3;
} else if (thresh_array[ithresh] == FY) {
ptr = &atom->f[0][1];
nstride = 3;
} else if (thresh_array[ithresh] == FZ) {
ptr = &atom->f[0][2];
nstride = 3;
} else if (thresh_array[ithresh] == Q) {
if (!atom->q_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = atom->q;
nstride = 1;
} else if (thresh_array[ithresh] == MUX) {
if (!atom->mu_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->mu[0][0];
nstride = 4;
} else if (thresh_array[ithresh] == MUY) {
if (!atom->mu_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->mu[0][1];
nstride = 4;
} else if (thresh_array[ithresh] == MUZ) {
if (!atom->mu_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->mu[0][2];
nstride = 4;
} else if (thresh_array[ithresh] == MU) {
if (!atom->mu_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->mu[0][3];
nstride = 4;
} else if (thresh_array[ithresh] == RADIUS) {
if (!atom->radius_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = atom->radius;
nstride = 1;
} else if (thresh_array[ithresh] == DIAMETER) {
if (!atom->radius_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
double *radius = atom->radius;
for (i = 0; i < nlocal; i++) dchoose[i] = 2.0*radius[i];
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == OMEGAX) {
if (!atom->omega_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->omega[0][0];
nstride = 3;
} else if (thresh_array[ithresh] == OMEGAY) {
if (!atom->omega_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->omega[0][1];
nstride = 3;
} else if (thresh_array[ithresh] == OMEGAZ) {
if (!atom->omega_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->omega[0][2];
nstride = 3;
} else if (thresh_array[ithresh] == ANGMOMX) {
if (!atom->angmom_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->angmom[0][0];
nstride = 3;
} else if (thresh_array[ithresh] == ANGMOMY) {
if (!atom->angmom_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->angmom[0][1];
nstride = 3;
} else if (thresh_array[ithresh] == ANGMOMZ) {
if (!atom->angmom_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->angmom[0][2];
nstride = 3;
} else if (thresh_array[ithresh] == TQX) {
if (!atom->torque_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->torque[0][0];
nstride = 3;
} else if (thresh_array[ithresh] == TQY) {
if (!atom->torque_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->torque[0][1];
nstride = 3;
} else if (thresh_array[ithresh] == TQZ) {
if (!atom->torque_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = &atom->torque[0][2];
nstride = 3;
} else if (thresh_array[ithresh] == SPIN) {
if (!atom->spin_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
int *spin = atom->spin;
for (i = 0; i < nlocal; i++) dchoose[i] = spin[i];
ptr = dchoose;
nstride = 1;
} else if (thresh_array[ithresh] == ERADIUS) {
if (!atom->eradius_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = atom->eradius;
nstride = 1;
} else if (thresh_array[ithresh] == ERVEL) {
if (!atom->ervel_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = atom->ervel;
nstride = 1;
} else if (thresh_array[ithresh] == ERFORCE) {
if (!atom->erforce_flag)
- error->all("Threshhold for an atom property that isn't allocated");
+ error->all(FLERR,"Threshhold for an atom property that isn't allocated");
ptr = atom->erforce;
nstride = 1;
} else if (thresh_array[ithresh] == COMPUTE) {
i = nfield + ithresh;
if (argindex[i] == 0) {
ptr = compute[field2index[i]]->vector_atom;
nstride = 1;
} else {
ptr = &compute[field2index[i]]->array_atom[0][argindex[i]-1];
nstride = compute[field2index[i]]->size_peratom_cols;
}
} else if (thresh_array[ithresh] == FIX) {
i = nfield + ithresh;
if (argindex[i] == 0) {
ptr = fix[field2index[i]]->vector_atom;
nstride = 1;
} else {
ptr = &fix[field2index[i]]->array_atom[0][argindex[i]-1];
nstride = fix[field2index[i]]->size_peratom_cols;
}
} else if (thresh_array[ithresh] == VARIABLE) {
i = nfield + ithresh;
ptr = vbuf[field2index[i]];
nstride = 1;
}
// unselect atoms that don't meet threshhold criterion
value = thresh_value[ithresh];
if (thresh_op[ithresh] == LT) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr >= value) choose[i] = 0;
} else if (thresh_op[ithresh] == LE) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr > value) choose[i] = 0;
} else if (thresh_op[ithresh] == GT) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr <= value) choose[i] = 0;
} else if (thresh_op[ithresh] == GE) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr < value) choose[i] = 0;
} else if (thresh_op[ithresh] == EQ) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr != value) choose[i] = 0;
} else if (thresh_op[ithresh] == NEQ) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr == value) choose[i] = 0;
}
}
}
// compress choose flags into clist
// nchoose = # of selected atoms
// clist[i] = local index of each selected atom
nchoose = 0;
for (i = 0; i < nlocal; i++)
if (choose[i]) clist[nchoose++] = i;
return nchoose;
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack(int *ids)
{
for (int n = 0; n < size_one; n++) (this->*pack_choice[n])(n);
if (ids) {
int *tag = atom->tag;
for (int i = 0; i < nchoose; i++)
ids[i] = tag[clist[i]];
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::write_data(int n, double *mybuf)
{
(this->*write_choice)(n,mybuf);
}
/* ---------------------------------------------------------------------- */
void DumpCustom::write_binary(int n, double *mybuf)
{
n *= size_one;
fwrite(&n,sizeof(int),1,fp);
fwrite(mybuf,sizeof(double),n,fp);
}
/* ---------------------------------------------------------------------- */
void DumpCustom::write_text(int n, double *mybuf)
{
int i,j;
int m = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < size_one; j++) {
if (vtype[j] == INT) fprintf(fp,vformat[j],static_cast<int> (mybuf[m]));
else if (vtype[j] == DOUBLE) fprintf(fp,vformat[j],mybuf[m]);
else if (vtype[j] == STRING)
fprintf(fp,vformat[j],typenames[(int) mybuf[m]]);
m++;
}
fprintf(fp,"\n");
}
}
/* ---------------------------------------------------------------------- */
int DumpCustom::parse_fields(int narg, char **arg)
{
// customize by adding to if statement
int i;
for (int iarg = 5; iarg < narg; iarg++) {
i = iarg-5;
if (strcmp(arg[iarg],"id") == 0) {
pack_choice[i] = &DumpCustom::pack_id;
vtype[i] = INT;
} else if (strcmp(arg[iarg],"mol") == 0) {
if (!atom->molecule_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_molecule;
vtype[i] = INT;
} else if (strcmp(arg[iarg],"type") == 0) {
pack_choice[i] = &DumpCustom::pack_type;
vtype[i] = INT;
} else if (strcmp(arg[iarg],"element") == 0) {
pack_choice[i] = &DumpCustom::pack_type;
vtype[i] = STRING;
} else if (strcmp(arg[iarg],"mass") == 0) {
pack_choice[i] = &DumpCustom::pack_mass;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"x") == 0) {
pack_choice[i] = &DumpCustom::pack_x;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"y") == 0) {
pack_choice[i] = &DumpCustom::pack_y;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"z") == 0) {
pack_choice[i] = &DumpCustom::pack_z;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"xs") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_xs_triclinic;
else pack_choice[i] = &DumpCustom::pack_xs;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"ys") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_ys_triclinic;
else pack_choice[i] = &DumpCustom::pack_ys;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"zs") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_zs_triclinic;
else pack_choice[i] = &DumpCustom::pack_zs;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"xu") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_xu_triclinic;
else pack_choice[i] = &DumpCustom::pack_xu;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"yu") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_yu_triclinic;
else pack_choice[i] = &DumpCustom::pack_yu;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"zu") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_zu_triclinic;
else pack_choice[i] = &DumpCustom::pack_zu;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"xsu") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_xsu_triclinic;
else pack_choice[i] = &DumpCustom::pack_xsu;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"ysu") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_ysu_triclinic;
else pack_choice[i] = &DumpCustom::pack_ysu;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"zsu") == 0) {
if (domain->triclinic) pack_choice[i] = &DumpCustom::pack_zsu_triclinic;
else pack_choice[i] = &DumpCustom::pack_zsu;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"ix") == 0) {
pack_choice[i] = &DumpCustom::pack_ix;
vtype[i] = INT;
} else if (strcmp(arg[iarg],"iy") == 0) {
pack_choice[i] = &DumpCustom::pack_iy;
vtype[i] = INT;
} else if (strcmp(arg[iarg],"iz") == 0) {
pack_choice[i] = &DumpCustom::pack_iz;
vtype[i] = INT;
} else if (strcmp(arg[iarg],"vx") == 0) {
pack_choice[i] = &DumpCustom::pack_vx;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"vy") == 0) {
pack_choice[i] = &DumpCustom::pack_vy;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"vz") == 0) {
pack_choice[i] = &DumpCustom::pack_vz;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"fx") == 0) {
pack_choice[i] = &DumpCustom::pack_fx;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"fy") == 0) {
pack_choice[i] = &DumpCustom::pack_fy;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"fz") == 0) {
pack_choice[i] = &DumpCustom::pack_fz;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"q") == 0) {
if (!atom->q_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_q;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"mux") == 0) {
if (!atom->mu_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_mux;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"muy") == 0) {
if (!atom->mu_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_muy;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"muz") == 0) {
if (!atom->mu_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_muz;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"mu") == 0) {
if (!atom->mu_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_mu;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"radius") == 0) {
if (!atom->radius_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_radius;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"diameter") == 0) {
if (!atom->radius_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_diameter;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"omegax") == 0) {
if (!atom->omega_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_omegax;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"omegay") == 0) {
if (!atom->omega_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_omegay;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"omegaz") == 0) {
if (!atom->omega_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_omegaz;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"angmomx") == 0) {
if (!atom->angmom_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_angmomx;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"angmomy") == 0) {
if (!atom->angmom_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_angmomy;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"angmomz") == 0) {
if (!atom->angmom_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_angmomz;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"tqx") == 0) {
if (!atom->torque_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_tqx;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"tqy") == 0) {
if (!atom->torque_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_tqy;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"tqz") == 0) {
if (!atom->torque_flag)
- error->all("Dumping an atom property that isn't allocated");
+ error->all(FLERR,"Dumping an atom property that isn't allocated");
pack_choice[i] = &DumpCustom::pack_tqz;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"spin") == 0) {
if (!atom->spin_flag)
- error->all("Dumping an atom quantity that isn't allocated");
+ error->all(FLERR,"Dumping an atom quantity that isn't allocated");
pack_choice[i] = &DumpCustom::pack_spin;
vtype[i] = INT;
} else if (strcmp(arg[iarg],"eradius") == 0) {
if (!atom->eradius_flag)
- error->all("Dumping an atom quantity that isn't allocated");
+ error->all(FLERR,"Dumping an atom quantity that isn't allocated");
pack_choice[i] = &DumpCustom::pack_eradius;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"ervel") == 0) {
if (!atom->ervel_flag)
- error->all("Dumping an atom quantity that isn't allocated");
+ error->all(FLERR,"Dumping an atom quantity that isn't allocated");
pack_choice[i] = &DumpCustom::pack_ervel;
vtype[i] = DOUBLE;
} else if (strcmp(arg[iarg],"erforce") == 0) {
if (!atom->erforce_flag)
- error->all("Dumping an atom quantity that isn't allocated");
+ error->all(FLERR,"Dumping an atom quantity that isn't allocated");
pack_choice[i] = &DumpCustom::pack_erforce;
vtype[i] = DOUBLE;
// compute value = c_ID
// if no trailing [], then arg is set to 0, else arg is int between []
} else if (strncmp(arg[iarg],"c_",2) == 0) {
pack_choice[i] = &DumpCustom::pack_compute;
vtype[i] = DOUBLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Invalid attribute in dump custom command");
+ error->all(FLERR,"Invalid attribute in dump custom command");
argindex[i] = atoi(ptr+1);
*ptr = '\0';
} else argindex[i] = 0;
n = modify->find_compute(suffix);
- if (n < 0) error->all("Could not find dump custom compute ID");
+ if (n < 0) error->all(FLERR,"Could not find dump custom compute ID");
if (modify->compute[n]->peratom_flag == 0)
- error->all("Dump custom compute does not compute per-atom info");
+ error->all(FLERR,"Dump custom compute does not compute per-atom info");
if (argindex[i] == 0 && modify->compute[n]->size_peratom_cols > 0)
- error->all("Dump custom compute does not calculate per-atom vector");
+ error->all(FLERR,"Dump custom compute does not calculate per-atom vector");
if (argindex[i] > 0 && modify->compute[n]->size_peratom_cols == 0)
- error->all("Dump custom compute does not calculate per-atom array");
+ error->all(FLERR,"Dump custom compute does not calculate per-atom array");
if (argindex[i] > 0 &&
argindex[i] > modify->compute[n]->size_peratom_cols)
- error->all("Dump custom compute vector is accessed out-of-range");
+ error->all(FLERR,"Dump custom compute vector is accessed out-of-range");
field2index[i] = add_compute(suffix);
delete [] suffix;
// fix value = f_ID
// if no trailing [], then arg is set to 0, else arg is between []
} else if (strncmp(arg[iarg],"f_",2) == 0) {
pack_choice[i] = &DumpCustom::pack_fix;
vtype[i] = DOUBLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Invalid attribute in dump custom command");
+ error->all(FLERR,"Invalid attribute in dump custom command");
argindex[i] = atoi(ptr+1);
*ptr = '\0';
} else argindex[i] = 0;
n = modify->find_fix(suffix);
- if (n < 0) error->all("Could not find dump custom fix ID");
+ if (n < 0) error->all(FLERR,"Could not find dump custom fix ID");
if (modify->fix[n]->peratom_flag == 0)
- error->all("Dump custom fix does not compute per-atom info");
+ error->all(FLERR,"Dump custom fix does not compute per-atom info");
if (argindex[i] == 0 && modify->fix[n]->size_peratom_cols > 0)
- error->all("Dump custom fix does not compute per-atom vector");
+ error->all(FLERR,"Dump custom fix does not compute per-atom vector");
if (argindex[i] > 0 && modify->fix[n]->size_peratom_cols == 0)
- error->all("Dump custom fix does not compute per-atom array");
+ error->all(FLERR,"Dump custom fix does not compute per-atom array");
if (argindex[i] > 0 &&
argindex[i] > modify->fix[n]->size_peratom_cols)
- error->all("Dump custom fix vector is accessed out-of-range");
+ error->all(FLERR,"Dump custom fix vector is accessed out-of-range");
field2index[i] = add_fix(suffix);
delete [] suffix;
// variable value = v_name
} else if (strncmp(arg[iarg],"v_",2) == 0) {
pack_choice[i] = &DumpCustom::pack_variable;
vtype[i] = DOUBLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
argindex[i] = 0;
n = input->variable->find(suffix);
- if (n < 0) error->all("Could not find dump custom variable name");
+ if (n < 0) error->all(FLERR,"Could not find dump custom variable name");
if (input->variable->atomstyle(n) == 0)
- error->all("Dump custom variable is not atom-style variable");
+ error->all(FLERR,"Dump custom variable is not atom-style variable");
field2index[i] = add_variable(suffix);
delete [] suffix;
} else return iarg;
}
return narg;
}
/* ----------------------------------------------------------------------
add Compute to list of Compute objects used by dump
return index of where this Compute is in list
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
int DumpCustom::add_compute(char *id)
{
int icompute;
for (icompute = 0; icompute < ncompute; icompute++)
if (strcmp(id,id_compute[icompute]) == 0) break;
if (icompute < ncompute) return icompute;
id_compute = (char **)
memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),"dump:id_compute");
delete [] compute;
compute = new Compute*[ncompute+1];
int n = strlen(id) + 1;
id_compute[ncompute] = new char[n];
strcpy(id_compute[ncompute],id);
ncompute++;
return ncompute-1;
}
/* ----------------------------------------------------------------------
add Fix to list of Fix objects used by dump
return index of where this Fix is in list
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
int DumpCustom::add_fix(char *id)
{
int ifix;
for (ifix = 0; ifix < nfix; ifix++)
if (strcmp(id,id_fix[ifix]) == 0) break;
if (ifix < nfix) return ifix;
id_fix = (char **)
memory->srealloc(id_fix,(nfix+1)*sizeof(char *),"dump:id_fix");
delete [] fix;
fix = new Fix*[nfix+1];
int n = strlen(id) + 1;
id_fix[nfix] = new char[n];
strcpy(id_fix[nfix],id);
nfix++;
return nfix-1;
}
/* ----------------------------------------------------------------------
add Variable to list of Variables used by dump
return index of where this Variable is in list
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
int DumpCustom::add_variable(char *id)
{
int ivariable;
for (ivariable = 0; ivariable < nvariable; ivariable++)
if (strcmp(id,id_variable[ivariable]) == 0) break;
if (ivariable < nvariable) return ivariable;
id_variable = (char **)
memory->srealloc(id_variable,(nvariable+1)*sizeof(char *),
"dump:id_variable");
delete [] variable;
variable = new int[nvariable+1];
delete [] vbuf;
vbuf = new double*[nvariable+1];
for (int i = 0; i <= nvariable; i++) vbuf[i] = NULL;
int n = strlen(id) + 1;
id_variable[nvariable] = new char[n];
strcpy(id_variable[nvariable],id);
nvariable++;
return nvariable-1;
}
/* ---------------------------------------------------------------------- */
int DumpCustom::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"region") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"none") == 0) iregion = -1;
else {
iregion = domain->find_region(arg[1]);
- if (iregion == -1) error->all("Dump_modify region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Dump_modify region ID does not exist");
int n = strlen(arg[1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[1]);
}
return 2;
} else if (strcmp(arg[0],"element") == 0) {
if (narg < ntypes+1)
- error->all("Dump modify element names do not match atom types");
+ error->all(FLERR,"Dump modify element names do not match atom types");
if (typenames) {
for (int i = 1; i <= ntypes; i++) delete [] typenames[i];
delete [] typenames;
typenames = NULL;
}
typenames = new char*[ntypes+1];
for (int itype = 1; itype <= ntypes; itype++) {
int n = strlen(arg[itype]) + 1;
typenames[itype] = new char[n];
strcpy(typenames[itype],arg[itype]);
}
return ntypes+1;
} else if (strcmp(arg[0],"thresh") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"none") == 0) {
if (nthresh) {
memory->destroy(thresh_array);
memory->destroy(thresh_op);
memory->destroy(thresh_value);
thresh_array = NULL;
thresh_op = NULL;
thresh_value = NULL;
}
nthresh = 0;
return 2;
}
- if (narg < 4) error->all("Illegal dump_modify command");
+ if (narg < 4) error->all(FLERR,"Illegal dump_modify command");
// grow threshhold arrays
memory->grow(thresh_array,nthresh+1,"dump:thresh_array");
memory->grow(thresh_op,(nthresh+1),"dump:thresh_op");
memory->grow(thresh_value,(nthresh+1),"dump:thresh_value");
// set attribute type of threshhold
// customize by adding to if statement
if (strcmp(arg[1],"id") == 0) thresh_array[nthresh] = ID;
else if (strcmp(arg[1],"mol") == 0) thresh_array[nthresh] = MOL;
else if (strcmp(arg[1],"type") == 0) thresh_array[nthresh] = TYPE;
else if (strcmp(arg[1],"mass") == 0) thresh_array[nthresh] = MASS;
else if (strcmp(arg[1],"x") == 0) thresh_array[nthresh] = X;
else if (strcmp(arg[1],"y") == 0) thresh_array[nthresh] = Y;
else if (strcmp(arg[1],"z") == 0) thresh_array[nthresh] = Z;
else if (strcmp(arg[1],"xs") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = XS;
else if (strcmp(arg[1],"xs") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = XSTRI;
else if (strcmp(arg[1],"ys") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = YS;
else if (strcmp(arg[1],"ys") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = YSTRI;
else if (strcmp(arg[1],"zs") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = ZS;
else if (strcmp(arg[1],"zs") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = ZSTRI;
else if (strcmp(arg[1],"xu") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = XU;
else if (strcmp(arg[1],"xu") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = XUTRI;
else if (strcmp(arg[1],"yu") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = YU;
else if (strcmp(arg[1],"yu") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = YUTRI;
else if (strcmp(arg[1],"zu") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = ZU;
else if (strcmp(arg[1],"zu") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = ZUTRI;
else if (strcmp(arg[1],"xsu") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = XSU;
else if (strcmp(arg[1],"xsu") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = XSUTRI;
else if (strcmp(arg[1],"ysu") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = YSU;
else if (strcmp(arg[1],"ysu") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = YSUTRI;
else if (strcmp(arg[1],"zsu") == 0 && domain->triclinic == 0)
thresh_array[nthresh] = ZSU;
else if (strcmp(arg[1],"zsu") == 0 && domain->triclinic == 1)
thresh_array[nthresh] = ZSUTRI;
else if (strcmp(arg[1],"ix") == 0) thresh_array[nthresh] = IX;
else if (strcmp(arg[1],"iy") == 0) thresh_array[nthresh] = IY;
else if (strcmp(arg[1],"iz") == 0) thresh_array[nthresh] = IZ;
else if (strcmp(arg[1],"vx") == 0) thresh_array[nthresh] = VX;
else if (strcmp(arg[1],"vy") == 0) thresh_array[nthresh] = VY;
else if (strcmp(arg[1],"vz") == 0) thresh_array[nthresh] = VZ;
else if (strcmp(arg[1],"fx") == 0) thresh_array[nthresh] = FX;
else if (strcmp(arg[1],"fy") == 0) thresh_array[nthresh] = FY;
else if (strcmp(arg[1],"fz") == 0) thresh_array[nthresh] = FZ;
else if (strcmp(arg[1],"q") == 0) thresh_array[nthresh] = Q;
else if (strcmp(arg[1],"mux") == 0) thresh_array[nthresh] = MUX;
else if (strcmp(arg[1],"muy") == 0) thresh_array[nthresh] = MUY;
else if (strcmp(arg[1],"muz") == 0) thresh_array[nthresh] = MUZ;
else if (strcmp(arg[1],"mu") == 0) thresh_array[nthresh] = MU;
else if (strcmp(arg[1],"radius") == 0) thresh_array[nthresh] = RADIUS;
else if (strcmp(arg[1],"diameter") == 0) thresh_array[nthresh] = DIAMETER;
else if (strcmp(arg[1],"omegax") == 0) thresh_array[nthresh] = OMEGAX;
else if (strcmp(arg[1],"omegay") == 0) thresh_array[nthresh] = OMEGAY;
else if (strcmp(arg[1],"omegaz") == 0) thresh_array[nthresh] = OMEGAZ;
else if (strcmp(arg[1],"angmomx") == 0) thresh_array[nthresh] = ANGMOMX;
else if (strcmp(arg[1],"angmomy") == 0) thresh_array[nthresh] = ANGMOMY;
else if (strcmp(arg[1],"angmomz") == 0) thresh_array[nthresh] = ANGMOMZ;
else if (strcmp(arg[1],"tqx") == 0) thresh_array[nthresh] = TQX;
else if (strcmp(arg[1],"tqy") == 0) thresh_array[nthresh] = TQY;
else if (strcmp(arg[1],"tqz") == 0) thresh_array[nthresh] = TQZ;
else if (strcmp(arg[1],"spin") == 0) thresh_array[nthresh] = SPIN;
else if (strcmp(arg[1],"eradius") == 0) thresh_array[nthresh] = ERADIUS;
else if (strcmp(arg[1],"ervel") == 0) thresh_array[nthresh] = ERVEL;
else if (strcmp(arg[1],"erforce") == 0) thresh_array[nthresh] = ERFORCE;
// compute value = c_ID
// if no trailing [], then arg is set to 0, else arg is between []
// must grow field2index and argindex arrays, since access is beyond nfield
else if (strncmp(arg[1],"c_",2) == 0) {
thresh_array[nthresh] = COMPUTE;
memory->grow(field2index,nfield+nthresh+1,"dump:field2index");
memory->grow(argindex,nfield+nthresh+1,"dump:argindex");
int n = strlen(arg[1]);
char *suffix = new char[n];
strcpy(suffix,&arg[1][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Invalid attribute in dump modify command");
+ error->all(FLERR,"Invalid attribute in dump modify command");
argindex[nfield+nthresh] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nfield+nthresh] = 0;
n = modify->find_compute(suffix);
- if (n < 0) error->all("Could not find dump modify compute ID");
+ if (n < 0) error->all(FLERR,"Could not find dump modify compute ID");
if (modify->compute[n]->peratom_flag == 0)
- error->all("Dump modify compute ID does not compute per-atom info");
+ error->all(FLERR,"Dump modify compute ID does not compute per-atom info");
if (argindex[nfield+nthresh] == 0 &&
modify->compute[n]->size_peratom_cols > 0)
- error->all("Dump modify compute ID does not compute per-atom vector");
+ error->all(FLERR,"Dump modify compute ID does not compute per-atom vector");
if (argindex[nfield+nthresh] > 0 &&
modify->compute[n]->size_peratom_cols == 0)
- error->all("Dump modify compute ID does not compute per-atom array");
+ error->all(FLERR,"Dump modify compute ID does not compute per-atom array");
if (argindex[nfield+nthresh] > 0 &&
argindex[nfield+nthresh] > modify->compute[n]->size_peratom_cols)
- error->all("Dump modify compute ID vector is not large enough");
+ error->all(FLERR,"Dump modify compute ID vector is not large enough");
field2index[nfield+nthresh] = add_compute(suffix);
delete [] suffix;
// fix value = f_ID
// if no trailing [], then arg is set to 0, else arg is between []
// must grow field2index and argindex arrays, since access is beyond nfield
} else if (strncmp(arg[1],"f_",2) == 0) {
thresh_array[nthresh] = FIX;
memory->grow(field2index,nfield+nthresh+1,"dump:field2index");
memory->grow(argindex,nfield+nthresh+1,"dump:argindex");
int n = strlen(arg[1]);
char *suffix = new char[n];
strcpy(suffix,&arg[1][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Invalid attribute in dump modify command");
+ error->all(FLERR,"Invalid attribute in dump modify command");
argindex[nfield+nthresh] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nfield+nthresh] = 0;
n = modify->find_fix(suffix);
- if (n < 0) error->all("Could not find dump modify fix ID");
+ if (n < 0) error->all(FLERR,"Could not find dump modify fix ID");
if (modify->fix[n]->peratom_flag == 0)
- error->all("Dump modify fix ID does not compute per-atom info");
+ error->all(FLERR,"Dump modify fix ID does not compute per-atom info");
if (argindex[nfield+nthresh] == 0 &&
modify->fix[n]->size_peratom_cols > 0)
- error->all("Dump modify fix ID does not compute per-atom vector");
+ error->all(FLERR,"Dump modify fix ID does not compute per-atom vector");
if (argindex[nfield+nthresh] > 0 &&
modify->fix[n]->size_peratom_cols == 0)
- error->all("Dump modify fix ID does not compute per-atom array");
+ error->all(FLERR,"Dump modify fix ID does not compute per-atom array");
if (argindex[nfield+nthresh] > 0 &&
argindex[nfield+nthresh] > modify->fix[n]->size_peratom_cols)
- error->all("Dump modify fix ID vector is not large enough");
+ error->all(FLERR,"Dump modify fix ID vector is not large enough");
field2index[nfield+nthresh] = add_fix(suffix);
delete [] suffix;
// variable value = v_ID
// must grow field2index and argindex arrays, since access is beyond nfield
} else if (strncmp(arg[1],"v_",2) == 0) {
thresh_array[nthresh] = VARIABLE;
memory->grow(field2index,nfield+nthresh+1,"dump:field2index");
memory->grow(argindex,nfield+nthresh+1,"dump:argindex");
int n = strlen(arg[1]);
char *suffix = new char[n];
strcpy(suffix,&arg[1][2]);
argindex[nfield+nthresh] = 0;
n = input->variable->find(suffix);
- if (n < 0) error->all("Could not find dump modify variable name");
+ if (n < 0) error->all(FLERR,"Could not find dump modify variable name");
if (input->variable->atomstyle(n) == 0)
- error->all("Dump modify variable is not atom-style variable");
+ error->all(FLERR,"Dump modify variable is not atom-style variable");
field2index[nfield+nthresh] = add_variable(suffix);
delete [] suffix;
- } else error->all("Invalid dump_modify threshhold operator");
+ } else error->all(FLERR,"Invalid dump_modify threshhold operator");
// set operation type of threshhold
if (strcmp(arg[2],"<") == 0) thresh_op[nthresh] = LT;
else if (strcmp(arg[2],"<=") == 0) thresh_op[nthresh] = LE;
else if (strcmp(arg[2],">") == 0) thresh_op[nthresh] = GT;
else if (strcmp(arg[2],">=") == 0) thresh_op[nthresh] = GE;
else if (strcmp(arg[2],"==") == 0) thresh_op[nthresh] = EQ;
else if (strcmp(arg[2],"!=") == 0) thresh_op[nthresh] = NEQ;
- else error->all("Invalid dump_modify threshhold operator");
+ else error->all(FLERR,"Invalid dump_modify threshhold operator");
// set threshhold value
thresh_value[nthresh] = atof(arg[3]);
nthresh++;
return 4;
}
return 0;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory in buf, choose, variable arrays
------------------------------------------------------------------------- */
bigint DumpCustom::memory_usage()
{
bigint bytes = Dump::memory_usage();
bytes += memory->usage(choose,maxlocal);
bytes += memory->usage(dchoose,maxlocal);
bytes += memory->usage(clist,maxlocal);
bytes += memory->usage(vbuf,nvariable,maxlocal);
return bytes;
}
/* ----------------------------------------------------------------------
extraction of Compute, Fix, Variable results
------------------------------------------------------------------------- */
void DumpCustom::pack_compute(int n)
{
double *vector = compute[field2index[n]]->vector_atom;
double **array = compute[field2index[n]]->array_atom;
int index = argindex[n];
if (index == 0) {
for (int i = 0; i < nchoose; i++) {
buf[n] = vector[clist[i]];
n += size_one;
}
} else {
index--;
for (int i = 0; i < nchoose; i++) {
buf[n] = array[clist[i]][index];
n += size_one;
}
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_fix(int n)
{
double *vector = fix[field2index[n]]->vector_atom;
double **array = fix[field2index[n]]->array_atom;
int index = argindex[n];
if (index == 0) {
for (int i = 0; i < nchoose; i++) {
buf[n] = vector[clist[i]];
n += size_one;
}
} else {
index--;
for (int i = 0; i < nchoose; i++) {
buf[n] = array[clist[i]][index];
n += size_one;
}
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_variable(int n)
{
double *vector = vbuf[field2index[n]];
for (int i = 0; i < nchoose; i++) {
buf[n] = vector[clist[i]];
n += size_one;
}
}
/* ----------------------------------------------------------------------
one method for every attribute dump custom can output
the atom property is packed into buf starting at n with stride size_one
customize a new attribute by adding a method
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_id(int n)
{
int *tag = atom->tag;
for (int i = 0; i < nchoose; i++) {
buf[n] = tag[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_molecule(int n)
{
int *molecule = atom->molecule;
for (int i = 0; i < nchoose; i++) {
buf[n] = molecule[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_type(int n)
{
int *type = atom->type;
for (int i = 0; i < nchoose; i++) {
buf[n] = type[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_mass(int n)
{
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
if (rmass) {
for (int i = 0; i < nchoose; i++) {
buf[n] = rmass[clist[i]];
n += size_one;
}
} else {
for (int i = 0; i < nchoose; i++) {
buf[n] = mass[type[clist[i]]];
n += size_one;
}
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_x(int n)
{
double **x = atom->x;
for (int i = 0; i < nchoose; i++) {
buf[n] = x[clist[i]][0];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_y(int n)
{
double **x = atom->x;
for (int i = 0; i < nchoose; i++) {
buf[n] = x[clist[i]][1];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_z(int n)
{
double **x = atom->x;
for (int i = 0; i < nchoose; i++) {
buf[n] = x[clist[i]][2];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_xs(int n)
{
double **x = atom->x;
double boxxlo = domain->boxlo[0];
double invxprd = 1.0/domain->xprd;
for (int i = 0; i < nchoose; i++) {
buf[n] = (x[clist[i]][0] - boxxlo) * invxprd;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_ys(int n)
{
double **x = atom->x;
double boxylo = domain->boxlo[1];
double invyprd = 1.0/domain->yprd;
for (int i = 0; i < nchoose; i++) {
buf[n] = (x[clist[i]][1] - boxylo) * invyprd;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_zs(int n)
{
double **x = atom->x;
double boxzlo = domain->boxlo[2];
double invzprd = 1.0/domain->zprd;
for (int i = 0; i < nchoose; i++) {
buf[n] = (x[clist[i]][2] - boxzlo) * invzprd;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_xs_triclinic(int n)
{
int j;
double **x = atom->x;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = h_inv[0]*(x[j][0]-boxlo[0]) + h_inv[5]*(x[j][1]-boxlo[1]) +
h_inv[4]*(x[j][2]-boxlo[2]);
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_ys_triclinic(int n)
{
int j;
double **x = atom->x;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = h_inv[1]*(x[j][1]-boxlo[1]) + h_inv[3]*(x[j][2]-boxlo[2]);
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_zs_triclinic(int n)
{
double **x = atom->x;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nchoose; i++) {
buf[n] = h_inv[2]*(x[clist[i]][2]-boxlo[2]);
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_xu(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double xprd = domain->xprd;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = x[j][0] + ((image[j] & 1023) - 512) * xprd;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_yu(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double yprd = domain->yprd;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = x[j][1] + ((image[j] >> 10 & 1023) - 512) * yprd;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_zu(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double zprd = domain->zprd;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = x[j][2] + ((image[j] >> 20) - 512) * zprd;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_xu_triclinic(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double *h = domain->h;
int xbox,ybox,zbox;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
xbox = (image[j] & 1023) - 512;
ybox = (image[j] >> 10 & 1023) - 512;
zbox = (image[j] >> 20) - 512;
buf[n] = x[j][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_yu_triclinic(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double *h = domain->h;
int ybox,zbox;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
ybox = (image[j] >> 10 & 1023) - 512;
zbox = (image[j] >> 20) - 512;
buf[n] = x[j][1] + h[1]*ybox + h[3]*zbox;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_zu_triclinic(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double *h = domain->h;
int zbox;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
zbox = (image[j] >> 20) - 512;
buf[n] = x[j][2] + h[2]*zbox;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_xsu(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double boxxlo = domain->boxlo[0];
double invxprd = 1.0/domain->xprd;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = (x[j][0] - boxxlo) * invxprd + (image[j] & 1023) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_ysu(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double boxylo = domain->boxlo[1];
double invyprd = 1.0/domain->yprd;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = (x[j][1] - boxylo) * invyprd + (image[j] >> 10 & 1023) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_zsu(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double boxzlo = domain->boxlo[2];
double invzprd = 1.0/domain->zprd;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = (x[j][2] - boxzlo) * invzprd + (image[j] >> 20) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_xsu_triclinic(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = h_inv[0]*(x[j][0]-boxlo[0]) + h_inv[5]*(x[j][1]-boxlo[1]) +
h_inv[4]*(x[j][2]-boxlo[2]) + (image[j] & 1023) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_ysu_triclinic(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = h_inv[1]*(x[j][1]-boxlo[1]) + h_inv[3]*(x[j][2]-boxlo[2]) +
(image[j] >> 10 & 1023) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_zsu_triclinic(int n)
{
int j;
double **x = atom->x;
int *image = atom->image;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nchoose; i++) {
j = clist[i];
buf[n] = h_inv[2]*(x[j][2]-boxlo[2]) + (image[j] >> 20) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_ix(int n)
{
int *image = atom->image;
for (int i = 0; i < nchoose; i++) {
buf[n] = (image[clist[i]] & 1023) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_iy(int n)
{
int *image = atom->image;
for (int i = 0; i < nchoose; i++) {
buf[n] = (image[clist[i]] >> 10 & 1023) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_iz(int n)
{
int *image = atom->image;
for (int i = 0; i < nchoose; i++) {
buf[n] = (image[clist[i]] >> 20) - 512;
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_vx(int n)
{
double **v = atom->v;
for (int i = 0; i < nchoose; i++) {
buf[n] = v[clist[i]][0];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_vy(int n)
{
double **v = atom->v;
for (int i = 0; i < nchoose; i++) {
buf[n] = v[clist[i]][1];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_vz(int n)
{
double **v = atom->v;
for (int i = 0; i < nchoose; i++) {
buf[n] = v[clist[i]][2];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_fx(int n)
{
double **f = atom->f;
for (int i = 0; i < nchoose; i++) {
buf[n] = f[clist[i]][0];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_fy(int n)
{
double **f = atom->f;
for (int i = 0; i < nchoose; i++) {
buf[n] = f[clist[i]][1];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_fz(int n)
{
double **f = atom->f;
for (int i = 0; i < nchoose; i++) {
buf[n] = f[clist[i]][2];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_q(int n)
{
double *q = atom->q;
for (int i = 0; i < nchoose; i++) {
buf[n] = q[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_mux(int n)
{
double **mu = atom->mu;
for (int i = 0; i < nchoose; i++) {
buf[n] = mu[clist[i]][0];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_muy(int n)
{
double **mu = atom->mu;
for (int i = 0; i < nchoose; i++) {
buf[n] = mu[clist[i]][1];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_muz(int n)
{
double **mu = atom->mu;
for (int i = 0; i < nchoose; i++) {
buf[n] = mu[clist[i]][2];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_mu(int n)
{
double **mu = atom->mu;
for (int i = 0; i < nchoose; i++) {
buf[n] = mu[clist[i]][3];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_radius(int n)
{
double *radius = atom->radius;
for (int i = 0; i < nchoose; i++) {
buf[n] = radius[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_diameter(int n)
{
double *radius = atom->radius;
for (int i = 0; i < nchoose; i++) {
buf[n] = 2.0*radius[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_omegax(int n)
{
double **omega = atom->omega;
for (int i = 0; i < nchoose; i++) {
buf[n] = omega[clist[i]][0];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_omegay(int n)
{
double **omega = atom->omega;
for (int i = 0; i < nchoose; i++) {
buf[n] = omega[clist[i]][1];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_omegaz(int n)
{
double **omega = atom->omega;
for (int i = 0; i < nchoose; i++) {
buf[n] = omega[clist[i]][2];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_angmomx(int n)
{
double **angmom = atom->angmom;
for (int i = 0; i < nchoose; i++) {
buf[n] = angmom[clist[i]][0];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_angmomy(int n)
{
double **angmom = atom->angmom;
for (int i = 0; i < nchoose; i++) {
buf[n] = angmom[clist[i]][1];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_angmomz(int n)
{
double **angmom = atom->angmom;
for (int i = 0; i < nchoose; i++) {
buf[n] = angmom[clist[i]][2];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_tqx(int n)
{
double **torque = atom->torque;
for (int i = 0; i < nchoose; i++) {
buf[n] = torque[clist[i]][0];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_tqy(int n)
{
double **torque = atom->torque;
for (int i = 0; i < nchoose; i++) {
buf[n] = torque[clist[i]][1];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_tqz(int n)
{
double **torque = atom->torque;
for (int i = 0; i < nchoose; i++) {
buf[n] = torque[clist[i]][2];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_spin(int n)
{
int *spin = atom->spin;
for (int i = 0; i < nchoose; i++) {
buf[n] = spin[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_eradius(int n)
{
double *eradius = atom->eradius;
for (int i = 0; i < nchoose; i++) {
buf[n] = eradius[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_ervel(int n)
{
double *ervel = atom->ervel;
for (int i = 0; i < nchoose; i++) {
buf[n] = ervel[clist[i]];
n += size_one;
}
}
/* ---------------------------------------------------------------------- */
void DumpCustom::pack_erforce(int n)
{
double *erforce = atom->erforce;
for (int i = 0; i < nchoose; i++) {
buf[n] = erforce[clist[i]];
n += size_one;
}
}
diff --git a/src/dump_dcd.cpp b/src/dump_dcd.cpp
index d00c1cc5b..a9d048f8d 100644
--- a/src/dump_dcd.cpp
+++ b/src/dump_dcd.cpp
@@ -1,371 +1,371 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Naveen Michaud-Agrawal (Johns Hopkins U)
Axel Kohlmeyer (Temple U), support for groups
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "inttypes.h"
#include "stdio.h"
#include "time.h"
#include "string.h"
#include "dump_dcd.h"
#include "domain.h"
#include "atom.h"
#include "update.h"
#include "output.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define NFILE_POS 8L
#define NSTEP_POS 20L
// necessary to set SEEK params b/c MPI-2 messes with these settings
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
/* ---------------------------------------------------------------------- */
static inline void fwrite_int32(FILE* fd, uint32_t i)
{
fwrite(&i,sizeof(uint32_t),1,fd);
}
/* ---------------------------------------------------------------------- */
DumpDCD::DumpDCD(LAMMPS *lmp, int narg, char **arg) : Dump(lmp, narg, arg)
{
- if (narg != 5) error->all("Illegal dump dcd command");
+ if (narg != 5) error->all(FLERR,"Illegal dump dcd command");
if (binary || compressed || multifile || multiproc)
- error->all("Invalid dump dcd filename");
+ error->all(FLERR,"Invalid dump dcd filename");
size_one = 3;
sort_flag = 1;
sortcol = 0;
unwrap_flag = 0;
format_default = NULL;
// allocate global array for atom coords
bigint n = group->count(igroup);
- if (n > MAXSMALLINT/sizeof(float)) error->all("Too many atoms for dump dcd");
+ if (n > MAXSMALLINT/sizeof(float)) error->all(FLERR,"Too many atoms for dump dcd");
natoms = static_cast<int> (n);
memory->create(coords,3*natoms,"dump:coords");
xf = &coords[0*natoms];
yf = &coords[1*natoms];
zf = &coords[2*natoms];
openfile();
headerflag = 0;
nevery_save = 0;
ntotal = 0;
}
/* ---------------------------------------------------------------------- */
DumpDCD::~DumpDCD()
{
memory->destroy(coords);
}
/* ---------------------------------------------------------------------- */
void DumpDCD::init_style()
{
if (sort_flag == 0 || sortcol != 0)
- error->all("Dump dcd requires sorting by atom ID");
+ error->all(FLERR,"Dump dcd requires sorting by atom ID");
// check that dump frequency has not changed and is not a variable
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
if (output->every_dump[idump] == 0)
- error->all("Cannot use variable every setting for dump dcd");
+ error->all(FLERR,"Cannot use variable every setting for dump dcd");
if (nevery_save == 0) nevery_save = output->every_dump[idump];
else if (nevery_save != output->every_dump[idump])
- error->all("Cannot change dump_modify every for dump dcd");
+ error->all(FLERR,"Cannot change dump_modify every for dump dcd");
}
/* ---------------------------------------------------------------------- */
void DumpDCD::openfile()
{
if (me == 0) {
fp = fopen(filename,"wb");
- if (fp == NULL) error->one("Cannot open dump file");
+ if (fp == NULL) error->one(FLERR,"Cannot open dump file");
}
}
/* ---------------------------------------------------------------------- */
void DumpDCD::write_header(bigint n)
{
- if (n != natoms) error->all("Dump dcd of non-matching # of atoms");
+ if (n != natoms) error->all(FLERR,"Dump dcd of non-matching # of atoms");
if (update->ntimestep > MAXSMALLINT)
- error->all("Too big a timestep for dump dcd");
+ error->all(FLERR,"Too big a timestep for dump dcd");
// first time, write header for entire file
if (headerflag == 0) {
if (me == 0) write_dcd_header("Written by LAMMPS");
headerflag = 1;
nframes = 0;
}
// dim[] = size and angle cosines of orthogonal or triclinic box
// dim[0] = a = length of unit cell vector along x-axis
// dim[1] = gamma = cosine of angle between a and b
// dim[2] = b = length of unit cell vector in xy-plane
// dim[3] = beta = cosine of angle between a and c
// dim[4] = alpha = cosine of angle between b and c
// dim[5] = c = length of final unit cell vector
// 48 = 6 doubles
double dim[6];
if (domain->triclinic) {
double *h = domain->h;
double alen = h[0];
double blen = sqrt(h[5]*h[5] + h[1]*h[1]);
double clen = sqrt(h[4]*h[4] + h[3]*h[3] + h[2]*h[2]);
dim[0] = alen;
dim[2] = blen;
dim[5] = clen;
dim[4] = (h[5]*h[4] + h[1]*h[3]) / blen/clen; // alpha
dim[3] = (h[0]*h[4]) / alen/clen; // beta
dim[1] = (h[0]*h[5]) / alen/blen; // gamma
} else {
dim[0] = domain->xprd;
dim[2] = domain->yprd;
dim[5] = domain->zprd;
dim[1] = dim[3] = dim[4] = 0.0;
}
if (me == 0) {
uint32_t out_integer = 48;
fwrite_int32(fp,out_integer);
fwrite(dim,out_integer,1,fp);
fwrite_int32(fp,out_integer);
if (flush_flag) fflush(fp);
}
}
/* ---------------------------------------------------------------------- */
int DumpDCD::count()
{
if (igroup == 0) return atom->nlocal;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) m++;
return m;
}
/* ---------------------------------------------------------------------- */
void DumpDCD::pack(int *ids)
{
int m,n;
int *tag = atom->tag;
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
m = n = 0;
if (unwrap_flag) {
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double xy = domain->xy;
double xz = domain->xz;
double yz = domain->yz;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
int ix = (image[i] & 1023) - 512;
int iy = (image[i] >> 10 & 1023) - 512;
int iz = (image[i] >> 20) - 512;
if (domain->triclinic) {
buf[m++] = x[i][0] + ix * xprd + iy * xy + iz * xz;
buf[m++] = x[i][1] + iy * yprd + iz * yz;
buf[m++] = x[i][2] + iz * zprd;
} else {
buf[m++] = x[i][0] + ix * xprd;
buf[m++] = x[i][1] + iy * yprd;
buf[m++] = x[i][2] + iz * zprd;
}
ids[n++] = tag[i];
}
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
ids[n++] = tag[i];
}
}
}
/* ---------------------------------------------------------------------- */
void DumpDCD::write_data(int n, double *mybuf)
{
// copy buf atom coords into 3 global arrays
int m = 0;
for (int i = 0; i < n; i++) {
xf[ntotal] = mybuf[m++];
yf[ntotal] = mybuf[m++];
zf[ntotal] = mybuf[m++];
ntotal++;
}
// if last chunk of atoms in this snapshot, write global arrays to file
if (ntotal == natoms) {
write_frame();
ntotal = 0;
}
}
/* ---------------------------------------------------------------------- */
int DumpDCD::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"unwrap") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1;
else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
return 2;
}
return 0;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory in buf and global coords array
------------------------------------------------------------------------- */
bigint DumpDCD::memory_usage()
{
bigint bytes = Dump::memory_usage();
bytes += memory->usage(coords,natoms*3);
return bytes;
}
/* ---------------------------------------------------------------------- */
void DumpDCD::write_frame()
{
// write coords
uint32_t out_integer = natoms*sizeof(float);
fwrite_int32(fp,out_integer);
fwrite(xf,out_integer,1,fp);
fwrite_int32(fp,out_integer);
fwrite_int32(fp,out_integer);
fwrite(yf,out_integer,1,fp);
fwrite_int32(fp,out_integer);
fwrite_int32(fp,out_integer);
fwrite(zf,out_integer,1,fp);
fwrite_int32(fp,out_integer);
// update NFILE and NSTEP fields in DCD header
nframes++;
out_integer = nframes;
fseek(fp,NFILE_POS,SEEK_SET);
fwrite_int32(fp,out_integer);
out_integer = update->ntimestep;
fseek(fp,NSTEP_POS,SEEK_SET);
fwrite_int32(fp,out_integer);
fseek(fp,0,SEEK_END);
}
/* ---------------------------------------------------------------------- */
void DumpDCD::write_dcd_header(const char *remarks)
{
uint32_t out_integer;
float out_float;
char title_string[200];
time_t cur_time;
struct tm *tmbuf;
int ntimestep = update->ntimestep;
out_integer = 84;
fwrite_int32(fp,out_integer);
strcpy(title_string,"CORD");
fwrite(title_string,4,1,fp);
fwrite_int32(fp,0); // NFILE = # of snapshots in file
fwrite_int32(fp,ntimestep); // START = timestep of first snapshot
fwrite_int32(fp,nevery_save); // SKIP = interval between snapshots
fwrite_int32(fp,ntimestep); // NSTEP = timestep of last snapshot
fwrite_int32(fp,0); // NAMD writes NSTEP or ISTART
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
out_float = update->dt;
fwrite(&out_float,sizeof(float),1,fp);
fwrite_int32(fp,1);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,0);
fwrite_int32(fp,24); // pretend to be Charmm version 24
fwrite_int32(fp,84);
fwrite_int32(fp,164);
fwrite_int32(fp,2);
strncpy(title_string,remarks,80);
title_string[79] = '\0';
fwrite(title_string,80,1,fp);
cur_time=time(NULL);
tmbuf=localtime(&cur_time);
memset(title_string,' ',81);
strftime(title_string,80,"REMARKS Created %d %B,%Y at %R",tmbuf);
fwrite(title_string,80,1,fp);
fwrite_int32(fp,164);
fwrite_int32(fp,4);
fwrite_int32(fp,natoms); // number of atoms in each snapshot
fwrite_int32(fp,4);
if (flush_flag) fflush(fp);
}
diff --git a/src/dump_image.cpp b/src/dump_image.cpp
index 717fb0a7f..25dc36109 100644
--- a/src/dump_image.cpp
+++ b/src/dump_image.cpp
@@ -1,2312 +1,2311 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Nathan Fabian (Sandia)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "ctype.h"
#include "stdlib.h"
#include "string.h"
#include "dump_image.h"
#include "math_extra.h"
#include "atom.h"
#include "domain.h"
#include "group.h"
#include "force.h"
#include "comm.h"
#include "input.h"
#include "variable.h"
#include "random_mars.h"
#include "error.h"
#include "memory.h"
#ifdef LAMMPS_JPEG
#include "jpeglib.h"
#endif
using namespace LAMMPS_NS;
#define NCOLORS 140
#define NELEMENTS 109
#define BIG 1.0e20
enum{PPM,JPG};
enum{NUMERIC,ATOM,TYPE,ELEMENT,ATTRIBUTE,MINVALUE,MAXVALUE};
enum{STATIC,DYNAMIC};
enum{CONTINUOUS,DISCRETE,SEQUENTIAL};
enum{ABSOLUTE,FRACTIONAL};
enum{NO,YES};
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
DumpCustom(lmp, narg, arg)
{
- if (binary || multiproc) error->all("Invalid dump image filename");
+ if (binary || multiproc) error->all(FLERR,"Invalid dump image filename");
PI = 4.0*atan(1.0);
// set filetype based on filename suffix
int n = strlen(filename);
if (strlen(filename) > 4 && strcmp(&filename[n-4],".jpg") == 0)
filetype = JPG;
else if (strlen(filename) > 5 && strcmp(&filename[n-5],".jpeg") == 0)
filetype = JPG;
else filetype = PPM;
#ifndef LAMMPS_JPEG
- if (filetype == JPG) error->all("Cannot dump JPG file");
+ if (filetype == JPG) error->all(FLERR,"Cannot dump JPG file");
#endif
// atom color,diameter settings
- if (nfield != 2) error->all("Illegal dump image command");
+ if (nfield != 2) error->all(FLERR,"Illegal dump image command");
acolor = ATTRIBUTE;
if (strcmp(arg[5],"type") == 0) acolor = TYPE;
else if (strcmp(arg[5],"element") == 0) acolor = ELEMENT;
adiam = ATTRIBUTE;
if (strcmp(arg[6],"type") == 0) adiam = TYPE;
else if (strcmp(arg[6],"element") == 0) adiam = ELEMENT;
// set defaults for optional args
atomflag = YES;
if (atom->nbondtypes == 0) bondflag = NO;
else {
bondflag = YES;
bcolor = ATOM;
bdiam = NUMERIC;
bdiamvalue = 0.5;
}
width = height = 512;
theta = 60.0 * PI/180.0;
phi = 30.0 * PI/180.0;
thetastr = phistr = NULL;
cflag = STATIC;
cx = cy = cz = 0.5;
cxstr = cystr = czstr = NULL;
if (domain->dimension == 3) {
up[0] = 0.0; up[1] = 0.0; up[2] = 1.0;
} else {
up[0] = 0.0; up[1] = 1.0; up[2] = 0.0;
}
upxstr = upystr = upzstr = NULL;
zoom = 1.0;
zoomstr = NULL;
persp = 0.0;
perspstr = NULL;
boxflag = YES;
boxdiam = 0.02;
axesflag = NO;
shiny = 1.0;
ssao = NO;
// parse optional args
int iarg = ioptional;
while (iarg < narg) {
if (strcmp(arg[iarg],"adiam") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump image command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
adiam = NUMERIC;
adiamvalue = atof(arg[iarg+1]);
- if (adiamvalue <= 0.0) error->all("Illegal dump image command");
+ if (adiamvalue <= 0.0) error->all(FLERR,"Illegal dump image command");
iarg += 2;
} else if (strcmp(arg[iarg],"atom") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump image command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
if (strcmp(arg[iarg+1],"yes") == 0) atomflag = YES;
else if (strcmp(arg[iarg+1],"no") == 0) atomflag = NO;
- else error->all("Illegal dump image command");
+ else error->all(FLERR,"Illegal dump image command");
iarg += 2;
} else if (strcmp(arg[iarg],"bond") == 0) {
- if (iarg+3 > narg) error->all("Illegal dump image command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
if (atom->nbondtypes == 0)
- error->all("Dump image bond not allowed with no bond types");
+ error->all(FLERR,"Dump image bond not allowed with no bond types");
bondflag = YES;
if (strcmp(arg[iarg+1],"none") == 0) bondflag = NO;
else if (strcmp(arg[iarg+1],"atom") == 0) bcolor = ATOM;
else if (strcmp(arg[iarg+1],"type") == 0) bcolor = TYPE;
- else error->all("Illegal dump image command");
+ else error->all(FLERR,"Illegal dump image command");
if (!islower(arg[iarg+2][0])) {
bdiam = NUMERIC;
bdiamvalue = atof(arg[iarg+2]);
- if (bdiamvalue <= 0.0) error->all("Illegal dump image command");
+ if (bdiamvalue <= 0.0) error->all(FLERR,"Illegal dump image command");
} else if (strcmp(arg[iarg+2],"atom") == 0) bdiam = ATOM;
else if (strcmp(arg[iarg+2],"type") == 0) bdiam = TYPE;
else if (strcmp(arg[iarg+2],"none") == 0) bondflag = NO;
- else error->all("Illegal dump image command");
+ else error->all(FLERR,"Illegal dump image command");
iarg += 3;
} else if (strcmp(arg[iarg],"size") == 0) {
- if (iarg+3 > narg) error->all("Illegal dump image command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
width = atoi(arg[iarg+1]);
height = atoi(arg[iarg+2]);
- if (width <= 0 || height <= 0) error->all("Illegal dump image command");
+ if (width <= 0 || height <= 0) error->all(FLERR,"Illegal dump image command");
iarg += 3;
} else if (strcmp(arg[iarg],"view") == 0) {
- if (iarg+3 > narg) error->all("Illegal dump image command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
thetastr = new char[n];
strcpy(thetastr,&arg[iarg+1][2]);
} else {
theta = atof(arg[iarg+1]);
if (theta < 0.0 || theta > 180.0)
- error->all("Invalid dump image theta value");
+ error->all(FLERR,"Invalid dump image theta value");
theta *= PI/180.0;
}
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
phistr = new char[n];
strcpy(phistr,&arg[iarg+2][2]);
} else {
phi = atof(arg[iarg+2]);
phi *= PI/180.0;
}
iarg += 3;
} else if (strcmp(arg[iarg],"center") == 0) {
- if (iarg+5 > narg) error->all("Illegal dump image command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal dump image command");
if (strcmp(arg[iarg+1],"s") == 0) cflag = STATIC;
else if (strcmp(arg[iarg+1],"d") == 0) cflag = DYNAMIC;
- else error->all("Illegal dump image command");
+ else error->all(FLERR,"Illegal dump image command");
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
cxstr = new char[n];
strcpy(cxstr,&arg[iarg+2][2]);
cflag = DYNAMIC;
} else cx = atof(arg[iarg+2]);
if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) {
int n = strlen(&arg[iarg+3][2]) + 1;
cystr = new char[n];
strcpy(cystr,&arg[iarg+3][2]);
cflag = DYNAMIC;
} else cy = atof(arg[iarg+3]);
if (strstr(arg[iarg+4],"v_") == arg[iarg+4]) {
int n = strlen(&arg[iarg+4][2]) + 1;
czstr = new char[n];
strcpy(czstr,&arg[iarg+4][2]);
cflag = DYNAMIC;
} else cz = atof(arg[iarg+4]);
iarg += 5;
} else if (strcmp(arg[iarg],"up") == 0) {
- if (iarg+4 > narg) error->all("Illegal dump image command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
upxstr = new char[n];
strcpy(upxstr,&arg[iarg+1][2]);
} else up[0] = atof(arg[iarg+1]);
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
upystr = new char[n];
strcpy(upystr,&arg[iarg+2][2]);
} else up[1] = atof(arg[iarg+1]);
if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) {
int n = strlen(&arg[iarg+3][2]) + 1;
upzstr = new char[n];
strcpy(upzstr,&arg[iarg+3][2]);
} else up[2] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"zoom") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump image command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
zoomstr = new char[n];
strcpy(zoomstr,&arg[iarg+1][2]);
} else {
zoom = atof(arg[iarg+1]);
- if (zoom <= 0.0) error->all("Illegal dump image command");
+ if (zoom <= 0.0) error->all(FLERR,"Illegal dump image command");
}
iarg += 2;
} else if (strcmp(arg[iarg],"persp") == 0) {
- error->all("Dump image persp option is not yet supported");
- if (iarg+2 > narg) error->all("Illegal dump image command");
+ error->all(FLERR,"Dump image persp option is not yet supported");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
perspstr = new char[n];
strcpy(perspstr,&arg[iarg+1][2]);
} else {
persp = atof(arg[iarg+1]);
- if (persp < 0.0) error->all("Illegal dump image command");
+ if (persp < 0.0) error->all(FLERR,"Illegal dump image command");
}
iarg += 2;
} else if (strcmp(arg[iarg],"box") == 0) {
- if (iarg+3 > narg) error->all("Illegal dump image command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
if (strcmp(arg[iarg+1],"yes") == 0) boxflag = YES;
else if (strcmp(arg[iarg+1],"no") == 0) boxflag = NO;
- else error->all("Illegal dump image command");
+ else error->all(FLERR,"Illegal dump image command");
boxdiam = atof(arg[iarg+2]);
- if (boxdiam < 0.0) error->all("Illegal dump image command");
+ if (boxdiam < 0.0) error->all(FLERR,"Illegal dump image command");
iarg += 3;
} else if (strcmp(arg[iarg],"axes") == 0) {
- if (iarg+3 > narg) error->all("Illegal dump image command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
if (strcmp(arg[iarg+1],"yes") == 0) axesflag = YES;
else if (strcmp(arg[iarg+1],"no") == 0) axesflag = NO;
- else error->all("Illegal dump image command");
+ else error->all(FLERR,"Illegal dump image command");
axeslen = atof(arg[iarg+2]);
axesdiam = atof(arg[iarg+3]);
if (axeslen < 0.0 || axesdiam < 0.0)
- error->all("Illegal dump image command");
+ error->all(FLERR,"Illegal dump image command");
iarg += 4;
} else if (strcmp(arg[iarg],"shiny") == 0) {
- if (iarg+2 > narg) error->all("Illegal dump image command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
shiny = atof(arg[iarg+1]);
if (shiny < 0.0 || shiny > 1.0)
- error->all("Illegal dump image command");
+ error->all(FLERR,"Illegal dump image command");
iarg += 2;
} else if (strcmp(arg[iarg],"ssao") == 0) {
- if (iarg+4 > narg) error->all("Illegal dump image command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
if (strcmp(arg[iarg+1],"yes") == 0) ssao = YES;
else if (strcmp(arg[iarg+1],"no") == 0) ssao = NO;
- else error->all("Illegal dump image command");
+ else error->all(FLERR,"Illegal dump image command");
seed = atoi(arg[iarg+2]);
- if (seed <= 0) error->all("Illegal dump image command");
+ if (seed <= 0) error->all(FLERR,"Illegal dump image command");
ssaoint = atof(arg[iarg+3]);
if (ssaoint < 0.0 || ssaoint > 1.0)
- error->all("Illegal dump image command");
+ error->all(FLERR,"Illegal dump image command");
iarg += 4;
- } else error->all("Illegal dump image command");
+ } else error->all(FLERR,"Illegal dump image command");
}
// params based on args
npixels = width * height;
if (bondflag) {
if (bcolor == ATOM || bdiam == ATOM) comm_forward = 3;
else comm_forward = 1;
}
// additional defaults for dump_modify options
ncolors = 0;
username = NULL;
userrgb = NULL;
diamtype = new double[ntypes+1];
diamelement = new double[ntypes+1];
colortype = new double*[ntypes+1];
colorelement = new double*[ntypes+1];
for (int i = 1; i <= ntypes; i++) {
diamtype[i] = 1.0;
if (i % 6 == 1) colortype[i] = color2rgb("red");
else if (i % 6 == 2) colortype[i] = color2rgb("green");
else if (i % 6 == 3) colortype[i] = color2rgb("blue");
else if (i % 6 == 4) colortype[i] = color2rgb("yellow");
else if (i % 6 == 5) colortype[i] = color2rgb("aqua");
else if (i % 6 == 0) colortype[i] = color2rgb("cyan");
}
if (bondflag) {
bdiamtype = new double[atom->nbondtypes+1];
bcolortype = new double*[atom->nbondtypes+1];
for (int i = 1; i <= atom->nbondtypes; i++) {
bdiamtype[i] = 0.5;
if (i % 6 == 1) bcolortype[i] = color2rgb("red");
else if (i % 6 == 2) bcolortype[i] = color2rgb("green");
else if (i % 6 == 3) bcolortype[i] = color2rgb("blue");
else if (i % 6 == 4) bcolortype[i] = color2rgb("yellow");
else if (i % 6 == 5) bcolortype[i] = color2rgb("aqua");
else if (i % 6 == 0) bcolortype[i] = color2rgb("cyan");
}
} else {
bdiamtype = NULL;
bcolortype = NULL;
}
boxcolor = color2rgb("yellow");
background[0] = background[1] = background[2] = 0;
mlo = MINVALUE;
mhi = MAXVALUE;
mstyle = CONTINUOUS;
mrange = FRACTIONAL;
nentry = 2;
mentry = new MapEntry[nentry];
mentry[0].svalue = 0.0;
mentry[0].color = color2rgb("blue");
mentry[1].svalue = 1.0;
mentry[1].color = color2rgb("red");
// static parameters
FOV = PI/6.0; // 30 degrees
ambientColor[0] = 0.0;
ambientColor[1] = 0.0;
ambientColor[2] = 0.0;
keyLightPhi = -PI/4.0; // -45 degrees
keyLightTheta = PI/6.0; // 30 degrees
keyLightColor[0] = 0.9;
keyLightColor[1] = 0.9;
keyLightColor[2] = 0.9;
fillLightPhi = PI/6.0; // 30 degrees
fillLightTheta = 0;
- fillLightColor[0] = 0.9;
- fillLightColor[1] = 0.9;
- fillLightColor[2] = 0.9;
+ fillLightColor[0] = 0.45;
+ fillLightColor[1] = 0.45;
+ fillLightColor[2] = 0.45;
backLightPhi = PI; // 180 degrees
backLightTheta = PI/12.0; // 15 degrees
backLightColor[0] = 0.9;
backLightColor[1] = 0.9;
backLightColor[2] = 0.9;
// viewflag = DYNAMIC if any view parameter is dynamic
viewflag = STATIC;
if (thetastr || phistr || cflag == DYNAMIC ||
upxstr || upystr || upzstr || zoomstr || perspstr) viewflag = DYNAMIC;
if (cflag == STATIC) box_center();
if (viewflag == STATIC) view_params();
// image and depth buffers
depthBuffer = (double *) memory->smalloc(npixels*sizeof(double),
"dump:depthBuffer");
surfaceBuffer = (double *) memory->smalloc(2*npixels*sizeof(double),
"dump:surfaceBuffer");
imageBuffer = (char *) memory->smalloc(3*npixels*sizeof(char),
"dump:imageBuffer");
depthcopy = (double *) memory->smalloc(npixels*sizeof(double),
"dump:depthcopy");
surfacecopy = (double *) memory->smalloc(npixels*2*sizeof(double),
"dump:surfacecopy");
rgbcopy = (char *) memory->smalloc(3*npixels*sizeof(char),
"dump:rgbcopy");
maxbufcopy = 0;
bufcopy = NULL;
// RNG for SSAO depth shading
if (ssao) random = new RanMars(lmp,seed+me);
else random = NULL;
}
/* ---------------------------------------------------------------------- */
DumpImage::~DumpImage()
{
delete [] diamtype;
delete [] diamelement;
delete [] colortype;
delete [] colorelement;
delete [] bdiamtype;
delete [] bcolortype;
for (int i = 0; i < ncolors; i++) delete [] username[i];
memory->sfree(username);
memory->destroy(userrgb);
delete [] mentry;
memory->sfree(depthBuffer);
memory->sfree(surfaceBuffer);
memory->sfree(imageBuffer);
memory->sfree(depthcopy);
memory->sfree(surfacecopy);
memory->sfree(rgbcopy);
memory->destroy(bufcopy);
delete random;
}
/* ---------------------------------------------------------------------- */
void DumpImage::init_style()
{
- if (multifile == 0) error->all("Dump image requires one snapshot per file");
- if (sort_flag) error->all("Dump image cannot perform sorting");
+ if (multifile == 0) error->all(FLERR,"Dump image requires one snapshot per file");
+ if (sort_flag) error->all(FLERR,"Dump image cannot perform sorting");
DumpCustom::init_style();
// check variables
if (thetastr) {
thetavar = input->variable->find(thetastr);
if (thetavar < 0)
- error->all("Variable name for dump image theta does not exist");
+ error->all(FLERR,"Variable name for dump image theta does not exist");
if (!input->variable->equalstyle(thetavar))
- error->all("Variable for dump image theta is invalid style");
+ error->all(FLERR,"Variable for dump image theta is invalid style");
}
if (phistr) {
phivar = input->variable->find(phistr);
if (phivar < 0)
- error->all("Variable name for dump image phi does not exist");
+ error->all(FLERR,"Variable name for dump image phi does not exist");
if (!input->variable->equalstyle(phivar))
- error->all("Variable for dump image phi is invalid style");
+ error->all(FLERR,"Variable for dump image phi is invalid style");
}
if (cxstr) {
cxvar = input->variable->find(cxstr);
if (cxvar < 0)
- error->all("Variable name for dump image center does not exist");
+ error->all(FLERR,"Variable name for dump image center does not exist");
if (!input->variable->equalstyle(cxvar))
- error->all("Variable for dump image center is invalid style");
+ error->all(FLERR,"Variable for dump image center is invalid style");
}
if (cystr) {
cyvar = input->variable->find(cystr);
if (cyvar < 0)
- error->all("Variable name for dump image center does not exist");
+ error->all(FLERR,"Variable name for dump image center does not exist");
if (!input->variable->equalstyle(cyvar))
- error->all("Variable for dump image center is invalid style");
+ error->all(FLERR,"Variable for dump image center is invalid style");
}
if (czstr) {
czvar = input->variable->find(czstr);
if (czvar < 0)
- error->all("Variable name for dump image center does not exist");
+ error->all(FLERR,"Variable name for dump image center does not exist");
if (!input->variable->equalstyle(czvar))
- error->all("Variable for dump image center is invalid style");
+ error->all(FLERR,"Variable for dump image center is invalid style");
}
if (upxstr) {
upxvar = input->variable->find(upxstr);
if (upxvar < 0)
- error->all("Variable name for dump image center does not exist");
+ error->all(FLERR,"Variable name for dump image center does not exist");
if (!input->variable->equalstyle(upxvar))
- error->all("Variable for dump image center is invalid style");
+ error->all(FLERR,"Variable for dump image center is invalid style");
}
if (upystr) {
upyvar = input->variable->find(upystr);
if (upyvar < 0)
- error->all("Variable name for dump image center does not exist");
+ error->all(FLERR,"Variable name for dump image center does not exist");
if (!input->variable->equalstyle(upyvar))
- error->all("Variable for dump image center is invalid style");
+ error->all(FLERR,"Variable for dump image center is invalid style");
}
if (upzstr) {
upzvar = input->variable->find(upzstr);
if (upzvar < 0)
- error->all("Variable name for dump image center does not exist");
+ error->all(FLERR,"Variable name for dump image center does not exist");
if (!input->variable->equalstyle(upzvar))
- error->all("Variable for dump image center is invalid style");
+ error->all(FLERR,"Variable for dump image center is invalid style");
}
if (zoomstr) {
zoomvar = input->variable->find(zoomstr);
if (zoomvar < 0)
- error->all("Variable name for dump image zoom does not exist");
+ error->all(FLERR,"Variable name for dump image zoom does not exist");
if (!input->variable->equalstyle(zoomvar))
- error->all("Variable for dump image zoom is invalid style");
+ error->all(FLERR,"Variable for dump image zoom is invalid style");
}
if (perspstr) {
perspvar = input->variable->find(perspstr);
if (perspvar < 0)
- error->all("Variable name for dump image persp does not exist");
+ error->all(FLERR,"Variable name for dump image persp does not exist");
if (!input->variable->equalstyle(perspvar))
- error->all("Variable for dump image persp is invalid style");
+ error->all(FLERR,"Variable for dump image persp is invalid style");
}
// set up type -> element mapping
if (atomflag && acolor == ELEMENT) {
for (int i = 1; i <= ntypes; i++) {
colorelement[i] = element2color(typenames[i]);
if (colorelement[i] == NULL)
- error->all("Invalid dump image element name");
+ error->all(FLERR,"Invalid dump image element name");
}
}
if (atomflag && adiam == ELEMENT) {
for (int i = 1; i <= ntypes; i++) {
diamelement[i] = element2diam(typenames[i]);
if (diamelement[i] == 0.0)
- error->all("Invalid dump image element name");
+ error->all(FLERR,"Invalid dump image element name");
}
}
}
/* ---------------------------------------------------------------------- */
void DumpImage::write()
{
MPI_Request requests[3];
MPI_Status statuses[3];
// open new file
openfile();
// reset box center and view parameters if dynamic
if (cflag == DYNAMIC) box_center();
if (viewflag == DYNAMIC) view_params();
// nme = # of atoms this proc will contribute to dump
// pack buf with x,y,z,color,diameter
// set minmax color range if using color map
// create my portion of image for my particles
nme = count();
if (nme > maxbuf) {
maxbuf = nme;
memory->destroy(buf);
memory->create(buf,maxbuf*size_one,"dump:buf");
}
pack(NULL);
if (acolor == ATTRIBUTE) color_minmax();
create_image();
// merge images across procs using depth buffer
// hi procs send to lo procs, cascading down logarithmically
int nhalf = 1;
while (nhalf < nprocs) nhalf *= 2;
nhalf /= 2;
while (nhalf) {
if (me < nhalf && me+nhalf < nprocs) {
MPI_Irecv(rgbcopy,npixels*3,MPI_BYTE,me+nhalf,0,world,&requests[0]);
MPI_Irecv(depthcopy,npixels,MPI_DOUBLE,me+nhalf,0,world,&requests[1]);
if (ssao)
MPI_Irecv(surfacecopy,npixels*2,MPI_DOUBLE,
me+nhalf,0,world,&requests[2]);
if (ssao) MPI_Waitall(3,requests,statuses);
else MPI_Waitall(2,requests,statuses);
for (int i = 0; i < npixels; i++) {
if (depthBuffer[i] < 0 || (depthcopy[i] >= 0 &&
depthcopy[i] < depthBuffer[i])) {
depthBuffer[i] = depthcopy[i];
imageBuffer[i*3+0] = rgbcopy[i*3+0];
imageBuffer[i*3+1] = rgbcopy[i*3+1];
imageBuffer[i*3+2] = rgbcopy[i*3+2];
if (ssao) {
surfaceBuffer[i*2+0] = surfacecopy[i*2+0];
surfaceBuffer[i*2+1] = surfacecopy[i*2+1];
}
}
}
} else if (me >= nhalf && me < 2*nhalf) {
MPI_Send(imageBuffer,npixels*3,MPI_BYTE,me-nhalf,0,world);
MPI_Send(depthBuffer,npixels,MPI_DOUBLE,me-nhalf,0,world);
if (ssao) MPI_Send(surfaceBuffer,npixels*2,MPI_DOUBLE,me-nhalf,0,world);
}
nhalf /= 2;
}
// extra SSAO enhancement
// bcast full image to all procs
// each works on subset of pixels
// gather result back to proc 0
if (ssao) {
MPI_Bcast(imageBuffer,npixels*3,MPI_BYTE,0,world);
MPI_Bcast(surfaceBuffer,npixels*2,MPI_DOUBLE,0,world);
MPI_Bcast(depthBuffer,npixels,MPI_DOUBLE,0,world);
compute_SSAO();
int pixelPart = height/nprocs * width*3;
MPI_Gather(imageBuffer+me*pixelPart,pixelPart,MPI_BYTE,
rgbcopy,pixelPart,MPI_BYTE,0,world);
writeBuffer = rgbcopy;
} else {
writeBuffer = imageBuffer;
}
// write image file
if (me == 0) {
if (filetype == JPG) write_JPG();
else write_PPM();
fclose(fp);
}
}
/* ----------------------------------------------------------------------
reset view parameters
called once from constructor if view is STATIC
called every snapshot from write() if view is DYNAMIC
------------------------------------------------------------------------- */
void DumpImage::box_center()
{
box_bounds();
if (cxstr) phi = input->variable->compute_equal(cxvar);
if (cystr) phi = input->variable->compute_equal(cyvar);
if (czstr) phi = input->variable->compute_equal(czvar);
xctr = boxxlo + cx*(boxxhi-boxxlo);
yctr = boxylo + cy*(boxyhi-boxylo);
zctr = boxzlo + cz*(boxzhi-boxzlo);
}
/* ----------------------------------------------------------------------
reset view parameters
called once from constructor if view is STATIC
called every snapshot from write() if view is DYNAMIC
------------------------------------------------------------------------- */
void DumpImage::view_params()
{
// camDir = camera direction
if (thetastr) {
theta = input->variable->compute_equal(thetavar);
if (theta < 0.0 || theta > 180.0)
- error->all("Invalid dump image theta value");
+ error->all(FLERR,"Invalid dump image theta value");
theta *= PI/180.0;
}
if (phistr) {
phi = input->variable->compute_equal(phivar);
phi *= PI/180.0;
}
camDir[0] = sin(theta)*cos(phi);
camDir[1] = sin(theta)*sin(phi);
camDir[2] = cos(theta);
// up vector
if (upxstr) up[0] = input->variable->compute_equal(upxvar);
if (upystr) up[1] = input->variable->compute_equal(upyvar);
if (upzstr) up[2] = input->variable->compute_equal(upzvar);
// zdist = camera distance = function of zoom & bounding box
// camPos = camera position = function of camDir and zdist
box_bounds();
if (zoomstr) zoom = input->variable->compute_equal(zoomvar);
- if (zoom <= 0.0) error->all("Invalid dump image zoom value");
+ if (zoom <= 0.0) error->all(FLERR,"Invalid dump image zoom value");
if (perspstr) persp = input->variable->compute_equal(perspvar);
- if (persp < 0.0) error->all("Invalid dump image persp value");
+ if (persp < 0.0) error->all(FLERR,"Invalid dump image persp value");
double delx = 2.0*(boxxhi-boxxlo);
double dely = 2.0*(boxyhi-boxylo);
double delz = 2.0*(boxzhi-boxzlo);
double maxdel = MAX(delx,dely);
maxdel = MAX(maxdel,delz);
zdist = maxdel;
zdist /= tan(FOV);
zdist += 0.5 * (delx*camDir[0] + dely*camDir[1] + delz*camDir[2]);
zdist /= zoom;
camPos[0] = camDir[0] * zdist;
camPos[1] = camDir[1] * zdist;
camPos[2] = camDir[2] * zdist;
// camUp = camDir x (Up x camDir)
// camDir points at the camera, view direction = -camDir
if (camDir[0] == up[0] && camDir[1] == up[1] && camDir[2] == up[2]) {
double tmp = up[0];
up[0] = up[1];
up[1] = up[2];
up[2] = tmp;
}
MathExtra::cross3(up,camDir,camRight);
MathExtra::norm3(camRight);
MathExtra::cross3(camDir,camRight,camUp);
if (camUp[0] == 0.0 && camUp[1] == 0.0 && camUp[2] == 0.0)
- error->all("Invalid dump image up vector");
+ error->all(FLERR,"Invalid dump image up vector");
MathExtra::norm3(camUp);
// light directions in terms of -camDir = z
keyLightDir[0] = cos(keyLightTheta) * sin(keyLightPhi);
keyLightDir[1] = sin(keyLightTheta);
keyLightDir[2] = cos(keyLightTheta) * cos(keyLightPhi);
fillLightDir[0] = cos(fillLightTheta) * sin(fillLightPhi);
fillLightDir[1] = sin(fillLightTheta);
fillLightDir[2] = cos(fillLightTheta) * cos(fillLightPhi);
backLightDir[0] = cos(backLightTheta) * sin(backLightPhi);
backLightDir[1] = sin(backLightTheta);
backLightDir[2] = cos(backLightTheta) * cos(backLightPhi);
keyHalfDir[0] = 0 + keyLightDir[0];
keyHalfDir[1] = 0 + keyLightDir[1];
keyHalfDir[2] = 1 + keyLightDir[2];
MathExtra::norm3(keyHalfDir);
// adjust shinyness of the reflection
specularHardness = 16.0 * shiny;
specularIntensity = shiny;
// adjust strength of the SSAO
if (ssao) {
SSAORadius = maxdel * 0.05 * ssaoint;
SSAOSamples = static_cast<int> (8.0 + 32.0*ssaoint);
SSAOJitter = PI / 12;
ambientColor[0] = 0.5;
ambientColor[1] = 0.5;
ambientColor[2] = 0.5;
}
// param for rasterizing spheres
tanPerPixel = -(maxdel / (double) height);
}
/* ----------------------------------------------------------------------
simulation box bounds
------------------------------------------------------------------------- */
void DumpImage::box_bounds()
{
if (domain->triclinic == 0) {
boxxlo = domain->boxlo[0];
boxxhi = domain->boxhi[0];
boxylo = domain->boxlo[1];
boxyhi = domain->boxhi[1];
boxzlo = domain->boxlo[2];
boxzhi = domain->boxhi[2];
} else {
boxxlo = domain->boxlo_bound[0];
boxxhi = domain->boxhi_bound[0];
boxylo = domain->boxlo_bound[1];
boxyhi = domain->boxhi_bound[1];
boxzlo = domain->boxlo_bound[2];
boxzhi = domain->boxhi_bound[2];
boxxy = domain->xy;
boxxz = domain->xz;
boxyz = domain->yz;
}
}
/* ----------------------------------------------------------------------
set explicit values for all min/max settings in color map
lo/hi current and lvalue/hvalue settings for lo/hi = MIN/MAX VALUE in entries
if mlo/mhi = MIN/MAX VALUE, compute bounds on just the atoms being visualized
------------------------------------------------------------------------- */
void DumpImage::color_minmax()
{
double two[2],twoall[2];
if (mlo == MINVALUE || mhi == MAXVALUE) {
double lo = BIG;
double hi = -BIG;
int m = 0;
for (int i = 0; i < nchoose; i++) {
lo = MIN(lo,buf[m]);
hi = MAX(hi,buf[m+1]);
m += size_one;
}
two[0] = -lo;
two[1] = hi;
MPI_Allreduce(two,twoall,2,MPI_DOUBLE,MPI_MAX,world);
}
if (mlo == MINVALUE) locurrent = -twoall[0];
else locurrent = mlovalue;
if (mhi == MAXVALUE) hicurrent = twoall[1];
else hicurrent = mhivalue;
- if (locurrent > hicurrent) error->all("Invalid dump image color range");
+ if (locurrent > hicurrent) error->all(FLERR,"Invalid dump image color range");
if (mstyle == CONTINUOUS) {
if (mrange == ABSOLUTE) mentry[0].svalue = locurrent;
else mentry[0].svalue = 0.0;
if (mrange == ABSOLUTE) mentry[nentry-1].svalue = hicurrent;
else mentry[nentry-1].svalue = 1.0;
} else if (mstyle == DISCRETE) {
for (int i = 0; i < nentry; i++) {
if (mentry[i].lo == MINVALUE) {
if (mrange == ABSOLUTE) mentry[i].lvalue = locurrent;
else mentry[i].lvalue = 0.0;
}
if (mentry[i].hi == MAXVALUE) {
if (mrange == ABSOLUTE) mentry[i].hvalue = hicurrent;
else mentry[i].hvalue = 1.0;
}
}
}
}
/* ----------------------------------------------------------------------
create image for atoms on this proc
every pixel has depth
------------------------------------------------------------------------- */
void DumpImage::create_image()
{
int i,j,m,itype,atom1,atom2;
double diameter,delx,dely,delz;
double *color,*color1,*color2;
double xmid[3];
// initialze image buffers
// no need to init surfaceBuffer, since will be based on depth
int red = background[0];
int green = background[1];
int blue = background[2];
int ix,iy;
for (iy = 0; iy < height; iy ++) {
for (ix = 0; ix < width; ix ++) {
imageBuffer[iy * width * 3 + ix * 3 + 0] = red;
imageBuffer[iy * width * 3 + ix * 3 + 1] = green;
imageBuffer[iy * width * 3 + ix * 3 + 2] = blue;
depthBuffer[iy * width + ix] = -1;
}
}
// render my atoms
if (atomflag) {
double **x = atom->x;
m = 0;
for (i = 0; i < nchoose; i++) {
j = clist[i];
if (acolor == TYPE) {
itype = static_cast<int> (buf[m]);
color = colortype[itype];
} else if (acolor == ELEMENT) {
itype = static_cast<int> (buf[m]);
color = colorelement[itype];
} else if (acolor == ATTRIBUTE) {
color = value2color(buf[m]);
}
if (adiam == NUMERIC) {
diameter = adiamvalue;
} else if (adiam == TYPE) {
itype = static_cast<int> (buf[m+1]);
diameter = diamtype[itype];
} else if (adiam == ELEMENT) {
itype = static_cast<int> (buf[m+1]);
diameter = diamelement[itype];
} else if (adiam == ATTRIBUTE) {
diameter = buf[m+1];
}
draw_sphere(x[j],color,diameter);
m += size_one;
}
}
// render bonds for my atoms
// both atoms in bond must be selected for bond to be rendered
// if newton_bond is off, only render bond once
// render bond in 2 pieces if crosses periodic boundary
// if bond is deleted (type = 0), do not render
// if bond is turned off (type < 0), still render
if (bondflag) {
double **x = atom->x;
int *tag = atom->tag;
int **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int *num_bond = atom->num_bond;
int *type = atom->type;
int nlocal = atom->nlocal;
int nall = atom->nlocal + atom->nghost;
int newton_bond = force->newton_bond;
// communicate choose flag for ghost atoms to know if they are selected
// if bcolor/bdiam = ATOM, setup bufcopy to comm atom color/diam attributes
if (comm_forward == 3) {
if (nall > maxbufcopy) {
maxbufcopy = atom->nmax;
memory->destroy(bufcopy);
memory->create(bufcopy,maxbufcopy,2,"dump:bufcopy");
}
for (i = 0; i < nlocal; i++) bufcopy[i][0] = bufcopy[i][1] = 0.0;
m = 0;
for (i = 0; i < nchoose; i++) {
j = clist[i];
bufcopy[j][0] = buf[m];
bufcopy[j][1] = buf[m+1];
m += size_one;
}
}
comm->forward_comm_dump(this);
for (i = 0; i < nchoose; i++) {
atom1 = clist[i];
for (m = 0; m < num_bond[atom1]; m++) {
atom2 = atom->map(bond_atom[atom1][m]);
if (atom2 < 0 || !choose[atom2]) continue;
if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue;
if (bond_type[atom1][m] == 0) continue;
if (bcolor == ATOM) {
if (acolor == TYPE) {
color1 = colortype[type[atom1]];
color2 = colortype[type[atom2]];
} else if (acolor == ELEMENT) {
color1 = colorelement[type[atom1]];
color2 = colorelement[type[atom2]];
} else if (acolor == ATTRIBUTE) {
color1 = value2color(bufcopy[atom1][0]);
color2 = value2color(bufcopy[atom2][0]);
}
} else if (bcolor == TYPE) {
itype = bond_type[atom1][m];
if (itype < 0) itype = -itype;
color = bcolortype[itype];
}
if (bdiam == NUMERIC) {
diameter = bdiamvalue;
} else if (bdiam == ATOM) {
if (adiam == NUMERIC) {
diameter = adiamvalue;
} else if (adiam == TYPE) {
diameter = MIN(diamtype[type[atom1]],diamtype[type[atom1]]);
} else if (adiam == ELEMENT) {
diameter = MIN(diamelement[type[atom1]],diamelement[type[atom1]]);
} else if (adiam == ATTRIBUTE) {
diameter = MIN(bufcopy[atom1][1],bufcopy[atom2][1]);
}
} else if (bdiam == TYPE) {
itype = bond_type[atom1][m];
if (itype < 0) itype = -itype;
diameter = bdiamtype[itype];
}
// draw cylinder in 2 pieces if bcolor = ATOM
// or bond crosses periodic boundary
delx = x[atom2][0] - x[atom1][0];
dely = x[atom2][1] - x[atom1][1];
delz = x[atom2][2] - x[atom1][2];
if (bcolor == ATOM || domain->minimum_image_check(delx,dely,delz)) {
domain->minimum_image(delx,dely,delz);
xmid[0] = x[atom1][0] + 0.5*delx;
xmid[1] = x[atom1][1] + 0.5*dely;
xmid[2] = x[atom1][2] + 0.5*delz;
if (bcolor == ATOM) draw_cylinder(x[atom1],xmid,color1,diameter,3);
else draw_cylinder(x[atom1],xmid,color,diameter,3);
xmid[0] = x[atom2][0] - 0.5*delx;
xmid[1] = x[atom2][1] - 0.5*dely;
xmid[2] = x[atom2][2] - 0.5*delz;
if (bcolor == ATOM) draw_cylinder(xmid,x[atom2],color2,diameter,3);
else draw_cylinder(xmid,x[atom2],color,diameter,3);
} else draw_cylinder(x[atom1],x[atom2],color,diameter,3);
}
}
}
// render outline of simulation box, orthogonal or triclinic
if (boxflag) {
double diameter = MIN(boxxhi-boxxlo,boxyhi-boxylo);
if (domain->dimension == 3) diameter = MIN(diameter,boxzhi-boxzlo);
diameter *= boxdiam;
double (*corners)[3];
double corner[8][3];
if (domain->triclinic == 0) {
corner[0][0] = boxxlo; corner[0][1] = boxylo; corner[0][2] = boxzlo;
corner[1][0] = boxxhi; corner[1][1] = boxylo; corner[1][2] = boxzlo;
corner[2][0] = boxxlo; corner[2][1] = boxyhi; corner[2][2] = boxzlo;
corner[3][0] = boxxhi; corner[3][1] = boxyhi; corner[3][2] = boxzlo;
corner[4][0] = boxxlo; corner[4][1] = boxylo; corner[4][2] = boxzhi;
corner[5][0] = boxxhi; corner[5][1] = boxylo; corner[5][2] = boxzhi;
corner[6][0] = boxxlo; corner[6][1] = boxyhi; corner[6][2] = boxzhi;
corner[7][0] = boxxhi; corner[7][1] = boxyhi; corner[7][2] = boxzhi;
corners = corner;
} else {
domain->box_corners();
corners = domain->corners;
}
draw_cylinder(corners[0],corners[1],boxcolor,diameter,3);
draw_cylinder(corners[2],corners[3],boxcolor,diameter,3);
draw_cylinder(corners[0],corners[2],boxcolor,diameter,3);
draw_cylinder(corners[1],corners[3],boxcolor,diameter,3);
draw_cylinder(corners[0],corners[4],boxcolor,diameter,3);
draw_cylinder(corners[1],corners[5],boxcolor,diameter,3);
draw_cylinder(corners[2],corners[6],boxcolor,diameter,3);
draw_cylinder(corners[3],corners[7],boxcolor,diameter,3);
draw_cylinder(corners[4],corners[5],boxcolor,diameter,3);
draw_cylinder(corners[6],corners[7],boxcolor,diameter,3);
draw_cylinder(corners[4],corners[6],boxcolor,diameter,3);
draw_cylinder(corners[5],corners[7],boxcolor,diameter,3);
}
// render XYZ axes in red/green/blue
// offset by 10% of box size and scale by axeslen
if (axesflag) {
double diameter = MIN(boxxhi-boxxlo,boxyhi-boxylo);
if (domain->dimension == 3) diameter = MIN(diameter,boxzhi-boxzlo);
diameter *= axesdiam;
double (*corners)[3];
double corner[8][3];
if (domain->triclinic == 0) {
corner[0][0] = boxxlo; corner[0][1] = boxylo; corner[0][2] = boxzlo;
corner[1][0] = boxxhi; corner[1][1] = boxylo; corner[1][2] = boxzlo;
corner[2][0] = boxxlo; corner[2][1] = boxyhi; corner[2][2] = boxzlo;
corner[4][0] = boxxlo; corner[4][1] = boxylo; corner[4][2] = boxzhi;
corners = corner;
} else {
domain->box_corners();
corners = domain->corners;
}
double offset = MAX(boxxhi-boxxlo,boxyhi-boxylo);
if (domain->dimension == 3) offset = MAX(offset,boxzhi-boxzlo);
offset *= 0.1;
corners[0][0] -= offset; corners[0][1] -= offset; corners[0][2] -= offset;
corners[1][0] -= offset; corners[1][1] -= offset; corners[1][2] -= offset;
corners[2][0] -= offset; corners[2][1] -= offset; corners[2][2] -= offset;
corners[4][0] -= offset; corners[4][1] -= offset; corners[4][2] -= offset;
corners[1][0] = corners[0][0] + axeslen*(corners[1][0]-corners[0][0]);
corners[1][1] = corners[0][1] + axeslen*(corners[1][1]-corners[0][1]);
corners[1][2] = corners[0][2] + axeslen*(corners[1][2]-corners[0][2]);
corners[2][0] = corners[0][0] + axeslen*(corners[2][0]-corners[0][0]);
corners[2][1] = corners[0][1] + axeslen*(corners[2][1]-corners[0][1]);
corners[2][2] = corners[0][2] + axeslen*(corners[2][2]-corners[0][2]);
corners[4][0] = corners[0][0] + axeslen*(corners[4][0]-corners[0][0]);
corners[4][1] = corners[0][1] + axeslen*(corners[4][1]-corners[0][1]);
corners[4][2] = corners[0][2] + axeslen*(corners[4][2]-corners[0][2]);
draw_cylinder(corners[0],corners[1],color2rgb("red"),diameter,3);
draw_cylinder(corners[0],corners[2],color2rgb("green"),diameter,3);
draw_cylinder(corners[0],corners[4],color2rgb("blue"),diameter,3);
}
}
/* ----------------------------------------------------------------------
draw sphere at x with surfaceColor and diameter
render pixel by pixel onto image plane with depth buffering
------------------------------------------------------------------------- */
void DumpImage::draw_sphere(double *x, double *surfaceColor, double diameter)
{
int ix,iy;
double projRad;
double xlocal[3],surface[3];
double depth;
xlocal[0] = x[0] - xctr;
xlocal[1] = x[1] - yctr;
xlocal[2] = x[2] - zctr;
double xmap = MathExtra::dot3(camRight,xlocal);
double ymap = MathExtra::dot3(camUp,xlocal);
double dist = MathExtra::dot3(camPos,camDir) - MathExtra::dot3(xlocal,camDir);
double radius = 0.5*diameter;
double radsq = radius*radius;
double pixelWidth = (tanPerPixel > 0) ? tanPerPixel * dist :
-tanPerPixel / zoom;
double pixelRadiusFull = radius / pixelWidth;
int pixelRadius = static_cast<int> (pixelRadiusFull + 0.5) + 1;
double xf = xmap / pixelWidth;
double yf = ymap / pixelWidth;
int xc = static_cast<int> (xf);
int yc = static_cast<int> (yf);
double width_error = xf - xc;
double height_error = yf - yc;
// shift 0,0 to screen center (vs lower left)
xc += width / 2;
yc += height / 2;
for (iy = yc - pixelRadius; iy <= yc + pixelRadius; iy++) {
for (ix = xc - pixelRadius; ix <= xc + pixelRadius; ix++) {
if (iy < 0 || iy >= height || ix < 0 || ix >= width) continue;
surface[1] = ((iy - yc) - height_error) * pixelWidth;
surface[0] = ((ix - xc) - width_error) * pixelWidth;
projRad = surface[0]*surface[0] + surface[1]*surface[1];
// outside the sphere in the projected image
if (projRad > radsq) continue;
surface[2] = sqrt(radsq - projRad);
depth = dist - surface[2];
surface[0] /= radius;
surface[1] /= radius;
surface[2] /= radius;
draw_pixel (ix, iy, depth, surface, surfaceColor);
}
}
}
/* ----------------------------------------------------------------------
draw cylinder from x to y with surfaceColor and diameter
render pixel by pixel onto image plane with depth buffering
if sflag = 0, draw no end spheres
if sflag = 1, draw 1st end sphere
if sflag = 2, draw 2nd end sphere
if sflag = 3, draw both end spheres
------------------------------------------------------------------------- */
void DumpImage::draw_cylinder(double *x, double *y,
double *surfaceColor, double diameter, int sflag)
{
double surface[3], normal[3];
double mid[3],xaxis[3],yaxis[3],zaxis[3];
double camLDir[3], camLRight[3], camLUp[3];
double zmin, zmax;
if (sflag % 2) draw_sphere(x,surfaceColor,diameter);
if (sflag/2) draw_sphere(y,surfaceColor,diameter);
double radius = 0.5*diameter;
double radsq = radius*radius;
zaxis[0] = y[0] - x[0];
zaxis[1] = y[1] - x[1];
zaxis[2] = y[2] - x[2];
double rasterWidth = fabs(MathExtra::dot3(zaxis, camRight)) + diameter;
double rasterHeight = fabs(MathExtra::dot3(zaxis, camUp)) + diameter;
mid[0] = (y[0] + x[0]) * 0.5 - xctr;
mid[1] = (y[1] + x[1]) * 0.5 - yctr;
mid[2] = (y[2] + x[2]) * 0.5 - zctr;
double len = MathExtra::len3(zaxis);
MathExtra::scale3(1.0/len,zaxis);
len *= 0.5;
zmax = len;
zmin = -len;
double xmap = MathExtra::dot3(camRight,mid);
double ymap = MathExtra::dot3(camUp,mid);
double dist = MathExtra::dot3(camPos,camDir) - MathExtra::dot3(mid,camDir);
double pixelWidth = (tanPerPixel > 0) ? tanPerPixel * dist :
-tanPerPixel / zoom;
double xf = xmap / pixelWidth;
double yf = ymap / pixelWidth;
int xc = static_cast<int> (xf);
int yc = static_cast<int> (yf);
double width_error = xf - xc;
double height_error = yf - yc;
// shift 0,0 to screen center (vs lower left)
xc += width / 2;
yc += height / 2;
double pixelHalfWidthFull = (rasterWidth * 0.5) / pixelWidth;
double pixelHalfHeightFull = (rasterHeight * 0.5) / pixelWidth;
int pixelHalfWidth = static_cast<int> (pixelHalfWidthFull + 0.5);
int pixelHalfHeight = static_cast<int> (pixelHalfHeightFull + 0.5);
if (zaxis[0] == camDir[0] && zaxis[1] == camDir[1] && zaxis[2] == camDir[2])
return;
+ if (zaxis[0] == -camDir[0] && zaxis[1] == -camDir[1] &&
+ zaxis[2] == -camDir[2]) return;
MathExtra::cross3(zaxis,camDir,yaxis);
MathExtra::norm3(yaxis);
MathExtra::cross3(yaxis,zaxis,xaxis);
MathExtra::norm3(xaxis);
camLDir[0] = MathExtra::dot3(camDir,xaxis);
camLDir[1] = 0.0;
camLDir[2] = MathExtra::dot3(camDir,zaxis);
camLRight[0] = MathExtra::dot3(camRight,xaxis);
camLRight[1] = MathExtra::dot3(camRight,yaxis);
camLRight[2] = MathExtra::dot3(camRight,zaxis);
MathExtra::norm3(camLRight);
camLUp[0] = MathExtra::dot3(camUp,xaxis);
camLUp[1] = MathExtra::dot3(camUp,yaxis);
camLUp[2] = MathExtra::dot3(camUp,zaxis);
MathExtra::norm3(camLUp);
double a = camLDir[0] * camLDir[0];
for (int iy = yc - pixelHalfHeight; iy <= yc + pixelHalfHeight; iy ++) {
for (int ix = xc - pixelHalfWidth; ix <= xc + pixelHalfWidth; ix ++) {
if (iy < 0 || iy >= height || ix < 0 || ix >= width) continue;
double sy = ((iy - yc) - height_error) * pixelWidth;
double sx = ((ix - xc) - width_error) * pixelWidth;
surface[0] = camLRight[0] * sx + camLUp[0] * sy;
surface[1] = camLRight[1] * sx + camLUp[1] * sy;
surface[2] = camLRight[2] * sx + camLUp[2] * sy;
double b = 2 * camLDir[0] * surface[0];
double c = surface[0] * surface[0] + surface[1] * surface[1] - radsq;
double partial = b*b - 4*a*c;
if (partial < 0) continue;
partial = sqrt (partial);
double t = (-b + partial) / (2*a);
double t2 = (-b - partial) / (2*a);
if (t2 > t) { t = t2; }
surface[0] += t * camLDir[0];
surface[1] += t * camLDir[1];
surface[2] += t * camLDir[2];
if (surface[2] > zmax || surface[2] < zmin) continue;
// convert surface into the surface normal
normal[0] = surface[0] / radius;
normal[1] = surface[1] / radius;
normal[2] = 0.0;
// in camera space
surface[0] = MathExtra::dot3 (normal, camLRight);
surface[1] = MathExtra::dot3 (normal, camLUp);
surface[2] = MathExtra::dot3 (normal, camLDir);
double depth = dist - t;
draw_pixel (ix, iy, depth, surface, surfaceColor);
}
}
}
/* ---------------------------------------------------------------------- */
void DumpImage::draw_pixel(int ix, int iy, double depth,
double *surface, double *surfaceColor)
{
double diffuseKey,diffuseFill,diffuseBack,specularKey;
if (depth < 0 || (depthBuffer[ix + iy*width] >= 0 &&
depth >= depthBuffer[ix + iy*width])) return;
depthBuffer[ix + iy*width] = depth;
// store only the tangent relative to the camera normal (0,0,-1)
surfaceBuffer[0 + ix * 2 + iy*width * 2] = surface[1];
surfaceBuffer[1 + ix * 2 + iy*width * 2] = -surface[0];
diffuseKey = saturate(MathExtra::dot3(surface, keyLightDir));
diffuseFill = saturate(MathExtra::dot3(surface, fillLightDir));
diffuseBack = saturate(MathExtra::dot3(surface, backLightDir));
specularKey = pow(saturate(MathExtra::dot3(surface, keyHalfDir)),
specularHardness) * specularIntensity;
double c[3];
c[0] = surfaceColor[0] * ambientColor[0];
c[1] = surfaceColor[1] * ambientColor[1];
c[2] = surfaceColor[2] * ambientColor[2];
c[0] += surfaceColor[0] * keyLightColor[0] * diffuseKey;
c[1] += surfaceColor[1] * keyLightColor[1] * diffuseKey;
c[2] += surfaceColor[2] * keyLightColor[2] * diffuseKey;
c[0] += keyLightColor[0] * specularKey;
c[1] += keyLightColor[1] * specularKey;
c[2] += keyLightColor[2] * specularKey;
c[0] += surfaceColor[0] * fillLightColor[0] * diffuseFill;
c[1] += surfaceColor[1] * fillLightColor[1] * diffuseFill;
c[2] += surfaceColor[2] * fillLightColor[2] * diffuseFill;
c[0] += surfaceColor[0] * backLightColor[0] * diffuseBack;
c[1] += surfaceColor[1] * backLightColor[1] * diffuseBack;
c[2] += surfaceColor[2] * backLightColor[2] * diffuseBack;
c[0] = saturate(c[0]);
c[1] = saturate(c[1]);
c[2] = saturate(c[2]);
imageBuffer[0 + ix*3 + iy*width*3] = static_cast<int>(c[0] * 255.0);
imageBuffer[1 + ix*3 + iy*width*3] = static_cast<int>(c[1] * 255.0);
imageBuffer[2 + ix*3 + iy*width*3] = static_cast<int>(c[2] * 255.0);
}
/* ---------------------------------------------------------------------- */
void DumpImage::compute_SSAO()
{
// used for rasterizing the spheres
double delTheta = 2.0*PI / SSAOSamples;
// typical neighborhood value for shading
double pixelWidth = (tanPerPixel > 0) ? tanPerPixel :
-tanPerPixel / zoom;
int pixelRadius = (int) trunc (SSAORadius / pixelWidth + 0.5);
int x,y,s;
int hPart = height / nprocs;
int index = me * hPart * width;
for (y = me * hPart; y < (me + 1) * hPart; y ++) {
for (x = 0; x < width; x ++, index ++) {
double cdepth = depthBuffer[index];
if (cdepth < 0) { continue; }
double sx = surfaceBuffer[index * 2 + 0];
double sy = surfaceBuffer[index * 2 + 1];
double sin_t = -sqrt(sx*sx + sy*sy);
double theta = random->uniform() * SSAOJitter;
double ao = 0.0;
for (s = 0; s < SSAOSamples; s ++) {
double hx = cos(theta);
double hy = sin(theta);
theta += delTheta;
// multiply by z cross surface tangent
// so that dot (aka cos) works here
double scaled_sin_t = sin_t * (hx*sy + hy*sx);
// Bresenham's line algorithm to march over depthBuffer
int dx = static_cast<int> (hx * pixelRadius);
int dy = static_cast<int> (hy * pixelRadius);
int ex = x + dx;
if (ex < 0) { ex = 0; } if (ex >= width) { ex = width - 1; }
int ey = y + dy;
if (ey < 0) { ey = 0; } if (ey >= height) { ey = height - 1; }
double delta;
int small, large;
double lenIncr;
if (fabs(hx) > fabs(hy)) {
small = (hx > 0) ? 1 : -1;
large = (hy > 0) ? width : -width;
delta = fabs(hy / hx);
} else {
small = (hy > 0) ? width : -width;
large = (hx > 0) ? 1 : -1;
delta = fabs(hx / hy);
}
lenIncr = sqrt (1 + delta * delta) * pixelWidth;
// initialize with one step
// because the center point doesn't need testing
int end = ex + ey * width;
int ind = index + small;
double len = lenIncr;
double err = delta;
if (err >= 1.0) {
ind += large;
err -= 1.0;
}
double minPeak = -1;
double peakLen = 0.0;
int stepsTaken = 1;
while ((small > 0 && ind <= end) || (small < 0 && ind >= end)) {
if (ind < 0 || ind >= (width*height)) {
break;
}
// cdepth - depthBuffer B/C we want it in the negative z direction
if (minPeak < 0 || (depthBuffer[ind] >= 0 &&
depthBuffer[ind] < minPeak)) {
minPeak = depthBuffer[ind];
peakLen = len;
}
ind += small;
len += lenIncr;
err += delta;
if (err >= 1.0) {
ind += large;
err -= 1.0;
}
stepsTaken ++;
}
if (peakLen > 0) {
double h = atan ((cdepth - minPeak) / peakLen);
ao += saturate(sin (h) - scaled_sin_t);
} else {
ao += saturate(-scaled_sin_t);
}
}
ao /= (double)SSAOSamples;
double c[3];
c[0] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 0]);
c[1] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 1]);
c[2] = (double) (*(unsigned char *) &imageBuffer[index * 3 + 2]);
c[0] *= (1.0 - ao);
c[1] *= (1.0 - ao);
c[2] *= (1.0 - ao);
imageBuffer[index * 3 + 0] = (int) c[0];
imageBuffer[index * 3 + 1] = (int) c[1];
imageBuffer[index * 3 + 2] = (int) c[2];
}
}
}
/* ---------------------------------------------------------------------- */
void DumpImage::write_JPG()
{
#ifdef LAMMPS_JPEG
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, fp);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 100, 1);
jpeg_start_compress(&cinfo, 1);
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer = (JSAMPROW)
&writeBuffer[(cinfo.image_height - 1 - cinfo.next_scanline) * 3 * width];
jpeg_write_scanlines(&cinfo, &row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
#endif
}
/* ---------------------------------------------------------------------- */
void DumpImage::write_PPM()
{
int x,y;
fprintf (fp,"P6\n%d %d\n255\n",width,height);
for (y = height-1; y >= 0; y --)
for (x = 0; x < width; x ++)
fprintf (fp,"%c%c%c",
writeBuffer[0 + x*3 + y*width*3],
writeBuffer[1 + x*3 + y*width*3],
writeBuffer[2 + x*3 + y*width*3]);
}
/* ---------------------------------------------------------------------- */
int DumpImage::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
m = 0;
if (comm_forward == 1) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = choose[j];
}
} else {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = choose[j];
buf[m++] = bufcopy[j][0];
buf[m++] = bufcopy[j][1];
}
}
return comm_forward;
}
/* ---------------------------------------------------------------------- */
void DumpImage::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
if (comm_forward == 1)
for (i = first; i < last; i++) choose[i] = static_cast<int> (buf[m++]);
else {
for (i = first; i < last; i++) {
choose[i] = static_cast<int> (buf[m++]);
bufcopy[i][0] = buf[m++];
bufcopy[i][1] = buf[m++];
}
}
}
/* ---------------------------------------------------------------------- */
int DumpImage::modify_param(int narg, char **arg)
{
int n = DumpCustom::modify_param(narg,arg);
if (n) return n;
if (strcmp(arg[0],"acolor") == 0) {
- if (narg < 3) error->all("Illegal dump_modify command");
+ if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
int nlo,nhi;
force->bounds(arg[1],atom->ntypes,nlo,nhi);
// ptrs = list of ncount colornames separated by '/'
int ncount = 1;
char *nextptr;
char *ptr = arg[2];
while (nextptr = strchr(ptr,'/')) {
ptr = nextptr + 1;
ncount++;
}
char **ptrs = new char*[ncount+1];
ncount = 0;
ptrs[ncount++] = strtok(arg[2],"/");
while (ptrs[ncount++] = strtok(NULL,"/"));
ncount--;
// assign each of ncount colors in round-robin fashion to types
int m = 0;
for (int i = nlo; i <= nhi; i++) {
colortype[i] = color2rgb(ptrs[m%ncount]);
if (colortype[i] == NULL)
- error->all("Invalid color in dump_modify command");
+ error->all(FLERR,"Invalid color in dump_modify command");
m++;
}
delete [] ptrs;
return 3;
} else if (strcmp(arg[0],"adiam") == 0) {
- if (narg < 3) error->all("Illegal dump_modify command");
+ if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
int nlo,nhi;
force->bounds(arg[1],atom->ntypes,nlo,nhi);
double diam = atof(arg[2]);
- if (diam <= 0.0) error->all("Illegal dump_modify command");
+ if (diam <= 0.0) error->all(FLERR,"Illegal dump_modify command");
for (int i = nlo; i <= nhi; i++) diamtype[i] = diam;
return 3;
} else if (strcmp(arg[0],"amap") == 0) {
- if (narg < 6) error->all("Illegal dump_modify command");
+ if (narg < 6) error->all(FLERR,"Illegal dump_modify command");
if (!islower(arg[1][0])) {
mlo = NUMERIC;
mlovalue = atof(arg[1]);
} else if (strcmp(arg[1],"min") == 0) mlo = MINVALUE;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
if (!islower(arg[2][0])) {
mhi = NUMERIC;
mhivalue = atof(arg[2]);
} else if (strcmp(arg[2],"max") == 0) mhi = MAXVALUE;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
if (mlo == NUMERIC && mhi == NUMERIC && mlovalue >= mhivalue)
- error->all("Illega dump_modify command");
+ error->all(FLERR,"Illega dump_modify command");
- if (strlen(arg[3]) != 2) error->all("Illegal dump_modify command");
+ if (strlen(arg[3]) != 2) error->all(FLERR,"Illegal dump_modify command");
if (arg[3][0] == 'c') mstyle = CONTINUOUS;
else if (arg[3][0] == 'd') mstyle = DISCRETE;
else if (arg[3][0] == 's') mstyle = SEQUENTIAL;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
if (arg[3][1] == 'a') mrange = ABSOLUTE;
else if (arg[3][1] == 'f') mrange = FRACTIONAL;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
if (mstyle == SEQUENTIAL) {
mbinsize = atof(arg[4]);
- if (mbinsize <= 0.0) error->all("Illegal dump_modify command");
+ if (mbinsize <= 0.0) error->all(FLERR,"Illegal dump_modify command");
}
mbinsizeinv = 1.0/mbinsize;
nentry = atoi(arg[5]);
mentry = new MapEntry[nentry];
int n = 6;
for (int i = 0; i < nentry; i++) {
if (mstyle == CONTINUOUS) {
- if (n+2 > narg) error->all("Illegal dump_modify command");
+ if (n+2 > narg) error->all(FLERR,"Illegal dump_modify command");
if (!islower(arg[n][0])) {
mentry[i].single = NUMERIC;
mentry[i].svalue = atof(arg[n]);
} else if (strcmp(arg[n],"min") == 0) mentry[i].single = MINVALUE;
else if (strcmp(arg[n],"max") == 0) mentry[i].single = MAXVALUE;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
mentry[i].color = color2rgb(arg[n+1]);
n += 2;
} else if (mstyle == DISCRETE) {
- if (n+3 > narg) error->all("Illegal dump_modify command");
+ if (n+3 > narg) error->all(FLERR,"Illegal dump_modify command");
if (!islower(arg[n][0])) {
mentry[i].lo = NUMERIC;
mentry[i].lvalue = atof(arg[n]);
} else if (strcmp(arg[n],"min") == 0) mentry[i].single = MINVALUE;
else if (strcmp(arg[n],"max") == 0) mentry[i].single = MAXVALUE;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
if (!islower(arg[n+1][0])) {
mentry[i].hi = NUMERIC;
mentry[i].hvalue = atof(arg[n+1]);
} else if (strcmp(arg[n+1],"min") == 0) mentry[i].single = MINVALUE;
else if (strcmp(arg[n+1],"max") == 0) mentry[i].single = MAXVALUE;
- else error->all("Illegal dump_modify command");
+ else error->all(FLERR,"Illegal dump_modify command");
mentry[i].color = color2rgb(arg[n+2]);
n += 3;
} else if (mstyle == SEQUENTIAL) {
- if (n+1 > narg) error->all("Illegal dump_modify command");
+ if (n+1 > narg) error->all(FLERR,"Illegal dump_modify command");
mentry[i].color = color2rgb(arg[n]);
n += 1;
}
if (mentry[i].color == NULL)
- error->all("Invalid color in dump_modify command");
+ error->all(FLERR,"Invalid color in dump_modify command");
}
if (mstyle == CONTINUOUS) {
- if (nentry < 2) error->all("Invalid color map in dump_modify command");
+ if (nentry < 2) error->all(FLERR,"Invalid color map in dump_modify command");
if (mentry[0].single != MINVALUE || mentry[nentry-1].single != MAXVALUE)
- error->all("Invalid color map in dump_modify command");
+ error->all(FLERR,"Invalid color map in dump_modify command");
for (int i = 2; i < nentry-1; i++)
if (mentry[i].svalue <= mentry[i-1].svalue)
- error->all("Invalid color map in dump_modify command");
+ error->all(FLERR,"Invalid color map in dump_modify command");
} else if (mstyle == DISCRETE) {
- if (nentry < 1) error->all("Invalid color map in dump_modify command");
+ if (nentry < 1) error->all(FLERR,"Invalid color map in dump_modify command");
if (mentry[nentry-1].lo != MINVALUE || mentry[nentry-1].hi != MAXVALUE)
- error->all("Invalid color map in dump_modify command");
+ error->all(FLERR,"Invalid color map in dump_modify command");
} else if (mstyle == SEQUENTIAL) {
- if (nentry < 1) error->all("Invalid color map in dump_modify command");
+ if (nentry < 1) error->all(FLERR,"Invalid color map in dump_modify command");
}
return n;
} else if (strcmp(arg[0],"bcolor") == 0) {
- if (narg < 3) error->all("Illegal dump_modify command");
+ if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
if (atom->nbondtypes == 0)
- error->all("Dump modify bcolor not allowed with no bond types");
+ error->all(FLERR,"Dump modify bcolor not allowed with no bond types");
int nlo,nhi;
force->bounds(arg[1],atom->nbondtypes,nlo,nhi);
// ptrs = list of ncount colornames separated by '/'
int ncount = 1;
char *nextptr;
char *ptr = arg[2];
while (nextptr = strchr(ptr,'/')) {
ptr = nextptr + 1;
ncount++;
}
char **ptrs = new char*[ncount+1];
ncount = 0;
ptrs[ncount++] = strtok(arg[2],"/");
while (ptrs[ncount++] = strtok(NULL,"/"));
ncount--;
// assign each of ncount colors in round-robin fashion to types
int m = 0;
for (int i = nlo; i <= nhi; i++) {
bcolortype[i] = color2rgb(ptrs[m%ncount]);
if (bcolortype[i] == NULL)
- error->all("Invalid color in dump_modify command");
+ error->all(FLERR,"Invalid color in dump_modify command");
m++;
}
delete [] ptrs;
return 3;
} else if (strcmp(arg[0],"bdiam") == 0) {
- if (narg < 3) error->all("Illegal dump_modify command");
+ if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
if (atom->nbondtypes == 0)
- error->all("Dump modify bdiam not allowed with no bond types");
+ error->all(FLERR,"Dump modify bdiam not allowed with no bond types");
int nlo,nhi;
force->bounds(arg[1],atom->ntypes,nlo,nhi);
double diam = atof(arg[2]);
- if (diam <= 0.0) error->all("Illegal dump_modify command");
+ if (diam <= 0.0) error->all(FLERR,"Illegal dump_modify command");
for (int i = nlo; i <= nhi; i++) bdiamtype[i] = diam;
return 3;
} else if (strcmp(arg[0],"backcolor") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
double *color = color2rgb(arg[1]);
- if (color == NULL) error->all("Invalid color in dump_modify command");
+ if (color == NULL) error->all(FLERR,"Invalid color in dump_modify command");
background[0] = static_cast<int> (color[0]*255.0);
background[1] = static_cast<int> (color[1]*255.0);
background[2] = static_cast<int> (color[2]*255.0);
return 2;
} else if (strcmp(arg[0],"boxcolor") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
boxcolor = color2rgb(arg[1]);
- if (boxcolor == NULL) error->all("Invalid color in dump_modify command");
+ if (boxcolor == NULL) error->all(FLERR,"Invalid color in dump_modify command");
return 2;
} else if (strcmp(arg[0],"color") == 0) {
- if (narg < 5) error->all("Illegal dump_modify command");
+ if (narg < 5) error->all(FLERR,"Illegal dump_modify command");
username = (char **)
memory->srealloc(username,(ncolors+1)*sizeof(char *),"dump:username");
memory->grow(userrgb,ncolors+1,3,"dump:userrgb");
int n = strlen(arg[1]) + 1;
username[ncolors] = new char[n];
strcpy(username[ncolors],arg[1]);
userrgb[ncolors][0] = atof(arg[2]);
userrgb[ncolors][1] = atof(arg[3]);
userrgb[ncolors][2] = atof(arg[4]);
if (userrgb[ncolors][0] < 0.0 || userrgb[ncolors][0] > 1.0 ||
userrgb[ncolors][1] < 0.0 || userrgb[ncolors][1] > 1.0 ||
userrgb[ncolors][2] < 0.0 || userrgb[ncolors][2] > 1.0)
- error->all("Illegal dump_modify command");
+ error->all(FLERR,"Illegal dump_modify command");
ncolors++;
return 5;
}
return 0;
}
/* ----------------------------------------------------------------------
convert value into an RGB color via color map
------------------------------------------------------------------------- */
double *DumpImage::value2color(double value)
{
double lo,hi;
value = MAX(value,locurrent);
value = MIN(value,hicurrent);
if (mrange == FRACTIONAL) {
if (locurrent == hicurrent) value = 0.0;
else value = (value-locurrent) / (hicurrent-locurrent);
lo = 0.0;
hi = 1.0;
} else {
lo = locurrent;
hi = hicurrent;
}
if (mstyle == CONTINUOUS) {
for (int i = 0; i < nentry-1; i++)
if (value >= mentry[i].svalue && value <= mentry[i+1].svalue) {
double fraction = (value-mentry[i].svalue) /
(mentry[i+1].svalue-mentry[i].svalue);
interpolate[0] = mentry[i].color[0] +
fraction*(mentry[i+1].color[0]-mentry[i].color[0]);
interpolate[1] = mentry[i].color[1] +
fraction*(mentry[i+1].color[1]-mentry[i].color[1]);
interpolate[2] = mentry[i].color[2] +
fraction*(mentry[i+1].color[2]-mentry[i].color[2]);
return interpolate;
}
} else if (mstyle == DISCRETE) {
for (int i = 0; i < nentry; i++)
if (value >= mentry[i].lvalue && value <= mentry[i].hvalue)
return mentry[i].color;
} else {
int ibin = static_cast<int> ((value-lo) * mbinsizeinv);
return mentry[ibin%nentry].color;
}
return NULL;
}
/* ----------------------------------------------------------------------
search the list of color names for the string color
return a pointer to the 3 floating point RGB values
search user-defined color names first, then the list of NCOLORS names
------------------------------------------------------------------------- */
double *DumpImage::color2rgb(char *color)
{
static char *name[NCOLORS] = {
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"azure",
"beige",
"bisque",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgreen",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"green",
"greenyellow",
"honeydew",
"hotpink",
"indianred",
"indigo",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgreen",
"lightgrey",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen"
};
static double rgb[NCOLORS][3] = {
{240/255.0, 248/255.0, 255/255.0},
{250/255.0, 235/255.0, 215/255.0},
{0/255.0, 255/255.0, 255/255.0},
{127/255.0, 255/255.0, 212/255.0},
{240/255.0, 255/255.0, 255/255.0},
{245/255.0, 245/255.0, 220/255.0},
{255/255.0, 228/255.0, 196/255.0},
{0/255.0, 0/255.0, 0/255.0},
{255/255.0, 255/255.0, 205/255.0},
{0/255.0, 0/255.0, 255/255.0},
{138/255.0, 43/255.0, 226/255.0},
{165/255.0, 42/255.0, 42/255.0},
{222/255.0, 184/255.0, 135/255.0},
{95/255.0, 158/255.0, 160/255.0},
{127/255.0, 255/255.0, 0/255.0},
{210/255.0, 105/255.0, 30/255.0},
{255/255.0, 127/255.0, 80/255.0},
{100/255.0, 149/255.0, 237/255.0},
{255/255.0, 248/255.0, 220/255.0},
{220/255.0, 20/255.0, 60/255.0},
{0/255.0, 255/255.0, 255/255.0},
{0/255.0, 0/255.0, 139/255.0},
{0/255.0, 139/255.0, 139/255.0},
{184/255.0, 134/255.0, 11/255.0},
{169/255.0, 169/255.0, 169/255.0},
{0/255.0, 100/255.0, 0/255.0},
{189/255.0, 183/255.0, 107/255.0},
{139/255.0, 0/255.0, 139/255.0},
{85/255.0, 107/255.0, 47/255.0},
{255/255.0, 140/255.0, 0/255.0},
{153/255.0, 50/255.0, 204/255.0},
{139/255.0, 0/255.0, 0/255.0},
{233/255.0, 150/255.0, 122/255.0},
{143/255.0, 188/255.0, 143/255.0},
{72/255.0, 61/255.0, 139/255.0},
{47/255.0, 79/255.0, 79/255.0},
{0/255.0, 206/255.0, 209/255.0},
{148/255.0, 0/255.0, 211/255.0},
{255/255.0, 20/255.0, 147/255.0},
{0/255.0, 191/255.0, 255/255.0},
{105/255.0, 105/255.0, 105/255.0},
{30/255.0, 144/255.0, 255/255.0},
{178/255.0, 34/255.0, 34/255.0},
{255/255.0, 250/255.0, 240/255.0},
{34/255.0, 139/255.0, 34/255.0},
{255/255.0, 0/255.0, 255/255.0},
{220/255.0, 220/255.0, 220/255.0},
{248/255.0, 248/255.0, 255/255.0},
{255/255.0, 215/255.0, 0/255.0},
{218/255.0, 165/255.0, 32/255.0},
{128/255.0, 128/255.0, 128/255.0},
{0/255.0, 128/255.0, 0/255.0},
{173/255.0, 255/255.0, 47/255.0},
{240/255.0, 255/255.0, 240/255.0},
{255/255.0, 105/255.0, 180/255.0},
{205/255.0, 92/255.0, 92/255.0},
{75/255.0, 0/255.0, 130/255.0},
{255/255.0, 240/255.0, 240/255.0},
{240/255.0, 230/255.0, 140/255.0},
{230/255.0, 230/255.0, 250/255.0},
{255/255.0, 240/255.0, 245/255.0},
{124/255.0, 252/255.0, 0/255.0},
{255/255.0, 250/255.0, 205/255.0},
{173/255.0, 216/255.0, 230/255.0},
{240/255.0, 128/255.0, 128/255.0},
{224/255.0, 255/255.0, 255/255.0},
{250/255.0, 250/255.0, 210/255.0},
{144/255.0, 238/255.0, 144/255.0},
{211/255.0, 211/255.0, 211/255.0},
{255/255.0, 182/255.0, 193/255.0},
{255/255.0, 160/255.0, 122/255.0},
{32/255.0, 178/255.0, 170/255.0},
{135/255.0, 206/255.0, 250/255.0},
{119/255.0, 136/255.0, 153/255.0},
{176/255.0, 196/255.0, 222/255.0},
{255/255.0, 255/255.0, 224/255.0},
{0/255.0, 255/255.0, 0/255.0},
{50/255.0, 205/255.0, 50/255.0},
{250/255.0, 240/255.0, 230/255.0},
{255/255.0, 0/255.0, 255/255.0},
{128/255.0, 0/255.0, 0/255.0},
{102/255.0, 205/255.0, 170/255.0},
{0/255.0, 0/255.0, 205/255.0},
{186/255.0, 85/255.0, 211/255.0},
{147/255.0, 112/255.0, 219/255.0},
{60/255.0, 179/255.0, 113/255.0},
{123/255.0, 104/255.0, 238/255.0},
{0/255.0, 250/255.0, 154/255.0},
{72/255.0, 209/255.0, 204/255.0},
{199/255.0, 21/255.0, 133/255.0},
{25/255.0, 25/255.0, 112/255.0},
{245/255.0, 255/255.0, 250/255.0},
{255/255.0, 228/255.0, 225/255.0},
{255/255.0, 228/255.0, 181/255.0},
{255/255.0, 222/255.0, 173/255.0},
{0/255.0, 0/255.0, 128/255.0},
{253/255.0, 245/255.0, 230/255.0},
{128/255.0, 128/255.0, 0/255.0},
{107/255.0, 142/255.0, 35/255.0},
{255/255.0, 165/255.0, 0/255.0},
{255/255.0, 69/255.0, 0/255.0},
{218/255.0, 112/255.0, 214/255.0},
{238/255.0, 232/255.0, 170/255.0},
{152/255.0, 251/255.0, 152/255.0},
{175/255.0, 238/255.0, 238/255.0},
{219/255.0, 112/255.0, 147/255.0},
{255/255.0, 239/255.0, 213/255.0},
{255/255.0, 239/255.0, 213/255.0},
{205/255.0, 133/255.0, 63/255.0},
{255/255.0, 192/255.0, 203/255.0},
{221/255.0, 160/255.0, 221/255.0},
{176/255.0, 224/255.0, 230/255.0},
{128/255.0, 0/255.0, 128/255.0},
{255/255.0, 0/255.0, 0/255.0},
{188/255.0, 143/255.0, 143/255.0},
{65/255.0, 105/255.0, 225/255.0},
{139/255.0, 69/255.0, 19/255.0},
{250/255.0, 128/255.0, 114/255.0},
{244/255.0, 164/255.0, 96/255.0},
{46/255.0, 139/255.0, 87/255.0},
{255/255.0, 245/255.0, 238/255.0},
{160/255.0, 82/255.0, 45/255.0},
{192/255.0, 192/255.0, 192/255.0},
{135/255.0, 206/255.0, 235/255.0},
{106/255.0, 90/255.0, 205/255.0},
{112/255.0, 128/255.0, 144/255.0},
{255/255.0, 250/255.0, 250/255.0},
{0/255.0, 255/255.0, 127/255.0},
{70/255.0, 130/255.0, 180/255.0},
{210/255.0, 180/255.0, 140/255.0},
{0/255.0, 128/255.0, 128/255.0},
{216/255.0, 191/255.0, 216/255.0},
{253/255.0, 99/255.0, 71/255.0},
{64/255.0, 224/255.0, 208/255.0},
{238/255.0, 130/255.0, 238/255.0},
{245/255.0, 222/255.0, 179/255.0},
{255/255.0, 255/255.0, 255/255.0},
{245/255.0, 245/255.0, 245/255.0},
{255/255.0, 255/255.0, 0/255.0},
{154/255.0, 205/255.0, 50/255.0}
};
for (int i = 0; i < ncolors; i++)
if (strcmp(color,username[i]) == 0) return userrgb[i];
for (int i = 0; i < NCOLORS; i++)
if (strcmp(color,name[i]) == 0) return rgb[i];
return NULL;
}
/* ----------------------------------------------------------------------
search the list of element names for the string element
return a pointer to the 3 floating point RGB values
this list is used by AtomEye and is taken from its Mendeleyev.c file
------------------------------------------------------------------------- */
double *DumpImage::element2color(char *element)
{
static char *name[NELEMENTS] = {
"H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne",
"Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca",
"Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn",
"Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr",
"Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn",
"Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd",
"Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb",
"Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg",
"Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th",
"Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm",
"Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt"
};
static double rgb[NELEMENTS][3] = {
{0.8, 0.8, 0.8},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.7, 0.7, 0.7},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.9, 0.4, 0},
{0.35, 0.35, 0.35},
{0.2, 0.2, 0.8},
{0.8, 0.2, 0.2},
{0.7, 0.85, 0.45},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6, 0.6, 0.6},
{0.6, 0.6, 0.7},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6901960784, 0.768627451, 0.8705882353},
{0.1, 0.7, 0.3},
{0.95, 0.9, 0.2},
{0.15, 0.5, 0.1},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.5, 0.5, 0.5},
{0.8, 0.8, 0.7},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0, 0.8, 0},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.5176470588, 0.5764705882, 0.6529411765},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.257254902, 0.2666666667, 0.271372549},
{0.95, 0.7900735294, 0.01385869565},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.9, 0, 1},
{0.6431372549, 0.6666666667, 0.6784313725},
{1, 1, 0.3},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.5, 0.08, 0.12},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.5, 0.1, 0.5},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.8, 0.8, 0},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{1, 0.8431372549, 0},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.9, 0.8, 0},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.8, 0.2, 0.2},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.1, 0.7, 0.3},
{0.1, 0.3, 0.7},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.9, 0.8, 0},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725},
{0.6431372549, 0.6666666667, 0.6784313725}
};
for (int i = 0; i < NELEMENTS; i++)
if (strcmp(element,name[i]) == 0) return rgb[i];
return NULL;
}
/* ----------------------------------------------------------------------
search the list of element names for the string element
return a pointer to the 3 floating point RGB values
this list is used by AtomEye and is taken from its Mendeleyev.c file
------------------------------------------------------------------------- */
double DumpImage::element2diam(char *element)
{
static char *name[NELEMENTS] = {
"H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne",
"Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca",
"Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn",
"Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr",
"Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn",
"Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd",
"Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb",
"Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg",
"Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th",
"Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm",
"Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt"
};
static double diameter[NELEMENTS] = {
0.35, 1.785, 1.45, 1.05, 0.85, 0.72, 0.65, 0.6, 0.5, 1.5662,
1.8, 1.5, 1.4255, 1.07, 1, 1, 1, 1.8597, 2.2, 1.8,
1.6, 1.4, 1.51995, 1.44225, 1.4, 1.43325, 1.35, 1.35, 1.278, 1.35,
1.3, 1.25, 1.15, 1.15, 1.15, 2.0223, 2.35, 2, 1.8, 1.55,
1.6504, 1.3872, 1.35, 1.3, 1.35, 1.4, 1.6, 1.55, 1.55, 1.45,
1.45, 1.4, 1.4, 2.192, 2.6, 2.15, 1.95, 1.85, 1.85, 1.85,
1.85, 1.85, 1.85, 1.8, 1.75, 1.75, 1.75, 1.75, 1.75, 1.75,
1.75, 1.55, 1.6529, 1.5826, 1.35, 1.3, 1.35, 1.35, 1.35, 1.5,
1.9, 1.8, 1.6, 1.9, 1.6, 1.0, 1.0, 2.15, 1.95, 1.8,
1.8, 1.75, 1.75, 1.75, 1.75, 1.0, 1.0, 1.6, 1.6, 1.0,
1.0, 1.0, 1.0, 1.0, 1.6, 1.0, 1.0, 1.0, 1.0
};
for (int i = 0; i < NELEMENTS; i++)
if (strcmp(element,name[i]) == 0) return diameter[i];
return 0.0;
}
diff --git a/src/dump_local.cpp b/src/dump_local.cpp
index aa1bad31c..c95f77e7c 100644
--- a/src/dump_local.cpp
+++ b/src/dump_local.cpp
@@ -1,470 +1,470 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "dump_local.h"
#include "atom.h"
#include "modify.h"
#include "fix.h"
#include "compute.h"
#include "domain.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{INT,DOUBLE};
#define INVOKED_LOCAL 16
/* ---------------------------------------------------------------------- */
DumpLocal::DumpLocal(LAMMPS *lmp, int narg, char **arg) :
Dump(lmp, narg, arg)
{
- if (narg == 5) error->all("No dump local arguments specified");
+ if (narg == 5) error->all(FLERR,"No dump local arguments specified");
clearstep = 1;
nevery = atoi(arg[3]);
size_one = nfield = narg-5;
pack_choice = new FnPtrPack[nfield];
vtype = new int[nfield];
// computes & fixes which the dump accesses
field2index = new int[nfield];
argindex = new int[nfield];
ncompute = 0;
id_compute = NULL;
compute = NULL;
nfix = 0;
id_fix = NULL;
fix = NULL;
// process attributes
parse_fields(narg,arg);
// setup format strings
vformat = new char*[size_one];
format_default = new char[3*size_one+1];
format_default[0] = '\0';
for (int i = 0; i < size_one; i++) {
if (vtype[i] == INT) format_default = strcat(format_default,"%d ");
else format_default = strcat(format_default,"%g ");
vformat[i] = NULL;
}
// setup column string
int n = 0;
for (int iarg = 5; iarg < narg; iarg++) n += strlen(arg[iarg]) + 2;
columns = new char[n];
columns[0] = '\0';
for (int iarg = 5; iarg < narg; iarg++) {
strcat(columns,arg[iarg]);
strcat(columns," ");
}
// setup default label string
char *str = "ENTRIES";
n = strlen(str) + 1;
label = new char[n];
strcpy(label,str);
}
/* ---------------------------------------------------------------------- */
DumpLocal::~DumpLocal()
{
delete [] pack_choice;
delete [] vtype;
delete [] field2index;
delete [] argindex;
for (int i = 0; i < ncompute; i++) delete [] id_compute[i];
memory->sfree(id_compute);
delete [] compute;
for (int i = 0; i < nfix; i++) delete [] id_fix[i];
memory->sfree(id_fix);
delete [] fix;
for (int i = 0; i < size_one; i++) delete [] vformat[i];
delete [] vformat;
delete [] columns;
delete [] label;
}
/* ---------------------------------------------------------------------- */
void DumpLocal::init_style()
{
if (sort_flag && sortcol == 0)
- error->all("Dump local cannot sort by atom ID");
+ error->all(FLERR,"Dump local cannot sort by atom ID");
delete [] format;
char *str;
if (format_user) str = format_user;
else str = format_default;
int n = strlen(str) + 1;
format = new char[n];
strcpy(format,str);
// tokenize the format string and add space at end of each format element
char *ptr;
for (int i = 0; i < size_one; i++) {
if (i == 0) ptr = strtok(format," \0");
else ptr = strtok(NULL," \0");
delete [] vformat[i];
vformat[i] = new char[strlen(ptr) + 2];
strcpy(vformat[i],ptr);
vformat[i] = strcat(vformat[i]," ");
}
// find current ptr for each compute,fix,variable
// check that fix frequency is acceptable
int icompute;
for (int i = 0; i < ncompute; i++) {
icompute = modify->find_compute(id_compute[i]);
- if (icompute < 0) error->all("Could not find dump local compute ID");
+ if (icompute < 0) error->all(FLERR,"Could not find dump local compute ID");
compute[i] = modify->compute[icompute];
}
int ifix;
for (int i = 0; i < nfix; i++) {
ifix = modify->find_fix(id_fix[i]);
- if (ifix < 0) error->all("Could not find dump local fix ID");
+ if (ifix < 0) error->all(FLERR,"Could not find dump local fix ID");
fix[i] = modify->fix[ifix];
if (nevery % modify->fix[ifix]->local_freq)
- error->all("Dump local and fix not computed at compatible times");
+ error->all(FLERR,"Dump local and fix not computed at compatible times");
}
// open single file, one time only
if (multifile == 0) openfile();
}
/* ---------------------------------------------------------------------- */
int DumpLocal::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"label") == 0) {
- if (narg < 2) error->all("Illegal dump_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
delete [] label;
int n = strlen(arg[1]) + 1;
label = new char[n];
strcpy(label,arg[1]);
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void DumpLocal::write_header(bigint ndump)
{
if (me == 0) {
fprintf(fp,"ITEM: TIMESTEP\n");
fprintf(fp,BIGINT_FORMAT "\n",update->ntimestep);
fprintf(fp,"ITEM: NUMBER OF %s\n",label);
fprintf(fp,BIGINT_FORMAT "\n",ndump);
fprintf(fp,"ITEM: %s %s\n",label,columns);
}
}
/* ---------------------------------------------------------------------- */
int DumpLocal::count()
{
int i;
// invoke Computes for local quantities
if (ncompute) {
for (i = 0; i < ncompute; i++) {
if (!(compute[i]->invoked_flag & INVOKED_LOCAL)) {
compute[i]->compute_local();
compute[i]->invoked_flag |= INVOKED_LOCAL;
}
}
}
// nmine = # of local values I contribute
// must be consistent for all input fields
nmine = -1;
for (int i = 0; i < ncompute; i++) {
if (nmine < 0) nmine = compute[i]->size_local_rows;
else if (nmine != compute[i]->size_local_rows)
- error->one("Dump local count is not consistent across input fields");
+ error->one(FLERR,"Dump local count is not consistent across input fields");
}
for (int i = 0; i < nfix; i++) {
if (nmine < 0) nmine = fix[i]->size_local_rows;
else if (nmine != fix[i]->size_local_rows)
- error->one("Dump local count is not consistent across input fields");
+ error->one(FLERR,"Dump local count is not consistent across input fields");
}
return nmine;
}
/* ---------------------------------------------------------------------- */
void DumpLocal::pack(int *dummy)
{
for (int n = 0; n < size_one; n++) (this->*pack_choice[n])(n);
}
/* ---------------------------------------------------------------------- */
void DumpLocal::write_data(int n, double *mybuf)
{
int i,j;
int m = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < size_one; j++) {
if (vtype[j] == INT) fprintf(fp,vformat[j],static_cast<int> (mybuf[m]));
else fprintf(fp,vformat[j],mybuf[m]);
m++;
}
fprintf(fp,"\n");
}
}
/* ---------------------------------------------------------------------- */
void DumpLocal::parse_fields(int narg, char **arg)
{
int computefixflag = 0;
// customize by adding to if statement
int i;
for (int iarg = 5; iarg < narg; iarg++) {
i = iarg-5;
if (strcmp(arg[iarg],"index") == 0) {
pack_choice[i] = &DumpLocal::pack_index;
vtype[i] = INT;
// compute value = c_ID
// if no trailing [], then arg is set to 0, else arg is int between []
} else if (strncmp(arg[iarg],"c_",2) == 0) {
computefixflag = 1;
pack_choice[i] = &DumpLocal::pack_compute;
vtype[i] = DOUBLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Invalid attribute in dump local command");
+ error->all(FLERR,"Invalid attribute in dump local command");
argindex[i] = atoi(ptr+1);
*ptr = '\0';
} else argindex[i] = 0;
n = modify->find_compute(suffix);
- if (n < 0) error->all("Could not find dump local compute ID");
+ if (n < 0) error->all(FLERR,"Could not find dump local compute ID");
if (modify->compute[n]->local_flag == 0)
- error->all("Dump local compute does not compute local info");
+ error->all(FLERR,"Dump local compute does not compute local info");
if (argindex[i] == 0 && modify->compute[n]->size_local_cols > 0)
- error->all("Dump local compute does not calculate local vector");
+ error->all(FLERR,"Dump local compute does not calculate local vector");
if (argindex[i] > 0 && modify->compute[n]->size_local_cols == 0)
- error->all("Dump local compute does not calculate local array");
+ error->all(FLERR,"Dump local compute does not calculate local array");
if (argindex[i] > 0 &&
argindex[i] > modify->compute[n]->size_local_cols)
- error->all("Dump local compute vector is accessed out-of-range");
+ error->all(FLERR,"Dump local compute vector is accessed out-of-range");
field2index[i] = add_compute(suffix);
delete [] suffix;
// fix value = f_ID
// if no trailing [], then arg is set to 0, else arg is between []
} else if (strncmp(arg[iarg],"f_",2) == 0) {
computefixflag = 1;
pack_choice[i] = &DumpLocal::pack_fix;
vtype[i] = DOUBLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Invalid attribute in dump local command");
+ error->all(FLERR,"Invalid attribute in dump local command");
argindex[i] = atoi(ptr+1);
*ptr = '\0';
} else argindex[i] = 0;
n = modify->find_fix(suffix);
- if (n < 0) error->all("Could not find dump local fix ID");
+ if (n < 0) error->all(FLERR,"Could not find dump local fix ID");
if (modify->fix[n]->local_flag == 0)
- error->all("Dump local fix does not compute local info");
+ error->all(FLERR,"Dump local fix does not compute local info");
if (argindex[i] == 0 && modify->fix[n]->size_local_cols > 0)
- error->all("Dump local fix does not compute local vector");
+ error->all(FLERR,"Dump local fix does not compute local vector");
if (argindex[i] > 0 && modify->fix[n]->size_local_cols == 0)
- error->all("Dump local fix does not compute local array");
+ error->all(FLERR,"Dump local fix does not compute local array");
if (argindex[i] > 0 &&
argindex[i] > modify->fix[n]->size_local_cols)
- error->all("Dump local fix vector is accessed out-of-range");
+ error->all(FLERR,"Dump local fix vector is accessed out-of-range");
field2index[i] = add_fix(suffix);
delete [] suffix;
- } else error->all("Invalid attribute in dump local command");
+ } else error->all(FLERR,"Invalid attribute in dump local command");
}
if (computefixflag == 0)
- error->all("Dump local attributes contain no compute or fix");
+ error->all(FLERR,"Dump local attributes contain no compute or fix");
}
/* ----------------------------------------------------------------------
add Compute to list of Compute objects used by dump
return index of where this Compute is in list
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
int DumpLocal::add_compute(char *id)
{
int icompute;
for (icompute = 0; icompute < ncompute; icompute++)
if (strcmp(id,id_compute[icompute]) == 0) break;
if (icompute < ncompute) return icompute;
id_compute = (char **)
memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),"dump:id_compute");
delete [] compute;
compute = new Compute*[ncompute+1];
int n = strlen(id) + 1;
id_compute[ncompute] = new char[n];
strcpy(id_compute[ncompute],id);
ncompute++;
return ncompute-1;
}
/* ----------------------------------------------------------------------
add Fix to list of Fix objects used by dump
return index of where this Fix is in list
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
int DumpLocal::add_fix(char *id)
{
int ifix;
for (ifix = 0; ifix < nfix; ifix++)
if (strcmp(id,id_fix[ifix]) == 0) break;
if (ifix < nfix) return ifix;
id_fix = (char **)
memory->srealloc(id_fix,(nfix+1)*sizeof(char *),"dump:id_fix");
delete [] fix;
fix = new Fix*[nfix+1];
int n = strlen(id) + 1;
id_fix[nfix] = new char[n];
strcpy(id_fix[nfix],id);
nfix++;
return nfix-1;
}
/* ----------------------------------------------------------------------
extraction of Compute, Fix results
------------------------------------------------------------------------- */
void DumpLocal::pack_compute(int n)
{
double *vector = compute[field2index[n]]->vector_local;
double **array = compute[field2index[n]]->array_local;
int ncount = compute[field2index[n]]->size_local_rows;
int index = argindex[n];
if (index == 0) {
for (int i = 0; i < ncount; i++) {
buf[n] = vector[i];
n += size_one;
}
} else {
index--;
for (int i = 0; i < ncount; i++) {
buf[n] = array[i][index];
n += size_one;
}
}
}
/* ---------------------------------------------------------------------- */
void DumpLocal::pack_fix(int n)
{
double *vector = fix[field2index[n]]->vector_local;
double **array = fix[field2index[n]]->array_local;
int index = argindex[n];
if (index == 0) {
for (int i = 0; i < nmine; i++) {
buf[n] = vector[i];
n += size_one;
}
} else {
index--;
for (int i = 0; i < nmine; i++) {
buf[n] = array[i][index];
n += size_one;
}
}
}
/* ----------------------------------------------------------------------
one method for every attribute dump local can output
the local value is packed into buf starting at n with stride size_one
customize a new attribute by adding a method
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void DumpLocal::pack_index(int n)
{
int index;
MPI_Scan(&nmine,&index,1,MPI_INT,MPI_SUM,world);
index -= nmine;
for (int i = 0; i < nmine; i++) {
buf[n] = ++index;
n += size_one;
}
}
diff --git a/src/dump_xyz.cpp b/src/dump_xyz.cpp
index d9814cdf7..817e376fb 100644
--- a/src/dump_xyz.cpp
+++ b/src/dump_xyz.cpp
@@ -1,118 +1,118 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "dump_xyz.h"
#include "atom.h"
#include "group.h"
#include "error.h"
#include "memory.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
DumpXYZ::DumpXYZ(LAMMPS *lmp, int narg, char **arg) : Dump(lmp, narg, arg)
{
- if (narg != 5) error->all("Illegal dump xyz command");
- if (binary || multiproc) error->all("Invalid dump xyz filename");
+ if (narg != 5) error->all(FLERR,"Illegal dump xyz command");
+ if (binary || multiproc) error->all(FLERR,"Invalid dump xyz filename");
size_one = 5;
sort_flag = 1;
sortcol = 0;
char *str = (char *) "%d %g %g %g";
int n = strlen(str) + 1;
format_default = new char[n];
strcpy(format_default,str);
}
/* ---------------------------------------------------------------------- */
void DumpXYZ::init_style()
{
delete [] format;
char *str;
if (format_user) str = format_user;
else str = format_default;
int n = strlen(str) + 2;
format = new char[n];
strcpy(format,str);
strcat(format,"\n");
// open single file, one time only
if (multifile == 0) openfile();
}
/* ---------------------------------------------------------------------- */
void DumpXYZ::write_header(bigint n)
{
if (me == 0) {
fprintf(fp,BIGINT_FORMAT "\n",n);
fprintf(fp,"Atoms\n");
}
}
/* ---------------------------------------------------------------------- */
int DumpXYZ::count()
{
if (igroup == 0) return atom->nlocal;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) m++;
return m;
}
/* ---------------------------------------------------------------------- */
void DumpXYZ::pack(int *ids)
{
int m,n;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
double **x = atom->x;
int nlocal = atom->nlocal;
m = n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
buf[m++] = tag[i];
buf[m++] = type[i];
buf[m++] = x[i][0];
buf[m++] = x[i][1];
buf[m++] = x[i][2];
if (ids) ids[n++] = tag[i];
}
}
/* ---------------------------------------------------------------------- */
void DumpXYZ::write_data(int n, double *mybuf)
{
int m = 0;
for (int i = 0; i < n; i++) {
fprintf(fp,format,
static_cast<int> (mybuf[m+1]),mybuf[m+2],mybuf[m+3],mybuf[m+4]);
m += size_one;
}
}
diff --git a/src/error.cpp b/src/error.cpp
index 81f40a549..c9297eb75 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -1,141 +1,147 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdlib.h"
#include "error.h"
#include "universe.h"
#include "memory.h"
#include "output.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Error::Error(LAMMPS *lmp) : Pointers(lmp) {}
/* ----------------------------------------------------------------------
called by all procs in universe
close all output, screen, and log files in world and universe
------------------------------------------------------------------------- */
-void Error::universe_all(const char *str)
+void Error::universe_all(const char *file, int line, const char *str)
{
MPI_Barrier(universe->uworld);
if (universe->me == 0) {
- if (universe->uscreen) fprintf(universe->uscreen,"ERROR: %s\n",str);
- if (universe->ulogfile) fprintf(universe->ulogfile,"ERROR: %s\n",str);
+ if (universe->uscreen) fprintf(universe->uscreen,
+ "ERROR: %s (%s:%d)\n",str,file,line);
+ if (universe->ulogfile) fprintf(universe->ulogfile,
+ "ERROR: %s (%s:%d)\n",str,file,line);
}
if (output) delete output;
if (universe->nworlds > 1) {
if (screen && screen != stdout) fclose(screen);
if (logfile) fclose(logfile);
}
if (universe->ulogfile) fclose(universe->ulogfile);
MPI_Finalize();
exit(1);
}
/* ----------------------------------------------------------------------
called by one proc in universe
------------------------------------------------------------------------- */
-void Error::universe_one(const char *str)
+void Error::universe_one(const char *file, int line, const char *str)
{
if (universe->uscreen)
- fprintf(universe->uscreen,"ERROR on proc %d: %s\n",universe->me,str);
+ fprintf(universe->uscreen,"ERROR on proc %d: %s (%s:%d)\n",
+ universe->me,str,file,line);
MPI_Abort(universe->uworld,1);
}
/* ----------------------------------------------------------------------
called by all procs in one world
close all output, screen, and log files in world
------------------------------------------------------------------------- */
-void Error::all(const char *str)
+void Error::all(const char *file, int line, const char *str)
{
MPI_Barrier(world);
int me;
MPI_Comm_rank(world,&me);
if (me == 0) {
- if (screen) fprintf(screen,"ERROR: %s\n",str);
- if (logfile) fprintf(logfile,"ERROR: %s\n",str);
+ if (screen) fprintf(screen,"ERROR: %s (%s:%d)\n",str,file,line);
+ if (logfile) fprintf(logfile,"ERROR: %s (%s:%d)\n",str,file,line);
}
if (output) delete output;
if (screen && screen != stdout) fclose(screen);
if (logfile) fclose(logfile);
MPI_Finalize();
exit(1);
}
/* ----------------------------------------------------------------------
called by one proc in world
write to world screen only if non-NULL on this proc
always write to universe screen
------------------------------------------------------------------------- */
-void Error::one(const char *str)
+void Error::one(const char *file, int line, const char *str)
{
int me;
MPI_Comm_rank(world,&me);
- if (screen) fprintf(screen,"ERROR on proc %d: %s\n",me,str);
+ if (screen) fprintf(screen,"ERROR on proc %d: %s (%s:%d)\n",
+ me,str,file,line);
if (universe->nworlds > 1)
- fprintf(universe->uscreen,"ERROR on proc %d: %s\n",universe->me,str);
+ fprintf(universe->uscreen,"ERROR on proc %d: %s (%s:%d)\n",
+ universe->me,str,file,line);
MPI_Abort(world,1);
}
/* ----------------------------------------------------------------------
called by one proc in world
only write to screen if non-NULL on this proc since could be file
------------------------------------------------------------------------- */
-void Error::warning(const char *str, int logflag)
+void Error::warning(const char *file, int line, const char *str, int logflag)
{
- if (screen) fprintf(screen,"WARNING: %s\n",str);
- if (logflag && logfile) fprintf(logfile,"WARNING: %s\n",str);
+ if (screen) fprintf(screen,"WARNING: %s (%s:%d)\n",str,file,line);
+ if (logflag && logfile) fprintf(logfile,"WARNING: %s (%s:%d)\n",
+ str,file,line);
}
/* ----------------------------------------------------------------------
called by one proc in world, typically proc 0
write message to screen and logfile (if logflag is set)
------------------------------------------------------------------------- */
-void Error::message(char *str, int logflag)
+void Error::message(const char *file, int line, char *str, int logflag)
{
- if (screen) fprintf(screen,"%s\n",str);
- if (logflag && logfile) fprintf(logfile,"%s\n",str);
+ if (screen) fprintf(screen,"%s (%s:%d)\n",str,file,line);
+ if (logflag && logfile) fprintf(logfile,"%s (%s:%d)\n",str,file,line);
}
/* ----------------------------------------------------------------------
called by all procs in one world
close all output, screen, and log files in world
------------------------------------------------------------------------- */
void Error::done()
{
MPI_Barrier(world);
if (output) delete output;
if (screen && screen != stdout) fclose(screen);
if (logfile) fclose(logfile);
MPI_Finalize();
exit(1);
}
diff --git a/src/error.h b/src/error.h
index 8c55a046c..395581dee 100644
--- a/src/error.h
+++ b/src/error.h
@@ -1,37 +1,37 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifndef LMP_ERROR_H
#define LMP_ERROR_H
#include "pointers.h"
namespace LAMMPS_NS {
class Error : protected Pointers {
public:
Error(class LAMMPS *);
- void universe_all(const char *);
- void universe_one(const char *);
+ void universe_all(const char *, int, const char *);
+ void universe_one(const char *, int, const char *);
- void all(const char *);
- void one(const char *);
- void warning(const char *, int = 1);
- void message(char *, int = 1);
+ void all(const char *, int, const char *);
+ void one(const char *, int, const char *);
+ void warning(const char *, int, const char *, int = 1);
+ void message(const char *, int, char *, int = 1);
void done();
};
}
#endif
diff --git a/src/finish.cpp b/src/finish.cpp
index 52fc2f312..fb43f1c7b 100644
--- a/src/finish.cpp
+++ b/src/finish.cpp
@@ -1,673 +1,670 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "stdio.h"
#include "finish.h"
#include "timer.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "update.h"
#include "min.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "output.h"
#include "memory.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
Finish::Finish(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void Finish::end(int flag)
{
int i,m,nneigh,nneighfull;
int histo[10];
int loopflag,minflag,prdflag,tadflag,timeflag,fftflag,histoflag,neighflag;
double time,tmp,ave,max,min;
double time_loop,time_other;
int me,nprocs;
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
// choose flavors of statistical output
// flag determines caller
// flag = 0 = just loop summary
// flag = 1 = dynamics or minimization
// flag = 2 = PRD
// flag = 3 = TAD
loopflag = 1;
minflag = prdflag = tadflag = timeflag = fftflag = histoflag = neighflag = 0;
if (flag == 1) {
if (update->whichflag == 2) minflag = 1;
timeflag = histoflag = neighflag = 1;
if (strstr(force->kspace_style,"pppm")) fftflag = 1;
}
if (flag == 2) prdflag = histoflag = neighflag = 1;
if (flag == 3) tadflag = histoflag = neighflag = 1;
// loop stats
if (loopflag) {
time_other = timer->array[TIME_LOOP] -
(timer->array[TIME_PAIR] + timer->array[TIME_BOND] +
timer->array[TIME_KSPACE] + timer->array[TIME_NEIGHBOR] +
timer->array[TIME_COMM] + timer->array[TIME_OUTPUT]);
time_loop = timer->array[TIME_LOOP];
MPI_Allreduce(&time_loop,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time_loop = tmp/nprocs;
// overall loop time
#if defined(_OPENMP)
if (me == 0) {
int ntasks = nprocs * comm->nthreads;
if (screen) fprintf(screen,
"Loop time of %g on %d procs (%d MPI x %d OpenMP) "
"for %d steps with " BIGINT_FORMAT " atoms\n",
time_loop,ntasks,nprocs,comm->nthreads,
update->nsteps,atom->natoms);
if (logfile) fprintf(logfile,
"Loop time of %g on %d procs (%d MPI x %d OpenMP) "
"for %d steps with " BIGINT_FORMAT " atoms\n",
time_loop,ntasks,nprocs,comm->nthreads,
update->nsteps,atom->natoms);
}
#else
if (me == 0) {
if (screen) fprintf(screen,
"Loop time of %g on %d procs for %d steps with "
BIGINT_FORMAT " atoms\n",
time_loop,nprocs,update->nsteps,atom->natoms);
if (logfile) fprintf(logfile,
"Loop time of %g on %d procs for %d steps with "
BIGINT_FORMAT " atoms\n",
time_loop,nprocs,update->nsteps,atom->natoms);
}
#endif
if (time_loop == 0.0) time_loop = 1.0;
}
// minimization stats
if (minflag) {
if (me == 0) {
if (screen) fprintf(screen,"\n");
if (logfile) fprintf(logfile,"\n");
}
if (me == 0) {
if (screen) {
fprintf(screen,"Minimization stats:\n");
fprintf(screen," Stopping criterion = %s\n",
update->minimize->stopstr);
fprintf(screen," Energy initial, next-to-last, final = \n"
" %18.12g %18.12g %18.12g\n",
update->minimize->einitial,update->minimize->eprevious,
update->minimize->efinal);
fprintf(screen," Force two-norm initial, final = %g %g\n",
update->minimize->fnorm2_init,update->minimize->fnorm2_final);
fprintf(screen," Force max component initial, final = %g %g\n",
update->minimize->fnorminf_init,
update->minimize->fnorminf_final);
fprintf(screen," Final line search alpha, max atom move = %g %g\n",
update->minimize->alpha_final,
update->minimize->alpha_final*
update->minimize->fnorminf_final);
fprintf(screen," Iterations, force evaluations = %d %d\n",
update->minimize->niter,update->minimize->neval);
}
if (logfile) {
fprintf(logfile,"Minimization stats:\n");
fprintf(logfile," Stopping criterion = %s\n",
update->minimize->stopstr);
fprintf(logfile," Energy initial, next-to-last, final = \n"
" %18.12g %18.12g %18.12g\n",
update->minimize->einitial,update->minimize->eprevious,
update->minimize->efinal);
fprintf(logfile," Force two-norm initial, final = %g %g\n",
update->minimize->fnorm2_init,update->minimize->fnorm2_final);
fprintf(logfile," Force max component initial, final = %g %g\n",
update->minimize->fnorminf_init,
update->minimize->fnorminf_final);
fprintf(logfile," Final line search alpha, max atom move = %g %g\n",
update->minimize->alpha_final,
update->minimize->alpha_final*
update->minimize->fnorminf_final);
fprintf(logfile," Iterations, force evaluations = %d %d\n",
update->minimize->niter,update->minimize->neval);
}
}
}
// PRD stats using PAIR,BOND,KSPACE for dephase,dynamics,quench
if (prdflag) {
if (me == 0) {
if (screen) fprintf(screen,"\n");
if (logfile) fprintf(logfile,"\n");
}
if (screen) fprintf(screen,"PRD stats:\n");
if (logfile) fprintf(logfile,"PRD stats:\n");
time = timer->array[TIME_PAIR];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Dephase time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Dephase time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_BOND];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Dynamics time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Dynamics time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_KSPACE];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Quench time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Quench time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = time_other;
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Other time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Other time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
}
// TAD stats using PAIR,BOND,KSPACE for neb,dynamics,quench
if (tadflag) {
if (me == 0) {
if (screen) fprintf(screen,"\n");
if (logfile) fprintf(logfile,"\n");
}
if (screen) fprintf(screen,"TAD stats:\n");
if (logfile) fprintf(logfile,"TAD stats:\n");
time = timer->array[TIME_PAIR];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," NEB time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," NEB time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_BOND];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Dynamics time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Dynamics time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_KSPACE];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Quench time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Quench time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_COMM];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Comm time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Comm time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_OUTPUT];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Output time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Output time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = time_other;
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen," Other time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile," Other time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
}
// timing breakdowns
if (timeflag) {
if (me == 0) {
if (screen) fprintf(screen,"\n");
if (logfile) fprintf(logfile,"\n");
}
time = timer->array[TIME_PAIR];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen,"Pair time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile,"Pair time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
if (atom->molecular) {
time = timer->array[TIME_BOND];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen,"Bond time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile,"Bond time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
}
if (force->kspace) {
time = timer->array[TIME_KSPACE];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen,"Kspce time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile,"Kspce time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
}
time = timer->array[TIME_NEIGHBOR];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen,"Neigh time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile,"Neigh time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_COMM];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen,"Comm time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile,"Comm time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = timer->array[TIME_OUTPUT];
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen,"Outpt time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile,"Outpt time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
time = time_other;
MPI_Allreduce(&time,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time = tmp/nprocs;
if (me == 0) {
if (screen)
fprintf(screen,"Other time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
if (logfile)
fprintf(logfile,"Other time (%%) = %g (%g)\n",
time,time/time_loop*100.0);
}
}
// FFT timing statistics
// time3d,time1d = total time during run for 3d and 1d FFTs
if (fftflag) {
if (me == 0) {
if (screen) fprintf(screen,"\n");
if (logfile) fprintf(logfile,"\n");
}
int nsteps = update->nsteps;
int nsample = 5;
double time3d,time1d;
force->kspace->timing(nsample,time3d,time1d);
time3d = nsteps * time3d / nsample;
MPI_Allreduce(&time3d,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time3d = tmp/nprocs;
time1d = nsteps * time1d / nsample;
MPI_Allreduce(&time1d,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time1d = tmp/nprocs;
double time_kspace = timer->array[TIME_KSPACE];
MPI_Allreduce(&time_kspace,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
time_kspace = tmp/nprocs;
double ntotal = 1.0 * force->kspace->nx_pppm *
force->kspace->ny_pppm * force->kspace->nz_pppm;
double nflops = 5.0 * ntotal * log(ntotal);
double fraction,flop3,flop1;
if (nsteps) {
fraction = time3d/time_kspace*100.0;
flop3 = nflops/1.0e9/(time3d/4.0/nsteps);
flop1 = nflops/1.0e9/(time1d/4.0/nsteps);
} else fraction = flop3 = flop1 = 0.0;
if (me == 0) {
if (screen) {
fprintf(screen,"FFT time (%% of Kspce) = %g (%g)\n",time3d,fraction);
fprintf(screen,"FFT Gflps 3d (1d only) = %g %g\n",flop3,flop1);
}
if (logfile) {
fprintf(logfile,"FFT time (%% of Kspce) = %g (%g)\n",time3d,fraction);
fprintf(logfile,"FFT Gflps 3d (1d only) = %g %g\n",flop3,flop1);
}
}
}
if (histoflag) {
if (me == 0) {
if (screen) fprintf(screen,"\n");
if (logfile) fprintf(logfile,"\n");
}
tmp = atom->nlocal;
stats(1,&tmp,&ave,&max,&min,10,histo);
if (me == 0) {
if (screen) {
fprintf(screen,"Nlocal: %g ave %g max %g min\n",ave,max,min);
fprintf(screen,"Histogram:");
for (i = 0; i < 10; i++) fprintf(screen," %d",histo[i]);
fprintf(screen,"\n");
}
if (logfile) {
fprintf(logfile,"Nlocal: %g ave %g max %g min\n",ave,max,min);
fprintf(logfile,"Histogram:");
for (i = 0; i < 10; i++) fprintf(logfile," %d",histo[i]);
fprintf(logfile,"\n");
}
}
tmp = atom->nghost;
stats(1,&tmp,&ave,&max,&min,10,histo);
if (me == 0) {
if (screen) {
fprintf(screen,"Nghost: %g ave %g max %g min\n",ave,max,min);
fprintf(screen,"Histogram:");
for (i = 0; i < 10; i++) fprintf(screen," %d",histo[i]);
fprintf(screen,"\n");
}
if (logfile) {
fprintf(logfile,"Nghost: %g ave %g max %g min\n",ave,max,min);
fprintf(logfile,"Histogram:");
for (i = 0; i < 10; i++) fprintf(logfile," %d",histo[i]);
fprintf(logfile,"\n");
}
}
// find a non-skip neighbor list containing half the pairwise interactions
// count neighbors in that list for stats purposes
for (m = 0; m < neighbor->old_nrequest; m++)
if ((neighbor->old_requests[m]->half ||
neighbor->old_requests[m]->gran ||
neighbor->old_requests[m]->respaouter ||
neighbor->old_requests[m]->half_from_full) &&
neighbor->old_requests[m]->skip == 0 &&
neighbor->lists[m]->numneigh) break;
nneigh = 0;
if (m < neighbor->old_nrequest) {
int inum = neighbor->lists[m]->inum;
int *ilist = neighbor->lists[m]->ilist;
int *numneigh = neighbor->lists[m]->numneigh;
for (i = 0; i < inum; i++)
nneigh += numneigh[ilist[i]];
}
tmp = nneigh;
stats(1,&tmp,&ave,&max,&min,10,histo);
if (me == 0) {
if (screen) {
fprintf(screen,"Neighs: %g ave %g max %g min\n",ave,max,min);
fprintf(screen,"Histogram:");
for (i = 0; i < 10; i++) fprintf(screen," %d",histo[i]);
fprintf(screen,"\n");
}
if (logfile) {
fprintf(logfile,"Neighs: %g ave %g max %g min\n",ave,max,min);
fprintf(logfile,"Histogram:");
for (i = 0; i < 10; i++) fprintf(logfile," %d",histo[i]);
fprintf(logfile,"\n");
}
}
// find a non-skip neighbor list containing full pairwise interactions
// count neighbors in that list for stats purposes
for (m = 0; m < neighbor->old_nrequest; m++)
if (neighbor->old_requests[m]->full &&
neighbor->old_requests[m]->skip == 0) break;
nneighfull = 0;
if (m < neighbor->old_nrequest) {
if (neighbor->lists[m]->numneigh > 0) {
int inum = neighbor->lists[m]->inum;
int *ilist = neighbor->lists[m]->ilist;
int *numneigh = neighbor->lists[m]->numneigh;
for (i = 0; i < inum; i++)
nneighfull += numneigh[ilist[i]];
}
tmp = nneighfull;
stats(1,&tmp,&ave,&max,&min,10,histo);
if (me == 0) {
if (screen) {
fprintf(screen,"FullNghs: %g ave %g max %g min\n",ave,max,min);
fprintf(screen,"Histogram:");
for (i = 0; i < 10; i++) fprintf(screen," %d",histo[i]);
fprintf(screen,"\n");
}
if (logfile) {
fprintf(logfile,"FullNghs: %g ave %g max %g min\n",ave,max,min);
fprintf(logfile,"Histogram:");
for (i = 0; i < 10; i++) fprintf(logfile," %d",histo[i]);
fprintf(logfile,"\n");
}
}
}
}
if (neighflag) {
if (me == 0) {
if (screen) fprintf(screen,"\n");
if (logfile) fprintf(logfile,"\n");
}
tmp = MAX(nneigh,nneighfull);
double nall;
MPI_Allreduce(&tmp,&nall,1,MPI_DOUBLE,MPI_SUM,world);
int nspec;
double nspec_all;
if (atom->molecular) {
nspec = 0;
for (i = 0; i < atom->nlocal; i++) nspec += atom->nspecial[i][2];
tmp = nspec;
MPI_Allreduce(&tmp,&nspec_all,1,MPI_DOUBLE,MPI_SUM,world);
}
if (me == 0) {
if (screen) {
if (nall < 2.0e9)
fprintf(screen,
"Total # of neighbors = %d\n",static_cast<int> (nall));
else fprintf(screen,"Total # of neighbors = %g\n",nall);
if (atom->natoms > 0)
fprintf(screen,"Ave neighs/atom = %g\n",nall/atom->natoms);
if (atom->molecular && atom->natoms > 0)
fprintf(screen,"Ave special neighs/atom = %g\n",
nspec_all/atom->natoms);
fprintf(screen,"Neighbor list builds = %d\n",neighbor->ncalls);
fprintf(screen,"Dangerous builds = %d\n",neighbor->ndanger);
}
if (logfile) {
if (nall < 2.0e9)
fprintf(logfile,
"Total # of neighbors = %d\n",static_cast<int> (nall));
else fprintf(logfile,"Total # of neighbors = %g\n",nall);
if (atom->natoms > 0)
fprintf(logfile,"Ave neighs/atom = %g\n",nall/atom->natoms);
if (atom->molecular && atom->natoms > 0)
fprintf(logfile,"Ave special neighs/atom = %g\n",
nspec_all/atom->natoms);
fprintf(logfile,"Neighbor list builds = %d\n",neighbor->ncalls);
fprintf(logfile,"Dangerous builds = %d\n",neighbor->ndanger);
}
}
}
if (logfile) fflush(logfile);
}
/* ---------------------------------------------------------------------- */
void Finish::stats(int n, double *data,
double *pave, double *pmax, double *pmin,
int nhisto, int *histo)
{
int i,m;
int *histotmp;
double min = 1.0e20;
double max = -1.0e20;
double ave = 0.0;
for (i = 0; i < n; i++) {
ave += data[i];
if (data[i] < min) min = data[i];
if (data[i] > max) max = data[i];
}
int ntotal;
MPI_Allreduce(&n,&ntotal,1,MPI_INT,MPI_SUM,world);
double tmp;
MPI_Allreduce(&ave,&tmp,1,MPI_DOUBLE,MPI_SUM,world);
ave = tmp/ntotal;
MPI_Allreduce(&min,&tmp,1,MPI_DOUBLE,MPI_MIN,world);
min = tmp;
MPI_Allreduce(&max,&tmp,1,MPI_DOUBLE,MPI_MAX,world);
max = tmp;
for (i = 0; i < nhisto; i++) histo[i] = 0;
double del = max - min;
for (i = 0; i < n; i++) {
if (del == 0.0) m = 0;
else m = static_cast<int> ((data[i]-min)/del * nhisto);
if (m > nhisto-1) m = nhisto-1;
histo[m]++;
}
memory->create(histotmp,nhisto,"finish:histotmp");
MPI_Allreduce(histo,histotmp,nhisto,MPI_INT,MPI_SUM,world);
for (i = 0; i < nhisto; i++) histo[i] = histotmp[i];
memory->destroy(histotmp);
*pave = ave;
*pmax = max;
*pmin = min;
}
diff --git a/src/fix.cpp b/src/fix.cpp
index 2ed2dc748..dc4263b7d 100644
--- a/src/fix.cpp
+++ b/src/fix.cpp
@@ -1,201 +1,201 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "ctype.h"
#include "fix.h"
#include "atom.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Fix::Fix(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
// fix ID, group, and style
// ID must be all alphanumeric chars or underscores
int n = strlen(arg[0]) + 1;
id = new char[n];
strcpy(id,arg[0]);
for (int i = 0; i < n-1; i++)
if (!isalnum(id[i]) && id[i] != '_')
- error->all("Fix ID must be alphanumeric or underscore characters");
+ error->all(FLERR,"Fix ID must be alphanumeric or underscore characters");
igroup = group->find(arg[1]);
- if (igroup == -1) error->all("Could not find fix group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find fix group ID");
groupbit = group->bitmask[igroup];
n = strlen(arg[2]) + 1;
style = new char[n];
strcpy(style,arg[2]);
restart_global = 0;
restart_peratom = 0;
force_reneighbor = 0;
box_change = 0;
box_change_size = 0;
box_change_shape = 0;
thermo_energy = 0;
rigid_flag = 0;
virial_flag = 0;
no_change_box = 0;
time_integrate = 0;
time_depend = 0;
create_attribute = 0;
restart_pbc = 0;
cudable_comm = 0;
scalar_flag = vector_flag = array_flag = 0;
peratom_flag = local_flag = 0;
comm_forward = comm_reverse = 0;
maxvatom = 0;
vatom = NULL;
// mask settings - same as in modify.cpp
INITIAL_INTEGRATE = 1;
POST_INTEGRATE = 2;
PRE_EXCHANGE = 4;
PRE_NEIGHBOR = 8;
PRE_FORCE = 16;
POST_FORCE = 32;
FINAL_INTEGRATE = 64;
END_OF_STEP = 128;
THERMO_ENERGY = 256;
INITIAL_INTEGRATE_RESPA = 512;
POST_INTEGRATE_RESPA = 1024;
PRE_FORCE_RESPA = 2048;
POST_FORCE_RESPA = 4096;
FINAL_INTEGRATE_RESPA = 8192;
MIN_PRE_EXCHANGE = 16384;
MIN_PRE_FORCE = 32768;
MIN_POST_FORCE = 65536;
MIN_ENERGY = 131072;
POST_RUN = 262144;
}
/* ---------------------------------------------------------------------- */
Fix::~Fix()
{
delete [] id;
delete [] style;
memory->destroy(vatom);
}
/* ----------------------------------------------------------------------
process params common to all fixes here
if unknown param, call modify_param specific to the fix
------------------------------------------------------------------------- */
void Fix::modify_params(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal fix_modify command");
+ if (narg == 0) error->all(FLERR,"Illegal fix_modify command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"energy") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix_modify command");
if (strcmp(arg[iarg+1],"no") == 0) thermo_energy = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) thermo_energy = 1;
- else error->all("Illegal fix_modify command");
+ else error->all(FLERR,"Illegal fix_modify command");
iarg += 2;
} else {
int n = modify_param(narg-iarg,&arg[iarg]);
- if (n == 0) error->all("Illegal fix_modify command");
+ if (n == 0) error->all(FLERR,"Illegal fix_modify command");
iarg += n;
}
}
}
/* ----------------------------------------------------------------------
setup for virial computation
see integrate::ev_set() for values of vflag (0-6)
------------------------------------------------------------------------- */
void Fix::v_setup(int vflag)
{
int i,n;
evflag = 1;
vflag_global = vflag % 4;
vflag_atom = vflag / 4;
// reallocate per-atom array if necessary
if (vflag_atom && atom->nlocal > maxvatom) {
maxvatom = atom->nmax;
memory->destroy(vatom);
memory->create(vatom,maxvatom,6,"bond:vatom");
}
// zero accumulators
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
if (vflag_atom) {
n = atom->nlocal;
for (i = 0; i < n; i++) {
vatom[i][0] = 0.0;
vatom[i][1] = 0.0;
vatom[i][2] = 0.0;
vatom[i][3] = 0.0;
vatom[i][4] = 0.0;
vatom[i][5] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
tally virial into global and per-atom accumulators
v = total virial for the interaction involving total atoms
n = # of local atoms involved, with local indices in list
increment global virial by n/total fraction
increment per-atom virial of each atom in list by 1/total fraction
assumes other procs will tally left-over fractions
------------------------------------------------------------------------- */
void Fix::v_tally(int n, int *list, double total, double *v)
{
int m;
if (vflag_global) {
double fraction = n/total;
virial[0] += fraction*v[0];
virial[1] += fraction*v[1];
virial[2] += fraction*v[2];
virial[3] += fraction*v[3];
virial[4] += fraction*v[4];
virial[5] += fraction*v[5];
}
if (vflag_atom) {
double fraction = 1.0/total;
for (int i = 0; i < n; i++) {
m = list[i];
vatom[m][0] += fraction*v[0];
vatom[m][1] += fraction*v[1];
vatom[m][2] += fraction*v[2];
vatom[m][3] += fraction*v[3];
vatom[m][4] += fraction*v[4];
vatom[m][5] += fraction*v[5];
}
}
}
diff --git a/src/fix_adapt.cpp b/src/fix_adapt.cpp
index d5825b561..fd1a256b8 100644
--- a/src/fix_adapt.cpp
+++ b/src/fix_adapt.cpp
@@ -1,373 +1,370 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_adapt.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "force.h"
#include "pair.h"
#include "pair_hybrid.h"
#include "kspace.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{PAIR,KSPACE,ATOM};
enum{DIAMETER};
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixAdapt::FixAdapt(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix adapt command");
+ if (narg < 5) error->all(FLERR,"Illegal fix adapt command");
nevery = atoi(arg[3]);
- if (nevery < 0) error->all("Illegal fix adapt command");
+ if (nevery < 0) error->all(FLERR,"Illegal fix adapt command");
// count # of adaptations
nadapt = 0;
int iarg = 4;
while (iarg < narg) {
if (strcmp(arg[iarg],"pair") == 0) {
- if (iarg+6 > narg) error->all("Illegal fix adapt command");
+ if (iarg+6 > narg) error->all(FLERR,"Illegal fix adapt command");
nadapt++;
iarg += 6;
} else if (strcmp(arg[iarg],"kspace") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix adapt command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt command");
nadapt++;
iarg += 2;
} else if (strcmp(arg[iarg],"atom") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix adapt command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix adapt command");
nadapt++;
iarg += 3;
} else break;
}
- if (nadapt == 0) error->all("Illegal fix adapt command");
+ if (nadapt == 0) error->all(FLERR,"Illegal fix adapt command");
adapt = new Adapt[nadapt];
// parse keywords
nadapt = 0;
diamflag = 0;
iarg = 4;
while (iarg < narg) {
if (strcmp(arg[iarg],"pair") == 0) {
- if (iarg+6 > narg) error->all("Illegal fix adapt command");
+ if (iarg+6 > narg) error->all(FLERR,"Illegal fix adapt command");
adapt[nadapt].which = PAIR;
int n = strlen(arg[iarg+1]) + 1;
adapt[nadapt].pstyle = new char[n];
strcpy(adapt[nadapt].pstyle,arg[iarg+1]);
n = strlen(arg[iarg+2]) + 1;
adapt[nadapt].pparam = new char[n];
strcpy(adapt[nadapt].pparam,arg[iarg+2]);
force->bounds(arg[iarg+3],atom->ntypes,
adapt[nadapt].ilo,adapt[nadapt].ihi);
force->bounds(arg[iarg+4],atom->ntypes,
adapt[nadapt].jlo,adapt[nadapt].jhi);
if (strstr(arg[iarg+5],"v_") == arg[iarg+5]) {
n = strlen(&arg[iarg+5][2]) + 1;
adapt[nadapt].var = new char[n];
strcpy(adapt[nadapt].var,&arg[iarg+5][2]);
- } else error->all("Illegal fix adapt command");
+ } else error->all(FLERR,"Illegal fix adapt command");
nadapt++;
iarg += 6;
} else if (strcmp(arg[iarg],"kspace") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix adapt command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt command");
adapt[nadapt].which = KSPACE;
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
adapt[nadapt].var = new char[n];
strcpy(adapt[nadapt].var,&arg[iarg+1][2]);
- } else error->all("Illegal fix adapt command");
+ } else error->all(FLERR,"Illegal fix adapt command");
nadapt++;
iarg += 2;
} else if (strcmp(arg[iarg],"atom") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix adapt command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix adapt command");
adapt[nadapt].which = ATOM;
if (strcmp(arg[iarg+1],"diameter") == 0) {
adapt[nadapt].aparam = DIAMETER;
diamflag = 1;
- } else error->all("Illegal fix adapt command");
+ } else error->all(FLERR,"Illegal fix adapt command");
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
adapt[nadapt].var = new char[n];
strcpy(adapt[nadapt].var,&arg[iarg+2][2]);
- } else error->all("Illegal fix adapt command");
+ } else error->all(FLERR,"Illegal fix adapt command");
nadapt++;
iarg += 3;
} else break;
}
// optional keywords
resetflag = 0;
scaleflag = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"reset") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix adapt command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt command");
if (strcmp(arg[iarg+1],"no") == 0) resetflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) resetflag = 1;
- else error->all("Illegal fix adapt command");
+ else error->all(FLERR,"Illegal fix adapt command");
iarg += 2;
} else if (strcmp(arg[iarg],"scale") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix adapt command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix adapt command");
if (strcmp(arg[iarg+1],"no") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) scaleflag = 1;
- else error->all("Illegal fix adapt command");
+ else error->all(FLERR,"Illegal fix adapt command");
iarg += 2;
- } else error->all("Illegal fix adapt command");
+ } else error->all(FLERR,"Illegal fix adapt command");
}
// allocate pair style arrays
int n = atom->ntypes;
for (int m = 0; m < nadapt; m++)
if (adapt[m].which == PAIR)
memory->create(adapt[m].array_orig,n+1,n+1,"adapt:array_orig");
}
/* ---------------------------------------------------------------------- */
FixAdapt::~FixAdapt()
{
for (int m = 0; m < nadapt; m++) {
delete [] adapt[m].var;
if (adapt[m].which == PAIR) {
delete [] adapt[m].pstyle;
delete [] adapt[m].pparam;
memory->destroy(adapt[m].array_orig);
}
}
delete [] adapt;
}
/* ---------------------------------------------------------------------- */
int FixAdapt::setmask()
{
int mask = 0;
mask |= PRE_FORCE;
mask |= POST_RUN;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAdapt::init()
{
int i,j;
// setup and error checks
anypair = 0;
for (int m = 0; m < nadapt; m++) {
Adapt *ad = &adapt[m];
ad->ivar = input->variable->find(ad->var);
if (ad->ivar < 0)
- error->all("Variable name for fix adapt does not exist");
+ error->all(FLERR,"Variable name for fix adapt does not exist");
if (!input->variable->equalstyle(ad->ivar))
- error->all("Variable for fix adapt is invalid style");
+ error->all(FLERR,"Variable for fix adapt is invalid style");
if (ad->which == PAIR) {
anypair = 1;
Pair *pair = force->pair_match(ad->pstyle,1);
- if (pair == NULL) error->all("Fix adapt pair style does not exist");
+ if (pair == NULL) error->all(FLERR,"Fix adapt pair style does not exist");
void *ptr = pair->extract(ad->pparam,ad->pdim);
- if (ptr == NULL) error->all("Fix adapt pair style param not supported");
+ if (ptr == NULL) error->all(FLERR,"Fix adapt pair style param not supported");
ad->pdim = 2;
if (ad->pdim == 0) ad->scalar = (double *) ptr;
if (ad->pdim == 2) ad->array = (double **) ptr;
// if pair hybrid, test that ilo,ihi,jlo,jhi are valid for sub-style
if (ad->pdim == 2 && (strcmp(force->pair_style,"hybrid") == 0 ||
strcmp(force->pair_style,"hybrid/overlay") == 0)) {
PairHybrid *pair = (PairHybrid *) force->pair;
for (i = ad->ilo; i <= ad->ihi; i++)
for (j = MAX(ad->jlo,i); j <= ad->jhi; j++)
if (!pair->check_ijtype(i,j,ad->pstyle))
- error->all("Fix adapt type pair range is not valid for "
+ error->all(FLERR,"Fix adapt type pair range is not valid for "
"pair hybrid sub-style");
}
} else if (ad->which == KSPACE) {
if (force->kspace == NULL)
- error->all("Fix adapt kspace style does not exist");
+ error->all(FLERR,"Fix adapt kspace style does not exist");
kspace_scale = (double *) force->kspace->extract("scale");
} else if (ad->which == ATOM) {
if (ad->aparam == DIAMETER) {
if (!atom->radius_flag)
- error->all("Fix adapt requires atom attribute diameter");
+ error->all(FLERR,"Fix adapt requires atom attribute diameter");
}
}
}
// make copy of original pair array values
for (int m = 0; m < nadapt; m++) {
Adapt *ad = &adapt[m];
if (ad->which == PAIR && ad->pdim == 2) {
for (i = ad->ilo; i <= ad->ihi; i++)
for (j = MAX(ad->jlo,i); j <= ad->jhi; j++)
ad->array_orig[i][j] = ad->array[i][j];
}
}
}
/* ---------------------------------------------------------------------- */
void FixAdapt::setup_pre_force(int vflag)
{
change_settings();
}
/* ---------------------------------------------------------------------- */
void FixAdapt::pre_force(int vflag)
{
if (nevery == 0) return;
if (update->ntimestep % nevery) return;
change_settings();
}
/* ---------------------------------------------------------------------- */
void FixAdapt::post_run()
{
if (resetflag) restore_settings();
}
/* ----------------------------------------------------------------------
change pair,kspace,atom parameters based on variable evaluation
------------------------------------------------------------------------- */
void FixAdapt::change_settings()
{
int i,j;
// variable evaluation may invoke computes so wrap with clear/add
modify->clearstep_compute();
for (int m = 0; m < nadapt; m++) {
Adapt *ad = &adapt[m];
double value = input->variable->compute_equal(ad->ivar);
// set global scalar or type pair array values
if (ad->which == PAIR) {
if (ad->pdim == 0) {
if (scaleflag) *ad->scalar = value * ad->scalar_orig;
else *ad->scalar = value;
} else if (ad->pdim == 2) {
if (scaleflag)
for (i = ad->ilo; i <= ad->ihi; i++)
for (j = MAX(ad->jlo,i); j <= ad->jhi; j++)
ad->array[i][j] = value*ad->array_orig[i][j];
else
for (i = ad->ilo; i <= ad->ihi; i++)
for (j = MAX(ad->jlo,i); j <= ad->jhi; j++)
ad->array[i][j] = value;
}
// set kspace scale factor
} else if (ad->which == KSPACE) {
*kspace_scale = value;
} else if (ad->which == ATOM) {
// set radius from diameter
// also scale rmass to new value
if (ad->aparam == DIAMETER) {
int mflag = 0;
if (atom->rmass_flag) mflag = 1;
double PI = 4.0*atan(1.0);
double density;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (mflag == 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
radius[i] = 0.5*value;
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
density = rmass[i] / (4.0*PI/3.0 * radius[i]*radius[i]*radius[i]);
radius[i] = 0.5*value;
rmass[i] = 4.0*PI/3.0 * radius[i]*radius[i]*radius[i] * density;
}
}
}
}
}
modify->addstep_compute(update->ntimestep + nevery);
// re-initialize pair styles if any PAIR settings were changed
// this resets other coeffs that may depend on changed values,
// and also offset and tail corrections
if (anypair) force->pair->reinit();
}
/* ----------------------------------------------------------------------
restore pair,kspace.atom parameters to original values
------------------------------------------------------------------------- */
void FixAdapt::restore_settings()
{
for (int m = 0; m < nadapt; m++) {
Adapt *ad = &adapt[m];
if (ad->which == PAIR) {
if (ad->pdim == 0) *ad->scalar = ad->scalar_orig;
else if (ad->pdim == 2) {
for (int i = ad->ilo; i <= ad->ihi; i++)
for (int j = MAX(ad->jlo,i); j <= ad->jhi; j++)
ad->array[i][j] = ad->array_orig[i][j];
}
} else if (ad->which == KSPACE) {
*kspace_scale = 1.0;
} else if (ad->which == ATOM) {
}
}
if (anypair) force->pair->reinit();
}
diff --git a/src/fix_addforce.cpp b/src/fix_addforce.cpp
index fa5c3be60..16a3c1fea 100644
--- a/src/fix_addforce.cpp
+++ b/src/fix_addforce.cpp
@@ -1,347 +1,347 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "fix_addforce.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "region.h"
#include "respa.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NONE,CONSTANT,EQUAL,ATOM};
/* ---------------------------------------------------------------------- */
FixAddForce::FixAddForce(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix addforce command");
+ if (narg < 6) error->all(FLERR,"Illegal fix addforce command");
scalar_flag = 1;
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extscalar = 1;
extvector = 1;
xstr = ystr = zstr = NULL;
if (strstr(arg[3],"v_") == arg[3]) {
int n = strlen(&arg[3][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[3][2]);
} else {
xvalue = atof(arg[3]);
xstyle = CONSTANT;
}
if (strstr(arg[4],"v_") == arg[4]) {
int n = strlen(&arg[4][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[4][2]);
} else {
yvalue = atof(arg[4]);
ystyle = CONSTANT;
}
if (strstr(arg[5],"v_") == arg[5]) {
int n = strlen(&arg[5][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[5][2]);
} else {
zvalue = atof(arg[5]);
zstyle = CONSTANT;
}
// optional args
iregion = -1;
idregion = NULL;
estr = NULL;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix addforce command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix addforce command");
iregion = domain->find_region(arg[iarg+1]);
if (iregion == -1)
- error->all("Region ID for fix addforce does not exist");
+ error->all(FLERR,"Region ID for fix addforce does not exist");
int n = strlen(arg[iarg+1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"energy") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix addforce command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix addforce command");
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
estr = new char[n];
strcpy(estr,&arg[iarg+1][2]);
- } else error->all("Illegal fix addforce command");
+ } else error->all(FLERR,"Illegal fix addforce command");
iarg += 2;
- } else error->all("Illegal fix addforce command");
+ } else error->all(FLERR,"Illegal fix addforce command");
}
force_flag = 0;
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
maxatom = 0;
sforce = NULL;
}
/* ---------------------------------------------------------------------- */
FixAddForce::~FixAddForce()
{
delete [] xstr;
delete [] ystr;
delete [] zstr;
delete [] estr;
delete [] idregion;
memory->destroy(sforce);
}
/* ---------------------------------------------------------------------- */
int FixAddForce::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAddForce::init()
{
// check variables
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for fix addforce does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for fix addforce does not exist");
if (input->variable->equalstyle(xvar)) xstyle = EQUAL;
else if (input->variable->atomstyle(xvar)) xstyle = ATOM;
- else error->all("Variable for fix addforce is invalid style");
+ else error->all(FLERR,"Variable for fix addforce is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for fix addforce does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for fix addforce does not exist");
if (input->variable->equalstyle(yvar)) ystyle = EQUAL;
else if (input->variable->atomstyle(yvar)) ystyle = ATOM;
- else error->all("Variable for fix addforce is invalid style");
+ else error->all(FLERR,"Variable for fix addforce is invalid style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for fix addforce does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for fix addforce does not exist");
if (input->variable->equalstyle(zvar)) zstyle = EQUAL;
else if (input->variable->atomstyle(zvar)) zstyle = ATOM;
- else error->all("Variable for fix addforce is invalid style");
+ else error->all(FLERR,"Variable for fix addforce is invalid style");
}
if (estr) {
evar = input->variable->find(estr);
- if (evar < 0) error->all("Variable name for fix addforce does not exist");
+ if (evar < 0) error->all(FLERR,"Variable name for fix addforce does not exist");
if (input->variable->atomstyle(evar)) estyle = ATOM;
- else error->all("Variable for fix addforce is invalid style");
+ else error->all(FLERR,"Variable for fix addforce is invalid style");
} else estyle = NONE;
// set index and check validity of region
if (iregion >= 0) {
iregion = domain->find_region(idregion);
- if (iregion == -1) error->all("Region ID for fix addforce does not exist");
+ if (iregion == -1) error->all(FLERR,"Region ID for fix addforce does not exist");
}
if (xstyle == ATOM || ystyle == ATOM || zstyle == ATOM)
varflag = ATOM;
else if (xstyle == EQUAL || ystyle == EQUAL || zstyle == EQUAL)
varflag = EQUAL;
else varflag = CONSTANT;
if (varflag == CONSTANT && estyle != NONE)
- error->all("Cannot use variable energy with "
+ error->all(FLERR,"Cannot use variable energy with "
"constant force in fix addforce");
if ((varflag == EQUAL || varflag == ATOM) &&
update->whichflag == 2 && estyle == NONE)
- error->all("Must use variable energy with fix addforce");
+ error->all(FLERR,"Must use variable energy with fix addforce");
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixAddForce::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixAddForce::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAddForce::post_force(int vflag)
{
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// reallocate sforce array if necessary
if ((varflag == ATOM || estyle == ATOM) && nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(sforce);
memory->create(sforce,maxatom,4,"addforce:sforce");
}
// foriginal[0] = "potential energy" for added force
// foriginal[123] = force on atoms before extra force added
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
force_flag = 0;
// constant force
// potential energy = - x dot f
if (varflag == CONSTANT) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
foriginal[0] -= xvalue*x[i][0] + yvalue*x[i][1] + zvalue*x[i][2];
foriginal[1] += f[i][0];
foriginal[2] += f[i][1];
foriginal[3] += f[i][2];
f[i][0] += xvalue;
f[i][1] += yvalue;
f[i][2] += zvalue;
}
// variable force, wrap with clear/add
// potential energy = evar if defined, else 0.0
// wrap with clear/add
} else {
modify->clearstep_compute();
if (xstyle == EQUAL) xvalue = input->variable->compute_equal(xvar);
else if (xstyle == ATOM && sforce)
input->variable->compute_atom(xvar,igroup,&sforce[0][0],4,0);
if (ystyle == EQUAL) yvalue = input->variable->compute_equal(yvar);
else if (ystyle == ATOM && sforce)
input->variable->compute_atom(yvar,igroup,&sforce[0][1],4,0);
if (zstyle == EQUAL) zvalue = input->variable->compute_equal(zvar);
else if (zstyle == ATOM && sforce)
input->variable->compute_atom(zvar,igroup,&sforce[0][2],4,0);
if (estyle == ATOM && sforce)
input->variable->compute_atom(evar,igroup,&sforce[0][3],4,0);
modify->addstep_compute(update->ntimestep + 1);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
if (estyle == ATOM) foriginal[0] += sforce[i][3];
foriginal[1] += f[i][0];
foriginal[2] += f[i][1];
foriginal[3] += f[i][2];
if (xstyle == ATOM) f[i][0] += sforce[i][0];
else if (xstyle) f[i][0] += xvalue;
if (ystyle == ATOM) f[i][1] += sforce[i][1];
else if (ystyle) f[i][1] += yvalue;
if (zstyle == ATOM) f[i][2] += sforce[i][2];
else if (zstyle) f[i][2] += zvalue;
}
}
}
/* ---------------------------------------------------------------------- */
void FixAddForce::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAddForce::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
potential energy of added force
------------------------------------------------------------------------- */
double FixAddForce::compute_scalar()
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[0];
}
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixAddForce::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[n+1];
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixAddForce::memory_usage()
{
double bytes = 0.0;
if (varflag == ATOM) bytes = atom->nmax*4 * sizeof(double);
return bytes;
}
diff --git a/src/fix_ave_atom.cpp b/src/fix_ave_atom.cpp
index b604977f7..01f21f950 100644
--- a/src/fix_ave_atom.cpp
+++ b/src/fix_ave_atom.cpp
@@ -1,449 +1,449 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_ave_atom.h"
#include "atom.h"
#include "domain.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{X,V,F,COMPUTE,FIX,VARIABLE};
#define INVOKED_PERATOM 8
/* ---------------------------------------------------------------------- */
FixAveAtom::FixAveAtom(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal fix ave/atom command");
+ if (narg < 7) error->all(FLERR,"Illegal fix ave/atom command");
time_depend = 1;
nevery = atoi(arg[3]);
nrepeat = atoi(arg[4]);
peratom_freq = atoi(arg[5]);
// parse remaining values
which = new int[narg-6];
argindex = new int[narg-6];
ids = new char*[narg-6];
value2index = new int[narg-6];
nvalues = 0;
int iarg = 6;
while (iarg < narg) {
ids[nvalues] = NULL;
if (strcmp(arg[iarg],"x") == 0) {
which[nvalues] = X;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"y") == 0) {
which[nvalues] = X;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"z") == 0) {
which[nvalues] = X;
argindex[nvalues++] = 2;
} else if (strcmp(arg[iarg],"vx") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"vy") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"vz") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 2;
} else if (strcmp(arg[iarg],"fx") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"fy") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"fz") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 2;
} else if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal fix ave/atom command");
+ error->all(FLERR,"Illegal fix ave/atom command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
nvalues++;
delete [] suffix;
- } else error->all("Illegal fix ave/atom command");
+ } else error->all(FLERR,"Illegal fix ave/atom command");
iarg++;
}
// setup and error check
// for fix inputs, check that fix frequency is acceptable
if (nevery <= 0 || nrepeat <= 0 || peratom_freq <= 0)
- error->all("Illegal fix ave/atom command");
+ error->all(FLERR,"Illegal fix ave/atom command");
if (peratom_freq % nevery || (nrepeat-1)*nevery >= peratom_freq)
- error->all("Illegal fix ave/atom command");
+ error->all(FLERR,"Illegal fix ave/atom command");
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/atom does not exist");
+ error->all(FLERR,"Compute ID for fix ave/atom does not exist");
if (modify->compute[icompute]->peratom_flag == 0)
- error->all("Fix ave/atom compute does not calculate per-atom values");
+ error->all(FLERR,"Fix ave/atom compute does not calculate per-atom values");
if (argindex[i] == 0 &&
modify->compute[icompute]->size_peratom_cols != 0)
- error->all("Fix ave/atom compute does not "
+ error->all(FLERR,"Fix ave/atom compute does not "
"calculate a per-atom vector");
if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0)
- error->all("Fix ave/atom compute does not "
+ error->all(FLERR,"Fix ave/atom compute does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_peratom_cols)
- error->all("Fix ave/atom compute array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/atom compute array is accessed out-of-range");
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/atom does not exist");
+ error->all(FLERR,"Fix ID for fix ave/atom does not exist");
if (modify->fix[ifix]->peratom_flag == 0)
- error->all("Fix ave/atom fix does not calculate per-atom values");
+ error->all(FLERR,"Fix ave/atom fix does not calculate per-atom values");
if (argindex[i] == 0 && modify->fix[ifix]->size_peratom_cols != 0)
- error->all("Fix ave/atom fix does not calculate a per-atom vector");
+ error->all(FLERR,"Fix ave/atom fix does not calculate a per-atom vector");
if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0)
- error->all("Fix ave/atom fix does not calculate a per-atom array");
+ error->all(FLERR,"Fix ave/atom fix does not calculate a per-atom array");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_peratom_cols)
- error->all("Fix ave/atom fix array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/atom fix array is accessed out-of-range");
if (nevery % modify->fix[ifix]->peratom_freq)
- error->all("Fix for fix ave/atom not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/atom not computed at compatible time");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/atom does not exist");
+ error->all(FLERR,"Variable name for fix ave/atom does not exist");
if (input->variable->atomstyle(ivariable) == 0)
- error->all("Fix ave/atom variable is not atom-style variable");
+ error->all(FLERR,"Fix ave/atom variable is not atom-style variable");
}
}
// this fix produces either a per-atom vector or array
peratom_flag = 1;
if (nvalues == 1) size_peratom_cols = 0;
else size_peratom_cols = nvalues;
// perform initial allocation of atom-based array
// register with Atom class
array = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
// zero the array since dump may access it on timestep 0
// zero the array since a variable may access it before first run
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
for (int m = 0; m < nvalues; m++)
array[i][m] = 0.0;
// nvalid = next step on which end_of_step does something
// add nvalid to all computes that store invocation times
// since don't know a priori which are invoked by this fix
// once in end_of_step() can set timestep for ones actually invoked
irepeat = 0;
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
/* ---------------------------------------------------------------------- */
FixAveAtom::~FixAveAtom()
{
// unregister callback to this fix from Atom class
atom->delete_callback(id,0);
delete [] which;
delete [] argindex;
for (int m = 0; m < nvalues; m++) delete [] ids[m];
delete [] ids;
delete [] value2index;
memory->destroy(array);
}
/* ---------------------------------------------------------------------- */
int FixAveAtom::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAveAtom::init()
{
// set indices and check validity of all computes,fixes,variables
for (int m = 0; m < nvalues; m++) {
if (which[m] == COMPUTE) {
int icompute = modify->find_compute(ids[m]);
if (icompute < 0)
- error->all("Compute ID for fix ave/atom does not exist");
+ error->all(FLERR,"Compute ID for fix ave/atom does not exist");
value2index[m] = icompute;
} else if (which[m] == FIX) {
int ifix = modify->find_fix(ids[m]);
if (ifix < 0)
- error->all("Fix ID for fix ave/atom does not exist");
+ error->all(FLERR,"Fix ID for fix ave/atom does not exist");
value2index[m] = ifix;
} else if (which[m] == VARIABLE) {
int ivariable = input->variable->find(ids[m]);
if (ivariable < 0)
- error->all("Variable name for fix ave/atom does not exist");
+ error->all(FLERR,"Variable name for fix ave/atom does not exist");
value2index[m] = ivariable;
} else value2index[m] = -1;
}
// need to reset nvalid if nvalid < ntimestep b/c minimize was performed
if (nvalid < update->ntimestep) {
irepeat = 0;
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
}
/* ----------------------------------------------------------------------
only does something if nvalid = current timestep
------------------------------------------------------------------------- */
void FixAveAtom::setup(int vflag)
{
end_of_step();
}
/* ---------------------------------------------------------------------- */
void FixAveAtom::end_of_step()
{
int i,j,m,n;
// skip if not step which requires doing something
bigint ntimestep = update->ntimestep;
if (ntimestep != nvalid) return;
// zero if first step
int nlocal = atom->nlocal;
if (irepeat == 0)
for (i = 0; i < nlocal; i++)
for (m = 0; m < nvalues; m++)
array[i][m] = 0.0;
// accumulate results of attributes,computes,fixes,variables to local copy
// compute/fix/variable may invoke computes so wrap with clear/add
modify->clearstep_compute();
int *mask = atom->mask;
for (m = 0; m < nvalues; m++) {
n = value2index[m];
j = argindex[m];
if (which[m] == X) {
double **x = atom->x;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) array[i][m] += x[i][j];
} else if (which[m] == V) {
double **v = atom->v;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) array[i][m] += v[i][j];
} else if (which[m] == F) {
double **f = atom->f;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) array[i][m] += f[i][j];
// invoke compute if not previously invoked
} else if (which[m] == COMPUTE) {
Compute *compute = modify->compute[n];
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
if (j == 0) {
double *compute_vector = compute->vector_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) array[i][m] += compute_vector[i];
} else {
int jm1 = j - 1;
double **compute_array = compute->array_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) array[i][m] += compute_array[i][jm1];
}
// access fix fields, guaranteed to be ready
} else if (which[m] == FIX) {
if (j == 0) {
double *fix_vector = modify->fix[n]->vector_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) array[i][m] += fix_vector[i];
} else {
int jm1 = j - 1;
double **fix_array = modify->fix[n]->array_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) array[i][m] += fix_array[i][jm1];
}
// evaluate atom-style variable
// final argument = 1 sums result to array
} else if (which[m] == VARIABLE && array)
input->variable->compute_atom(n,igroup,&array[0][m],nvalues,1);
}
// done if irepeat < nrepeat
// else reset irepeat and nvalid
irepeat++;
if (irepeat < nrepeat) {
nvalid += nevery;
modify->addstep_compute(nvalid);
return;
}
irepeat = 0;
nvalid = ntimestep+peratom_freq - (nrepeat-1)*nevery;
modify->addstep_compute(nvalid);
// average the final result for the Nfreq timestep
double repeat = nrepeat;
for (i = 0; i < nlocal; i++)
for (m = 0; m < nvalues; m++)
array[i][m] /= repeat;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixAveAtom::memory_usage()
{
double bytes;
bytes = atom->nmax*nvalues * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate atom-based array
------------------------------------------------------------------------- */
void FixAveAtom::grow_arrays(int nmax)
{
memory->grow(array,nmax,nvalues,"fix_ave/atom:array");
array_atom = array;
if (array) vector_atom = array[0];
else vector_atom = NULL;
}
/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */
void FixAveAtom::copy_arrays(int i, int j)
{
for (int m = 0; m < nvalues; m++)
array[j][m] = array[i][m];
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixAveAtom::pack_exchange(int i, double *buf)
{
for (int m = 0; m < nvalues; m++) buf[m] = array[i][m];
return nvalues;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixAveAtom::unpack_exchange(int nlocal, double *buf)
{
for (int m = 0; m < nvalues; m++) array[nlocal][m] = buf[m];
return nvalues;
}
/* ----------------------------------------------------------------------
calculate nvalid = next step on which end_of_step does something
can be this timestep if multiple of nfreq and nrepeat = 1
else backup from next multiple of nfreq
------------------------------------------------------------------------- */
bigint FixAveAtom::nextvalid()
{
bigint nvalid = (update->ntimestep/peratom_freq)*peratom_freq + peratom_freq;
if (nvalid-peratom_freq == update->ntimestep && nrepeat == 1)
nvalid = update->ntimestep;
else
nvalid -= (nrepeat-1)*nevery;
if (nvalid < update->ntimestep) nvalid += peratom_freq;
return nvalid;
}
diff --git a/src/fix_ave_correlate.cpp b/src/fix_ave_correlate.cpp
index 9abf3e46d..b84fc06b4 100644
--- a/src/fix_ave_correlate.cpp
+++ b/src/fix_ave_correlate.cpp
@@ -1,590 +1,594 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors:
Benoit Leblanc, Dave Rigby, Paul Saxe (Materials Design)
Reese Jones (Sandia)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_ave_correlate.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{COMPUTE,FIX,VARIABLE};
enum{ONE,RUNNING};
enum{AUTO,UPPER,LOWER,AUTOUPPER,AUTOLOWER,FULL};
#define INVOKED_SCALAR 1
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
/* ---------------------------------------------------------------------- */
FixAveCorrelate::FixAveCorrelate(LAMMPS * lmp, int narg, char **arg):
Fix (lmp, narg, arg)
{
- if (narg < 7) error->all ("Illegal fix ave/correlate command");
+ if (narg < 7) error->all(FLERR,"Illegal fix ave/correlate command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
nrepeat = atoi(arg[4]);
nfreq = atoi(arg[5]);
global_freq = nfreq;
time_depend = 1;
// parse values until one isn't recognized
which = new int[narg-6];
argindex = new int[narg-6];
ids = new char*[narg-6];
value2index = new int[narg-6];
nvalues = 0;
int iarg = 6;
while (iarg < narg) {
if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal fix ave/correlate command");
+ error->all(FLERR,"Illegal fix ave/correlate command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
delete [] suffix;
nvalues++;
iarg++;
} else break;
}
// optional args
type = AUTO;
ave = ONE;
startstep = 0;
prefactor = 1.0;
fp = NULL;
char *title1 = NULL;
char *title2 = NULL;
char *title3 = NULL;
while (iarg < narg) {
if (strcmp(arg[iarg],"type") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
if (strcmp(arg[iarg+1],"auto") == 0) type = AUTO;
else if (strcmp(arg[iarg+1],"upper") == 0) type = UPPER;
else if (strcmp(arg[iarg+1],"lower") == 0) type = LOWER;
else if (strcmp(arg[iarg+1],"auto/upper") == 0) type = AUTOUPPER;
else if (strcmp(arg[iarg+1],"auto/lower") == 0) type = AUTOLOWER;
else if (strcmp(arg[iarg+1],"full") == 0) type = FULL;
- else error->all("Illegal fix ave/correlate command");
+ else error->all(FLERR,"Illegal fix ave/correlate command");
iarg += 2;
} else if (strcmp(arg[iarg],"ave") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
if (strcmp(arg[iarg+1],"one") == 0) ave = ONE;
else if (strcmp(arg[iarg+1],"running") == 0) ave = RUNNING;
- else error->all("Illegal fix ave/correlate command");
+ else error->all(FLERR,"Illegal fix ave/correlate command");
iarg += 2;
} else if (strcmp(arg[iarg],"start") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
startstep = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"prefactor") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
prefactor = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"file") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
if (me == 0) {
fp = fopen(arg[iarg+1],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix ave/correlate file %s",arg[iarg+1]);
- error->one(str);
+ error->one(FLERR,str);
}
}
iarg += 2;
} else if (strcmp(arg[iarg],"title1") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
delete [] title1;
int n = strlen(arg[iarg+1]) + 1;
title1 = new char[n];
strcpy(title1,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title2") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
delete [] title2;
int n = strlen(arg[iarg+1]) + 1;
title2 = new char[n];
strcpy(title2,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title3") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/correlate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/correlate command");
delete [] title3;
int n = strlen(arg[iarg+1]) + 1;
title3 = new char[n];
strcpy(title3,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix ave/correlate command");
+ } else error->all(FLERR,"Illegal fix ave/correlate command");
}
// setup and error check
// for fix inputs, check that fix frequency is acceptable
if (nevery <= 0 || nrepeat <= 0 || nfreq <= 0)
- error->all("Illegal fix ave/correlate command");
+ error->all(FLERR,"Illegal fix ave/correlate command");
if (nfreq % nevery)
- error->all("Illegal fix ave/correlate command");
+ error->all(FLERR,"Illegal fix ave/correlate command");
if (ave == ONE && nfreq < (nrepeat-1)*nevery)
- error->all("Illegal fix ave/correlate command");
+ error->all(FLERR,"Illegal fix ave/correlate command");
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all ("Compute ID for fix ave/correlate does not exist");
+ error->all(FLERR,"Compute ID for fix ave/correlate does not exist");
if (argindex[i] == 0 && modify->compute[icompute]->scalar_flag == 0)
- error->all ("Fix ave/correlate compute does not calculate a scalar");
+ error->all(FLERR,
+ "Fix ave/correlate compute does not calculate a scalar");
if (argindex[i] && modify->compute[icompute]->vector_flag == 0)
- error->all ("Fix ave/correlate compute does not calculate a vector");
+ error->all(FLERR,
+ "Fix ave/correlate compute does not calculate a vector");
if (argindex[i] && argindex[i] > modify->compute[icompute]->size_vector)
- error->all ("Fix ave/correlate compute vector "
- "is accessed out-of-range");
+ error->all(FLERR,"Fix ave/correlate compute vector "
+ "is accessed out-of-range");
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all ("Fix ID for fix ave/correlate does not exist");
+ error->all(FLERR,"Fix ID for fix ave/correlate does not exist");
if (argindex[i] == 0 && modify->fix[ifix]->scalar_flag == 0)
- error->all ("Fix ave/correlate fix does not calculate a scalar");
+ error->all(FLERR,"Fix ave/correlate fix does not calculate a scalar");
if (argindex[i] && modify->fix[ifix]->vector_flag == 0)
- error->all ("Fix ave/correlate fix does not calculate a vector");
+ error->all(FLERR,"Fix ave/correlate fix does not calculate a vector");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_vector)
- error->all ("Fix ave/correlate fix vector is accessed out-of-range");
+ error->all(FLERR,
+ "Fix ave/correlate fix vector is accessed out-of-range");
if (nevery % modify->fix[ifix]->global_freq)
- error->all("Fix for fix ave/correlate "
+ error->all(FLERR,"Fix for fix ave/correlate "
"not computed at compatible time");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all ("Variable name for fix ave/correlate does not exist");
+ error->all(FLERR,"Variable name for fix ave/correlate does not exist");
if (input->variable->equalstyle(ivariable) == 0)
- error->all ("Fix ave/correlate variable is not equal-style variable");
+ error->all(FLERR,
+ "Fix ave/correlate variable is not equal-style variable");
}
}
// npair = # of correlation pairs to calculate
if (type == AUTO) npair = nvalues;
if (type == UPPER || type == LOWER) npair = nvalues*(nvalues-1)/2;
if (type == AUTOUPPER || type == AUTOLOWER) npair = nvalues*(nvalues+1)/2;
if (type == FULL) npair = nvalues*nvalues;
// print file comment lines
if (fp && me == 0) {
if (title1) fprintf(fp,"%s\n",title1);
else fprintf(fp,"# Time-correlated data for fix %s\n",id);
if (title2) fprintf(fp,"%s\n",title2);
else fprintf(fp,"# Timestep Number-of-time-windows\n");
if (title3) fprintf(fp,"%s\n",title3);
else {
fprintf(fp,"# Index TimeDelta Ncount");
if (type == AUTO)
for (int i = 0; i < nvalues; i++)
fprintf(fp," %s*%s",arg[6+i],arg[6+i]);
else if (type == UPPER)
for (int i = 0; i < nvalues; i++)
for (int j = i+1; j < nvalues; j++)
fprintf(fp," %s*%s",arg[6+i],arg[6+j]);
else if (type == LOWER)
for (int i = 0; i < nvalues; i++)
for (int j = 0; j < i-1; j++)
fprintf(fp," %s*%s",arg[6+i],arg[6+j]);
else if (type == AUTOUPPER)
for (int i = 0; i < nvalues; i++)
for (int j = i; j < nvalues; j++)
fprintf(fp," %s*%s",arg[6+i],arg[6+j]);
else if (type == AUTOLOWER)
for (int i = 0; i < nvalues; i++)
for (int j = 0; j < i; j++)
fprintf(fp," %s*%s",arg[6+i],arg[6+j]);
else if (type == FULL)
for (int i = 0; i < nvalues; i++)
for (int j = 0; j < nvalues; j++)
fprintf(fp," %s*%s",arg[6+i],arg[6+j]);
fprintf(fp,"\n");
}
}
delete [] title1;
delete [] title2;
delete [] title3;
// allocate and initialize memory for averaging
// set count and corr to zero since they accumulate
// also set save versions to zero in case accessed via compute_array()
memory->create(values,nrepeat,nvalues,"ave/correlate:values");
memory->create(count,nrepeat,"ave/correlate:count");
memory->create(save_count,nrepeat,"ave/correlate:save_count");
memory->create(corr,nrepeat,npair,"ave/correlate:corr");
memory->create(save_corr,nrepeat,npair,"ave/correlate:save_corr");
int i,j;
for (i = 0; i < nrepeat; i++) {
save_count[i] = count[i] = 0;
for (j = 0; j < npair; j++)
save_corr[i][j] = corr[i][j] = 0.0;
}
// this fix produces a global array
array_flag = 1;
size_array_rows = nrepeat;
size_array_cols = npair+2;
extarray = 0;
// nvalid = next step on which end_of_step does something
// add nvalid to all computes that store invocation times
// since don't know a priori which are invoked by this fix
// once in end_of_step() can set timestep for ones actually invoked
lastindex = -1;
firstindex = 0;
nsample = 0;
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
/* ---------------------------------------------------------------------- */
FixAveCorrelate::~FixAveCorrelate()
{
delete [] which;
delete [] argindex;
delete [] value2index;
for (int i = 0; i < nvalues; i++) delete [] ids[i];
delete [] ids;
memory->destroy(values);
memory->destroy(count);
memory->destroy(save_count);
memory->destroy(corr);
memory->destroy(save_corr);
if (fp && me == 0) fclose(fp);
}
/* ---------------------------------------------------------------------- */
int FixAveCorrelate::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAveCorrelate::init()
{
// set current indices for all computes,fixes,variables
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/correlate does not exist");
+ error->all(FLERR,"Compute ID for fix ave/correlate does not exist");
value2index[i] = icompute;
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/correlate does not exist");
+ error->all(FLERR,"Fix ID for fix ave/correlate does not exist");
value2index[i] = ifix;
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/correlate does not exist");
+ error->all(FLERR,"Variable name for fix ave/correlate does not exist");
value2index[i] = ivariable;
}
}
// need to reset nvalid if nvalid < ntimestep b/c minimize was performed
if (nvalid < update->ntimestep) {
lastindex = -1;
firstindex = 0;
nsample = 0;
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
}
/* ----------------------------------------------------------------------
only does something if nvalid = current timestep
------------------------------------------------------------------------- */
void FixAveCorrelate::setup(int vflag)
{
end_of_step();
}
/* ---------------------------------------------------------------------- */
void FixAveCorrelate::end_of_step()
{
int i,j,m;
double scalar;
// skip if not step which requires doing something
bigint ntimestep = update->ntimestep;
if (ntimestep != nvalid) return;
// accumulate results of computes,fixes,variables to origin
// compute/fix/variable may invoke computes so wrap with clear/add
modify->clearstep_compute();
// lastindex = index in values ring of latest time sample
lastindex++;
if (lastindex == nrepeat) lastindex = 0;
for (i = 0; i < nvalues; i++) {
m = value2index[i];
// invoke compute if not previously invoked
if (which[i] == COMPUTE) {
Compute *compute = modify->compute[m];
if (argindex[i] == 0) {
if (!(compute->invoked_flag & INVOKED_SCALAR)) {
compute->compute_scalar();
compute->invoked_flag |= INVOKED_SCALAR;
}
scalar = compute->scalar;
} else {
if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
scalar = compute->vector[argindex[i]-1];
}
// access fix fields, guaranteed to be ready
} else if (which[i] == FIX) {
if (argindex[i] == 0)
scalar = modify->fix[m]->compute_scalar();
else
scalar = modify->fix[m]->compute_vector(argindex[i]-1);
// evaluate equal-style variable
} else if (which[i] == VARIABLE)
scalar = input->variable->compute_equal(m);
values[lastindex][i] = scalar;
}
// fistindex = index in values ring of earliest time sample
// nsample = number of time samples in values ring
if (nsample < nrepeat) nsample++;
else {
firstindex++;
if (firstindex == nrepeat) firstindex = 0;
}
nvalid += nevery;
modify->addstep_compute(nvalid);
// calculate all Cij() enabled by latest values
accumulate();
if (ntimestep % nfreq) return;
// save results in save_count and save_corr
for (i = 0; i < nrepeat; i++) {
save_count[i] = count[i];
if (count[i])
for (j = 0; j < npair; j++)
save_corr[i][j] = prefactor*corr[i][j]/count[i];
else
for (j = 0; j < npair; j++)
save_corr[i][j] = 0.0;
}
// output to file
if (fp && me == 0) {
fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nrepeat);
for (i = 0; i < nrepeat; i++) {
fprintf(fp,"%d %d %d",i+1,i*nevery,count[i]);
if (count[i])
for (j = 0; j < npair; j++)
fprintf(fp," %g",prefactor*corr[i][j]/count[i]);
else
for (j = 0; j < npair; j++)
fprintf(fp," 0.0");
fprintf(fp,"\n");
}
fflush(fp);
}
// zero accumulation if requested
// recalculate Cij(0)
if (ave == ONE) {
for (i = 0; i < nrepeat; i++) {
count[i] = 0;
for (j = 0; j < npair; j++)
corr[i][j] = 0.0;
}
nsample = 1;
accumulate();
}
}
/* ----------------------------------------------------------------------
accumulate correlation data using more recently added values
------------------------------------------------------------------------- */
void FixAveCorrelate::accumulate()
{
int i,j,k,m,n,ipair;
for (k = 0; k < nsample; k++) count[k]++;
if (type == AUTO) {
m = n = lastindex;
for (k = 0; k < nsample; k++) {
ipair = 0;
for (i = 0; i < nvalues; i++) {
corr[k][ipair++] += values[m][i]*values[n][i];
}
m--;
if (m < 0) m = nrepeat-1;
}
} else if (type == UPPER) {
m = n = lastindex;
for (k = 0; k < nsample; k++) {
ipair = 0;
for (i = 0; i < nvalues; i++)
for (j = i+1; j < nvalues; j++)
corr[k][ipair++] += values[m][i]*values[n][j];
m--;
if (m < 0) m = nrepeat-1;
}
} else if (type == LOWER) {
m = n = lastindex;
for (k = 0; k < nsample; k++) {
ipair = 0;
for (i = 0; i < nvalues; i++)
for (j = 0; j < i-1; j++)
corr[k][ipair++] += values[m][i]*values[n][j];
m--;
if (m < 0) m = nrepeat-1;
}
} else if (type == AUTOUPPER) {
m = n = lastindex;
for (k = 0; k < nsample; k++) {
ipair = 0;
for (i = 0; i < nvalues; i++)
for (j = i; j < nvalues; j++)
corr[k][ipair++] += values[m][i]*values[n][j];
m--;
if (m < 0) m = nrepeat-1;
}
} else if (type == AUTOLOWER) {
m = n = lastindex;
for (k = 0; k < nsample; k++) {
ipair = 0;
for (i = 0; i < nvalues; i++)
for (j = 0; j < i; j++)
corr[k][ipair++] += values[m][i]*values[n][j];
m--;
if (m < 0) m = nrepeat-1;
}
} else if (type == FULL) {
m = n = lastindex;
for (k = 0; k < nsample; k++) {
ipair = 0;
for (i = 0; i < nvalues; i++)
for (j = 0; j < nvalues; j++)
corr[k][ipair++] += values[m][i]*values[n][j];
m--;
if (m < 0) m = nrepeat-1;
}
}
}
/* ----------------------------------------------------------------------
return I,J array value
------------------------------------------------------------------------- */
double FixAveCorrelate::compute_array(int i, int j)
{
if (j == 0) return 1.0*i*nevery;
else if (j == 1) return 1.0*save_count[i];
else if (save_count[i]) return save_corr[i][j-2];
return 0.0;
}
/* ----------------------------------------------------------------------
nvalid = next step on which end_of_step does something
this step if multiple of nevery, else next multiple
startstep is lower bound
------------------------------------------------------------------------- */
bigint FixAveCorrelate::nextvalid()
{
bigint nvalid = update->ntimestep;
if (startstep > nvalid) nvalid = startstep;
if (nvalid % nevery) nvalid = (nvalid/nevery)*nevery + nevery;
return nvalid;
}
diff --git a/src/fix_ave_histo.cpp b/src/fix_ave_histo.cpp
index 6692681f1..f7909ac25 100644
--- a/src/fix_ave_histo.cpp
+++ b/src/fix_ave_histo.cpp
@@ -1,996 +1,993 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_ave_histo.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "group.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{X,V,F,COMPUTE,FIX,VARIABLE};
enum{ONE,RUNNING};
enum{SCALAR,VECTOR,WINDOW};
enum{GLOBAL,PERATOM,LOCAL};
enum{IGNORE,END,EXTRA};
#define INVOKED_SCALAR 1
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
#define INVOKED_PERATOM 8
#define INVOKED_LOCAL 16
#define BIG 1.0e20
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 10) error->all("Illegal fix ave/histo command");
+ if (narg < 10) error->all(FLERR,"Illegal fix ave/histo command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
nrepeat = atoi(arg[4]);
nfreq = atoi(arg[5]);
global_freq = nfreq;
vector_flag = 1;
size_vector = 4;
extvector = 0;
array_flag = 1;
size_array_cols = 3;
extarray = 0;
time_depend = 1;
lo = atof(arg[6]);
hi = atof(arg[7]);
nbins = atoi(arg[8]);
// scan values to count them
// then read options so know mode = SCALAR/VECTOR before re-reading values
nvalues = 0;
int iarg = 9;
while (iarg < narg) {
if (strcmp(arg[iarg],"x") == 0 ||
strcmp(arg[iarg],"y") == 0 ||
strcmp(arg[iarg],"z") == 0 ||
strcmp(arg[iarg],"vx") == 0 ||
strcmp(arg[iarg],"vy") == 0 ||
strcmp(arg[iarg],"vz") == 0 ||
strcmp(arg[iarg],"fx") == 0 ||
strcmp(arg[iarg],"fy") == 0 ||
strcmp(arg[iarg],"fz") == 0 ||
strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
nvalues++;
iarg++;
} else break;
}
options(narg,arg);
// parse values until one isn't recognized
// if mode = VECTOR and value is a global array:
// expand it as if columns listed one by one
// adjust nvalues accordingly via maxvalues
which = argindex = value2index = NULL;
ids = NULL;
int maxvalues = nvalues;
allocate_values(maxvalues);
nvalues = 0;
iarg = 9;
while (iarg < narg) {
if (strcmp(arg[iarg],"x") == 0) {
which[nvalues] = X;
argindex[nvalues] = 0;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"y") == 0) {
which[nvalues] = X;
argindex[nvalues] = 1;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"z") == 0) {
which[nvalues] = X;
argindex[nvalues] = 2;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"vx") == 0) {
which[nvalues] = V;
argindex[nvalues] = 0;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"vy") == 0) {
which[nvalues] = V;
argindex[nvalues] = 1;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"vz") == 0) {
which[nvalues] = V;
argindex[nvalues] = 2;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"fx") == 0) {
which[nvalues] = F;
argindex[nvalues] = 0;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"fy") == 0) {
which[nvalues] = F;
argindex[nvalues] = 1;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if (strcmp(arg[iarg],"fz") == 0) {
which[nvalues] = F;
argindex[nvalues] = 2;
ids[nvalues] = NULL;
nvalues++;
iarg++;
} else if ((strncmp(arg[iarg],"c_",2) == 0) ||
(strncmp(arg[iarg],"f_",2) == 0) ||
(strncmp(arg[iarg],"v_",2) == 0)) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal fix ave/histo command");
+ error->all(FLERR,"Illegal fix ave/histo command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
delete [] suffix;
if (mode == VECTOR && which[nvalues] == COMPUTE &&
argindex[nvalues] == 0) {
int icompute = modify->find_compute(ids[nvalues]);
if (icompute < 0)
- error->all("Compute ID for fix ave/histo does not exist");
+ error->all(FLERR,"Compute ID for fix ave/histo does not exist");
if (modify->compute[icompute]->array_flag) {
int ncols = modify->compute[icompute]->size_array_cols;
maxvalues += ncols-1;
allocate_values(maxvalues);
argindex[nvalues] = 1;
for (int icol = 1; icol < ncols; icol++) {
which[nvalues+icol] = which[nvalues];
argindex[nvalues+icol] = icol+1;
n = strlen(ids[nvalues]) + 1;
ids[nvalues+icol] = new char[n];
strcpy(ids[nvalues+icol],ids[nvalues]);
}
nvalues += ncols-1;
}
} else if (mode == VECTOR && which[nvalues] == FIX &&
argindex[nvalues] == 0) {
int ifix = modify->find_fix(ids[nvalues]);
if (ifix < 0)
- error->all("Fix ID for fix ave/histo does not exist");
+ error->all(FLERR,"Fix ID for fix ave/histo does not exist");
if (modify->fix[ifix]->array_flag) {
int ncols = modify->fix[ifix]->size_array_cols;
maxvalues += ncols-1;
allocate_values(maxvalues);
argindex[nvalues] = 1;
for (int icol = 1; icol < ncols; icol++) {
which[nvalues+icol] = which[nvalues];
argindex[nvalues+icol] = icol+1;
n = strlen(ids[nvalues]) + 1;
ids[nvalues+icol] = new char[n];
strcpy(ids[nvalues+icol],ids[nvalues]);
}
nvalues += ncols-1;
}
}
nvalues++;
iarg++;
} else break;
}
// setup and error check
// kind = inputs are all global, or all per-atom, or all local
// for fix inputs, check that fix frequency is acceptable
if (nevery <= 0 || nrepeat <= 0 || nfreq <= 0)
- error->all("Illegal fix ave/histo command");
+ error->all(FLERR,"Illegal fix ave/histo command");
if (nfreq % nevery || (nrepeat-1)*nevery >= nfreq)
- error->all("Illegal fix ave/histo command");
- if (lo >= hi) error->all("Illegal fix ave/histo command");
- if (nbins <= 0) error->all("Illegal fix ave/histo command");
+ error->all(FLERR,"Illegal fix ave/histo command");
+ if (lo >= hi) error->all(FLERR,"Illegal fix ave/histo command");
+ if (nbins <= 0) error->all(FLERR,"Illegal fix ave/histo command");
int kindflag;
for (int i = 0; i < nvalues; i++) {
if (which[i] == X || which[i] == V || which[i] == F) kindflag = PERATOM;
else if (which[i] == COMPUTE) {
Compute *compute = modify->compute[modify->find_compute(ids[0])];
if (compute->scalar_flag || compute->vector_flag || compute->array_flag)
kindflag = GLOBAL;
else if (compute->peratom_flag) kindflag = PERATOM;
else if (compute->local_flag) kindflag = LOCAL;
- else error->all("Fix ave/histo input is invalid compute");
+ else error->all(FLERR,"Fix ave/histo input is invalid compute");
} else if (which[i] == FIX) {
Fix *fix = modify->fix[modify->find_fix(ids[0])];
if (fix->scalar_flag || fix->vector_flag || fix->array_flag)
kindflag = GLOBAL;
else if (fix->peratom_flag) kindflag = PERATOM;
else if (fix->local_flag) kindflag = LOCAL;
- else error->all("Fix ave/histo input is invalid fix");
+ else error->all(FLERR,"Fix ave/histo input is invalid fix");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (input->variable->equalstyle(ivariable)) kindflag = GLOBAL;
else if (input->variable->atomstyle(ivariable)) kindflag = PERATOM;
- else error->all("Fix ave/histo input is invalid variable");
+ else error->all(FLERR,"Fix ave/histo input is invalid variable");
}
if (i == 0) kind = kindflag;
else if (kindflag != kind)
- error->all("Fix ave/histo inputs are not all global, peratom, or local");
+ error->all(FLERR,"Fix ave/histo inputs are not all global, peratom, or local");
}
if (kind == PERATOM && mode == SCALAR)
- error->all("Fix ave/histo cannot input per-atom values in scalar mode");
+ error->all(FLERR,"Fix ave/histo cannot input per-atom values in scalar mode");
if (kind == LOCAL && mode == SCALAR)
- error->all("Fix ave/histo cannot input local values in scalar mode");
+ error->all(FLERR,"Fix ave/histo cannot input local values in scalar mode");
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE && kind == GLOBAL && mode == SCALAR) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/histo does not exist");
+ error->all(FLERR,"Compute ID for fix ave/histo does not exist");
if (argindex[i] == 0 && modify->compute[icompute]->scalar_flag == 0)
- error->all("Fix ave/histo compute does not calculate a global scalar");
+ error->all(FLERR,"Fix ave/histo compute does not calculate a global scalar");
if (argindex[i] && modify->compute[icompute]->vector_flag == 0)
- error->all("Fix ave/histo compute does not calculate a global vector");
+ error->all(FLERR,"Fix ave/histo compute does not calculate a global vector");
if (argindex[i] && argindex[i] > modify->compute[icompute]->size_vector)
- error->all("Fix ave/histo compute vector is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo compute vector is accessed out-of-range");
} else if (which[i] == COMPUTE && kind == GLOBAL && mode == VECTOR) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/histo does not exist");
+ error->all(FLERR,"Compute ID for fix ave/histo does not exist");
if (argindex[i] == 0 && modify->compute[icompute]->vector_flag == 0)
- error->all("Fix ave/histo compute does not calculate a global vector");
+ error->all(FLERR,"Fix ave/histo compute does not calculate a global vector");
if (argindex[i] && modify->compute[icompute]->array_flag == 0)
- error->all("Fix ave/histo compute does not calculate a global array");
+ error->all(FLERR,"Fix ave/histo compute does not calculate a global array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_array_cols)
- error->all("Fix ave/histo compute array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo compute array is accessed out-of-range");
} else if (which[i] == COMPUTE && kind == PERATOM) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/histo does not exist");
+ error->all(FLERR,"Compute ID for fix ave/histo does not exist");
if (modify->compute[icompute]->peratom_flag == 0)
- error->all("Fix ave/histo compute does not calculate per-atom values");
+ error->all(FLERR,"Fix ave/histo compute does not calculate per-atom values");
if (argindex[i] == 0 &&
modify->compute[icompute]->size_peratom_cols != 0)
- error->all("Fix ave/histo compute does not "
+ error->all(FLERR,"Fix ave/histo compute does not "
"calculate a per-atom vector");
if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0)
- error->all("Fix ave/histo compute does not "
+ error->all(FLERR,"Fix ave/histo compute does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_peratom_cols)
- error->all("Fix ave/histo compute array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo compute array is accessed out-of-range");
} else if (which[i] == COMPUTE && kind == LOCAL) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/histo does not exist");
+ error->all(FLERR,"Compute ID for fix ave/histo does not exist");
if (modify->compute[icompute]->local_flag == 0)
- error->all("Fix ave/histo compute does not calculate local values");
+ error->all(FLERR,"Fix ave/histo compute does not calculate local values");
if (argindex[i] == 0 &&
modify->compute[icompute]->size_local_cols != 0)
- error->all("Fix ave/histo compute does not "
+ error->all(FLERR,"Fix ave/histo compute does not "
"calculate a local vector");
if (argindex[i] && modify->compute[icompute]->size_local_cols == 0)
- error->all("Fix ave/histo compute does not "
+ error->all(FLERR,"Fix ave/histo compute does not "
"calculate a local array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_local_cols)
- error->all("Fix ave/histo compute array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo compute array is accessed out-of-range");
} else if (which[i] == FIX && kind == GLOBAL && mode == SCALAR) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/histo does not exist");
+ error->all(FLERR,"Fix ID for fix ave/histo does not exist");
if (argindex[i] == 0 && modify->fix[ifix]->scalar_flag == 0)
- error->all("Fix ave/histo fix does not calculate a global scalar");
+ error->all(FLERR,"Fix ave/histo fix does not calculate a global scalar");
if (argindex[i] && modify->fix[ifix]->vector_flag == 0)
- error->all("Fix ave/histo fix does not calculate a global vector");
+ error->all(FLERR,"Fix ave/histo fix does not calculate a global vector");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_vector)
- error->all("Fix ave/histo fix vector is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo fix vector is accessed out-of-range");
if (nevery % modify->fix[ifix]->global_freq)
- error->all("Fix for fix ave/histo not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/histo not computed at compatible time");
} else if (which[i] == FIX && kind == GLOBAL && mode == VECTOR) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/histo does not exist");
+ error->all(FLERR,"Fix ID for fix ave/histo does not exist");
if (argindex[i] == 0 && modify->fix[ifix]->vector_flag == 0)
- error->all("Fix ave/histo fix does not calculate a global vector");
+ error->all(FLERR,"Fix ave/histo fix does not calculate a global vector");
if (argindex[i] && modify->fix[ifix]->array_flag == 0)
- error->all("Fix ave/histo fix does not calculate a global array");
+ error->all(FLERR,"Fix ave/histo fix does not calculate a global array");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_array_cols)
- error->all("Fix ave/histo fix array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo fix array is accessed out-of-range");
if (nevery % modify->fix[ifix]->global_freq)
- error->all("Fix for fix ave/histo not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/histo not computed at compatible time");
} else if (which[i] == FIX && kind == PERATOM) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/histo does not exist");
+ error->all(FLERR,"Fix ID for fix ave/histo does not exist");
if (modify->fix[ifix]->peratom_flag == 0)
- error->all("Fix ave/histo fix does not calculate per-atom values");
+ error->all(FLERR,"Fix ave/histo fix does not calculate per-atom values");
if (argindex[i] == 0 &&
modify->fix[ifix]->size_peratom_cols != 0)
- error->all("Fix ave/histo fix does not "
+ error->all(FLERR,"Fix ave/histo fix does not "
"calculate a per-atom vector");
if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0)
- error->all("Fix ave/histo fix does not "
+ error->all(FLERR,"Fix ave/histo fix does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->fix[ifix]->size_peratom_cols)
- error->all("Fix ave/histo fix array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo fix array is accessed out-of-range");
if (nevery % modify->fix[ifix]->global_freq)
- error->all("Fix for fix ave/histo not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/histo not computed at compatible time");
} else if (which[i] == FIX && kind == LOCAL) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/histo does not exist");
+ error->all(FLERR,"Fix ID for fix ave/histo does not exist");
if (modify->fix[ifix]->local_flag == 0)
- error->all("Fix ave/histo fix does not calculate local values");
+ error->all(FLERR,"Fix ave/histo fix does not calculate local values");
if (argindex[i] == 0 &&
modify->fix[ifix]->size_local_cols != 0)
- error->all("Fix ave/histo fix does not "
+ error->all(FLERR,"Fix ave/histo fix does not "
"calculate a local vector");
if (argindex[i] && modify->fix[ifix]->size_local_cols == 0)
- error->all("Fix ave/histo fix does not "
+ error->all(FLERR,"Fix ave/histo fix does not "
"calculate a local array");
if (argindex[i] &&
argindex[i] > modify->fix[ifix]->size_local_cols)
- error->all("Fix ave/histo fix array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/histo fix array is accessed out-of-range");
if (nevery % modify->fix[ifix]->global_freq)
- error->all("Fix for fix ave/histo not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/histo not computed at compatible time");
} else if (which[i] == VARIABLE && kind == GLOBAL) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/histo does not exist");
+ error->all(FLERR,"Variable name for fix ave/histo does not exist");
} else if (which[i] == VARIABLE && kind == PERATOM) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/histo does not exist");
+ error->all(FLERR,"Variable name for fix ave/histo does not exist");
}
}
// print file comment lines
if (fp && me == 0) {
if (title1) fprintf(fp,"%s\n",title1);
else fprintf(fp,"# Histogrammed data for fix %s\n",id);
if (title2) fprintf(fp,"%s\n",title2);
else fprintf(fp,"# TimeStep Number-of-bins "
"Total-counts Missing-counts Min-value Max-value\n");
if (title3) fprintf(fp,"%s\n",title3);
else fprintf(fp,"# Bin Coord Count Count/Total\n");
}
delete [] title1;
delete [] title2;
delete [] title3;
// allocate and initialize memory for averaging
if (beyond == EXTRA) nbins += 2;
size_array_rows = nbins;
bin = new double[nbins];
bin_total = new double[nbins];
bin_all = new double[nbins];
coord = new double[nbins];
stats_list = NULL;
bin_list = NULL;
vector = NULL;
maxatom = 0;
if (ave == WINDOW) {
memory->create(stats_list,nwindow,4,"histo:stats_list");
memory->create(bin_list,nwindow,nbins,"ave/histo:bin_list");
}
// initializations
// set coord to bin centers
if (beyond == EXTRA) {
binsize = (hi-lo)/(nbins-2);
bininv = 1.0/binsize;
} else {
binsize = (hi-lo)/nbins;
bininv = 1.0/binsize;
}
if (beyond == EXTRA) {
coord[0] = lo;
coord[nbins-1] = hi;
for (int i = 1; i < nbins-1; i++)
coord[i] = lo + (i-1+0.5)*binsize;
} else {
for (int i = 0; i < nbins; i++)
coord[i] = lo + (i+0.5)*binsize;
}
irepeat = 0;
iwindow = window_limit = 0;
stats_total[0] = stats_total[1] = stats_total[2] = stats_total[3] = 0.0;
for (int i = 0; i < nbins; i++) bin_total[i] = 0.0;
// nvalid = next step on which end_of_step does something
// add nvalid to all computes that store invocation times
// since don't know a priori which are invoked by this fix
// once in end_of_step() can set timestep for ones actually invoked
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
/* ---------------------------------------------------------------------- */
FixAveHisto::~FixAveHisto()
{
memory->destroy(which);
memory->destroy(argindex);
memory->destroy(value2index);
for (int i = 0; i < nvalues; i++) delete [] ids[i];
memory->sfree(ids);
if (fp && me == 0) fclose(fp);
delete [] bin;
delete [] bin_total;
delete [] bin_all;
delete [] coord;
memory->destroy(stats_list);
memory->destroy(bin_list);
memory->destroy(vector);
}
/* ---------------------------------------------------------------------- */
int FixAveHisto::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAveHisto::init()
{
// set current indices for all computes,fixes,variables
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/histo does not exist");
+ error->all(FLERR,"Compute ID for fix ave/histo does not exist");
value2index[i] = icompute;
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/histo does not exist");
+ error->all(FLERR,"Fix ID for fix ave/histo does not exist");
value2index[i] = ifix;
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/histo does not exist");
+ error->all(FLERR,"Variable name for fix ave/histo does not exist");
value2index[i] = ivariable;
}
}
// need to reset nvalid if nvalid < ntimestep b/c minimize was performed
if (nvalid < update->ntimestep) {
irepeat = 0;
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
}
/* ----------------------------------------------------------------------
only does something if nvalid = current timestep
------------------------------------------------------------------------- */
void FixAveHisto::setup(int vflag)
{
end_of_step();
}
/* ---------------------------------------------------------------------- */
void FixAveHisto::end_of_step()
{
int i,j,m;
// skip if not step which requires doing something
bigint ntimestep = update->ntimestep;
if (ntimestep != nvalid) return;
// zero if first step
if (irepeat == 0) {
stats[0] = stats[1] = 0.0;
stats[2] = BIG;
stats[3] = -BIG;
for (i = 0; i < nbins; i++) bin[i] = 0.0;
}
// accumulate results of computes,fixes,variables to local copy
// compute/fix/variable may invoke computes so wrap with clear/add
modify->clearstep_compute();
for (i = 0; i < nvalues; i++) {
m = value2index[i];
j = argindex[i];
// atom attributes
if (which[i] == X)
bin_atoms(&atom->x[0][j],3);
else if (which[i] == V)
bin_atoms(&atom->v[0][j],3);
else if (which[i] == F)
bin_atoms(&atom->f[0][j],3);
// invoke compute if not previously invoked
if (which[i] == COMPUTE) {
Compute *compute = modify->compute[m];
if (kind == GLOBAL && mode == SCALAR) {
if (j == 0) {
if (!(compute->invoked_flag & INVOKED_SCALAR)) {
compute->compute_scalar();
compute->invoked_flag |= INVOKED_SCALAR;
}
bin_one(compute->scalar);
} else {
if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
bin_one(compute->vector[j-1]);
}
} else if (kind == GLOBAL && mode == VECTOR) {
if (j == 0) {
if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
bin_vector(compute->size_vector,compute->vector,1);
} else {
if (!(compute->invoked_flag & INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
}
bin_vector(compute->size_array_rows,&compute->array[0][j-1],
compute->size_array_cols);
}
} else if (kind == PERATOM) {
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
if (j == 0)
bin_atoms(compute->vector_atom,1);
else
bin_atoms(compute->array_atom[j-1],
compute->size_peratom_cols);
} else if (kind == LOCAL) {
if (!(compute->invoked_flag & INVOKED_LOCAL)) {
compute->compute_local();
compute->invoked_flag |= INVOKED_LOCAL;
}
if (j == 0)
bin_vector(compute->size_local_rows,compute->vector_local,1);
else
bin_vector(compute->size_local_rows,&compute->array_local[0][j-1],
compute->size_local_cols);
}
// access fix fields, guaranteed to be ready
} else if (which[i] == FIX) {
Fix *fix = modify->fix[m];
if (kind == GLOBAL && mode == SCALAR) {
if (j == 0) bin_one(fix->compute_scalar());
else bin_one(fix->compute_vector(j-1));
} else if (kind == GLOBAL && mode == VECTOR) {
if (j == 0) {
int n = fix->size_vector;
for (i = 0; i < n; i++) bin_one(fix->compute_vector(i));
} else {
int n = fix->size_vector;
for (i = 0; i < n; i++) bin_one(fix->compute_array(i,j-1));
}
} else if (kind == PERATOM) {
if (j == 0) bin_atoms(fix->vector_atom,1);
else bin_atoms(fix->array_atom[j-1],fix->size_peratom_cols);
} else if (kind == LOCAL) {
if (j == 0) bin_vector(fix->size_local_rows,fix->vector_local,1);
else
bin_vector(fix->size_local_rows,&fix->array_local[0][j-1],
fix->size_local_cols);
}
// evaluate equal-style variable
} else if (which[i] == VARIABLE && kind == GLOBAL) {
bin_one(input->variable->compute_equal(m));
} else if (which[i] == VARIABLE && kind == PERATOM) {
if (atom->nlocal > maxatom) {
memory->destroy(vector);
maxatom = atom->nmax;
memory->create(vector,maxatom,"ave/histo:vector");
}
input->variable->compute_atom(m,igroup,vector,1,0);
bin_atoms(vector,1);
}
}
// done if irepeat < nrepeat
// else reset irepeat and nvalid
irepeat++;
if (irepeat < nrepeat) {
nvalid += nevery;
modify->addstep_compute(nvalid);
return;
}
irepeat = 0;
nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
modify->addstep_compute(nvalid);
// merge histogram stats across procs if necessary
if (kind == PERATOM || kind == LOCAL) {
MPI_Allreduce(stats,stats_all,2,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(&stats[2],&stats_all[2],1,MPI_DOUBLE,MPI_MIN,world);
MPI_Allreduce(&stats[3],&stats_all[3],1,MPI_DOUBLE,MPI_MAX,world);
MPI_Allreduce(bin,bin_all,nbins,MPI_DOUBLE,MPI_SUM,world);
stats[0] = stats_all[0];
stats[1] = stats_all[1];
stats[2] = stats_all[2];
stats[3] = stats_all[3];
for (i = 0; i < nbins; i++) bin[i] = bin_all[i];
}
// if ave = ONE, only single Nfreq timestep value is needed
// if ave = RUNNING, combine with all previous Nfreq timestep values
// if ave = WINDOW, combine with nwindow most recent Nfreq timestep values
if (ntimestep >= startstep) {
if (ave == ONE) {
stats_total[0] = stats[0];
stats_total[1] = stats[1];
stats_total[2] = stats[2];
stats_total[3] = stats[3];
for (i = 0; i < nbins; i++) bin_total[i] = bin[i];
} else if (ave == RUNNING) {
stats_total[0] += stats[0];
stats_total[1] += stats[1];
stats_total[2] = MIN(stats_total[2],stats[2]);
stats_total[3] = MAX(stats_total[3],stats[3]);
for (i = 0; i < nbins; i++) bin_total[i] += bin[i];
} else if (ave == WINDOW) {
stats_total[0] += stats[0];
if (window_limit) stats_total[0] -= stats_list[iwindow][0];
stats_list[iwindow][0] = stats[0];
stats_total[1] += stats[1];
if (window_limit) stats_total[1] -= stats_list[iwindow][1];
stats_list[iwindow][1] = stats[1];
if (window_limit) m = nwindow;
else m = iwindow+1;
stats_list[iwindow][2] = stats[2];
stats_total[2] = stats_list[0][2];
for (i = 1; i < m; i++)
stats_total[2] = MIN(stats_total[2],stats_list[i][2]);
stats_list[iwindow][3] = stats[3];
stats_total[3] = stats_list[0][3];
for (i = 1; i < m; i++)
stats_total[3] = MAX(stats_total[3],stats_list[i][3]);
for (i = 0; i < nbins; i++) {
bin_total[i] += bin[i];
if (window_limit) bin_total[i] -= bin_list[iwindow][i];
bin_list[iwindow][i] = bin[i];
}
iwindow++;
if (iwindow == nwindow) {
iwindow = 0;
window_limit = 1;
}
}
}
// output result to file
if (fp && me == 0) {
fprintf(fp,BIGINT_FORMAT " %d %g %g %g %g\n",ntimestep,nbins,
stats_total[0],stats_total[1],stats_total[2],stats_total[3]);
if (stats_total[0] != 0.0)
for (i = 0; i < nbins; i++)
fprintf(fp,"%d %g %g %g\n",
i+1,coord[i],bin_total[i],bin_total[i]/stats_total[0]);
else
for (i = 0; i < nbins; i++)
fprintf(fp,"%d %g %g %g\n",i+1,coord[i],0.0,0.0);
fflush(fp);
}
}
/* ----------------------------------------------------------------------
return Ith vector value
------------------------------------------------------------------------- */
double FixAveHisto::compute_vector(int i)
{
return stats_total[i];
}
/* ----------------------------------------------------------------------
return I,J array value
------------------------------------------------------------------------- */
double FixAveHisto::compute_array(int i, int j)
{
if (j == 0) return coord[i];
else if (j == 1) return bin_total[i];
else if (stats_total[0] != 0.0) return bin_total[i]/stats_total[0];
return 0.0;
}
/* ----------------------------------------------------------------------
bin a single value
------------------------------------------------------------------------- */
void FixAveHisto::bin_one(double value)
{
stats[2] = MIN(stats[2],value);
stats[3] = MAX(stats[3],value);
if (value < lo) {
if (beyond == IGNORE) {
stats[1] += 1.0;
return;
} else bin[0] += 1.0;
} else if (value > hi) {
if (beyond == IGNORE) {
stats[1] += 1.0;
return;
} else bin[nbins-1] += 1.0;
} else {
int ibin = static_cast<int> ((value-lo)*bininv);
ibin = MIN(ibin,nbins-1);
if (beyond == EXTRA) ibin++;
bin[ibin] += 1.0;
}
stats[0] += 1.0;
}
/* ----------------------------------------------------------------------
bin a vector of values with stride
------------------------------------------------------------------------- */
void FixAveHisto::bin_vector(int n, double *values, int stride)
{
int m = 0;
for (int i = 0; i < n; i++) {
bin_one(values[m]);
m += stride;
}
}
/* ----------------------------------------------------------------------
bin a per-atom vector of values with stride
only bin if atom is in group
------------------------------------------------------------------------- */
void FixAveHisto::bin_atoms(double *values, int stride)
{
int *mask = atom->mask;
int nlocal = atom->nlocal;
int m = 0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) bin_one(values[m]);
m += stride;
}
}
/* ----------------------------------------------------------------------
parse optional args
------------------------------------------------------------------------- */
void FixAveHisto::options(int narg, char **arg)
{
// option defaults
fp = NULL;
ave = ONE;
startstep = 0;
mode = SCALAR;
beyond = IGNORE;
title1 = NULL;
title2 = NULL;
title3 = NULL;
// optional args
int iarg = 9 + nvalues;
while (iarg < narg) {
if (strcmp(arg[iarg],"file") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/histo command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command");
if (me == 0) {
fp = fopen(arg[iarg+1],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix ave/histo file %s",arg[iarg+1]);
- error->one(str);
+ error->one(FLERR,str);
}
}
iarg += 2;
} else if (strcmp(arg[iarg],"ave") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/histo command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command");
if (strcmp(arg[iarg+1],"one") == 0) ave = ONE;
else if (strcmp(arg[iarg+1],"running") == 0) ave = RUNNING;
else if (strcmp(arg[iarg+1],"window") == 0) ave = WINDOW;
- else error->all("Illegal fix ave/histo command");
+ else error->all(FLERR,"Illegal fix ave/histo command");
if (ave == WINDOW) {
- if (iarg+3 > narg) error->all("Illegal fix ave/histo command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix ave/histo command");
nwindow = atoi(arg[iarg+2]);
- if (nwindow <= 0) error->all("Illegal fix ave/histo command");
+ if (nwindow <= 0) error->all(FLERR,"Illegal fix ave/histo command");
}
iarg += 2;
if (ave == WINDOW) iarg++;
} else if (strcmp(arg[iarg],"start") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/histo command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command");
startstep = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"mode") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/histo command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command");
if (strcmp(arg[iarg+1],"scalar") == 0) mode = SCALAR;
else if (strcmp(arg[iarg+1],"vector") == 0) mode = VECTOR;
- else error->all("Illegal fix ave/histo command");
+ else error->all(FLERR,"Illegal fix ave/histo command");
iarg += 2;
} else if (strcmp(arg[iarg],"beyond") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/histo command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/histo command");
if (strcmp(arg[iarg+1],"ignore") == 0) beyond = IGNORE;
else if (strcmp(arg[iarg+1],"end") == 0) beyond = END;
else if (strcmp(arg[iarg+1],"extra") == 0) beyond = EXTRA;
- else error->all("Illegal fix ave/histo command");
+ else error->all(FLERR,"Illegal fix ave/histo command");
iarg += 2;
} else if (strcmp(arg[iarg],"title1") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title1;
int n = strlen(arg[iarg+1]) + 1;
title1 = new char[n];
strcpy(title1,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title2") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title2;
int n = strlen(arg[iarg+1]) + 1;
title2 = new char[n];
strcpy(title2,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title3") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title3;
int n = strlen(arg[iarg+1]) + 1;
title3 = new char[n];
strcpy(title3,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix ave/histo command");
+ } else error->all(FLERR,"Illegal fix ave/histo command");
}
}
/* ----------------------------------------------------------------------
reallocate vectors for each input value, of length N
------------------------------------------------------------------------- */
void FixAveHisto::allocate_values(int n)
{
memory->grow(which,n,"ave/time:which");
memory->grow(argindex,n,"ave/time:argindex");
memory->grow(value2index,n,"ave/time:value2index");
ids = (char **) memory->srealloc(ids,n*sizeof(char *),"ave/time:ids");
}
/* ----------------------------------------------------------------------
calculate nvalid = next step on which end_of_step does something
can be this timestep if multiple of nfreq and nrepeat = 1
else backup from next multiple of nfreq
------------------------------------------------------------------------- */
bigint FixAveHisto::nextvalid()
{
bigint nvalid = (update->ntimestep/nfreq)*nfreq + nfreq;
if (nvalid-nfreq == update->ntimestep && nrepeat == 1)
nvalid = update->ntimestep;
else
nvalid -= (nrepeat-1)*nevery;
if (nvalid < update->ntimestep) nvalid += nfreq;
return nvalid;
}
diff --git a/src/fix_ave_spatial.cpp b/src/fix_ave_spatial.cpp
index e1b47e501..0fd4672ec 100644
--- a/src/fix_ave_spatial.cpp
+++ b/src/fix_ave_spatial.cpp
@@ -1,1280 +1,1277 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_ave_spatial.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "domain.h"
#include "region.h"
#include "lattice.h"
#include "modify.h"
#include "compute.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{LOWER,CENTER,UPPER,COORD};
enum{V,F,DENSITY_NUMBER,DENSITY_MASS,COMPUTE,FIX,VARIABLE};
enum{SAMPLE,ALL};
enum{BOX,LATTICE,REDUCED};
enum{ONE,RUNNING,WINDOW};
#define INVOKED_PERATOM 8
#define BIG 1000000000
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix ave/spatial command");
+ if (narg < 6) error->all(FLERR,"Illegal fix ave/spatial command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
nrepeat = atoi(arg[4]);
nfreq = atoi(arg[5]);
global_freq = nfreq;
no_change_box = 1;
time_depend = 1;
ndim = 0;
int iarg = 6;
while (iarg < narg && ndim < 3) {
if (iarg+3 > narg) break;
if (strcmp(arg[iarg],"x") == 0) dim[ndim] = 0;
else if (strcmp(arg[iarg],"y") == 0) dim[ndim] = 1;
else if (strcmp(arg[iarg],"z") == 0) dim[ndim] = 2;
else break;
if (dim[ndim] == 2 && domain->dimension == 2)
- error->all("Cannot use fix ave/spatial z for 2 dimensional model");
+ error->all(FLERR,"Cannot use fix ave/spatial z for 2 dimensional model");
if (strcmp(arg[iarg+1],"lower") == 0) originflag[ndim] = LOWER;
if (strcmp(arg[iarg+1],"center") == 0) originflag[ndim] = CENTER;
if (strcmp(arg[iarg+1],"upper") == 0) originflag[ndim] = UPPER;
else originflag[ndim] = COORD;
if (originflag[ndim] == COORD) origin[ndim] = atof(arg[iarg+1]);
delta[ndim] = atof(arg[iarg+2]);
ndim++;
iarg += 3;
}
- if (!ndim) error->all("Illegal fix ave/spatial command");
+ if (!ndim) error->all(FLERR,"Illegal fix ave/spatial command");
if (ndim == 2 && dim[0] == dim[1])
- error->all("Same dimension twice in fix ave/spatial");
+ error->all(FLERR,"Same dimension twice in fix ave/spatial");
if (ndim == 3 && (dim[0] == dim[1] || dim[1] == dim[2] || dim[0] == dim[2]))
- error->all("Same dimension twice in fix ave/spatial");
+ error->all(FLERR,"Same dimension twice in fix ave/spatial");
// parse values until one isn't recognized
which = new int[narg-9];
argindex = new int[narg-9];
ids = new char*[narg-9];
value2index = new int[narg-9];
nvalues = 0;
while (iarg < narg) {
ids[nvalues] = NULL;
if (strcmp(arg[iarg],"vx") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"vy") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"vz") == 0) {
which[nvalues] = V;
argindex[nvalues++] = 2;
} else if (strcmp(arg[iarg],"fx") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"fy") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 1;
} else if (strcmp(arg[iarg],"fz") == 0) {
which[nvalues] = F;
argindex[nvalues++] = 2;
} else if (strcmp(arg[iarg],"density/number") == 0) {
which[nvalues] = DENSITY_NUMBER;
argindex[nvalues++] = 0;
} else if (strcmp(arg[iarg],"density/mass") == 0) {
which[nvalues] = DENSITY_MASS;
argindex[nvalues++] = 0;
} else if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal fix ave/spatial command");
+ error->all(FLERR,"Illegal fix ave/spatial command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
nvalues++;
delete [] suffix;
} else break;
iarg++;
}
// optional args
normflag = ALL;
scaleflag = LATTICE;
regionflag = 0;
idregion = NULL;
fp = NULL;
ave = ONE;
nwindow = 0;
char *title1 = NULL;
char *title2 = NULL;
char *title3 = NULL;
while (iarg < narg) {
if (strcmp(arg[iarg],"norm") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
if (strcmp(arg[iarg+1],"all") == 0) normflag = ALL;
else if (strcmp(arg[iarg+1],"sample") == 0) normflag = SAMPLE;
- else error->all("Illegal fix ave/spatial command");
+ else error->all(FLERR,"Illegal fix ave/spatial command");
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = BOX;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = LATTICE;
else if (strcmp(arg[iarg+1],"reduced") == 0) scaleflag = REDUCED;
- else error->all("Illegal fix ave/spatial command");
+ else error->all(FLERR,"Illegal fix ave/spatial command");
iarg += 2;
} else if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
iregion = domain->find_region(arg[iarg+1]);
if (iregion == -1)
- error->all("Region ID for fix ave/spatial does not exist");
+ error->all(FLERR,"Region ID for fix ave/spatial does not exist");
int n = strlen(arg[iarg+1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[iarg+1]);
regionflag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"file") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
if (me == 0) {
fp = fopen(arg[iarg+1],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix ave/spatial file %s",arg[iarg+1]);
- error->one(str);
+ error->one(FLERR,str);
}
}
iarg += 2;
} else if (strcmp(arg[iarg],"ave") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
if (strcmp(arg[iarg+1],"one") == 0) ave = ONE;
else if (strcmp(arg[iarg+1],"running") == 0) ave = RUNNING;
else if (strcmp(arg[iarg+1],"window") == 0) ave = WINDOW;
- else error->all("Illegal fix ave/spatial command");
+ else error->all(FLERR,"Illegal fix ave/spatial command");
if (ave == WINDOW) {
- if (iarg+3 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
nwindow = atoi(arg[iarg+2]);
- if (nwindow <= 0) error->all("Illegal fix ave/spatial command");
+ if (nwindow <= 0) error->all(FLERR,"Illegal fix ave/spatial command");
}
iarg += 2;
if (ave == WINDOW) iarg++;
} else if (strcmp(arg[iarg],"title1") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title1;
int n = strlen(arg[iarg+1]) + 1;
title1 = new char[n];
strcpy(title1,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title2") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title2;
int n = strlen(arg[iarg+1]) + 1;
title2 = new char[n];
strcpy(title2,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title3") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title3;
int n = strlen(arg[iarg+1]) + 1;
title3 = new char[n];
strcpy(title3,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix ave/spatial command");
+ } else error->all(FLERR,"Illegal fix ave/spatial command");
}
// setup and error check
if (nevery <= 0 || nrepeat <= 0 || nfreq <= 0)
- error->all("Illegal fix ave/spatial command");
+ error->all(FLERR,"Illegal fix ave/spatial command");
if (nfreq % nevery || (nrepeat-1)*nevery >= nfreq)
- error->all("Illegal fix ave/spatial command");
- if (delta[0] <= 0.0) error->all("Illegal fix ave/spatial command");
+ error->all(FLERR,"Illegal fix ave/spatial command");
+ if (delta[0] <= 0.0) error->all(FLERR,"Illegal fix ave/spatial command");
if (ndim >= 2 && delta[1] <= 0.0)
- error->all("Illegal fix ave/spatial command");
+ error->all(FLERR,"Illegal fix ave/spatial command");
if (ndim == 3 && delta[2] <= 0.0)
- error->all("Illegal fix ave/spatial command");
+ error->all(FLERR,"Illegal fix ave/spatial command");
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/spatial does not exist");
+ error->all(FLERR,"Compute ID for fix ave/spatial does not exist");
if (modify->compute[icompute]->peratom_flag == 0)
- error->all("Fix ave/spatial compute does not "
+ error->all(FLERR,"Fix ave/spatial compute does not "
"calculate per-atom values");
if (argindex[i] == 0 &&
modify->compute[icompute]->size_peratom_cols != 0)
- error->all("Fix ave/spatial compute does not "
+ error->all(FLERR,"Fix ave/spatial compute does not "
"calculate a per-atom vector");
if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0)
- error->all("Fix ave/spatial compute does not "
+ error->all(FLERR,"Fix ave/spatial compute does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_peratom_cols)
- error->all("Fix ave/spatial compute vector is accessed out-of-range");
+ error->all(FLERR,"Fix ave/spatial compute vector is accessed out-of-range");
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/spatial does not exist");
+ error->all(FLERR,"Fix ID for fix ave/spatial does not exist");
if (modify->fix[ifix]->peratom_flag == 0)
- error->all("Fix ave/spatial fix does not calculate per-atom values");
+ error->all(FLERR,"Fix ave/spatial fix does not calculate per-atom values");
if (argindex[i] && modify->fix[ifix]->size_peratom_cols != 0)
- error->all("Fix ave/spatial fix does not calculate a per-atom vector");
+ error->all(FLERR,"Fix ave/spatial fix does not calculate a per-atom vector");
if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0)
- error->all("Fix ave/spatial fix does not calculate a per-atom array");
+ error->all(FLERR,"Fix ave/spatial fix does not calculate a per-atom array");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_peratom_cols)
- error->all("Fix ave/spatial fix vector is accessed out-of-range");
+ error->all(FLERR,"Fix ave/spatial fix vector is accessed out-of-range");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/spatial does not exist");
+ error->all(FLERR,"Variable name for fix ave/spatial does not exist");
if (input->variable->atomstyle(ivariable) == 0)
- error->all("Fix ave/spatial variable is not atom-style variable");
+ error->all(FLERR,"Fix ave/spatial variable is not atom-style variable");
}
}
// print file comment lines
if (fp && me == 0) {
if (title1) fprintf(fp,"%s\n",title1);
else fprintf(fp,"# Spatial-averaged data for fix %s and group %s\n",
id,arg[1]);
if (title2) fprintf(fp,"%s\n",title2);
else fprintf(fp,"# Timestep Number-of-bins\n");
if (title3) fprintf(fp,"%s\n",title3);
else {
if (ndim == 1) fprintf(fp,"# Bin Coord Ncount");
else if (ndim == 2) fprintf(fp,"# Bin Coord1 Coord2 Ncount");
else if (ndim == 3) fprintf(fp,"# Bin Coord1 Coord2 Coord3 Ncount");
for (int i = 0; i < nvalues; i++) fprintf(fp," %s",arg[6+3*ndim+i]);
fprintf(fp,"\n");
}
}
delete [] title1;
delete [] title2;
delete [] title3;
// this fix produces a global array
array_flag = 1;
size_array_rows = BIG;
size_array_cols = 1 + ndim + nvalues;
extarray = 0;
// setup scaling
int triclinic = domain->triclinic;
if (triclinic == 1 && scaleflag != REDUCED)
- error->all("Fix ave/spatial for triclinic boxes requires units reduced");
+ error->all(FLERR,"Fix ave/spatial for triclinic boxes requires units reduced");
if (scaleflag == LATTICE && domain->lattice == NULL)
- error->all("Use of fix ave/spatial with undefined lattice");
+ error->all(FLERR,"Use of fix ave/spatial with undefined lattice");
if (scaleflag == LATTICE) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// apply scaling factors
double scale;
for (int idim = 0; idim < ndim; idim++) {
if (dim[idim] == 0) scale = xscale;
else if (dim[idim] == 1) scale = yscale;
else if (dim[idim] == 2) scale = zscale;
delta[idim] *= scale;
if (originflag[idim] == COORD) origin[idim] *= scale;
invdelta[idim] = 1.0/delta[idim];
}
// initializations
irepeat = 0;
iwindow = window_limit = 0;
norm = 0;
maxvar = 0;
varatom = NULL;
maxatom = 0;
bin = NULL;
nbins = maxbin = 0;
count_one = count_many = count_sum = count_total = NULL;
coord = NULL;
count_list = NULL;
values_one = values_many = values_sum = values_total = NULL;
values_list = NULL;
// nvalid = next step on which end_of_step does something
// add nvalid to all computes that store invocation times
// since don't know a priori which are invoked by this fix
// once in end_of_step() can set timestep for ones actually invoked
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
/* ---------------------------------------------------------------------- */
FixAveSpatial::~FixAveSpatial()
{
delete [] which;
delete [] argindex;
for (int i = 0; i < nvalues; i++) delete [] ids[i];
delete [] ids;
delete [] value2index;
delete [] idregion;
if (fp && me == 0) fclose(fp);
memory->destroy(varatom);
memory->destroy(bin);
memory->destroy(count_one);
memory->destroy(count_many);
memory->destroy(count_sum);
memory->destroy(count_total);
memory->destroy(coord);
memory->destroy(count_list);
memory->destroy(values_one);
memory->destroy(values_many);
memory->destroy(values_sum);
memory->destroy(values_total);
memory->destroy(values_list);
}
/* ---------------------------------------------------------------------- */
int FixAveSpatial::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAveSpatial::init()
{
// set and check validity of region
if (regionflag) {
iregion = domain->find_region(idregion);
if (iregion == -1)
- error->all("Region ID for fix ave/spatial does not exist");
+ error->all(FLERR,"Region ID for fix ave/spatial does not exist");
region = domain->regions[iregion];
}
// # of bins cannot vary for ave = RUNNING or WINDOW
if (ave == RUNNING || ave == WINDOW) {
if (scaleflag != REDUCED && domain->box_change)
- error->all("Fix ave/spatial settings invalid with changing box");
+ error->all(FLERR,"Fix ave/spatial settings invalid with changing box");
}
// set indices and check validity of all computes,fixes,variables
// check that fix frequency is acceptable
for (int m = 0; m < nvalues; m++) {
if (which[m] == COMPUTE) {
int icompute = modify->find_compute(ids[m]);
if (icompute < 0)
- error->all("Compute ID for fix ave/spatial does not exist");
+ error->all(FLERR,"Compute ID for fix ave/spatial does not exist");
value2index[m] = icompute;
} else if (which[m] == FIX) {
int ifix = modify->find_fix(ids[m]);
if (ifix < 0)
- error->all("Fix ID for fix ave/spatial does not exist");
+ error->all(FLERR,"Fix ID for fix ave/spatial does not exist");
value2index[m] = ifix;
if (nevery % modify->fix[ifix]->peratom_freq)
- error->all("Fix for fix ave/spatial not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/spatial not computed at compatible time");
} else if (which[m] == VARIABLE) {
int ivariable = input->variable->find(ids[m]);
if (ivariable < 0)
- error->all("Variable name for fix ave/spatial does not exist");
+ error->all(FLERR,"Variable name for fix ave/spatial does not exist");
value2index[m] = ivariable;
} else value2index[m] = -1;
}
// need to reset nvalid if nvalid < ntimestep b/c minimize was performed
if (nvalid < update->ntimestep) {
irepeat = 0;
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
}
/* ----------------------------------------------------------------------
setup initial bins
only does averaging if nvalid = current timestep
------------------------------------------------------------------------- */
void FixAveSpatial::setup(int vflag)
{
setup_bins();
end_of_step();
}
/* ---------------------------------------------------------------------- */
void FixAveSpatial::end_of_step()
{
int i,j,m,n;
// skip if not step which requires doing something
bigint ntimestep = update->ntimestep;
if (ntimestep != nvalid) return;
// zero out arrays that accumulate over many samples
// if box changes, first re-setup bins
if (irepeat == 0) {
if (domain->box_change) setup_bins();
for (m = 0; m < nbins; m++) {
count_many[m] = count_sum[m] = 0.0;
for (i = 0; i < nvalues; i++) values_many[m][i] = 0.0;
}
}
// zero out arrays for one sample
for (m = 0; m < nbins; m++) {
count_one[m] = 0.0;
for (i = 0; i < nvalues; i++) values_one[m][i] = 0.0;
}
// assign each atom to a bin
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(bin);
memory->create(bin,maxatom,"ave/spatial:bin");
}
if (ndim == 1) atom2bin1d();
else if (ndim == 2) atom2bin2d();
else atom2bin3d();
// perform the computation for one sample
// accumulate results of attributes,computes,fixes,variables to local copy
// sum within each bin, only include atoms in fix group
// compute/fix/variable may invoke computes so wrap with clear/add
modify->clearstep_compute();
for (m = 0; m < nvalues; m++) {
n = value2index[m];
j = argindex[m];
// V,F adds velocities,forces to values
if (which[m] == V || which[m] == F) {
double **attribute;
if (which[m] == V) attribute = atom->v;
else attribute = atom->f;
if (regionflag == 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
values_one[bin[i]][m] += attribute[i][j];
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
values_one[bin[i]][m] += attribute[i][j];
}
// DENSITY_NUMBER adds 1 to values
} else if (which[m] == DENSITY_NUMBER) {
if (regionflag == 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
values_one[bin[i]][m] += 1.0;
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
values_one[bin[i]][m] += 1.0;
}
// DENSITY_MASS adds mass to values
} else if (which[m] == DENSITY_MASS) {
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
if (regionflag == 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) values_one[bin[i]][m] += rmass[i];
else values_one[bin[i]][m] += mass[type[i]];
}
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (rmass) values_one[bin[i]][m] += rmass[i];
else values_one[bin[i]][m] += mass[type[i]];
}
}
// COMPUTE adds its scalar or vector component to values
// invoke compute if not previously invoked
} else if (which[m] == COMPUTE) {
Compute *compute = modify->compute[n];
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
double *vector = compute->vector_atom;
double **array = compute->array_atom;
int jm1 = j - 1;
if (regionflag == 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (j == 0) values_one[bin[i]][m] += vector[i];
else values_one[bin[i]][m] += array[i][jm1];
}
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (j == 0) values_one[bin[i]][m] += vector[i];
else values_one[bin[i]][m] += array[i][jm1];
}
}
// FIX adds its scalar or vector component to values
// access fix fields, guaranteed to be ready
} else if (which[m] == FIX) {
double *vector = modify->fix[n]->vector_atom;
double **array = modify->fix[n]->array_atom;
int jm1 = j - 1;
if (regionflag == 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (j == 0) values_one[bin[i]][m] += vector[i];
else values_one[bin[i]][m] += array[i][jm1];
}
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (j == 0) values_one[bin[i]][m] += vector[i];
else values_one[bin[i]][m] += array[i][jm1];
}
}
// VARIABLE adds its per-atom quantities to values
// evaluate atom-style variable
} else if (which[m] == VARIABLE) {
if (nlocal > maxvar) {
maxvar = atom->nmax;
memory->destroy(varatom);
memory->create(varatom,maxvar,"ave/spatial:varatom");
}
input->variable->compute_atom(n,igroup,varatom,1,0);
if (regionflag == 0) {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
values_one[bin[i]][m] += varatom[i];
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
values_one[bin[i]][m] += varatom[i];
}
}
}
// process a single sample
// if normflag = ALL, accumulate values,count separately to many
// if normflag = SAMPLE, one = value/count, accumulate one to many
// exception is SAMPLE density: no normalization by atom count
if (normflag == ALL) {
for (m = 0; m < nbins; m++) {
count_many[m] += count_one[m];
for (j = 0; j < nvalues; j++)
values_many[m][j] += values_one[m][j];
}
} else {
MPI_Allreduce(count_one,count_many,nbins,MPI_DOUBLE,MPI_SUM,world);
for (m = 0; m < nbins; m++) {
if (count_many[m] > 0.0)
for (j = 0; j < nvalues; j++) {
if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS)
values_many[m][j] += values_one[m][j];
else values_many[m][j] += values_one[m][j]/count_many[m];
}
count_sum[m] += count_many[m];
}
}
// done if irepeat < nrepeat
// else reset irepeat and nvalid
irepeat++;
if (irepeat < nrepeat) {
nvalid += nevery;
modify->addstep_compute(nvalid);
return;
}
irepeat = 0;
nvalid = ntimestep+nfreq - (nrepeat-1)*nevery;
modify->addstep_compute(nvalid);
// time average across samples
// if normflag = ALL, final is total value / total count
// if normflag = SAMPLE, final is sum of ave / repeat
// exception is densities: normalized by repeat, not total count
double repeat = nrepeat;
double mv2d = force->mv2d;
if (normflag == ALL) {
MPI_Allreduce(count_many,count_sum,nbins,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nbins*nvalues,
MPI_DOUBLE,MPI_SUM,world);
for (m = 0; m < nbins; m++) {
if (count_sum[m] > 0.0)
for (j = 0; j < nvalues; j++)
if (which[j] == DENSITY_NUMBER) values_sum[m][j] /= repeat;
else if (which[j] == DENSITY_MASS) values_sum[m][j] *= mv2d/repeat;
else values_sum[m][j] /= count_sum[m];
count_sum[m] /= repeat;
}
} else {
MPI_Allreduce(&values_many[0][0],&values_sum[0][0],nbins*nvalues,
MPI_DOUBLE,MPI_SUM,world);
for (m = 0; m < nbins; m++) {
for (j = 0; j < nvalues; j++)
values_sum[m][j] /= repeat;
count_sum[m] /= repeat;
}
}
// density is additionally normalized by bin volume
for (j = 0; j < nvalues; j++)
if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS)
for (m = 0; m < nbins; m++)
values_sum[m][j] /= bin_volume;
// if ave = ONE, only single Nfreq timestep value is needed
// if ave = RUNNING, combine with all previous Nfreq timestep values
// if ave = WINDOW, comine with nwindow most recent Nfreq timestep values
if (ave == ONE) {
for (m = 0; m < nbins; m++) {
for (i = 0; i < nvalues; i++)
values_total[m][i] = values_sum[m][i];
count_total[m] = count_sum[m];
}
norm = 1;
} else if (ave == RUNNING) {
for (m = 0; m < nbins; m++) {
for (i = 0; i < nvalues; i++)
values_total[m][i] += values_sum[m][i];
count_total[m] += count_sum[m];
}
norm++;
} else if (ave == WINDOW) {
for (m = 0; m < nbins; m++) {
for (i = 0; i < nvalues; i++) {
values_total[m][i] += values_sum[m][i];
if (window_limit) values_total[m][i] -= values_list[iwindow][m][i];
values_list[iwindow][m][i] = values_sum[m][i];
}
count_total[m] += count_sum[m];
if (window_limit) count_total[m] -= count_list[iwindow][m];
count_list[iwindow][m] = count_sum[m];
}
iwindow++;
if (iwindow == nwindow) {
iwindow = 0;
window_limit = 1;
}
if (window_limit) norm = nwindow;
else norm = iwindow;
}
// output result to file
if (fp && me == 0) {
fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nbins);
if (ndim == 1)
for (m = 0; m < nbins; m++) {
fprintf(fp," %d %g %g",m+1,coord[m][0],
count_total[m]/norm);
for (i = 0; i < nvalues; i++)
fprintf(fp," %g",values_total[m][i]/norm);
fprintf(fp,"\n");
}
else if (ndim == 2)
for (m = 0; m < nbins; m++) {
fprintf(fp," %d %g %g %g",m+1,coord[m][0],coord[m][1],
count_total[m]/norm);
for (i = 0; i < nvalues; i++)
fprintf(fp," %g",values_total[m][i]/norm);
fprintf(fp,"\n");
}
else
for (m = 0; m < nbins; m++) {
fprintf(fp," %d %g %g %g %g",m+1,coord[m][0],coord[m][1],coord[m][2],
count_total[m]/norm);
for (i = 0; i < nvalues; i++)
fprintf(fp," %g",values_total[m][i]/norm);
fprintf(fp,"\n");
}
fflush(fp);
}
}
/* ----------------------------------------------------------------------
setup 1d, 2d, or 3d bins and their extent and coordinates
called at setup() and when averaging occurs if box size changes
------------------------------------------------------------------------- */
void FixAveSpatial::setup_bins()
{
int i,j,k,m,n;
double lo,hi,coord1,coord2;
// lo = bin boundary immediately below boxlo
// hi = bin boundary immediately above boxhi
// allocate and initialize arrays based on new bin count
double *boxlo,*boxhi,*prd;
if (scaleflag == REDUCED) {
boxlo = domain->boxlo_lamda;
boxhi = domain->boxhi_lamda;
prd = domain->prd_lamda;
} else {
boxlo = domain->boxlo;
boxhi = domain->boxhi;
prd = domain->prd;
}
if (domain->dimension == 3)
bin_volume = domain->xprd * domain->yprd * domain->zprd;
else bin_volume = domain->xprd * domain->yprd;
nbins = 1;
for (m = 0; m < ndim; m++) {
if (originflag[m] == LOWER) origin[m] = boxlo[dim[m]];
else if (originflag[m] == UPPER) origin[m] = boxhi[dim[m]];
else if (originflag[m] == CENTER)
origin[m] = 0.5 * (boxlo[dim[m]] + boxhi[dim[m]]);
if (origin[m] < boxlo[dim[m]]) {
n = static_cast<int> ((boxlo[dim[m]] - origin[m]) * invdelta[m]);
lo = origin[m] + n*delta[m];
} else {
n = static_cast<int> ((origin[m] - boxlo[dim[m]]) * invdelta[m]);
lo = origin[m] - n*delta[m];
if (lo > boxlo[dim[m]]) lo -= delta[m];
}
if (origin[m] < boxhi[dim[m]]) {
n = static_cast<int> ((boxhi[dim[m]] - origin[m]) * invdelta[m]);
hi = origin[m] + n*delta[m];
if (hi < boxhi[dim[m]]) hi += delta[m];
} else {
n = static_cast<int> ((origin[m] - boxhi[dim[m]]) * invdelta[m]);
hi = origin[m] - n*delta[m];
}
offset[m] = lo;
nlayers[m] = static_cast<int> ((hi-lo) * invdelta[m] + 0.5);
nbins *= nlayers[m];
bin_volume *= delta[m]/prd[dim[m]];
}
// reallocate bin arrays if needed
if (nbins > maxbin) {
maxbin = nbins;
memory->grow(count_one,nbins,"ave/spatial:count_one");
memory->grow(count_many,nbins,"ave/spatial:count_many");
memory->grow(count_sum,nbins,"ave/spatial:count_sum");
memory->grow(count_total,nbins,"ave/spatial:count_total");
memory->grow(coord,nbins,ndim,"ave/spatial:coord");
memory->grow(values_one,nbins,nvalues,"ave/spatial:values_one");
memory->grow(values_many,nbins,nvalues,"ave/spatial:values_many");
memory->grow(values_sum,nbins,nvalues,"ave/spatial:values_sum");
memory->grow(values_total,nbins,nvalues,"ave/spatial:values_total");
// only allocate count and values list for ave = WINDOW
if (ave == WINDOW) {
memory->create(count_list,nwindow,nbins,"ave/spatial:count_list");
memory->create(values_list,nwindow,nbins,nvalues,
"ave/spatial:values_list");
}
// reinitialize regrown count/values total since they accumulate
for (m = 0; m < nbins; m++) {
for (i = 0; i < nvalues; i++) values_total[m][i] = 0.0;
count_total[m] = 0.0;
}
}
// set bin coordinates
if (ndim == 1) {
for (i = 0; i < nlayers[0]; i++)
coord[i][0] = offset[0] + (i+0.5)*delta[0];
} else if (ndim == 2) {
m = 0;
for (i = 0; i < nlayers[0]; i++) {
coord1 = offset[0] + (i+0.5)*delta[0];
for (j = 0; j < nlayers[1]; j++) {
coord[m][0] = coord1;
coord[m][1] = offset[1] + (j+0.5)*delta[1];
m++;
}
}
} else if (ndim == 3) {
m = 0;
for (i = 0; i < nlayers[0]; i++) {
coord1 = offset[0] + (i+0.5)*delta[0];
for (j = 0; j < nlayers[1]; j++) {
coord2 = offset[1] + (j+0.5)*delta[1];
for (k = 0; k < nlayers[2]; k++) {
coord[m][0] = coord1;
coord[m][1] = coord2;
coord[m][2] = offset[2] + (k+0.5)*delta[2];
m++;
}
}
}
}
}
/* ----------------------------------------------------------------------
assign each atom to a 1d bin
------------------------------------------------------------------------- */
void FixAveSpatial::atom2bin1d()
{
int i,ibin;
double *boxlo,*boxhi,*prd;
double xremap;
double lamda[3];
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int idim = dim[0];
int nlayerm1 = nlayers[0] - 1;
int periodicity = domain->periodicity[idim];
if (periodicity) {
if (scaleflag == REDUCED) {
boxlo = domain->boxlo_lamda;
boxhi = domain->boxhi_lamda;
prd = domain->prd_lamda;
} else {
boxlo = domain->boxlo;
boxhi = domain->boxhi;
prd = domain->prd;
}
}
// remap each atom's relevant coord back into box via PBC if necessary
// if scaleflag = REDUCED, box coords -> lamda coords
if (regionflag == 0) {
if (scaleflag == REDUCED) domain->x2lamda(nlocal);
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xremap = x[i][idim];
if (periodicity) {
if (xremap < boxlo[idim]) xremap += prd[idim];
if (xremap >= boxhi[idim]) xremap -= prd[idim];
}
ibin = static_cast<int> ((xremap - offset[0]) * invdelta[0]);
ibin = MAX(ibin,0);
ibin = MIN(ibin,nlayerm1);
bin[i] = ibin;
count_one[ibin] += 1.0;
}
if (scaleflag == REDUCED) domain->lamda2x(nlocal);
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (scaleflag == REDUCED) {
domain->x2lamda(x[i],lamda);
xremap = lamda[idim];
} else xremap = x[i][idim];
if (periodicity) {
if (xremap < boxlo[idim]) xremap += prd[idim];
if (xremap >= boxhi[idim]) xremap -= prd[idim];
}
ibin = static_cast<int> ((xremap - offset[0]) * invdelta[0]);
ibin = MAX(ibin,0);
ibin = MIN(ibin,nlayerm1);
bin[i] = ibin;
count_one[ibin] += 1.0;
}
}
}
/* ----------------------------------------------------------------------
assign each atom to a 2d bin
------------------------------------------------------------------------- */
void FixAveSpatial::atom2bin2d()
{
int i,ibin,i1bin,i2bin;
double *boxlo,*boxhi,*prd;
double xremap,yremap;
double lamda[3];
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int idim = dim[0];
int jdim = dim[1];
int nlayer1m1 = nlayers[0] - 1;
int nlayer2m1 = nlayers[1] - 1;
int* periodicity = domain->periodicity;
if (periodicity[idim] || periodicity[jdim]) {
if (scaleflag == REDUCED) {
boxlo = domain->boxlo_lamda;
boxhi = domain->boxhi_lamda;
prd = domain->prd_lamda;
} else {
boxlo = domain->boxlo;
boxhi = domain->boxhi;
prd = domain->prd;
}
}
// remap each atom's relevant coord back into box via PBC if necessary
// if scaleflag = REDUCED, box coords -> lamda coords
if (regionflag == 0) {
if (scaleflag == REDUCED) domain->x2lamda(nlocal);
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xremap = x[i][idim];
if (periodicity[idim]) {
if (xremap < boxlo[idim]) xremap += prd[idim];
if (xremap >= boxhi[idim]) xremap -= prd[idim];
}
i1bin = static_cast<int> ((xremap - offset[0]) * invdelta[0]);
i1bin = MAX(i1bin,0);
i1bin = MIN(i1bin,nlayer1m1);
yremap = x[i][jdim];
if (periodicity[jdim]) {
if (yremap < boxlo[jdim]) yremap += prd[jdim];
if (yremap >= boxhi[jdim]) yremap -= prd[jdim];
}
i2bin = static_cast<int> ((yremap - offset[1]) * invdelta[1]);
i2bin = MAX(i2bin,0);
i2bin = MIN(i2bin,nlayer2m1);
ibin = i1bin*nlayers[1] + i2bin;
bin[i] = ibin;
count_one[ibin] += 1.0;
}
if (scaleflag == REDUCED) domain->lamda2x(nlocal);
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (scaleflag == REDUCED) {
domain->x2lamda(x[i],lamda);
xremap = lamda[idim];
yremap = lamda[jdim];
} else {
xremap = x[i][idim];
yremap = x[i][jdim];
}
if (periodicity[idim]) {
if (xremap < boxlo[idim]) xremap += prd[idim];
if (xremap >= boxhi[idim]) xremap -= prd[idim];
}
i1bin = static_cast<int> ((xremap - offset[0]) * invdelta[0]);
i1bin = MAX(i1bin,0);
i1bin = MIN(i1bin,nlayer1m1-1);
if (periodicity[jdim]) {
if (yremap < boxlo[jdim]) yremap += prd[jdim];
if (yremap >= boxhi[jdim]) yremap -= prd[jdim];
}
i2bin = static_cast<int> ((yremap - offset[1]) * invdelta[1]);
i2bin = MAX(i2bin,0);
i2bin = MIN(i2bin,nlayer2m1-1);
ibin = i1bin*nlayers[1] + i2bin;
bin[i] = ibin;
count_one[ibin] += 1.0;
}
}
}
/* ----------------------------------------------------------------------
assign each atom to a 3d bin
------------------------------------------------------------------------- */
void FixAveSpatial::atom2bin3d()
{
int i,ibin,i1bin,i2bin,i3bin;
double *boxlo,*boxhi,*prd;
double xremap,yremap,zremap;
double lamda[3];
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int idim = dim[0];
int jdim = dim[1];
int kdim = dim[2];
int nlayer1m1 = nlayers[0] - 1;
int nlayer2m1 = nlayers[1] - 1;
int nlayer3m1 = nlayers[2] - 1;
int* periodicity = domain->periodicity;
if (periodicity[idim] || periodicity[jdim] || periodicity[kdim]) {
if (scaleflag == REDUCED) {
boxlo = domain->boxlo_lamda;
boxhi = domain->boxhi_lamda;
prd = domain->prd_lamda;
} else {
boxlo = domain->boxlo;
boxhi = domain->boxhi;
prd = domain->prd;
}
}
// remap each atom's relevant coord back into box via PBC if necessary
// if scaleflag = REDUCED, box coords -> lamda coords
if (regionflag == 0) {
if (scaleflag == REDUCED) domain->x2lamda(nlocal);
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xremap = x[i][idim];
if (periodicity[idim]) {
if (xremap < boxlo[idim]) xremap += prd[idim];
if (xremap >= boxhi[idim]) xremap -= prd[idim];
}
i1bin = static_cast<int> ((xremap - offset[0]) * invdelta[0]);
i1bin = MAX(i1bin,0);
i1bin = MIN(i1bin,nlayer1m1);
yremap = x[i][jdim];
if (periodicity[jdim]) {
if (yremap < boxlo[jdim]) yremap += prd[jdim];
if (yremap >= boxhi[jdim]) yremap -= prd[jdim];
}
i2bin = static_cast<int> ((yremap - offset[1]) * invdelta[1]);
i2bin = MAX(i2bin,0);
i2bin = MIN(i2bin,nlayer2m1);
zremap = x[i][kdim];
if (periodicity[kdim]) {
if (zremap < boxlo[kdim]) yremap += prd[kdim];
if (zremap >= boxhi[kdim]) yremap -= prd[kdim];
}
i3bin = static_cast<int> ((zremap - offset[2]) * invdelta[2]);
i3bin = MAX(i3bin,0);
i3bin = MIN(i3bin,nlayer3m1);
ibin = i1bin*nlayers[1]*nlayers[2] + i2bin*nlayers[2] + i3bin;
bin[i] = ibin;
count_one[ibin] += 1.0;
}
if (scaleflag == REDUCED) domain->lamda2x(nlocal);
} else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
if (scaleflag == REDUCED) {
domain->x2lamda(x[i],lamda);
xremap = lamda[idim];
yremap = lamda[jdim];
zremap = lamda[kdim];
} else {
xremap = x[i][idim];
yremap = x[i][jdim];
zremap = x[i][kdim];
}
if (periodicity[idim]) {
if (xremap < boxlo[idim]) xremap += prd[idim];
if (xremap >= boxhi[idim]) xremap -= prd[idim];
}
i1bin = static_cast<int> ((xremap - offset[0]) * invdelta[0]);
i1bin = MAX(i1bin,0);
i1bin = MIN(i1bin,nlayer1m1);
if (periodicity[jdim]) {
if (yremap < boxlo[jdim]) yremap += prd[jdim];
if (yremap >= boxhi[jdim]) yremap -= prd[jdim];
}
i2bin = static_cast<int> ((yremap - offset[1]) * invdelta[1]);
i2bin = MAX(i2bin,0);
i2bin = MIN(i2bin,nlayer2m1);
if (periodicity[kdim]) {
if (zremap < boxlo[kdim]) yremap += prd[kdim];
if (zremap >= boxhi[kdim]) yremap -= prd[kdim];
}
i3bin = static_cast<int> ((zremap - offset[2]) * invdelta[2]);
i3bin = MAX(i3bin,0);
i3bin = MIN(i3bin,nlayer3m1);
ibin = i1bin*nlayers[1]*nlayers[2] + i2bin*nlayers[2] + i3bin;
bin[i] = ibin;
count_one[ibin] += 1.0;
}
}
}
/* ----------------------------------------------------------------------
return I,J array value
if I exceeds current bins, return 0.0 instead of generating an error
column 1,2,3 = bin coords, next column = count, remaining columns = Nvalues
------------------------------------------------------------------------- */
double FixAveSpatial::compute_array(int i, int j)
{
if (values_total == NULL) return 0.0;
if (i >= nbins) return 0.0;
if (j < ndim) return coord[i][j];
j -= ndim+1;
if (j < 0) return count_total[i]/norm;
return values_total[i][j]/norm;
}
/* ----------------------------------------------------------------------
calculate nvalid = next step on which end_of_step does something
can be this timestep if multiple of nfreq and nrepeat = 1
else backup from next multiple of nfreq
------------------------------------------------------------------------- */
bigint FixAveSpatial::nextvalid()
{
bigint nvalid = (update->ntimestep/nfreq)*nfreq + nfreq;
if (nvalid-nfreq == update->ntimestep && nrepeat == 1)
nvalid = update->ntimestep;
else
nvalid -= (nrepeat-1)*nevery;
if (nvalid < update->ntimestep) nvalid += nfreq;
return nvalid;
}
/* ----------------------------------------------------------------------
memory usage of varatom and bins
------------------------------------------------------------------------- */
double FixAveSpatial::memory_usage()
{
double bytes = maxvar * sizeof(double); // varatom
bytes += maxatom * sizeof(int); // bin
bytes += 4*nbins * sizeof(double); // count one,many,sum,total
bytes += ndim*nbins * sizeof(double); // coord
bytes += nvalues*nbins * sizeof(double); // values one,many,sum,total
bytes += nwindow*nbins * sizeof(double); // count_list
bytes += nwindow*nbins*nvalues * sizeof(double); // values_list
return bytes;
}
diff --git a/src/fix_ave_time.cpp b/src/fix_ave_time.cpp
index 5addde625..6d93da8e6 100644
--- a/src/fix_ave_time.cpp
+++ b/src/fix_ave_time.cpp
@@ -1,927 +1,927 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "fix_ave_time.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "group.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{COMPUTE,FIX,VARIABLE};
enum{ONE,RUNNING,WINDOW};
enum{SCALAR,VECTOR};
#define INVOKED_SCALAR 1
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
/* ---------------------------------------------------------------------- */
FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal fix ave/time command");
+ if (narg < 7) error->all(FLERR,"Illegal fix ave/time command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
nrepeat = atoi(arg[4]);
nfreq = atoi(arg[5]);
global_freq = nfreq;
time_depend = 1;
// scan values to count them
// then read options so know mode = SCALAR/VECTOR before re-reading values
nvalues = 0;
int iarg = 6;
while (iarg < narg) {
if ((strncmp(arg[iarg],"c_",2) == 0) ||
(strncmp(arg[iarg],"f_",2) == 0) ||
(strncmp(arg[iarg],"v_",2) == 0)) {
nvalues++;
iarg++;
} else break;
}
options(narg,arg);
// parse values until one isn't recognized
// if mode = VECTOR and value is a global array:
// expand it as if columns listed one by one
// adjust nvalues accordingly via maxvalues
which = argindex = value2index = offcol = NULL;
ids = NULL;
int maxvalues = nvalues;
allocate_values(maxvalues);
nvalues = 0;
iarg = 6;
while (iarg < narg) {
if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal fix ave/time command");
+ error->all(FLERR,"Illegal fix ave/time command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
delete [] suffix;
if (mode == VECTOR && which[nvalues] == COMPUTE &&
argindex[nvalues] == 0) {
int icompute = modify->find_compute(ids[nvalues]);
if (icompute < 0)
- error->all("Compute ID for fix ave/time does not exist");
+ error->all(FLERR,"Compute ID for fix ave/time does not exist");
if (modify->compute[icompute]->array_flag) {
int ncols = modify->compute[icompute]->size_array_cols;
maxvalues += ncols-1;
allocate_values(maxvalues);
argindex[nvalues] = 1;
for (int icol = 1; icol < ncols; icol++) {
which[nvalues+icol] = which[nvalues];
argindex[nvalues+icol] = icol+1;
n = strlen(ids[nvalues]) + 1;
ids[nvalues+icol] = new char[n];
strcpy(ids[nvalues+icol],ids[nvalues]);
}
nvalues += ncols-1;
}
} else if (mode == VECTOR && which[nvalues] == FIX &&
argindex[nvalues] == 0) {
int ifix = modify->find_fix(ids[nvalues]);
if (ifix < 0)
- error->all("Fix ID for fix ave/time does not exist");
+ error->all(FLERR,"Fix ID for fix ave/time does not exist");
if (modify->fix[ifix]->array_flag) {
int ncols = modify->fix[ifix]->size_array_cols;
maxvalues += ncols-1;
allocate_values(maxvalues);
argindex[nvalues] = 1;
for (int icol = 1; icol < ncols; icol++) {
which[nvalues+icol] = which[nvalues];
argindex[nvalues+icol] = icol+1;
n = strlen(ids[nvalues]) + 1;
ids[nvalues+icol] = new char[n];
strcpy(ids[nvalues+icol],ids[nvalues]);
}
nvalues += ncols-1;
}
}
nvalues++;
iarg++;
} else break;
}
// set off columns now that nvalues is finalized
for (int i = 0; i < nvalues; i++) offcol[i] = 0;
for (int i = 0; i < noff; i++) {
if (offlist[i] < 1 || offlist[i] > nvalues)
- error->all("Invalid fix ave/time off column");
+ error->all(FLERR,"Invalid fix ave/time off column");
offcol[offlist[i]-1] = 1;
}
// setup and error check
// for fix inputs, check that fix frequency is acceptable
if (nevery <= 0 || nrepeat <= 0 || nfreq <= 0)
- error->all("Illegal fix ave/time command");
+ error->all(FLERR,"Illegal fix ave/time command");
if (nfreq % nevery || (nrepeat-1)*nevery >= nfreq)
- error->all("Illegal fix ave/time command");
+ error->all(FLERR,"Illegal fix ave/time command");
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE && mode == SCALAR) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/time does not exist");
+ error->all(FLERR,"Compute ID for fix ave/time does not exist");
if (argindex[i] == 0 && modify->compute[icompute]->scalar_flag == 0)
- error->all("Fix ave/time compute does not calculate a scalar");
+ error->all(FLERR,"Fix ave/time compute does not calculate a scalar");
if (argindex[i] && modify->compute[icompute]->vector_flag == 0)
- error->all("Fix ave/time compute does not calculate a vector");
+ error->all(FLERR,"Fix ave/time compute does not calculate a vector");
if (argindex[i] && argindex[i] > modify->compute[icompute]->size_vector)
- error->all("Fix ave/time compute vector is accessed out-of-range");
+ error->all(FLERR,"Fix ave/time compute vector is accessed out-of-range");
} else if (which[i] == COMPUTE && mode == VECTOR) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/time does not exist");
+ error->all(FLERR,"Compute ID for fix ave/time does not exist");
if (argindex[i] == 0 && modify->compute[icompute]->vector_flag == 0)
- error->all("Fix ave/time compute does not calculate a vector");
+ error->all(FLERR,"Fix ave/time compute does not calculate a vector");
if (argindex[i] && modify->compute[icompute]->array_flag == 0)
- error->all("Fix ave/time compute does not calculate an array");
+ error->all(FLERR,"Fix ave/time compute does not calculate an array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_array_cols)
- error->all("Fix ave/time compute array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/time compute array is accessed out-of-range");
} else if (which[i] == FIX && mode == SCALAR) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/time does not exist");
+ error->all(FLERR,"Fix ID for fix ave/time does not exist");
if (argindex[i] == 0 && modify->fix[ifix]->scalar_flag == 0)
- error->all("Fix ave/time fix does not calculate a scalar");
+ error->all(FLERR,"Fix ave/time fix does not calculate a scalar");
if (argindex[i] && modify->fix[ifix]->vector_flag == 0)
- error->all("Fix ave/time fix does not calculate a vector");
+ error->all(FLERR,"Fix ave/time fix does not calculate a vector");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_vector)
- error->all("Fix ave/time fix vector is accessed out-of-range");
+ error->all(FLERR,"Fix ave/time fix vector is accessed out-of-range");
if (nevery % modify->fix[ifix]->global_freq)
- error->all("Fix for fix ave/time not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/time not computed at compatible time");
} else if (which[i] == FIX && mode == VECTOR) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/time does not exist");
+ error->all(FLERR,"Fix ID for fix ave/time does not exist");
if (argindex[i] == 0 && modify->fix[ifix]->vector_flag == 0)
- error->all("Fix ave/time fix does not calculate a vector");
+ error->all(FLERR,"Fix ave/time fix does not calculate a vector");
if (argindex[i] && modify->fix[ifix]->array_flag == 0)
- error->all("Fix ave/time fix does not calculate an array");
+ error->all(FLERR,"Fix ave/time fix does not calculate an array");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_array_cols)
- error->all("Fix ave/time fix array is accessed out-of-range");
+ error->all(FLERR,"Fix ave/time fix array is accessed out-of-range");
if (nevery % modify->fix[ifix]->global_freq)
- error->all("Fix for fix ave/time not computed at compatible time");
+ error->all(FLERR,"Fix for fix ave/time not computed at compatible time");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/time does not exist");
+ error->all(FLERR,"Variable name for fix ave/time does not exist");
if (input->variable->equalstyle(ivariable) == 0)
- error->all("Fix ave/time variable is not equal-style variable");
+ error->all(FLERR,"Fix ave/time variable is not equal-style variable");
if (mode == VECTOR)
- error->all("Fix ave/time cannot use variable with vector mode");
+ error->all(FLERR,"Fix ave/time cannot use variable with vector mode");
}
}
// if VECTOR mode, check that all columns are same length
// nrows = # of rows in output array
if (mode == VECTOR) {
int length;
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (argindex[i] == 0) length = modify->compute[icompute]->size_vector;
else length = modify->compute[icompute]->size_array_rows;
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (argindex[i] == 0) length = modify->fix[ifix]->size_vector;
else length = modify->fix[ifix]->size_array_rows;
}
if (i == 0) nrows = length;
else if (length != nrows)
- error->all("Fix ave/time columns are inconsistent lengths");
+ error->all(FLERR,"Fix ave/time columns are inconsistent lengths");
}
column = new double[nrows];
} else column = NULL;
// print file comment lines
// for mode = VECTOR, cannot use arg to print
// since array args may have been expanded to multiple vectors
if (fp && me == 0) {
if (title1) fprintf(fp,"%s\n",title1);
else fprintf(fp,"# Time-averaged data for fix %s\n",id);
if (title2) fprintf(fp,"%s\n",title2);
else if (mode == SCALAR) {
fprintf(fp,"# TimeStep");
for (int i = 0; i < nvalues; i++) fprintf(fp," %s",arg[6+i]);
fprintf(fp,"\n");
} else fprintf(fp,"# TimeStep Number-of-rows\n");
if (title3 && mode == VECTOR) fprintf(fp,"%s\n",title3);
else if (mode == VECTOR) {
fprintf(fp,"# Row");
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) fprintf(fp," c_%s",ids[i]);
else if (which[i] == FIX) fprintf(fp," f_%s",ids[i]);
else if (which[i] == VARIABLE) fprintf(fp," v_%s",ids[i]);
if (argindex[i]) fprintf(fp,"[%d]",argindex[i]);
}
fprintf(fp,"\n");
}
}
delete [] title1;
delete [] title2;
delete [] title3;
// allocate memory for averaging
vector = vector_total = NULL;
vector_list = NULL;
array = array_total = NULL;
array_list = NULL;
if (mode == SCALAR) {
vector = new double[nvalues];
vector_total = new double[nvalues];
if (ave == WINDOW)
memory->create(vector_list,nwindow,nvalues,"ave/time:vector_list");
} else {
memory->create(array,nrows,nvalues,"ave/time:array");
memory->create(array_total,nrows,nvalues,"ave/time:array_total");
if (ave == WINDOW)
memory->create(array_list,nwindow,nrows,nvalues,"ave/time:array_list");
}
// this fix produces either a global scalar or vector or array
// SCALAR mode produces either a scalar or vector
// VECTOR mode produces either a vector or array
// intensive/extensive flags set by compute,fix,variable that produces value
extlist = NULL;
if (mode == SCALAR) {
if (nvalues == 1) {
scalar_flag = 1;
if (which[0] == COMPUTE) {
Compute *compute = modify->compute[modify->find_compute(ids[0])];
if (argindex[0] == 0) extscalar = compute->extscalar;
else if (compute->extvector >= 0) extscalar = compute->extvector;
else extscalar = compute->extlist[argindex[0]-1];
} else if (which[0] == FIX) {
Fix *fix = modify->fix[modify->find_fix(ids[0])];
if (argindex[0] == 0) extscalar = fix->extscalar;
else if (fix->extvector >= 0) extscalar = fix->extvector;
else extscalar = fix->extlist[argindex[0]-1];
} else if (which[0] == VARIABLE)
extscalar = 0;
} else {
vector_flag = 1;
size_vector = nvalues;
extvector = -1;
extlist = new int[nvalues];
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
Compute *compute = modify->compute[modify->find_compute(ids[i])];
if (argindex[i] == 0) extlist[i] = compute->extscalar;
else if (compute->extvector >= 0) extlist[i] = compute->extvector;
else extlist[i] = compute->extlist[argindex[i]-1];
} else if (which[i] == FIX) {
Fix *fix = modify->fix[modify->find_fix(ids[i])];
if (argindex[i] == 0) extlist[i] = fix->extscalar;
else if (fix->extvector >= 0) extlist[i] = fix->extvector;
else extlist[i] = fix->extlist[argindex[i]-1];
} else if (which[i] == VARIABLE)
extlist[i] = 0;
}
}
} else {
if (nvalues == 1) {
vector_flag = 1;
size_vector = nrows;
if (which[0] == COMPUTE) {
Compute *compute = modify->compute[modify->find_compute(ids[0])];
if (argindex[0] == 0) {
extvector = compute->extvector;
if (extvector == -1) {
extlist = new int[nrows];
for (int i = 0; i < nrows; i++) extlist[i] = compute->extlist[i];
}
} else extvector = compute->extarray;
} else if (which[0] == FIX) {
Fix *fix = modify->fix[modify->find_fix(ids[0])];
if (argindex[0] == 0) {
extvector = fix->extvector;
if (extvector == -1) {
extlist = new int[nrows];
for (int i = 0; i < nrows; i++) extlist[i] = fix->extlist[i];
}
} else extvector = fix->extarray;
}
} else {
array_flag = 1;
size_local_rows = nrows;
size_local_cols = nvalues;
int value;
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
Compute *compute = modify->compute[modify->find_compute(ids[i])];
if (argindex[i] == 0) value = compute->extvector;
else value = compute->extarray;
} else if (which[i] == FIX) {
Fix *fix = modify->fix[modify->find_fix(ids[i])];
if (argindex[i] == 0) value = fix->extvector;
else value = fix->extarray;
}
if (value == -1)
- error->all("Fix ave/time cannot set output array "
+ error->all(FLERR,"Fix ave/time cannot set output array "
"intensive/extensive from these inputs");
if (i == 0) extarray = value;
else if (value != extarray)
- error->all("Fix ave/time cannot set output array "
+ error->all(FLERR,"Fix ave/time cannot set output array "
"intensive/extensive from these inputs");
}
}
}
// initializations
// set vector_total/array_total to zero since it accumulates
irepeat = 0;
iwindow = window_limit = 0;
norm = 0;
if (mode == SCALAR)
for (int i = 0; i < nvalues; i++) vector_total[i] = 0.0;
else
for (int i = 0; i < nrows; i++)
for (int j = 0; j < nvalues; j++) array_total[i][j] = 0.0;
// nvalid = next step on which end_of_step does something
// add nvalid to all computes that store invocation times
// since don't know a priori which are invoked by this fix
// once in end_of_step() can set timestep for ones actually invoked
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
/* ---------------------------------------------------------------------- */
FixAveTime::~FixAveTime()
{
memory->destroy(which);
memory->destroy(argindex);
memory->destroy(value2index);
memory->destroy(offcol);
for (int i = 0; i < nvalues; i++) delete [] ids[i];
memory->sfree(ids);
delete [] extlist;
if (fp && me == 0) fclose(fp);
delete [] vector;
delete [] vector_total;
delete [] column;
memory->destroy(array);
memory->destroy(array_total);
memory->destroy(array_list);
}
/* ---------------------------------------------------------------------- */
int FixAveTime::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAveTime::init()
{
// set current indices for all computes,fixes,variables
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix ave/time does not exist");
+ error->all(FLERR,"Compute ID for fix ave/time does not exist");
value2index[i] = icompute;
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix ave/time does not exist");
+ error->all(FLERR,"Fix ID for fix ave/time does not exist");
value2index[i] = ifix;
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix ave/time does not exist");
+ error->all(FLERR,"Variable name for fix ave/time does not exist");
value2index[i] = ivariable;
}
}
// need to reset nvalid if nvalid < ntimestep b/c minimize was performed
if (nvalid < update->ntimestep) {
irepeat = 0;
nvalid = nextvalid();
modify->addstep_compute_all(nvalid);
}
}
/* ----------------------------------------------------------------------
only does something if nvalid = current timestep
------------------------------------------------------------------------- */
void FixAveTime::setup(int vflag)
{
end_of_step();
}
/* ---------------------------------------------------------------------- */
void FixAveTime::end_of_step()
{
// skip if not step which requires doing something
bigint ntimestep = update->ntimestep;
if (ntimestep != nvalid) return;
if (mode == SCALAR) invoke_scalar(ntimestep);
else invoke_vector(ntimestep);
}
/* ---------------------------------------------------------------------- */
void FixAveTime::invoke_scalar(bigint ntimestep)
{
int i,m;
double scalar;
// zero if first step
if (irepeat == 0)
for (i = 0; i < nvalues; i++) vector[i] = 0.0;
// accumulate results of computes,fixes,variables to local copy
// compute/fix/variable may invoke computes so wrap with clear/add
modify->clearstep_compute();
for (i = 0; i < nvalues; i++) {
m = value2index[i];
// invoke compute if not previously invoked
if (which[i] == COMPUTE) {
Compute *compute = modify->compute[m];
if (argindex[i] == 0) {
if (!(compute->invoked_flag & INVOKED_SCALAR)) {
compute->compute_scalar();
compute->invoked_flag |= INVOKED_SCALAR;
}
scalar = compute->scalar;
} else {
if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
scalar = compute->vector[argindex[i]-1];
}
// access fix fields, guaranteed to be ready
} else if (which[i] == FIX) {
if (argindex[i] == 0)
scalar = modify->fix[m]->compute_scalar();
else
scalar = modify->fix[m]->compute_vector(argindex[i]-1);
// evaluate equal-style variable
} else if (which[i] == VARIABLE)
scalar = input->variable->compute_equal(m);
// add value to vector or just set directly if offcol is set
if (offcol[i]) vector[i] = scalar;
else vector[i] += scalar;
}
// done if irepeat < nrepeat
// else reset irepeat and nvalid
irepeat++;
if (irepeat < nrepeat) {
nvalid += nevery;
modify->addstep_compute(nvalid);
return;
}
irepeat = 0;
nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
modify->addstep_compute(nvalid);
// average the final result for the Nfreq timestep
double repeat = nrepeat;
for (i = 0; i < nvalues; i++)
if (offcol[i] == 0) vector[i] /= repeat;
// if ave = ONE, only single Nfreq timestep value is needed
// if ave = RUNNING, combine with all previous Nfreq timestep values
// if ave = WINDOW, combine with nwindow most recent Nfreq timestep values
if (ntimestep >= startstep) {
if (ave == ONE) {
for (i = 0; i < nvalues; i++) vector_total[i] = vector[i];
norm = 1;
} else if (ave == RUNNING) {
for (i = 0; i < nvalues; i++) vector_total[i] += vector[i];
norm++;
} else if (ave == WINDOW) {
for (i = 0; i < nvalues; i++) {
vector_total[i] += vector[i];
if (window_limit) vector_total[i] -= vector_list[iwindow][i];
vector_list[iwindow][i] = vector[i];
}
iwindow++;
if (iwindow == nwindow) {
iwindow = 0;
window_limit = 1;
}
if (window_limit) norm = nwindow;
else norm = iwindow;
}
}
// insure any columns with offcol set are effectively set to last value
for (i = 0; i < nvalues; i++)
if (offcol[i]) vector_total[i] = norm*vector[i];
// output result to file
if (fp && me == 0) {
fprintf(fp,BIGINT_FORMAT,ntimestep);
for (i = 0; i < nvalues; i++) fprintf(fp," %g",vector_total[i]/norm);
fprintf(fp,"\n");
fflush(fp);
}
}
/* ---------------------------------------------------------------------- */
void FixAveTime::invoke_vector(bigint ntimestep)
{
int i,j,m;
// zero if first step
if (irepeat == 0)
for (i = 0; i < nrows; i++)
for (j = 0; j < nvalues; j++) array[i][j] = 0.0;
// accumulate results of computes,fixes,variables to local copy
// compute/fix/variable may invoke computes so wrap with clear/add
modify->clearstep_compute();
for (j = 0; j < nvalues; j++) {
m = value2index[j];
// invoke compute if not previously invoked
if (which[j] == COMPUTE) {
Compute *compute = modify->compute[m];
if (argindex[j] == 0) {
if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
double *cvector = compute->vector;
for (i = 0; i < nrows; i++)
column[i] = cvector[i];
} else {
if (!(compute->invoked_flag & INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
}
double **carray = compute->array;
int icol = argindex[j]-1;
for (i = 0; i < nrows; i++)
column[i] = carray[i][icol];
}
// access fix fields, guaranteed to be ready
} else if (which[j] == FIX) {
Fix *fix = modify->fix[m];
if (argindex[j] == 0)
for (i = 0; i < nrows; i++)
column[i] = fix->compute_vector(i);
else {
int icol = argindex[j]-1;
for (i = 0; i < nrows; i++)
column[i] = fix->compute_array(i,icol);
}
}
// add columns of values to array or just set directly if offcol is set
if (offcol[j]) {
for (i = 0; i < nrows; i++)
array[i][j] = column[i];
} else {
for (i = 0; i < nrows; i++)
array[i][j] += column[i];
}
}
// done if irepeat < nrepeat
// else reset irepeat and nvalid
irepeat++;
if (irepeat < nrepeat) {
nvalid += nevery;
modify->addstep_compute(nvalid);
return;
}
irepeat = 0;
nvalid = ntimestep+nfreq - (nrepeat-1)*nevery;
modify->addstep_compute(nvalid);
// average the final result for the Nfreq timestep
double repeat = nrepeat;
for (i = 0; i < nrows; i++)
for (j = 0; j < nvalues; j++)
if (offcol[j] == 0) array[i][j] /= repeat;
// if ave = ONE, only single Nfreq timestep value is needed
// if ave = RUNNING, combine with all previous Nfreq timestep values
// if ave = WINDOW, combine with nwindow most recent Nfreq timestep values
if (ntimestep >= startstep) {
if (ave == ONE) {
for (i = 0; i < nrows; i++)
for (j = 0; j < nvalues; j++) array_total[i][j] = array[i][j];
norm = 1;
} else if (ave == RUNNING) {
for (i = 0; i < nrows; i++)
for (j = 0; j < nvalues; j++) array_total[i][j] += array[i][j];
norm++;
} else if (ave == WINDOW) {
for (i = 0; i < nrows; i++)
for (j = 0; j < nvalues; j++) {
array_total[i][j] += array[i][j];
if (window_limit) array_total[i][j] -= array_list[iwindow][i][j];
array_list[iwindow][i][j] = array[i][j];
}
iwindow++;
if (iwindow == nwindow) {
iwindow = 0;
window_limit = 1;
}
if (window_limit) norm = nwindow;
else norm = iwindow;
}
}
// insure any columns with offcol set are effectively set to last value
for (i = 0; i < nrows; i++)
for (j = 0; j < nvalues; j++)
if (offcol[j]) array_total[i][j] = norm*array[i][j];
// output result to file
if (fp && me == 0) {
fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nrows);
for (i = 0; i < nrows; i++) {
fprintf(fp,"%d",i+1);
for (j = 0; j < nvalues; j++) fprintf(fp," %g",array_total[i][j]/norm);
fprintf(fp,"\n");
}
fflush(fp);
}
}
/* ----------------------------------------------------------------------
return scalar value
------------------------------------------------------------------------- */
double FixAveTime::compute_scalar()
{
if (norm) return vector_total[0]/norm;
return 0.0;
}
/* ----------------------------------------------------------------------
return Ith vector value
------------------------------------------------------------------------- */
double FixAveTime::compute_vector(int i)
{
if (norm) {
if (mode == SCALAR) return vector_total[i]/norm;
if (mode == VECTOR) return array_total[i][0];
}
return 0.0;
}
/* ----------------------------------------------------------------------
return I,J array value
------------------------------------------------------------------------- */
double FixAveTime::compute_array(int i, int j)
{
if (norm) return array_total[i][j]/norm;
return 0.0;
}
/* ----------------------------------------------------------------------
parse optional args
------------------------------------------------------------------------- */
void FixAveTime::options(int narg, char **arg)
{
// option defaults
fp = NULL;
ave = ONE;
startstep = 0;
mode = SCALAR;
noff = 0;
offlist = NULL;
title1 = NULL;
title2 = NULL;
title3 = NULL;
// optional args
int iarg = 6 + nvalues;
while (iarg < narg) {
if (strcmp(arg[iarg],"file") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/time command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
if (me == 0) {
fp = fopen(arg[iarg+1],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix ave/time file %s",arg[iarg+1]);
- error->one(str);
+ error->one(FLERR,str);
}
}
iarg += 2;
} else if (strcmp(arg[iarg],"ave") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/time command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
if (strcmp(arg[iarg+1],"one") == 0) ave = ONE;
else if (strcmp(arg[iarg+1],"running") == 0) ave = RUNNING;
else if (strcmp(arg[iarg+1],"window") == 0) ave = WINDOW;
- else error->all("Illegal fix ave/time command");
+ else error->all(FLERR,"Illegal fix ave/time command");
if (ave == WINDOW) {
- if (iarg+3 > narg) error->all("Illegal fix ave/time command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix ave/time command");
nwindow = atoi(arg[iarg+2]);
- if (nwindow <= 0) error->all("Illegal fix ave/time command");
+ if (nwindow <= 0) error->all(FLERR,"Illegal fix ave/time command");
}
iarg += 2;
if (ave == WINDOW) iarg++;
} else if (strcmp(arg[iarg],"start") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/time command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
startstep = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"mode") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/time command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
if (strcmp(arg[iarg+1],"scalar") == 0) mode = SCALAR;
else if (strcmp(arg[iarg+1],"vector") == 0) mode = VECTOR;
- else error->all("Illegal fix ave/time command");
+ else error->all(FLERR,"Illegal fix ave/time command");
iarg += 2;
} else if (strcmp(arg[iarg],"off") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/time command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
memory->grow(offlist,noff+1,"ave/time:offlist");
offlist[noff++] = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title1") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title1;
int n = strlen(arg[iarg+1]) + 1;
title1 = new char[n];
strcpy(title1,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title2") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title2;
int n = strlen(arg[iarg+1]) + 1;
title2 = new char[n];
strcpy(title2,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"title3") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix ave/spatial command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
delete [] title3;
int n = strlen(arg[iarg+1]) + 1;
title3 = new char[n];
strcpy(title3,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix ave/time command");
+ } else error->all(FLERR,"Illegal fix ave/time command");
}
}
/* ----------------------------------------------------------------------
reallocate vectors for each input value, of length N
------------------------------------------------------------------------- */
void FixAveTime::allocate_values(int n)
{
memory->grow(which,n,"ave/time:which");
memory->grow(argindex,n,"ave/time:argindex");
memory->grow(value2index,n,"ave/time:value2index");
memory->grow(offcol,n,"ave/time:offcol");
ids = (char **) memory->srealloc(ids,n*sizeof(char *),"ave/time:ids");
}
/* ----------------------------------------------------------------------
calculate nvalid = next step on which end_of_step does something
can be this timestep if multiple of nfreq and nrepeat = 1
else backup from next multiple of nfreq
------------------------------------------------------------------------- */
bigint FixAveTime::nextvalid()
{
bigint nvalid = (update->ntimestep/nfreq)*nfreq + nfreq;
if (nvalid-nfreq == update->ntimestep && nrepeat == 1)
nvalid = update->ntimestep;
else
nvalid -= (nrepeat-1)*nevery;
if (nvalid < update->ntimestep) nvalid += nfreq;
return nvalid;
}
diff --git a/src/fix_aveforce.cpp b/src/fix_aveforce.cpp
index b4fd4f333..c825e51b3 100644
--- a/src/fix_aveforce.cpp
+++ b/src/fix_aveforce.cpp
@@ -1,311 +1,311 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "fix_aveforce.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "region.h"
#include "respa.h"
#include "input.h"
#include "variable.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NONE,CONSTANT,EQUAL};
/* ---------------------------------------------------------------------- */
FixAveForce::FixAveForce(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix aveforce command");
+ if (narg < 6) error->all(FLERR,"Illegal fix aveforce command");
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extvector = 1;
xstr = ystr = zstr = NULL;
if (strstr(arg[3],"v_") == arg[3]) {
int n = strlen(&arg[3][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[3][2]);
} else if (strcmp(arg[3],"NULL") == 0) {
xstyle = NONE;
} else {
xvalue = atof(arg[3]);
xstyle = CONSTANT;
}
if (strstr(arg[4],"v_") == arg[4]) {
int n = strlen(&arg[4][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[4][2]);
} else if (strcmp(arg[4],"NULL") == 0) {
ystyle = NONE;
} else {
yvalue = atof(arg[4]);
ystyle = CONSTANT;
}
if (strstr(arg[5],"v_") == arg[5]) {
int n = strlen(&arg[5][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[5][2]);
} else if (strcmp(arg[5],"NULL") == 0) {
zstyle = NONE;
} else {
zvalue = atof(arg[5]);
zstyle = CONSTANT;
}
// optional args
iregion = -1;
idregion = NULL;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix aveforce command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix aveforce command");
iregion = domain->find_region(arg[iarg+1]);
if (iregion == -1)
- error->all("Region ID for fix aveforce does not exist");
+ error->all(FLERR,"Region ID for fix aveforce does not exist");
int n = strlen(arg[iarg+1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix aveforce command");
+ } else error->all(FLERR,"Illegal fix aveforce command");
}
foriginal_all[0] = foriginal_all[1] =
foriginal_all[2] = foriginal_all[3] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixAveForce::~FixAveForce()
{
delete [] xstr;
delete [] ystr;
delete [] zstr;
delete [] idregion;
}
/* ---------------------------------------------------------------------- */
int FixAveForce::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixAveForce::init()
{
// check variables
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for fix aveforce does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for fix aveforce does not exist");
if (input->variable->equalstyle(xvar)) xstyle = EQUAL;
- else error->all("Variable for fix aveforce is invalid style");
+ else error->all(FLERR,"Variable for fix aveforce is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for fix aveforce does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for fix aveforce does not exist");
if (input->variable->equalstyle(yvar)) ystyle = EQUAL;
- else error->all("Variable for fix aveforce is invalid style");
+ else error->all(FLERR,"Variable for fix aveforce is invalid style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for fix aveforce does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for fix aveforce does not exist");
if (input->variable->equalstyle(zvar)) zstyle = EQUAL;
- else error->all("Variable for fix aveforce is invalid style");
+ else error->all(FLERR,"Variable for fix aveforce is invalid style");
}
// set index and check validity of region
if (iregion >= 0) {
iregion = domain->find_region(idregion);
- if (iregion == -1) error->all("Region ID for fix aveforce does not exist");
+ if (iregion == -1) error->all(FLERR,"Region ID for fix aveforce does not exist");
}
if (xstyle == EQUAL || ystyle == EQUAL || zstyle == EQUAL) varflag = EQUAL;
else varflag = CONSTANT;
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixAveForce::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
}
/* ---------------------------------------------------------------------- */
void FixAveForce::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixAveForce::post_force(int vflag)
{
// sum forces on participating atoms
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double foriginal[4];
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
foriginal[0] += f[i][0];
foriginal[1] += f[i][1];
foriginal[2] += f[i][2];
foriginal[3] += 1.0;
}
// average the force on participating atoms
// add in requested amount, computed via variable evaluation if necessary
// wrap variable evaluation with clear/add
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
int ncount = static_cast<int> (foriginal_all[3]);
if (ncount == 0) return;
if (varflag == EQUAL) {
modify->clearstep_compute();
if (xstyle == EQUAL) xvalue = input->variable->compute_equal(xvar);
if (ystyle == EQUAL) yvalue = input->variable->compute_equal(yvar);
if (zstyle == EQUAL) zvalue = input->variable->compute_equal(zvar);
modify->addstep_compute(update->ntimestep + 1);
}
double fave[3];
fave[0] = foriginal_all[0]/ncount + xvalue;
fave[1] = foriginal_all[1]/ncount + yvalue;
fave[2] = foriginal_all[2]/ncount + zvalue;
// set force of all participating atoms to same value
// only for active dimensions
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
if (xstyle) f[i][0] = fave[0];
if (ystyle) f[i][1] = fave[1];
if (zstyle) f[i][2] = fave[2];
}
}
/* ---------------------------------------------------------------------- */
void FixAveForce::post_force_respa(int vflag, int ilevel, int iloop)
{
// ave + extra force on outermost level
// just ave on inner levels
if (ilevel == nlevels_respa-1) post_force(vflag);
else {
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double foriginal[4];
foriginal[0] = foriginal[1] = foriginal[2] = foriginal[3] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
foriginal[0] += f[i][0];
foriginal[1] += f[i][1];
foriginal[2] += f[i][2];
foriginal[3] += 1.0;
}
MPI_Allreduce(foriginal,foriginal_all,4,MPI_DOUBLE,MPI_SUM,world);
int ncount = static_cast<int> (foriginal_all[3]);
if (ncount == 0) return;
double fave[3];
fave[0] = foriginal_all[0]/ncount;
fave[1] = foriginal_all[1]/ncount;
fave[2] = foriginal_all[2]/ncount;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
if (xstyle) f[i][0] = fave[0];
if (ystyle) f[i][1] = fave[1];
if (zstyle) f[i][2] = fave[2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixAveForce::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixAveForce::compute_vector(int n)
{
return foriginal_all[n];
}
diff --git a/src/fix_box_relax.cpp b/src/fix_box_relax.cpp
index 7d4d74d08..09d6f2866 100644
--- a/src/fix_box_relax.cpp
+++ b/src/fix_box_relax.cpp
@@ -1,914 +1,911 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_box_relax.h"
#include "atom.h"
#include "domain.h"
#include "update.h"
#include "comm.h"
#include "force.h"
#include "kspace.h"
#include "modify.h"
#include "compute.h"
#include "error.h"
#include "math_extra.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
enum{NONE,XYZ,XY,YZ,XZ};
enum{ISO,ANISO,TRICLINIC};
#define MAX_LIFO_DEPTH 2 // 3 box0 arrays in *.h dimensioned to this
/* ---------------------------------------------------------------------- */
FixBoxRelax::FixBoxRelax(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix box/relax command");
+ if (narg < 5) error->all(FLERR,"Illegal fix box/relax command");
scalar_flag = 1;
extscalar = 1;
global_freq = 1;
box_change = 1;
no_change_box = 1;
// default values
pcouple = NONE;
allremap = 1;
vmax = 0.0001;
deviatoric_flag = 0;
nreset_h0 = 0;
p_target[0] = p_target[1] = p_target[2] =
p_target[3] = p_target[4] = p_target[5] = 0.0;
p_flag[0] = p_flag[1] = p_flag[2] =
p_flag[3] = p_flag[4] = p_flag[5] = 0;
// process keywords
dimension = domain->dimension;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"iso") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
pcouple = XYZ;
p_target[0] = p_target[1] = p_target[2] = atof(arg[iarg+1]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_target[2] = 0.0;
p_flag[2] = 0;
}
iarg += 2;
} else if (strcmp(arg[iarg],"aniso") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
pcouple = NONE;
p_target[0] = p_target[1] = p_target[2] = atof(arg[iarg+1]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_target[2] = 0.0;
p_flag[2] = 0;
}
iarg += 2;
} else if (strcmp(arg[iarg],"tri") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
pcouple = NONE;
p_target[0] = p_target[1] = p_target[2] = atof(arg[iarg+1]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
p_target[3] = p_target[4] = p_target[5] = 0.0;
p_flag[3] = p_flag[4] = p_flag[5] = 1;
if (dimension == 2) {
p_target[2] = p_target[3] = p_target[4] = 0.0;
p_flag[2] = p_flag[3] = p_flag[4] = 0;
}
iarg += 2;
} else if (strcmp(arg[iarg],"x") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
p_target[0] = atof(arg[iarg+1]);
p_flag[0] = 1;
deviatoric_flag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"y") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
p_target[1] = atof(arg[iarg+1]);
p_flag[1] = 1;
deviatoric_flag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"z") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
p_target[2] = atof(arg[iarg+1]);
p_flag[2] = 1;
deviatoric_flag = 1;
iarg += 2;
if (dimension == 2)
- error->all("Invalid fix box/relax command for a 2d simulation");
+ error->all(FLERR,"Invalid fix box/relax command for a 2d simulation");
} else if (strcmp(arg[iarg],"yz") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
p_target[3] = atof(arg[iarg+1]);
p_flag[3] = 1;
deviatoric_flag = 1;
iarg += 2;
if (dimension == 2)
- error->all("Invalid fix box/relax command for a 2d simulation");
+ error->all(FLERR,"Invalid fix box/relax command for a 2d simulation");
} else if (strcmp(arg[iarg],"xz") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
p_target[4] = atof(arg[iarg+1]);
p_flag[4] = 1;
deviatoric_flag = 1;
iarg += 2;
if (dimension == 2)
- error->all("Invalid fix box/relax command for a 2d simulation");
+ error->all(FLERR,"Invalid fix box/relax command for a 2d simulation");
} else if (strcmp(arg[iarg],"xy") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
p_target[5] = atof(arg[iarg+1]);
p_flag[5] = 1;
deviatoric_flag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"couple") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
if (strcmp(arg[iarg+1],"xyz") == 0) pcouple = XYZ;
else if (strcmp(arg[iarg+1],"xy") == 0) pcouple = XY;
else if (strcmp(arg[iarg+1],"yz") == 0) pcouple = YZ;
else if (strcmp(arg[iarg+1],"xz") == 0) pcouple = XZ;
else if (strcmp(arg[iarg+1],"none") == 0) pcouple = NONE;
- else error->all("Illegal fix box/relax command");
+ else error->all(FLERR,"Illegal fix box/relax command");
iarg += 2;
} else if (strcmp(arg[iarg],"dilate") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
if (strcmp(arg[iarg+1],"all") == 0) allremap = 1;
else if (strcmp(arg[iarg+1],"partial") == 0) allremap = 0;
- else error->all("Illegal fix box/relax command");
+ else error->all(FLERR,"Illegal fix box/relax command");
iarg += 2;
} else if (strcmp(arg[iarg],"vmax") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
vmax = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"nreset") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix box/relax command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix box/relax command");
nreset_h0 = atoi(arg[iarg+1]);
- if (nreset_h0 < 0) error->all("Illegal fix box/relax command");
+ if (nreset_h0 < 0) error->all(FLERR,"Illegal fix box/relax command");
iarg += 2;
- } else error->all("Illegal fix box/relax command");
+ } else error->all(FLERR,"Illegal fix box/relax command");
}
if (p_flag[0] || p_flag[1] || p_flag[2]) box_change_size = 1;
if (p_flag[3] || p_flag[4] || p_flag[5]) box_change_shape = 1;
if (allremap == 0) restart_pbc = 1;
// error checks
if (dimension == 2 && (p_flag[2] || p_flag[3] || p_flag[4]))
- error->all("Invalid fix box/relax command for a 2d simulation");
+ error->all(FLERR,"Invalid fix box/relax command for a 2d simulation");
if (dimension == 2 && (pcouple == YZ || pcouple == XZ))
- error->all("Invalid fix box/relax command for a 2d simulation");
+ error->all(FLERR,"Invalid fix box/relax command for a 2d simulation");
if (pcouple == XYZ && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix box/relax command pressure settings");
+ error->all(FLERR,"Invalid fix box/relax command pressure settings");
if (pcouple == XYZ && dimension == 3 && p_flag[2] == 0)
- error->all("Invalid fix box/relax command pressure settings");
+ error->all(FLERR,"Invalid fix box/relax command pressure settings");
if (pcouple == XY && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix box/relax command pressure settings");
+ error->all(FLERR,"Invalid fix box/relax command pressure settings");
if (pcouple == YZ && (p_flag[1] == 0 || p_flag[2] == 0))
- error->all("Invalid fix box/relax command pressure settings");
+ error->all(FLERR,"Invalid fix box/relax command pressure settings");
if (pcouple == XZ && (p_flag[0] == 0 || p_flag[2] == 0))
- error->all("Invalid fix box/relax command pressure settings");
+ error->all(FLERR,"Invalid fix box/relax command pressure settings");
if (p_flag[0] && domain->xperiodic == 0)
- error->all("Cannot use fix box/relax on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix box/relax on a non-periodic dimension");
if (p_flag[1] && domain->yperiodic == 0)
- error->all("Cannot use fix box/relax on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix box/relax on a non-periodic dimension");
if (p_flag[2] && domain->zperiodic == 0)
- error->all("Cannot use fix box/relax on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix box/relax on a non-periodic dimension");
if (p_flag[3] && domain->zperiodic == 0)
- error->all("Cannot use fix box/relax on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix box/relax on a 2nd non-periodic dimension");
if (p_flag[4] && domain->zperiodic == 0)
- error->all("Cannot use fix box/relax on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix box/relax on a 2nd non-periodic dimension");
if (p_flag[5] && domain->yperiodic == 0)
- error->all("Cannot use fix box/relax on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix box/relax on a 2nd non-periodic dimension");
if (!domain->triclinic && (p_flag[3] || p_flag[4] || p_flag[5]))
- error->all("Can not specify Pxy/Pxz/Pyz in "
+ error->all(FLERR,"Can not specify Pxy/Pxz/Pyz in "
"fix box/relax with non-triclinic box");
if (pcouple == XYZ && dimension == 3 &&
(p_target[0] != p_target[1] || p_target[0] != p_target[2]))
- error->all("Invalid fix box/relax pressure settings");
+ error->all(FLERR,"Invalid fix box/relax pressure settings");
if (pcouple == XYZ && dimension == 2 && p_target[0] != p_target[1])
- error->all("Invalid fix box/relax pressure settings");
+ error->all(FLERR,"Invalid fix box/relax pressure settings");
if (pcouple == XY && p_target[0] != p_target[1])
- error->all("Invalid fix box/relax pressure settings");
+ error->all(FLERR,"Invalid fix box/relax pressure settings");
if (pcouple == YZ && p_target[1] != p_target[2])
- error->all("Invalid fix box/relax pressure settings");
+ error->all(FLERR,"Invalid fix box/relax pressure settings");
if (pcouple == XZ && p_target[0] != p_target[2])
- error->all("Invalid fix box/relax pressure settings");
+ error->all(FLERR,"Invalid fix box/relax pressure settings");
- if (vmax <= 0.0) error->all("Illegal fix box/relax command");
+ if (vmax <= 0.0) error->all(FLERR,"Illegal fix box/relax command");
// pstyle = TRICLINIC if any off-diagonal term is controlled -> 6 dof
// else pstyle = ISO if XYZ coupling or XY coupling in 2d -> 1 dof
// else pstyle = ANISO -> 3 dof
if (p_flag[3] || p_flag[4] || p_flag[5]) pstyle = TRICLINIC;
else if (pcouple == XYZ || (dimension == 2 && pcouple == XY)) pstyle = ISO;
else pstyle = ANISO;
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style (virial only)
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[5];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
newarg[4] = (char *) "virial";
modify->add_compute(5,newarg);
delete [] newarg;
pflag = 1;
dimension = domain->dimension;
nrigid = 0;
rfix = 0;
current_lifo = 0;
}
/* ---------------------------------------------------------------------- */
FixBoxRelax::~FixBoxRelax()
{
delete [] rfix;
// delete temperature and pressure if fix created them
if (tflag) modify->delete_compute(id_temp);
if (pflag) modify->delete_compute(id_press);
delete [] id_temp;
delete [] id_press;
}
/* ---------------------------------------------------------------------- */
int FixBoxRelax::setmask()
{
int mask = 0;
mask |= MIN_ENERGY;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixBoxRelax::init()
{
// set temperature and pressure ptrs
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix box/relax does not exist");
+ error->all(FLERR,"Temperature ID for fix box/relax does not exist");
temperature = modify->compute[icompute];
icompute = modify->find_compute(id_press);
- if (icompute < 0) error->all("Pressure ID for fix box/relax does not exist");
+ if (icompute < 0) error->all(FLERR,"Pressure ID for fix box/relax does not exist");
pressure = modify->compute[icompute];
pv2e = 1.0 / force->nktv2p;
if (force->kspace) kspace_flag = 1;
else kspace_flag = 0;
// detect if any rigid fixes exist so rigid bodies move when box is remapped
// rfix[] = indices to each fix rigid
delete [] rfix;
nrigid = 0;
rfix = NULL;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) nrigid++;
if (nrigid) {
rfix = new int[nrigid];
nrigid = 0;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) rfix[nrigid++] = i;
}
// initial box dimensions
xprdinit = domain->xprd;
yprdinit = domain->yprd;
zprdinit = domain->zprd;
if (dimension == 2) zprdinit = 1.0;
vol0 = xprdinit * yprdinit * zprdinit;
// hydrostatic target pressure and deviatoric target stress
compute_press_target();
if (deviatoric_flag) compute_sigma();
}
/* ----------------------------------------------------------------------
compute energy and force due to extra degrees of freedom
------------------------------------------------------------------------- */
double FixBoxRelax::min_energy(double *fextra)
{
double eng,scale,scalex,scaley,scalez,scalevol;
temperature->compute_scalar();
if (pstyle == ISO) pressure->compute_scalar();
else {
temperature->compute_vector();
pressure->compute_vector();
}
couple();
// trigger virial computation on every iteration of minimizer
pressure->addstep(update->ntimestep+1);
// compute energy, forces for each extra degree of freedom
// returned eng = PV must be in units of energy
// returned fextra must likewise be in units of energy
if (pstyle == ISO) {
scale = domain->xprd/xprdinit;
if (dimension == 3) {
eng = pv2e * p_target[0] * (scale*scale*scale-1.0)*vol0;
fextra[0] = pv2e * (p_current[0] - p_target[0])*3.0*scale*scale*vol0;
} else {
eng = pv2e * p_target[0] * (scale*scale-1.0)*vol0;
fextra[0] = pv2e * (p_current[0] - p_target[0])*2.0*scale*vol0;
}
} else {
fextra[0] = fextra[1] = fextra[2] = 0.0;
scalex = scaley = scalez = 1.0;
if (p_flag[0]) scalex = domain->xprd/xprdinit;
if (p_flag[1]) scaley = domain->yprd/yprdinit;
if (p_flag[2]) scalez = domain->zprd/zprdinit;
scalevol = scalex*scaley*scalez;
eng = pv2e * p_hydro * (scalevol-1.0)*vol0;
if (p_flag[0])
fextra[0] = pv2e * (p_current[0] - p_hydro)*scaley*scalez*vol0;
if (p_flag[1])
fextra[1] = pv2e * (p_current[1] - p_hydro)*scalex*scalez*vol0;
if (p_flag[2])
fextra[2] = pv2e * (p_current[2] - p_hydro)*scalex*scaley*vol0;
if (pstyle == TRICLINIC) {
fextra[3] = fextra[4] = fextra[5] = 0.0;
if (p_flag[3])
fextra[3] = pv2e*p_current[3]*scaley*yprdinit*scalex*xprdinit*yprdinit;
if (p_flag[4])
fextra[4] = pv2e*p_current[4]*scalex*xprdinit*scaley*yprdinit*xprdinit;
if (p_flag[5])
fextra[5] = pv2e*p_current[5]*scalex*xprdinit*scalez*zprdinit*xprdinit;
}
if (deviatoric_flag) {
compute_deviatoric();
if (p_flag[0]) fextra[0] -= fdev[0]*xprdinit;
if (p_flag[1]) fextra[1] -= fdev[1]*yprdinit;
if (p_flag[2]) fextra[2] -= fdev[2]*zprdinit;
if (pstyle == TRICLINIC) {
if (p_flag[3]) fextra[3] -= fdev[3]*yprdinit;
if (p_flag[4]) fextra[4] -= fdev[4]*xprdinit;
if (p_flag[5]) fextra[5] -= fdev[5]*xprdinit;
}
eng += compute_strain_energy();
}
}
return eng;
}
/* ----------------------------------------------------------------------
store extra dof values for minimization linesearch starting point
boxlo0,boxhi0 = box dimensions
s0 = ratio of current boxsize to initial boxsize
box values are pushed onto a LIFO stack so nested calls can be made
values are popped by calling min_step(0.0)
------------------------------------------------------------------------- */
void FixBoxRelax::min_store()
{
for (int i = 0; i < 3; i++) {
boxlo0[current_lifo][i] = domain->boxlo[i];
boxhi0[current_lifo][i] = domain->boxhi[i];
}
s0[0] = (boxhi0[current_lifo][0]-boxlo0[current_lifo][0])/xprdinit;
s0[1] = (boxhi0[current_lifo][1]-boxlo0[current_lifo][1])/yprdinit;
s0[2] = (boxhi0[current_lifo][2]-boxlo0[current_lifo][2])/zprdinit;
if (pstyle == TRICLINIC) {
boxtilt0[current_lifo][0] = domain->yz;
boxtilt0[current_lifo][1] = domain->xz;
boxtilt0[current_lifo][2] = domain->xy;
}
}
/* ----------------------------------------------------------------------
clear the LIFO stack for min_store
------------------------------------------------------------------------- */
void FixBoxRelax::min_clearstore()
{
current_lifo = 0;
}
/* ----------------------------------------------------------------------
push the LIFO stack for min_store
------------------------------------------------------------------------- */
void FixBoxRelax::min_pushstore()
{
if (current_lifo >= MAX_LIFO_DEPTH) {
- error->all("Attempt to push beyond stack limit in fix box/relax");
+ error->all(FLERR,"Attempt to push beyond stack limit in fix box/relax");
return;
}
current_lifo++;
}
/* ----------------------------------------------------------------------
pop the LIFO stack for min_store
------------------------------------------------------------------------- */
void FixBoxRelax::min_popstore()
{
if (current_lifo <= 0) {
- error->all("Attempt to pop empty stack in fix box/relax");
+ error->all(FLERR,"Attempt to pop empty stack in fix box/relax");
return;
}
current_lifo--;
}
/* ----------------------------------------------------------------------
check if time to reset reference state. If so, do so.
------------------------------------------------------------------------- */
int FixBoxRelax::min_reset_ref()
{
int itmp = 0;
// if nreset_h0 > 0, reset reference box
// every nreset_h0 timesteps
// only needed for deviatoric external stress
if (deviatoric_flag && nreset_h0 > 0) {
int delta = update->ntimestep - update->beginstep;
if (delta % nreset_h0 == 0) {
compute_sigma();
itmp = 1;
}
}
return itmp;
}
/* ----------------------------------------------------------------------
change the box dimensions by fraction ds = alpha*hextra
------------------------------------------------------------------------- */
void FixBoxRelax::min_step(double alpha, double *hextra)
{
if (pstyle == ISO) {
ds[0] = ds[1] = ds[2] = alpha*hextra[0];
} else {
ds[0] = ds[1] = ds[2] = 0.0;
if (p_flag[0]) ds[0] = alpha*hextra[0];
if (p_flag[1]) ds[1] = alpha*hextra[1];
if (p_flag[2]) ds[2] = alpha*hextra[2];
if (pstyle == TRICLINIC) {
ds[3] = ds[4] = ds[5] = 0.0;
if (p_flag[3]) ds[3] = alpha*hextra[3];
if (p_flag[4]) ds[4] = alpha*hextra[4];
if (p_flag[5]) ds[5] = alpha*hextra[5];
}
}
remap();
if (kspace_flag) force->kspace->setup();
}
/* ----------------------------------------------------------------------
max allowed step size along hextra
------------------------------------------------------------------------- */
double FixBoxRelax::max_alpha(double *hextra)
{
double alpha = 1.0;
if (pstyle == ISO) alpha = vmax/fabs(hextra[0]);
else {
if (p_flag[0]) alpha = MIN(alpha,vmax/fabs(hextra[0]));
if (p_flag[1]) alpha = MIN(alpha,vmax/fabs(hextra[1]));
if (p_flag[2]) alpha = MIN(alpha,vmax/fabs(hextra[2]));
if (pstyle == TRICLINIC) {
if (p_flag[3]) alpha = MIN(alpha,vmax/fabs(hextra[3]));
if (p_flag[4]) alpha = MIN(alpha,vmax/fabs(hextra[4]));
if (p_flag[5]) alpha = MIN(alpha,vmax/fabs(hextra[5]));
}
}
return alpha;
}
/* ----------------------------------------------------------------------
return number of degrees of freedom added by this fix
------------------------------------------------------------------------- */
int FixBoxRelax::min_dof()
{
if (pstyle == ISO) return 1;
if (pstyle == TRICLINIC) return 6;
return 3;
}
/* ----------------------------------------------------------------------
dilate the box and owned/ghost atoms around center of box
------------------------------------------------------------------------- */
void FixBoxRelax::remap()
{
int i,n;
double ctr;
// ctr = geometric center of box in a dimension
// rescale simulation box from linesearch starting point
// scale atom coords for all atoms or only for fix group atoms
double **x = atom->x;
int *mask = atom->mask;
n = atom->nlocal + atom->nghost;
// convert pertinent atoms and rigid bodies to lamda coords
if (allremap) domain->x2lamda(n);
else {
for (i = 0; i < n; i++)
if (mask[i] & groupbit)
domain->x2lamda(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(0);
// reset global and local box to new size/shape
for (i = 0; i < 3; i++)
if (p_flag[i]) {
double currentBoxLo0 = boxlo0[current_lifo][i];
double currentBoxHi0 = boxhi0[current_lifo][i];
ctr = 0.5 * (currentBoxLo0 + currentBoxHi0);
domain->boxlo[i] = currentBoxLo0 + (currentBoxLo0-ctr)*ds[i]/s0[i];
domain->boxhi[i] = currentBoxHi0 + (currentBoxHi0-ctr)*ds[i]/s0[i];
if (domain->boxlo[i] >= domain->boxhi[i])
- error->all("Fix box/relax generated negative box length");
+ error->all(FLERR,"Fix box/relax generated negative box length");
}
if (pstyle == TRICLINIC) {
if (p_flag[3]) domain->yz = boxtilt0[current_lifo][0]+ds[3]*yprdinit;
if (p_flag[4]) domain->xz = boxtilt0[current_lifo][1]+ds[4]*xprdinit;
if (p_flag[5]) domain->xy = boxtilt0[current_lifo][2]+ds[5]*xprdinit;
}
domain->set_global_box();
domain->set_local_box();
// convert pertinent atoms and rigid bodies back to box coords
if (allremap) domain->lamda2x(n);
else {
for (i = 0; i < n; i++)
if (mask[i] & groupbit)
domain->lamda2x(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(1);
}
/* ---------------------------------------------------------------------- */
void FixBoxRelax::couple()
{
double *tensor = pressure->vector;
if (pstyle == ISO)
p_current[0] = p_current[1] = p_current[2] = pressure->scalar;
else if (pcouple == XYZ) {
double ave = 1.0/3.0 * (tensor[0] + tensor[1] + tensor[2]);
p_current[0] = p_current[1] = p_current[2] = ave;
} else if (pcouple == XY) {
double ave = 0.5 * (tensor[0] + tensor[1]);
p_current[0] = p_current[1] = ave;
p_current[2] = tensor[2];
} else if (pcouple == YZ) {
double ave = 0.5 * (tensor[1] + tensor[2]);
p_current[1] = p_current[2] = ave;
p_current[0] = tensor[0];
} else if (pcouple == XZ) {
double ave = 0.5 * (tensor[0] + tensor[2]);
p_current[0] = p_current[2] = ave;
p_current[1] = tensor[1];
} else {
p_current[0] = tensor[0];
p_current[1] = tensor[1];
p_current[2] = tensor[2];
}
// switch order from xy-xz-yz to Voigt
if (pstyle == TRICLINIC) {
p_current[3] = tensor[5];
p_current[4] = tensor[4];
p_current[5] = tensor[3];
}
}
/* ---------------------------------------------------------------------- */
int FixBoxRelax::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != 0 && comm->me == 0)
- error->warning("Temperature for fix modify is not for group all");
+ error->warning(FLERR,"Temperature for fix modify is not for group all");
// reset id_temp of pressure to new temperature ID
icompute = modify->find_compute(id_press);
- if (icompute < 0) error->all("Pressure ID for fix modify does not exist");
+ if (icompute < 0) error->all(FLERR,"Pressure ID for fix modify does not exist");
modify->compute[icompute]->reset_extra_compute_fix(id_temp);
return 2;
} else if (strcmp(arg[0],"press") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (pflag) {
modify->delete_compute(id_press);
pflag = 0;
}
delete [] id_press;
int n = strlen(arg[1]) + 1;
id_press = new char[n];
strcpy(id_press,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify pressure ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify pressure ID");
pressure = modify->compute[icompute];
if (pressure->pressflag == 0)
- error->all("Fix_modify pressure ID does not compute pressure");
+ error->all(FLERR,"Fix_modify pressure ID does not compute pressure");
return 2;
}
return 0;
}
/* ----------------------------------------------------------------------
compute sigma tensor (needed whenever reference box is reset)
-----------------------------------------------------------------------*/
void FixBoxRelax::compute_sigma()
{
double pdeviatoric[3][3],htmp[3][3];
double tmp1[3][3],sigma_tensor[3][3],h_invtmp[3][3];
// reset reference box dimensions
xprdinit = domain->xprd;
yprdinit = domain->yprd;
zprdinit = domain->zprd;
if (dimension == 2) zprdinit = 1.0;
vol0 = xprdinit * yprdinit * zprdinit;
h0[0] = domain->h[0];
h0[1] = domain->h[1];
h0[2] = domain->h[2];
h0[3] = domain->h[3];
h0[4] = domain->h[4];
h0[5] = domain->h[5];
h0_inv[0] = domain->h_inv[0];
h0_inv[1] = domain->h_inv[1];
h0_inv[2] = domain->h_inv[2];
h0_inv[3] = domain->h_inv[3];
h0_inv[4] = domain->h_inv[4];
h0_inv[5] = domain->h_inv[5];
htmp[0][0] = h0[0];
htmp[1][1] = h0[1];
htmp[2][2] = h0[2];
htmp[1][2] = h0[3];
htmp[0][2] = h0[4];
htmp[0][1] = h0[5];
htmp[2][1] = 0.0;
htmp[2][0] = 0.0;
htmp[1][0] = 0.0;
h_invtmp[0][0] = h0_inv[0];
h_invtmp[1][1] = h0_inv[1];
h_invtmp[2][2] = h0_inv[2];
h_invtmp[1][2] = h0_inv[3];
h_invtmp[0][2] = h0_inv[4];
h_invtmp[0][1] = h0_inv[5];
h_invtmp[2][1] = 0.0;
h_invtmp[2][0] = 0.0;
h_invtmp[1][0] = 0.0;
// compute target deviatoric stress tensor pdevmod
pdeviatoric[0][0] = pdeviatoric[1][1] = pdeviatoric[2][2] = 0.0;
if (p_flag[0]) pdeviatoric[0][0] = p_target[0] - p_hydro;
if (p_flag[1]) pdeviatoric[1][1] = p_target[1] - p_hydro;
if (p_flag[2]) pdeviatoric[2][2] = p_target[2] - p_hydro;
pdeviatoric[1][2] = pdeviatoric[2][1] = p_target[3];
pdeviatoric[0][2] = pdeviatoric[2][0] = p_target[4];
pdeviatoric[0][1] = pdeviatoric[1][0] = p_target[5];
// Modify to account for off-diagonal terms
// These equations come from the stationarity relation:
// Pdev,sys = Pdev,targ*hinv^t*hdiag
// where:
// Pdev,sys is the system deviatoric stress tensor,
// Pdev,targ = pdeviatoric, effective target deviatoric stress
// hinv^t is the transpose of the inverse h tensor
// hdiag is the diagonal part of the h tensor
pdeviatoric[1][1] -= pdeviatoric[1][2]*h0_inv[3]*h0[1];
pdeviatoric[0][1] -= pdeviatoric[0][2]*h0_inv[3]*h0[1];
pdeviatoric[1][0] = pdeviatoric[0][1];
pdeviatoric[0][0] -= pdeviatoric[0][1]*h0_inv[5]*h0[0] +
pdeviatoric[0][2]*h0_inv[4]*h0[0];
// compute symmetric sigma tensor
MathExtra::times3(h_invtmp,pdeviatoric,tmp1);
MathExtra::times3_transpose(tmp1,h_invtmp,sigma_tensor);
MathExtra::scalar_times3(vol0,sigma_tensor);
sigma[0] = sigma_tensor[0][0];
sigma[1] = sigma_tensor[1][1];
sigma[2] = sigma_tensor[2][2];
sigma[3] = sigma_tensor[1][2];
sigma[4] = sigma_tensor[0][2];
sigma[5] = sigma_tensor[0][1];
}
/* ----------------------------------------------------------------------
compute strain energy
-----------------------------------------------------------------------*/
double FixBoxRelax::compute_strain_energy()
{
// compute strain energy = 0.5*Tr(sigma*h*h^t) in energy units
double* h = domain->h;
double d0,d1,d2;
if (dimension == 3) {
d0 =
sigma[0]*(h[0]*h[0]+h[5]*h[5]+h[4]*h[4]) +
sigma[5]*( h[1]*h[5]+h[3]*h[4]) +
sigma[4]*( h[2]*h[4]);
d1 =
sigma[5]*( h[5]*h[1]+h[4]*h[3]) +
sigma[1]*( h[1]*h[1]+h[3]*h[3]) +
sigma[3]*( h[2]*h[3]);
d2 =
sigma[4]*( h[4]*h[2]) +
sigma[3]*( h[3]*h[2]) +
sigma[2]*( h[2]*h[2]);
} else {
d0 = sigma[0]*(h[0]*h[0]+h[5]*h[5]) + sigma[5]*h[1]*h[5];
d1 = sigma[5]*h[5]*h[1] + sigma[1]*h[1]*h[1];
d2 = 0.0;
}
double energy = 0.5*(d0+d1+d2)*pv2e;
return energy;
}
/* ----------------------------------------------------------------------
compute deviatoric barostat force = h*sigma*h^t
-----------------------------------------------------------------------*/
void FixBoxRelax::compute_deviatoric()
{
double* h = domain->h;
// [ 0 5 4 ] [ 0 5 4 ] [ 0 5 4 ]
// [ 5 1 3 ] = [ - 1 3 ] [ 5 1 3 ]
// [ 4 3 2 ] [ - - 2 ] [ 4 3 2 ]
if (dimension == 3) {
fdev[0] = pv2e*(h[0]*sigma[0]+h[5]*sigma[5]+h[4]*sigma[4]);
fdev[1] = pv2e*(h[1]*sigma[1]+h[3]*sigma[3]);
fdev[2] = pv2e*(h[2]*sigma[2]);
fdev[3] = pv2e*(h[1]*sigma[3]+h[3]*sigma[2]);
fdev[4] = pv2e*(h[0]*sigma[4]+h[5]*sigma[3]+h[4]*sigma[2]);
fdev[5] = pv2e*(h[0]*sigma[5]+h[5]*sigma[1]+h[4]*sigma[3]);
} else {
fdev[0] = pv2e*(h[0]*sigma[0]+h[5]*sigma[5]);
fdev[1] = pv2e*(h[1]*sigma[1]);
fdev[5] = pv2e*(h[0]*sigma[5]+h[5]*sigma[1]);
}
}
/* ----------------------------------------------------------------------
compute hydrostatic target pressure
-----------------------------------------------------------------------*/
void FixBoxRelax::compute_press_target()
{
pflagsum = p_flag[0] + p_flag[1] + p_flag[2];
p_hydro = 0.0;
for (int i = 0; i < 3; i++)
if (p_flag[i]) p_hydro += p_target[i];
if (pflagsum) p_hydro /= pflagsum;
for (int i = 0; i < 3; i++) {
if (p_flag[i] && fabs(p_hydro - p_target[i]) > 1.0e-6) deviatoric_flag = 1;
}
if (pstyle == TRICLINIC) {
for (int i = 3; i < 6; i++)
if (p_flag[i] && fabs(p_target[i]) > 1.0e-6) deviatoric_flag = 1;
}
}
/* ----------------------------------------------------------------------
compute PV and strain energy for access to the user
/* ---------------------------------------------------------------------- */
double FixBoxRelax::compute_scalar()
{
double ftmp[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
if (update->ntimestep == 0) return 0.0;
return min_energy(ftmp);
}
diff --git a/src/fix_deform.cpp b/src/fix_deform.cpp
index 75db86729..039bba40b 100644
--- a/src/fix_deform.cpp
+++ b/src/fix_deform.cpp
@@ -1,848 +1,848 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_deform.h"
#include "atom.h"
#include "update.h"
#include "comm.h"
#include "irregular.h"
#include "domain.h"
#include "lattice.h"
#include "force.h"
#include "modify.h"
#include "kspace.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NONE,FINAL,DELTA,SCALE,VEL,ERATE,TRATE,VOLUME,WIGGLE};
enum{ONE_FROM_ONE,ONE_FROM_TWO,TWO_FROM_ONE};
// same as domain.cpp, fix_nvt_sllod.cpp, compute_temp_deform.cpp
enum{NO_REMAP,X_REMAP,V_REMAP};
/* ---------------------------------------------------------------------- */
FixDeform::FixDeform(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix deform command");
+ if (narg < 4) error->all(FLERR,"Illegal fix deform command");
box_change = 1;
no_change_box = 1;
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix deform command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix deform command");
// set defaults
set = new Set[6];
set[0].style = set[1].style = set[2].style =
set[3].style = set[4].style = set[5].style = NONE;
// parse arguments
triclinic = domain->triclinic;
int index;
int iarg = 4;
while (iarg < narg) {
if (strcmp(arg[iarg],"x") == 0 ||
strcmp(arg[iarg],"y") == 0 ||
strcmp(arg[iarg],"z") == 0) {
if (strcmp(arg[iarg],"x") == 0) index = 0;
else if (strcmp(arg[iarg],"y") == 0) index = 1;
else if (strcmp(arg[iarg],"z") == 0) index = 2;
- if (iarg+2 > narg) error->all("Illegal fix deform command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deform command");
if (strcmp(arg[iarg+1],"final") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix deform command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = FINAL;
set[index].flo = atof(arg[iarg+2]);
set[index].fhi = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg+1],"delta") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix deform command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = DELTA;
set[index].dlo = atof(arg[iarg+2]);
set[index].dhi = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg+1],"scale") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = SCALE;
set[index].scale = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"vel") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = VEL;
set[index].vel = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"erate") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = ERATE;
set[index].rate = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"trate") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = TRATE;
set[index].rate = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"volume") == 0) {
set[index].style = VOLUME;
iarg += 2;
} else if (strcmp(arg[iarg+1],"wiggle") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix deform command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = WIGGLE;
set[index].amplitude = atof(arg[iarg+2]);
set[index].tperiod = atof(arg[iarg+3]);
if (set[index].tperiod <= 0.0)
- error->all("Illegal fix deform command");
+ error->all(FLERR,"Illegal fix deform command");
iarg += 4;
- } else error->all("Illegal fix deform command");
+ } else error->all(FLERR,"Illegal fix deform command");
} else if (strcmp(arg[iarg],"xy") == 0 ||
strcmp(arg[iarg],"xz") == 0 ||
strcmp(arg[iarg],"yz") == 0) {
if (triclinic == 0)
- error->all("Fix deform tilt factors require triclinic box");
+ error->all(FLERR,"Fix deform tilt factors require triclinic box");
if (strcmp(arg[iarg],"xy") == 0) index = 5;
else if (strcmp(arg[iarg],"xz") == 0) index = 4;
else if (strcmp(arg[iarg],"yz") == 0) index = 3;
- if (iarg+2 > narg) error->all("Illegal fix deform command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deform command");
if (strcmp(arg[iarg+1],"final") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = FINAL;
set[index].ftilt = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"delta") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = DELTA;
set[index].dtilt = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"vel") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = VEL;
set[index].vel = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"erate") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = ERATE;
set[index].rate = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"trate") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deform command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = TRATE;
set[index].rate = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg+1],"wiggle") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix deform command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix deform command");
set[index].style = WIGGLE;
set[index].amplitude = atof(arg[iarg+2]);
set[index].tperiod = atof(arg[iarg+3]);
if (set[index].tperiod <= 0.0)
- error->all("Illegal fix deform command");
+ error->all(FLERR,"Illegal fix deform command");
iarg += 4;
- } else error->all("Illegal fix deform command");
+ } else error->all(FLERR,"Illegal fix deform command");
} else break;
}
// read options from end of input line
// no x remap effectively moves atoms within box, so set restart_pbc
options(narg-iarg,&arg[iarg]);
if (remapflag != X_REMAP) restart_pbc = 1;
// setup dimflags used by other classes to check for volume-change conflicts
for (int i = 0; i < 6; i++)
if (set[i].style == NONE) dimflag[i] = 0;
else dimflag[i] = 1;
if (dimflag[0] || dimflag[1] || dimflag[2]) box_change_size = 1;
if (dimflag[3] || dimflag[4] || dimflag[5]) box_change_shape = 1;
// check periodicity
if ((set[0].style && domain->xperiodic == 0) ||
(set[1].style && domain->yperiodic == 0) ||
(set[2].style && domain->zperiodic == 0))
- error->all("Cannot use fix deform on a non-periodic boundary");
+ error->all(FLERR,"Cannot use fix deform on a non-periodic boundary");
if (set[3].style && domain->zperiodic == 0)
- error->all("Cannot use fix deform on a 2nd non-periodic boundary");
+ error->all(FLERR,"Cannot use fix deform on a 2nd non-periodic boundary");
if (set[4].style && domain->zperiodic == 0)
- error->all("Cannot use fix deform on a 2nd non-periodic boundary");
+ error->all(FLERR,"Cannot use fix deform on a 2nd non-periodic boundary");
if (set[5].style && domain->yperiodic == 0)
- error->all("Cannot use fix deform on a 2nd non-periodic boundary");
+ error->all(FLERR,"Cannot use fix deform on a 2nd non-periodic boundary");
// apply scaling to FINAL,DELTA,VEL,WIGGLE since they have distance/vel units
int flag = 0;
for (int i = 0; i < 6; i++)
if (set[i].style == FINAL || set[i].style == DELTA ||
set[i].style == VEL || set[i].style == WIGGLE) flag = 1;
if (flag && scaleflag && domain->lattice == NULL)
- error->all("Use of fix deform with undefined lattice");
+ error->all(FLERR,"Use of fix deform with undefined lattice");
double xscale,yscale,zscale;
if (flag && scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// for 3,4,5: scaling is in 1st dimension, e.g. x for xz
double map[6];
map[0] = xscale; map[1] = yscale; map[2] = zscale;
map[3] = yscale; map[4] = xscale; map[5] = xscale;
for (int i = 0; i < 3; i++) {
if (set[i].style == FINAL) {
set[i].flo *= map[i];
set[i].fhi *= map[i];
} else if (set[i].style == DELTA) {
set[i].dlo *= map[i];
set[i].dhi *= map[i];
} else if (set[i].style == VEL) {
set[i].vel *= map[i];
} else if (set[i].style == WIGGLE) {
set[i].amplitude *= map[i];
}
}
for (int i = 3; i < 6; i++) {
if (set[i].style == FINAL) set[i].ftilt *= map[i];
else if (set[i].style == DELTA) set[i].dtilt *= map[i];
else if (set[i].style == VEL) set[i].vel *= map[i];
else if (set[i].style == WIGGLE) set[i].amplitude *= map[i];
}
// for VOLUME, setup links to other dims
// fixed, dynamic1, dynamic2
for (int i = 0; i < 3; i++) {
if (set[i].style != VOLUME) continue;
int other1 = (i+1) % 3;
int other2 = (i+2) % 3;
if (set[other1].style == NONE) {
if (set[other2].style == NONE || set[other2].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = ONE_FROM_ONE;
set[i].fixed = other1;
set[i].dynamic1 = other2;
} else if (set[other2].style == NONE) {
if (set[other1].style == NONE || set[other1].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = ONE_FROM_ONE;
set[i].fixed = other2;
set[i].dynamic1 = other1;
} else if (set[other1].style == VOLUME) {
if (set[other2].style == NONE || set[other2].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = TWO_FROM_ONE;
set[i].fixed = other1;
set[i].dynamic1 = other2;
} else if (set[other2].style == VOLUME) {
if (set[other1].style == NONE || set[other1].style == VOLUME)
- error->all("Fix deform volume setting is invalid");
+ error->all(FLERR,"Fix deform volume setting is invalid");
set[i].substyle = TWO_FROM_ONE;
set[i].fixed = other2;
set[i].dynamic1 = other1;
} else {
set[i].substyle = ONE_FROM_TWO;
set[i].dynamic1 = other1;
set[i].dynamic2 = other2;
}
}
// set initial values at time fix deform is issued
for (int i = 0; i < 3; i++) {
set[i].lo_initial = domain->boxlo[i];
set[i].hi_initial = domain->boxhi[i];
set[i].vol_initial = domain->xprd * domain->yprd * domain->zprd;
}
for (int i = 3; i < 6; i++) {
if (i == 5) set[i].tilt_initial = domain->xy;
else if (i == 4) set[i].tilt_initial = domain->xz;
else if (i == 3) set[i].tilt_initial = domain->yz;
}
// reneighboring only forced if flips will occur due to shape changes
if (set[3].style || set[4].style || set[5].style) force_reneighbor = 1;
next_reneighbor = -1;
nrigid = 0;
rfix = NULL;
flip = 0;
if (force_reneighbor) irregular = new Irregular(lmp);
else irregular = NULL;
TWOPI = 8.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
FixDeform::~FixDeform()
{
delete [] set;
delete [] rfix;
delete irregular;
// reset domain's h_rate = 0.0, since this fix may have made it non-zero
double *h_rate = domain->h_rate;
double *h_ratelo = domain->h_ratelo;
h_rate[0] = h_rate[1] = h_rate[2] =
h_rate[3] = h_rate[4] = h_rate[5] = 0.0;
h_ratelo[0] = h_ratelo[1] = h_ratelo[2] = 0.0;
}
/* ---------------------------------------------------------------------- */
int FixDeform::setmask()
{
int mask = 0;
if (force_reneighbor) mask |= PRE_EXCHANGE;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixDeform::init()
{
// error if more than one fix deform
// domain, fix nvt/sllod, compute temp/deform only work on single h_rate
int count = 0;
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) count++;
- if (count > 1) error->all("More than one fix deform");
+ if (count > 1) error->all(FLERR,"More than one fix deform");
// Kspace setting
if (force->kspace) kspace_flag = 1;
else kspace_flag = 0;
// elapsed time for entire simulation, including multiple runs if defined
double delt = (update->endstep - update->beginstep) * update->dt;
// set start/stop values for box size and shape
// if single run, start is current values
// if multiple runs enabled via run start/stop settings,
// start is value when fix deform was issued
// if NONE, no need to set
for (int i = 0; i < 3; i++) {
if (update->firststep == update->beginstep) {
set[i].lo_start = domain->boxlo[i];
set[i].hi_start = domain->boxhi[i];
set[i].vol_start = domain->xprd * domain->yprd * domain->zprd;
} else {
set[i].lo_start = set[i].lo_initial;
set[i].hi_start = set[i].hi_initial;
set[i].vol_start = set[i].vol_initial;
}
if (set[i].style == FINAL) {
set[i].lo_stop = set[i].flo;
set[i].hi_stop = set[i].fhi;
} else if (set[i].style == DELTA) {
set[i].lo_stop = set[i].lo_start + set[i].dlo;
set[i].hi_stop = set[i].hi_start + set[i].dhi;
} else if (set[i].style == SCALE) {
set[i].lo_stop = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*set[i].scale*(set[i].hi_start-set[i].lo_start);
set[i].hi_stop = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*set[i].scale*(set[i].hi_start-set[i].lo_start);
} else if (set[i].style == VEL) {
set[i].lo_stop = set[i].lo_start - 0.5*delt*set[i].vel;
set[i].hi_stop = set[i].hi_start + 0.5*delt*set[i].vel;
} else if (set[i].style == ERATE) {
set[i].lo_stop = set[i].lo_start -
0.5*delt*set[i].rate * (set[i].hi_start-set[i].lo_start);
set[i].hi_stop = set[i].hi_start +
0.5*delt*set[i].rate * (set[i].hi_start-set[i].lo_start);
if (set[i].hi_stop <= set[i].lo_stop)
- error->all("Final box dimension due to fix deform is < 0.0");
+ error->all(FLERR,"Final box dimension due to fix deform is < 0.0");
} else if (set[i].style == TRATE) {
set[i].lo_stop = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*((set[i].hi_start-set[i].lo_start) * exp(set[i].rate*delt));
set[i].hi_stop = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*((set[i].hi_start-set[i].lo_start) * exp(set[i].rate*delt));
} else if (set[i].style == WIGGLE) {
set[i].lo_stop = set[i].lo_start -
0.5*set[i].amplitude * sin(TWOPI*delt/set[i].tperiod);
set[i].hi_stop = set[i].hi_start +
0.5*set[i].amplitude * sin(TWOPI*delt/set[i].tperiod);
}
}
for (int i = 3; i < 6; i++) {
if (update->firststep == update->beginstep) {
if (i == 5) set[i].tilt_start = domain->xy;
else if (i == 4) set[i].tilt_start = domain->xz;
else if (i == 3) set[i].tilt_start = domain->yz;
} else set[i].tilt_start = set[i].tilt_initial;
if (set[i].style == FINAL) {
set[i].tilt_stop = set[i].ftilt;
} else if (set[i].style == DELTA) {
set[i].tilt_stop = set[i].tilt_start + set[i].dtilt;
} else if (set[i].style == VEL) {
set[i].tilt_stop = set[i].tilt_start + delt*set[i].vel;
} else if (set[i].style == ERATE) {
if (i == 3) set[i].tilt_stop = set[i].tilt_start +
delt*set[i].rate * (set[2].hi_start-set[2].lo_start);
if (i == 4) set[i].tilt_stop = set[i].tilt_start +
delt*set[i].rate * (set[2].hi_start-set[2].lo_start);
if (i == 5) set[i].tilt_stop = set[i].tilt_start +
delt*set[i].rate * (set[1].hi_start-set[1].lo_start);
} else if (set[i].style == TRATE) {
set[i].tilt_stop = set[i].tilt_start * exp(set[i].rate*delt);
} else if (set[i].style == WIGGLE) {
set[i].tilt_stop = set[i].tilt_start +
set[i].amplitude * sin(TWOPI*delt/set[i].tperiod);
// compute min/max for WIGGLE = extrema tilt factor will ever reach
if (set[i].amplitude >= 0.0) {
if (delt < 0.25*set[i].tperiod) {
set[i].tilt_min = set[i].tilt_start;
set[i].tilt_max = set[i].tilt_start +
set[i].amplitude*sin(TWOPI*delt/set[i].tperiod);
} else if (delt < 0.5*set[i].tperiod) {
set[i].tilt_min = set[i].tilt_start;
set[i].tilt_max = set[i].tilt_start + set[i].amplitude;
} else if (delt < 0.75*set[i].tperiod) {
set[i].tilt_min = set[i].tilt_start -
set[i].amplitude*sin(TWOPI*delt/set[i].tperiod);
set[i].tilt_max = set[i].tilt_start + set[i].amplitude;
} else {
set[i].tilt_min = set[i].tilt_start - set[i].amplitude;
set[i].tilt_max = set[i].tilt_start + set[i].amplitude;
}
} else {
if (delt < 0.25*set[i].tperiod) {
set[i].tilt_min = set[i].tilt_start -
set[i].amplitude*sin(TWOPI*delt/set[i].tperiod);
set[i].tilt_max = set[i].tilt_start;
} else if (delt < 0.5*set[i].tperiod) {
set[i].tilt_min = set[i].tilt_start - set[i].amplitude;
set[i].tilt_max = set[i].tilt_start;
} else if (delt < 0.75*set[i].tperiod) {
set[i].tilt_min = set[i].tilt_start - set[i].amplitude;
set[i].tilt_max = set[i].tilt_start +
set[i].amplitude*sin(TWOPI*delt/set[i].tperiod);
} else {
set[i].tilt_min = set[i].tilt_start - set[i].amplitude;
set[i].tilt_max = set[i].tilt_start + set[i].amplitude;
}
}
}
}
// if using tilt TRATE, then initial tilt must be non-zero
for (int i = 3; i < 6; i++)
if (set[i].style == TRATE && set[i].tilt_start == 0.0)
- error->all("Cannot use fix deform trate on a box with zero tilt");
+ error->all(FLERR,"Cannot use fix deform trate on a box with zero tilt");
// if yz changes and will cause box flip, then xy cannot be changing
// test for WIGGLE is on min/max oscillation limit, not tilt_stop
// this is b/c the flips would induce continuous changes in xz
// in order to keep the edge vectors of the flipped shape matrix
// an integer combination of the edge vectors of the unflipped shape matrix
if (set[3].style && set[5].style) {
int flag = 0;
double lo,hi;
if (set[3].style == WIGGLE) {
lo = set[3].tilt_min;
hi = set[3].tilt_max;
} else lo = hi = set[3].tilt_stop;
if (lo < -0.5*(set[1].hi_start-set[1].lo_start) ||
hi > 0.5*(set[1].hi_start-set[1].lo_start)) flag = 1;
if (set[1].style) {
if (lo < -0.5*(set[1].hi_stop-set[1].lo_stop) ||
hi > 0.5*(set[1].hi_stop-set[1].lo_stop)) flag = 1;
}
if (flag)
- error->all("Fix deform is changing yz by too much with changing xy");
+ error->all(FLERR,"Fix deform is changing yz by too much with changing xy");
}
// set domain->h_rate values for use by domain and other fixes/computes
// initialize all rates to 0.0
// cannot set here for TRATE,VOLUME,WIGGLE styles since not constant
h_rate = domain->h_rate;
h_ratelo = domain->h_ratelo;
for (int i = 0; i < 3; i++) {
h_rate[i] = h_ratelo[i] = 0.0;
if (set[i].style == FINAL || set[i].style == DELTA ||
set[i].style == SCALE || set[i].style == VEL ||
set[i].style == ERATE) {
double dlo_dt,dhi_dt;
if (delt != 0.0) {
dlo_dt = (set[i].lo_stop - set[i].lo_start) / delt;
dhi_dt = (set[i].hi_stop - set[i].hi_start) / delt;
} else dlo_dt = dhi_dt = 0.0;
h_rate[i] = dhi_dt - dlo_dt;
h_ratelo[i] = dlo_dt;
}
}
for (int i = 3; i < 6; i++) {
h_rate[i] = 0.0;
if (set[i].style == FINAL || set[i].style == DELTA ||
set[i].style == VEL || set[i].style == ERATE) {
if (delt != 0.0)
h_rate[i] = (set[i].tilt_stop - set[i].tilt_start) / delt;
else h_rate[i] = 0.0;
}
}
// detect if any rigid fixes exist so rigid bodies can be rescaled
// rfix[] = indices to each fix rigid
delete [] rfix;
nrigid = 0;
rfix = NULL;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) nrigid++;
if (nrigid) {
rfix = new int[nrigid];
nrigid = 0;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) rfix[nrigid++] = i;
}
}
/* ----------------------------------------------------------------------
box flipped on previous step
perform irregular comm to migrate atoms to new procs
reset box tilts for flipped config and create new box in domain
remap to put far-away atoms back into new box
perform irregular on atoms in lamda coords to get atoms to new procs
force reneighboring on next timestep
------------------------------------------------------------------------- */
void FixDeform::pre_exchange()
{
if (flip == 0) return;
domain->yz = set[3].tilt_target = set[3].tilt_flip;
domain->xz = set[4].tilt_target = set[4].tilt_flip;
domain->xy = set[5].tilt_target = set[5].tilt_flip;
domain->set_global_box();
domain->set_local_box();
double **x = atom->x;
int *image = atom->image;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);
domain->x2lamda(atom->nlocal);
irregular->migrate_atoms();
domain->lamda2x(atom->nlocal);
flip = 0;
}
/* ---------------------------------------------------------------------- */
void FixDeform::end_of_step()
{
int i;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
// set new box size
// for TRATE, set target directly based on current time, also set h_rate
// for WIGGLE, set target directly based on current time, also set h_rate
// for NONE, target is current box size
// for others except VOLUME, target is linear value between start and stop
for (i = 0; i < 3; i++) {
if (set[i].style == TRATE) {
double delt = (update->ntimestep - update->beginstep) * update->dt;
set[i].lo_target = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*((set[i].hi_start-set[i].lo_start) * exp(set[i].rate*delt));
set[i].hi_target = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*((set[i].hi_start-set[i].lo_start) * exp(set[i].rate*delt));
h_rate[i] = set[i].rate * domain->h[i];
h_ratelo[i] = -0.5*h_rate[i];
} else if (set[i].style == WIGGLE) {
double delt = (update->ntimestep - update->beginstep) * update->dt;
set[i].lo_target = set[i].lo_start -
0.5*set[i].amplitude * sin(TWOPI*delt/set[i].tperiod);
set[i].hi_target = set[i].hi_start +
0.5*set[i].amplitude * sin(TWOPI*delt/set[i].tperiod);
h_rate[i] = TWOPI/set[i].tperiod * set[i].amplitude *
cos(TWOPI*delt/set[i].tperiod);
h_ratelo[i] = -0.5*h_rate[i];
} else if (set[i].style == NONE) {
set[i].lo_target = domain->boxlo[i];
set[i].hi_target = domain->boxhi[i];
} else if (set[i].style != VOLUME) {
set[i].lo_target = set[i].lo_start +
delta*(set[i].lo_stop - set[i].lo_start);
set[i].hi_target = set[i].hi_start +
delta*(set[i].hi_stop - set[i].hi_start);
}
}
// set new box size for VOLUME dims that are linked to other dims
// NOTE: still need to set h_rate for these dims
for (int i = 0; i < 3; i++) {
if (set[i].style != VOLUME) continue;
if (set[i].substyle == ONE_FROM_ONE) {
set[i].lo_target = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_target -
set[set[i].dynamic1].lo_target) /
(set[set[i].fixed].hi_start-set[set[i].fixed].lo_start));
set[i].hi_target = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_target -
set[set[i].dynamic1].lo_target) /
(set[set[i].fixed].hi_start-set[set[i].fixed].lo_start));
} else if (set[i].substyle == ONE_FROM_TWO) {
set[i].lo_target = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_target -
set[set[i].dynamic1].lo_target) /
(set[set[i].dynamic2].hi_target -
set[set[i].dynamic2].lo_target));
set[i].hi_target = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*(set[i].vol_start /
(set[set[i].dynamic1].hi_target -
set[set[i].dynamic1].lo_target) /
(set[set[i].dynamic2].hi_target -
set[set[i].dynamic2].lo_target));
} else if (set[i].substyle == TWO_FROM_ONE) {
set[i].lo_target = 0.5*(set[i].lo_start+set[i].hi_start) -
0.5*sqrt(set[i].vol_start /
(set[set[i].dynamic1].hi_target -
set[set[i].dynamic1].lo_target) /
(set[set[i].fixed].hi_start -
set[set[i].fixed].lo_start) *
(set[i].hi_start - set[i].lo_start));
set[i].hi_target = 0.5*(set[i].lo_start+set[i].hi_start) +
0.5*sqrt(set[i].vol_start /
(set[set[i].dynamic1].hi_target -
set[set[i].dynamic1].lo_target) /
(set[set[i].fixed].hi_start -
set[set[i].fixed].lo_start) *
(set[i].hi_start - set[i].lo_start));
}
}
// for triclinic, set new box shape
// for TRATE, set target directly based on current time. also set h_rate
// for WIGGLE, set target directly based on current time. also set h_rate
// for NONE, target is current tilt
// for other styles, target is linear value between start and stop values
if (triclinic) {
double *h = domain->h;
for (i = 3; i < 6; i++) {
if (set[i].style == TRATE) {
double delt = (update->ntimestep - update->beginstep) * update->dt;
set[i].tilt_target = set[i].tilt_start * exp(set[i].rate*delt);
h_rate[i] = set[i].rate * domain->h[i];
} else if (set[i].style == WIGGLE) {
double delt = (update->ntimestep - update->beginstep) * update->dt;
set[i].tilt_target = set[i].tilt_start +
set[i].amplitude * sin(TWOPI*delt/set[i].tperiod);
h_rate[i] = TWOPI/set[i].tperiod * set[i].amplitude *
cos(TWOPI*delt/set[i].tperiod);
} else if (set[i].style == NONE) {
if (i == 5) set[i].tilt_target = domain->xy;
else if (i == 4) set[i].tilt_target = domain->xz;
else if (i == 3) set[i].tilt_target = domain->yz;
} else {
set[i].tilt_target = set[i].tilt_start +
delta*(set[i].tilt_stop - set[i].tilt_start);
}
// tilt_target can be large positive or large negative value
// add/subtract box lengths until tilt_target is closest to current value
int idenom;
if (i == 5) idenom = 0;
else if (i == 4) idenom = 0;
else if (i == 3) idenom = 1;
double denom = set[idenom].hi_target - set[idenom].lo_target;
double current = h[i]/h[idenom];
while (set[i].tilt_target/denom - current > 0.0)
set[i].tilt_target -= denom;
while (set[i].tilt_target/denom - current < 0.0)
set[i].tilt_target += denom;
if (fabs(set[i].tilt_target/denom - 1.0 - current) <
fabs(set[i].tilt_target/denom - current))
set[i].tilt_target -= denom;
}
}
// if any tilt targets exceed bounds, set flip flag and new tilt_flip values
// flip will be performed on next timestep before reneighboring
// when yz flips and xy is non-zero, xz must also change
// this is to keep the edge vectors of the flipped shape matrix
// an integer combination of the edge vectors of the unflipped shape matrix
if (triclinic) {
double xprd = set[0].hi_target - set[0].lo_target;
double yprd = set[1].hi_target - set[1].lo_target;
if (set[3].tilt_target < -0.5*yprd || set[3].tilt_target > 0.5*yprd ||
set[4].tilt_target < -0.5*xprd || set[4].tilt_target > 0.5*xprd ||
set[5].tilt_target < -0.5*xprd || set[5].tilt_target > 0.5*xprd) {
flip = 1;
next_reneighbor = update->ntimestep + 1;
set[3].tilt_flip = set[3].tilt_target;
set[4].tilt_flip = set[4].tilt_target;
set[5].tilt_flip = set[5].tilt_target;
if (set[3].tilt_flip < -0.5*yprd) {
set[3].tilt_flip += yprd;
set[4].tilt_flip += set[5].tilt_flip;
} else if (set[3].tilt_flip >= 0.5*yprd) {
set[3].tilt_flip -= yprd;
set[4].tilt_flip -= set[5].tilt_flip;
}
if (set[4].tilt_flip < -0.5*xprd) set[4].tilt_flip += xprd;
if (set[4].tilt_flip > 0.5*xprd) set[4].tilt_flip -= xprd;
if (set[5].tilt_flip < -0.5*xprd) set[5].tilt_flip += xprd;
if (set[5].tilt_flip > 0.5*xprd) set[5].tilt_flip -= xprd;
}
}
// convert atoms and rigid bodies to lamda coords
if (remapflag == X_REMAP) {
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->x2lamda(x[i],x[i]);
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(0);
}
// reset global and local box to new size/shape
// only if deform fix is controlling the dimension
if (set[0].style) {
domain->boxlo[0] = set[0].lo_target;
domain->boxhi[0] = set[0].hi_target;
}
if (set[1].style) {
domain->boxlo[1] = set[1].lo_target;
domain->boxhi[1] = set[1].hi_target;
}
if (set[2].style) {
domain->boxlo[2] = set[2].lo_target;
domain->boxhi[2] = set[2].hi_target;
}
if (triclinic) {
if (set[3].style) domain->yz = set[3].tilt_target;
if (set[4].style) domain->xz = set[4].tilt_target;
if (set[5].style) domain->xy = set[5].tilt_target;
}
domain->set_global_box();
domain->set_local_box();
// convert atoms and rigid bodies back to box coords
if (remapflag == X_REMAP) {
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->lamda2x(x[i],x[i]);
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(1);
}
// redo KSpace coeffs since box has changed
if (kspace_flag) force->kspace->setup();
}
/* ---------------------------------------------------------------------- */
void FixDeform::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal fix deform command");
+ if (narg < 0) error->all(FLERR,"Illegal fix deform command");
remapflag = X_REMAP;
scaleflag = 1;
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"remap") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix deform command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deform command");
if (strcmp(arg[iarg+1],"x") == 0) remapflag = X_REMAP;
else if (strcmp(arg[iarg+1],"v") == 0) remapflag = V_REMAP;
else if (strcmp(arg[iarg+1],"none") == 0) remapflag = NO_REMAP;
- else error->all("Illegal fix deform command");
+ else error->all(FLERR,"Illegal fix deform command");
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix deform command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deform command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix deform command");
+ else error->all(FLERR,"Illegal fix deform command");
iarg += 2;
- } else error->all("Illegal fix deform command");
+ } else error->all(FLERR,"Illegal fix deform command");
}
}
diff --git a/src/fix_deposit.cpp b/src/fix_deposit.cpp
index 357a32594..214856ce3 100644
--- a/src/fix_deposit.cpp
+++ b/src/fix_deposit.cpp
@@ -1,460 +1,460 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_deposit.h"
#include "atom.h"
#include "atom_vec.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "comm.h"
#include "domain.h"
#include "lattice.h"
#include "region.h"
#include "random_park.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixDeposit::FixDeposit(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal fix deposit command");
+ if (narg < 7) error->all(FLERR,"Illegal fix deposit command");
restart_global = 1;
time_depend = 1;
// required args
ninsert = atoi(arg[3]);
ntype = atoi(arg[4]);
nfreq = atoi(arg[5]);
seed = atoi(arg[6]);
- if (seed <= 0) error->all("Illegal fix deposit command");
+ if (seed <= 0) error->all(FLERR,"Illegal fix deposit command");
// set defaults
iregion = -1;
idregion = NULL;
globalflag = localflag = 0;
lo = hi = deltasq = 0.0;
nearsq = 0.0;
maxattempt = 10;
rateflag = 0;
vxlo = vxhi = vylo = vyhi = vzlo = vzhi = 0.0;
scaleflag = 1;
// read options from end of input line
options(narg-7,&arg[7]);
// error checks on region and its extent being inside simulation box
- if (iregion == -1) error->all("Must specify a region in fix deposit");
+ if (iregion == -1) error->all(FLERR,"Must specify a region in fix deposit");
if (domain->regions[iregion]->bboxflag == 0)
- error->all("Fix deposit region does not support a bounding box");
+ error->all(FLERR,"Fix deposit region does not support a bounding box");
if (domain->regions[iregion]->dynamic_check())
- error->all("Fix deposit region cannot be dynamic");
+ error->all(FLERR,"Fix deposit region cannot be dynamic");
xlo = domain->regions[iregion]->extent_xlo;
xhi = domain->regions[iregion]->extent_xhi;
ylo = domain->regions[iregion]->extent_ylo;
yhi = domain->regions[iregion]->extent_yhi;
zlo = domain->regions[iregion]->extent_zlo;
zhi = domain->regions[iregion]->extent_zhi;
if (domain->triclinic == 0) {
if (xlo < domain->boxlo[0] || xhi > domain->boxhi[0] ||
ylo < domain->boxlo[1] || yhi > domain->boxhi[1] ||
zlo < domain->boxlo[2] || zhi > domain->boxhi[2])
- error->all("Deposition region extends outside simulation box");
+ error->all(FLERR,"Deposition region extends outside simulation box");
} else {
if (xlo < domain->boxlo_bound[0] || xhi > domain->boxhi_bound[0] ||
ylo < domain->boxlo_bound[1] || yhi > domain->boxhi_bound[1] ||
zlo < domain->boxlo_bound[2] || zhi > domain->boxhi_bound[2])
- error->all("Deposition region extends outside simulation box");
+ error->all(FLERR,"Deposition region extends outside simulation box");
}
// setup scaling
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix deposit with undefined lattice");
+ error->all(FLERR,"Use of fix deposit with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// apply scaling to all input parameters with dist/vel units
if (domain->dimension == 2) {
lo *= yscale;
hi *= yscale;
rate *= yscale;
} else {
lo *= zscale;
hi *= zscale;
rate *= zscale;
}
deltasq *= xscale*xscale;
nearsq *= xscale*xscale;
vxlo *= xscale;
vxhi *= xscale;
vylo *= yscale;
vyhi *= yscale;
vzlo *= zscale;
vzhi *= zscale;
// random number generator, same for all procs
random = new RanPark(lmp,seed);
// set up reneighboring
force_reneighbor = 1;
next_reneighbor = update->ntimestep + 1;
nfirst = next_reneighbor;
ninserted = 0;
}
/* ---------------------------------------------------------------------- */
FixDeposit::~FixDeposit()
{
delete random;
delete [] idregion;
}
/* ---------------------------------------------------------------------- */
int FixDeposit::setmask()
{
int mask = 0;
mask |= PRE_EXCHANGE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixDeposit::init()
{
// set index and check validity of region
iregion = domain->find_region(idregion);
- if (iregion == -1) error->all("Region ID for fix deposit does not exist");
+ if (iregion == -1) error->all(FLERR,"Region ID for fix deposit does not exist");
}
/* ----------------------------------------------------------------------
perform particle insertion
------------------------------------------------------------------------- */
void FixDeposit::pre_exchange()
{
int i,j;
int flag,flagall;
double coord[3],lamda[3],delx,dely,delz,rsq;
double *newcoord;
// just return if should not be called on this timestep
if (next_reneighbor != update->ntimestep) return;
// compute current offset = bottom of insertion volume
double offset = 0.0;
if (rateflag) offset = (update->ntimestep - nfirst) * update->dt * rate;
double *sublo,*subhi;
if (domain->triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
// attempt an insertion until successful
int nfix = modify->nfix;
Fix **fix = modify->fix;
int success = 0;
int attempt = 0;
while (attempt < maxattempt) {
attempt++;
// choose random position for new atom within region
coord[0] = xlo + random->uniform() * (xhi-xlo);
coord[1] = ylo + random->uniform() * (yhi-ylo);
coord[2] = zlo + random->uniform() * (zhi-zlo);
while (domain->regions[iregion]->match(coord[0],coord[1],coord[2]) == 0) {
coord[0] = xlo + random->uniform() * (xhi-xlo);
coord[1] = ylo + random->uniform() * (yhi-ylo);
coord[2] = zlo + random->uniform() * (zhi-zlo);
}
// adjust vertical coord by offset
if (domain->dimension == 2) coord[1] += offset;
else coord[2] += offset;
// if global, reset vertical coord to be lo-hi above highest atom
// if local, reset vertical coord to be lo-hi above highest "nearby" atom
// local computation computes lateral distance between 2 particles w/ PBC
if (globalflag || localflag) {
int dim;
double max,maxall,delx,dely,delz,rsq;
if (domain->dimension == 2) {
dim = 1;
max = domain->boxlo[1];
} else {
dim = 2;
max = domain->boxlo[2];
}
double **x = atom->x;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (localflag) {
delx = coord[0] - x[i][0];
dely = coord[1] - x[i][1];
delz = 0.0;
domain->minimum_image(delx,dely,delz);
if (domain->dimension == 2) rsq = delx*delx;
else rsq = delx*delx + dely*dely;
if (rsq > deltasq) continue;
}
if (x[i][dim] > max) max = x[i][dim];
}
MPI_Allreduce(&max,&maxall,1,MPI_DOUBLE,MPI_MAX,world);
if (domain->dimension == 2)
coord[1] = maxall + lo + random->uniform()*(hi-lo);
else
coord[2] = maxall + lo + random->uniform()*(hi-lo);
}
// now have final coord
// if distance to any atom is less than near, try again
double **x = atom->x;
int nlocal = atom->nlocal;
flag = 0;
for (i = 0; i < nlocal; i++) {
delx = coord[0] - x[i][0];
dely = coord[1] - x[i][1];
delz = coord[2] - x[i][2];
domain->minimum_image(delx,dely,delz);
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < nearsq) flag = 1;
}
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_MAX,world);
if (flagall) continue;
// insertion will proceed
// choose random velocity for new atom
double vxtmp = vxlo + random->uniform() * (vxhi-vxlo);
double vytmp = vylo + random->uniform() * (vyhi-vylo);
double vztmp = vzlo + random->uniform() * (vzhi-vzlo);
// check if new atom is in my sub-box or above it if I'm highest proc
// if so, add to my list via create_atom()
// initialize info about the atoms
// set group mask to "all" plus fix group
if (domain->triclinic) {
domain->x2lamda(coord,lamda);
newcoord = lamda;
} else newcoord = coord;
flag = 0;
if (newcoord[0] >= sublo[0] && newcoord[0] < subhi[0] &&
newcoord[1] >= sublo[1] && newcoord[1] < subhi[1] &&
newcoord[2] >= sublo[2] && newcoord[2] < subhi[2]) flag = 1;
else if (domain->dimension == 3 && newcoord[2] >= domain->boxhi[2] &&
comm->myloc[2] == comm->procgrid[2]-1 &&
newcoord[0] >= sublo[0] && newcoord[0] < subhi[0] &&
newcoord[1] >= sublo[1] && newcoord[1] < subhi[1]) flag = 1;
else if (domain->dimension == 2 && newcoord[1] >= domain->boxhi[1] &&
comm->myloc[1] == comm->procgrid[1]-1 &&
newcoord[0] >= sublo[0] && newcoord[0] < subhi[0]) flag = 1;
if (flag) {
atom->avec->create_atom(ntype,coord);
int m = atom->nlocal - 1;
atom->type[m] = ntype;
atom->mask[m] = 1 | groupbit;
atom->v[m][0] = vxtmp;
atom->v[m][1] = vytmp;
atom->v[m][2] = vztmp;
for (j = 0; j < nfix; j++)
if (fix[j]->create_attribute) fix[j]->set_arrays(m);
}
MPI_Allreduce(&flag,&success,1,MPI_INT,MPI_MAX,world);
break;
}
// warn if not successful b/c too many attempts or no proc owned particle
if (!success && comm->me == 0)
- error->warning("Particle deposition was unsuccessful",0);
+ error->warning(FLERR,"Particle deposition was unsuccessful",0);
// reset global natoms
// set tag # of new particle beyond all previous atoms
// if global map exists, reset it now instead of waiting for comm
// since deleting atoms messes up ghosts
if (success) {
atom->natoms += 1;
if (atom->tag_enable) {
atom->tag_extend();
if (atom->map_style) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
}
}
// next timestep to insert
// next_reneighbor = 0 if done
if (success) ninserted++;
if (ninserted < ninsert) next_reneighbor += nfreq;
else next_reneighbor = 0;
}
/* ----------------------------------------------------------------------
parse optional parameters at end of input line
------------------------------------------------------------------------- */
void FixDeposit::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal fix indent command");
+ if (narg < 0) error->all(FLERR,"Illegal fix indent command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix deposit command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
iregion = domain->find_region(arg[iarg+1]);
if (iregion == -1)
- error->all("Region ID for fix deposit does not exist");
+ error->all(FLERR,"Region ID for fix deposit does not exist");
int n = strlen(arg[iarg+1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"global") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deposit command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deposit command");
globalflag = 1;
localflag = 0;
lo = atof(arg[iarg+1]);
hi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"local") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix deposit command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix deposit command");
localflag = 1;
globalflag = 0;
lo = atof(arg[iarg+1]);
hi = atof(arg[iarg+2]);
deltasq = atof(arg[iarg+3])*atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"near") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix deposit command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
nearsq = atof(arg[iarg+1])*atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"attempt") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix deposit command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
maxattempt = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"rate") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix deposit command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
rateflag = 1;
rate = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"vx") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deposit command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deposit command");
vxlo = atof(arg[iarg+1]);
vxhi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"vy") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deposit command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deposit command");
vylo = atof(arg[iarg+1]);
vyhi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"vz") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix deposit command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix deposit command");
vzlo = atof(arg[iarg+1]);
vzhi = atof(arg[iarg+2]);
iarg += 3;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix deposit command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix deposit command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix deposit command");
+ else error->all(FLERR,"Illegal fix deposit command");
iarg += 2;
- } else error->all("Illegal fix deposit command");
+ } else error->all(FLERR,"Illegal fix deposit command");
}
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixDeposit::write_restart(FILE *fp)
{
int n = 0;
double list[4];
list[n++] = random->state();
list[n++] = ninserted;
list[n++] = nfirst;
list[n++] = next_reneighbor;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),n,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixDeposit::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
seed = static_cast<int> (list[n++]);
ninserted = static_cast<int> (list[n++]);
nfirst = static_cast<int> (list[n++]);
next_reneighbor = static_cast<int> (list[n++]);
random->reset(seed);
}
diff --git a/src/fix_drag.cpp b/src/fix_drag.cpp
index 357495bd6..51e744aad 100644
--- a/src/fix_drag.cpp
+++ b/src/fix_drag.cpp
@@ -1,147 +1,147 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_drag.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixDrag::FixDrag(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 8) error->all("Illegal fix drag command");
+ if (narg != 8) error->all(FLERR,"Illegal fix drag command");
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extvector = 1;
xflag = yflag = zflag = 1;
if (strcmp(arg[3],"NULL") == 0) xflag = 0;
else xc = atof(arg[3]);
if (strcmp(arg[4],"NULL") == 0) yflag = 0;
else yc = atof(arg[4]);
if (strcmp(arg[5],"NULL") == 0) zflag = 0;
else zc = atof(arg[5]);
f_mag = atof(arg[6]);
delta = atof(arg[7]);
force_flag = 0;
ftotal[0] = ftotal[1] = ftotal[2] = 0.0;
}
/* ---------------------------------------------------------------------- */
int FixDrag::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixDrag::init()
{
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixDrag::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixDrag::post_force(int vflag)
{
// apply drag force to atoms in group of magnitude f_mag
// apply in direction (r-r0) if atom is further than delta away
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
ftotal[0] = ftotal[1] = ftotal[2] = 0.0;
force_flag = 0;
double dx,dy,dz,r,prefactor,fx,fy,fz;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dx = x[i][0] - xc;
dy = x[i][1] - yc;
dz = x[i][2] - zc;
if (!xflag) dx = 0.0;
if (!yflag) dy = 0.0;
if (!zflag) dz = 0.0;
domain->minimum_image(dx,dy,dz);
r = sqrt(dx*dx + dy*dy + dz*dz);
if (r > delta) {
prefactor = f_mag/r;
fx = prefactor*dx;
fy = prefactor*dy;
fz = prefactor*dz;
f[i][0] -= fx;
f[i][1] -= fy;
f[i][2] -= fz;
ftotal[0] -= fx;
ftotal[1] -= fy;
ftotal[2] -= fz;
}
}
}
/* ---------------------------------------------------------------------- */
void FixDrag::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ----------------------------------------------------------------------
return components of total drag force on fix group
------------------------------------------------------------------------- */
double FixDrag::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(ftotal,ftotal_all,3,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return ftotal_all[n];
}
diff --git a/src/fix_dt_reset.cpp b/src/fix_dt_reset.cpp
index 8991a879e..758c8b32a 100644
--- a/src/fix_dt_reset.cpp
+++ b/src/fix_dt_reset.cpp
@@ -1,203 +1,200 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_dt_reset.h"
#include "atom.h"
#include "update.h"
#include "integrate.h"
#include "domain.h"
#include "lattice.h"
#include "force.h"
#include "pair.h"
#include "modify.h"
#include "fix.h"
#include "output.h"
#include "dump.h"
#include "comm.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixDtReset::FixDtReset(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal fix dt/reset command");
+ if (narg < 7) error->all(FLERR,"Illegal fix dt/reset command");
time_depend = 1;
scalar_flag = 1;
vector_flag = 1;
size_vector = 1;
global_freq = 1;
extscalar = 0;
extvector = 0;
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix dt/reset command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix dt/reset command");
minbound = maxbound = 1;
tmin = tmax = 0.0;
if (strcmp(arg[4],"NULL") == 0) minbound = 0;
else tmin = atof(arg[4]);
if (strcmp(arg[5],"NULL") == 0) maxbound = 0;
else tmax = atof(arg[5]);
xmax = atof(arg[6]);
- if (minbound && tmin < 0.0) error->all("Illegal fix dt/reset command");
- if (maxbound && tmax < 0.0) error->all("Illegal fix dt/reset command");
+ if (minbound && tmin < 0.0) error->all(FLERR,"Illegal fix dt/reset command");
+ if (maxbound && tmax < 0.0) error->all(FLERR,"Illegal fix dt/reset command");
if (minbound && maxbound && tmin >= tmax)
- error->all("Illegal fix dt/reset command");
- if (xmax <= 0.0) error->all("Illegal fix dt/reset command");
+ error->all(FLERR,"Illegal fix dt/reset command");
+ if (xmax <= 0.0) error->all(FLERR,"Illegal fix dt/reset command");
int scaleflag = 1;
int iarg = 7;
while (iarg < narg) {
if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix dt/reset command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix dt/reset command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix dt/reset command");
+ else error->all(FLERR,"Illegal fix dt/reset command");
iarg += 2;
- } else error->all("Illegal fix dt/reset command");
+ } else error->all(FLERR,"Illegal fix dt/reset command");
}
// setup scaling, based on xlattice parameter
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix dt/reset with undefined lattice");
+ error->all(FLERR,"Use of fix dt/reset with undefined lattice");
if (scaleflag) xmax *= domain->lattice->xlattice;
// initializations
t_elapsed = 0.0;
laststep = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
int FixDtReset::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixDtReset::init()
{
// set rRESPA flag
respaflag = 0;
if (strstr(update->integrate_style,"respa")) respaflag = 1;
// check for DCD or XTC dumps
for (int i = 0; i < output->ndump; i++)
if ((strcmp(output->dump[i]->style,"dcd") == 0 ||
strcmp(output->dump[i]->style,"xtc") == 0) && comm->me == 0)
- error->warning("Dump dcd/xtc timestamp may be wrong with fix dt/reset");
+ error->warning(FLERR,"Dump dcd/xtc timestamp may be wrong with fix dt/reset");
ftm2v = force->ftm2v;
}
/* ---------------------------------------------------------------------- */
void FixDtReset::setup(int vflag)
{
end_of_step();
}
/* ---------------------------------------------------------------------- */
void FixDtReset::end_of_step()
{
double dt,dtv,dtf,dtsq;
double vsq,fsq,massinv;
double delx,dely,delz,delr;
// accumulate total time based on previous timestep
t_elapsed += (update->ntimestep - laststep) * update->dt;
// compute vmax and amax of any atom in group
double **v = atom->v;
double **f = atom->f;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double dtmin = BIG;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massinv = 1.0/rmass[i];
else massinv = 1.0/mass[type[i]];
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
fsq = f[i][0]*f[i][0] + f[i][1]*f[i][1] + f[i][2]*f[i][2];
dtv = dtf = BIG;
if (vsq > 0.0) dtv = xmax/sqrt(vsq);
if (fsq > 0.0) dtf = sqrt(2.0*xmax/(ftm2v*sqrt(fsq)*massinv));
dt = MIN(dtv,dtf);
dtsq = dt*dt;
delx = dt*v[i][0] + 0.5*dtsq*massinv*f[i][0] * ftm2v;
dely = dt*v[i][1] + 0.5*dtsq*massinv*f[i][1] * ftm2v;
delz = dt*v[i][2] + 0.5*dtsq*massinv*f[i][2] * ftm2v;
delr = sqrt(delx*delx + dely*dely + delz*delz);
if (delr > xmax) dt *= xmax/delr;
dtmin = MIN(dtmin,dt);
}
MPI_Allreduce(&dtmin,&dt,1,MPI_DOUBLE,MPI_MIN,world);
if (minbound) dt = MAX(dt,tmin);
if (maxbound) dt = MIN(dt,tmax);
// reset update->dt and other classes that depend on it
// rRESPA, pair style, fixes
laststep = update->ntimestep;
if (dt == update->dt) return;
update->dt = dt;
if (respaflag) update->integrate->reset_dt();
if (force->pair) force->pair->reset_dt();
for (int i = 0; i < modify->nfix; i++) modify->fix[i]->reset_dt();
}
/* ---------------------------------------------------------------------- */
double FixDtReset::compute_scalar()
{
return update->dt;
}
/* ---------------------------------------------------------------------- */
double FixDtReset::compute_vector(int n)
{
return t_elapsed;
}
diff --git a/src/fix_efield.cpp b/src/fix_efield.cpp
index 31c7ba147..42bc2efc9 100644
--- a/src/fix_efield.cpp
+++ b/src/fix_efield.cpp
@@ -1,223 +1,223 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Christina Payne (Vanderbilt U)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_efield.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "force.h"
#include "respa.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{CONSTANT,EQUAL,ATOM};
/* ---------------------------------------------------------------------- */
FixEfield::FixEfield(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal fix efield command");
+ if (narg != 6) error->all(FLERR,"Illegal fix efield command");
qe2f = force->qe2f;
xstr = ystr = zstr = NULL;
if (strstr(arg[3],"v_") == arg[3]) {
int n = strlen(&arg[3][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[3][2]);
} else {
ex = qe2f * atof(arg[3]);
xstyle = CONSTANT;
}
if (strstr(arg[4],"v_") == arg[4]) {
int n = strlen(&arg[4][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[4][2]);
} else {
ey = qe2f * atof(arg[4]);
ystyle = CONSTANT;
}
if (strstr(arg[5],"v_") == arg[5]) {
int n = strlen(&arg[5][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[5][2]);
} else {
ez = qe2f * atof(arg[5]);
zstyle = CONSTANT;
}
maxatom = 0;
efield = NULL;
}
/* ---------------------------------------------------------------------- */
FixEfield::~FixEfield()
{
delete [] xstr;
delete [] ystr;
delete [] zstr;
memory->destroy(efield);
}
/* ---------------------------------------------------------------------- */
int FixEfield::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixEfield::init()
{
- if (!atom->q_flag) error->all("Fix efield requires atom attribute q");
+ if (!atom->q_flag) error->all(FLERR,"Fix efield requires atom attribute q");
// check variables
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for fix efield does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for fix efield does not exist");
if (input->variable->equalstyle(xvar)) xstyle = EQUAL;
else if (input->variable->atomstyle(xvar)) xstyle = ATOM;
- else error->all("Variable for fix efield is invalid style");
+ else error->all(FLERR,"Variable for fix efield is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for fix efield does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for fix efield does not exist");
if (input->variable->equalstyle(yvar)) ystyle = EQUAL;
else if (input->variable->atomstyle(yvar)) ystyle = ATOM;
- else error->all("Variable for fix efield is invalid style");
+ else error->all(FLERR,"Variable for fix efield is invalid style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for fix efield does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for fix efield does not exist");
if (input->variable->equalstyle(zvar)) zstyle = EQUAL;
else if (input->variable->atomstyle(zvar)) zstyle = ATOM;
- else error->all("Variable for fix efield is invalid style");
+ else error->all(FLERR,"Variable for fix efield is invalid style");
}
if (xstyle == ATOM || ystyle == ATOM || zstyle == ATOM)
varflag = ATOM;
else if (xstyle == EQUAL || ystyle == EQUAL || zstyle == EQUAL)
varflag = EQUAL;
else varflag = CONSTANT;
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixEfield::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ----------------------------------------------------------------------
apply F = qE
------------------------------------------------------------------------- */
void FixEfield::post_force(int vflag)
{
double **f = atom->f;
double *q = atom->q;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// reallocate efield array if necessary
if (varflag == ATOM && nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(efield);
memory->create(efield,maxatom,3,"efield:efield");
}
if (varflag == CONSTANT) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
f[i][0] += q[i]*ex;
f[i][1] += q[i]*ey;
f[i][2] += q[i]*ez;
}
// variable efield, wrap with clear/add
} else {
modify->clearstep_compute();
if (xstyle == EQUAL) ex = qe2f * input->variable->compute_equal(xvar);
else if (xstyle == ATOM && efield)
input->variable->compute_atom(xvar,igroup,&efield[0][0],3,0);
if (ystyle == EQUAL) ey = qe2f * input->variable->compute_equal(yvar);
else if (ystyle == ATOM && efield)
input->variable->compute_atom(yvar,igroup,&efield[0][1],3,0);
if (zstyle == EQUAL) ez = qe2f * input->variable->compute_equal(zvar);
else if (zstyle == ATOM && efield)
input->variable->compute_atom(zvar,igroup,&efield[0][2],3,0);
modify->addstep_compute(update->ntimestep + 1);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (xstyle == ATOM) f[i][0] += qe2f * q[i]*efield[i][0];
else f[i][0] += q[i]*ex;
if (ystyle == ATOM) f[i][1] += qe2f * q[i]*efield[i][1];
else f[i][1] += q[i]*ey;
if (zstyle == ATOM) f[i][2] += qe2f * q[i]*efield[i][2];
else f[i][2] += q[i]*ez;
}
}
}
/* ---------------------------------------------------------------------- */
void FixEfield::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixEfield::memory_usage()
{
double bytes = 0.0;
if (varflag == ATOM) bytes = atom->nmax*3 * sizeof(double);
return bytes;
}
diff --git a/src/fix_enforce2d.cpp b/src/fix_enforce2d.cpp
index c08c1ecdc..ad7ef9f61 100644
--- a/src/fix_enforce2d.cpp
+++ b/src/fix_enforce2d.cpp
@@ -1,132 +1,132 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_enforce2d.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixEnforce2D::FixEnforce2D(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal fix enforce2d command");
+ if (narg != 3) error->all(FLERR,"Illegal fix enforce2d command");
}
/* ---------------------------------------------------------------------- */
int FixEnforce2D::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixEnforce2D::init()
{
if (domain->dimension == 3)
- error->all("Cannot use fix enforce2d with 3d simulation");
+ error->all(FLERR,"Cannot use fix enforce2d with 3d simulation");
}
/* ---------------------------------------------------------------------- */
void FixEnforce2D::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
int nlevels_respa = ((Respa *) update->integrate)->nlevels;
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
}
}
/* ---------------------------------------------------------------------- */
void FixEnforce2D::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixEnforce2D::post_force(int vflag)
{
double **v = atom->v;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][2] = 0.0;
f[i][2] = 0.0;
}
// for systems with omega/angmom/torque, zero x and y components
if (atom->omega_flag) {
double **omega = atom->omega;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
omega[i][0] = 0.0;
omega[i][1] = 0.0;
}
}
if (atom->angmom_flag) {
double **angmom = atom->angmom;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
angmom[i][0] = 0.0;
angmom[i][1] = 0.0;
}
}
if (atom->torque_flag) {
double **torque = atom->torque;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
}
}
}
/* ---------------------------------------------------------------------- */
void FixEnforce2D::post_force_respa(int vflag, int ilevel, int iloop)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixEnforce2D::min_post_force(int vflag)
{
post_force(vflag);
}
diff --git a/src/fix_evaporate.cpp b/src/fix_evaporate.cpp
index 4e8c77956..e00d0ca9e 100644
--- a/src/fix_evaporate.cpp
+++ b/src/fix_evaporate.cpp
@@ -1,381 +1,385 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_evaporate.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "domain.h"
#include "region.h"
#include "comm.h"
#include "force.h"
#include "group.h"
#include "random_park.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixEvaporate::FixEvaporate(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal fix evaporate command");
+ if (narg < 7) error->all(FLERR,"Illegal fix evaporate command");
scalar_flag = 1;
global_freq = 1;
extscalar = 0;
nevery = atoi(arg[3]);
nflux = atoi(arg[4]);
iregion = domain->find_region(arg[5]);
int n = strlen(arg[5]) + 1;
idregion = new char[n];
strcpy(idregion,arg[5]);
int seed = atoi(arg[6]);
- if (nevery <= 0 || nflux <= 0) error->all("Illegal fix evaporate command");
- if (iregion == -1) error->all("Region ID for fix evaporate does not exist");
- if (seed <= 0) error->all("Illegal fix evaporate command");
+ if (nevery <= 0 || nflux <= 0)
+ error->all(FLERR,"Illegal fix evaporate command");
+ if (iregion == -1)
+ error->all(FLERR,"Region ID for fix evaporate does not exist");
+ if (seed <= 0) error->all(FLERR,"Illegal fix evaporate command");
// random number generator, same for all procs
random = new RanPark(lmp,seed);
// optional args
molflag = 0;
int iarg = 7;
while (iarg < narg) {
if (strcmp(arg[iarg],"molecule") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix evaporate command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix evaporate command");
if (strcmp(arg[iarg+1],"no") == 0) molflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) molflag = 1;
- else error->all("Illegal fix evaporate command");
+ else error->all(FLERR,"Illegal fix evaporate command");
iarg += 2;
- } else error->all("Illegal fix evaporate command");
+ } else error->all(FLERR,"Illegal fix evaporate command");
}
// set up reneighboring
force_reneighbor = 1;
next_reneighbor = (update->ntimestep/nevery)*nevery + nevery;
ndeleted = 0;
nmax = 0;
list = NULL;
mark = NULL;
}
/* ---------------------------------------------------------------------- */
FixEvaporate::~FixEvaporate()
{
delete [] idregion;
delete random;
memory->destroy(list);
memory->destroy(mark);
}
/* ---------------------------------------------------------------------- */
int FixEvaporate::setmask()
{
int mask = 0;
mask |= PRE_EXCHANGE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixEvaporate::init()
{
// set index and check validity of region
iregion = domain->find_region(idregion);
if (iregion == -1)
- error->all("Region ID for fix evaporate does not exist");
+ error->all(FLERR,"Region ID for fix evaporate does not exist");
// check that no deletable atoms are in atom->firstgroup
// deleting such an atom would not leave firstgroup atoms first
if (atom->firstgroup >= 0) {
int *mask = atom->mask;
int nlocal = atom->nlocal;
int firstgroupbit = group->bitmask[atom->firstgroup];
int flag = 0;
for (int i = 0; i < nlocal; i++)
if ((mask[i] & groupbit) && (mask[i] && firstgroupbit)) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall)
- error->all("Cannot evaporate atoms in atom_modify first group");
+ error->all(FLERR,"Cannot evaporate atoms in atom_modify first group");
}
// if molflag not set, warn if any deletable atom has a mol ID
if (molflag == 0 && atom->molecule_flag) {
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int flag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (molecule[i]) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall && comm->me == 0)
- error->
- warning("Fix evaporate may delete atom with non-zero molecule ID");
+ error->warning(FLERR,
+ "Fix evaporate may delete atom with non-zero molecule ID");
}
if (molflag && atom->molecule_flag == 0)
- error->all("Fix evaporate molecule requires atom attribute molecule");
+ error->all(FLERR,
+ "Fix evaporate molecule requires atom attribute molecule");
}
/* ----------------------------------------------------------------------
perform particle deletion
done before exchange, borders, reneighbor
so that ghost atoms and neighbor lists will be correct
------------------------------------------------------------------------- */
void FixEvaporate::pre_exchange()
{
int i,j,m,iwhichglobal,iwhichlocal;
int ndel,ndeltopo[4];
if (update->ntimestep != next_reneighbor) return;
// grow list and mark arrays if necessary
if (atom->nlocal > nmax) {
memory->destroy(list);
memory->destroy(mark);
nmax = atom->nmax;
memory->create(list,nmax,"evaporate:list");
memory->create(mark,nmax,"evaporate:mark");
}
// ncount = # of deletable atoms in region that I own
// nall = # on all procs
// nbefore = # on procs before me
- // list[ncount] = list of local indices
+ // list[ncount] = list of local indices of atoms I can delete
double **x = atom->x;
int *mask = atom->mask;
+ int *tag = atom->tag;
int nlocal = atom->nlocal;
int ncount = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
list[ncount++] = i;
int nall,nbefore;
MPI_Allreduce(&ncount,&nall,1,MPI_INT,MPI_SUM,world);
MPI_Scan(&ncount,&nbefore,1,MPI_INT,MPI_SUM,world);
nbefore -= ncount;
// ndel = total # of atom deletions, in or out of region
// ndeltopo[1,2,3,4] = ditto for bonds, angles, dihedrals, impropers
// mark[] = 1 if deleted
ndel = 0;
for (i = 0; i < nlocal; i++) mark[i] = 0;
// atomic deletions
// choose atoms randomly across all procs and mark them for deletion
// shrink eligible list as my atoms get marked
// keep ndel,ncount,nall,nbefore current after each atom deletion
if (molflag == 0) {
while (nall && ndel < nflux) {
iwhichglobal = static_cast<int> (nall*random->uniform());
if (iwhichglobal < nbefore) nbefore--;
else if (iwhichglobal < nbefore + ncount) {
iwhichlocal = iwhichglobal - nbefore;
mark[list[iwhichlocal]] = 1;
list[iwhichlocal] = list[ncount-1];
ncount--;
}
ndel++;
nall--;
}
// molecule deletions
// choose one atom in one molecule randomly across all procs
// bcast mol ID and delete all atoms in that molecule on any proc
// update deletion count by total # of atoms in molecule
// shrink list of eligible candidates as any of my atoms get marked
// keep ndel,ndeltopo,ncount,nall,nbefore current after each mol deletion
} else {
- int me,proc,iatom,imolecule,ndelone;
+ int me,proc,iatom,imolecule,ndelone,ndelall;
int *molecule = atom->molecule;
ndeltopo[0] = ndeltopo[1] = ndeltopo[2] = ndeltopo[3] = 0;
while (nall && ndel < nflux) {
// pick an iatom,imolecule on proc me to delete
iwhichglobal = static_cast<int> (nall*random->uniform());
if (iwhichglobal >= nbefore && iwhichglobal < nbefore + ncount) {
iwhichlocal = iwhichglobal - nbefore;
iatom = list[iwhichlocal];
imolecule = molecule[iatom];
me = comm->me;
} else me = -1;
// bcast mol ID to delete all atoms from
// if mol ID > 0, delete any atom in molecule and decrement counters
// if mol ID == 0, delete single iatom
+ // be careful to delete correct # of bond,angle,etc for newton on or off
MPI_Allreduce(&me,&proc,1,MPI_INT,MPI_MAX,world);
MPI_Bcast(&imolecule,1,MPI_INT,proc,world);
ndelone = 0;
for (i = 0; i < nlocal; i++) {
if (imolecule && molecule[i] == imolecule) {
mark[i] = 1;
ndelone++;
if (atom->avec->bonds_allow) {
if (force->newton_bond) ndeltopo[0] += atom->num_bond[i];
else {
for (j = 0; j < atom->num_bond[i]; j++) {
- m = atom->map(atom->bond_atom[i][j]);
- if (m >= 0 && m < nlocal) ndeltopo[0]++;
+ if (tag[i] < atom->bond_atom[i][j]) ndeltopo[0]++;
}
}
}
if (atom->avec->angles_allow) {
if (force->newton_bond) ndeltopo[1] += atom->num_angle[i];
else {
for (j = 0; j < atom->num_angle[i]; j++) {
m = atom->map(atom->angle_atom2[i][j]);
if (m >= 0 && m < nlocal) ndeltopo[1]++;
}
}
}
if (atom->avec->dihedrals_allow) {
if (force->newton_bond) ndeltopo[2] += atom->num_dihedral[i];
else {
for (j = 0; j < atom->num_dihedral[i]; j++) {
m = atom->map(atom->dihedral_atom2[i][j]);
if (m >= 0 && m < nlocal) ndeltopo[2]++;
}
}
}
if (atom->avec->impropers_allow) {
if (force->newton_bond) ndeltopo[3] += atom->num_improper[i];
else {
for (j = 0; j < atom->num_improper[i]; j++) {
m = atom->map(atom->improper_atom2[i][j]);
if (m >= 0 && m < nlocal) ndeltopo[3]++;
}
}
}
} else if (me == proc && i == iatom) {
mark[i] = 1;
ndelone++;
}
}
// remove any atoms marked for deletion from my eligible list
i = 0;
while (i < ncount) {
if (mark[list[i]]) {
list[i] = list[ncount-1];
ncount--;
} else i++;
}
// update ndel,ncount,nall,nbefore
+ // ndelall is total atoms deleted on this iteration
+ // ncount is already correct, so resum to get nall and nbefore
- MPI_Allreduce(&ndelone,&ndel,1,MPI_INT,MPI_SUM,world);
+ MPI_Allreduce(&ndelone,&ndelall,1,MPI_INT,MPI_SUM,world);
+ ndel += ndelall;
MPI_Allreduce(&ncount,&nall,1,MPI_INT,MPI_SUM,world);
MPI_Scan(&ncount,&nbefore,1,MPI_INT,MPI_SUM,world);
nbefore -= ncount;
}
}
// delete my marked atoms
// loop in reverse order to avoid copying marked atoms
AtomVec *avec = atom->avec;
for (i = nlocal-1; i >= 0; i--) {
if (mark[i]) {
avec->copy(atom->nlocal-1,i,1);
atom->nlocal--;
}
}
// reset global natoms and bonds, angles, etc
// if global map exists, reset it now instead of waiting for comm
// since deleting atoms messes up ghosts
atom->natoms -= ndel;
if (molflag) {
int all[4];
MPI_Allreduce(ndeltopo,all,4,MPI_INT,MPI_SUM,world);
atom->nbonds -= all[0];
atom->nangles -= all[1];
atom->ndihedrals -= all[2];
atom->nimpropers -= all[3];
}
if (ndel && atom->map_style) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
// statistics
ndeleted += ndel;
next_reneighbor = update->ntimestep + nevery;
}
/* ----------------------------------------------------------------------
return number of deleted particles
------------------------------------------------------------------------- */
double FixEvaporate::compute_scalar()
{
return 1.0*ndeleted;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixEvaporate::memory_usage()
{
double bytes = 2*nmax * sizeof(int);
return bytes;
}
diff --git a/src/fix_external.cpp b/src/fix_external.cpp
index 449a6d07c..dd92847cf 100644
--- a/src/fix_external.cpp
+++ b/src/fix_external.cpp
@@ -1,120 +1,120 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdio.h"
#include "string.h"
#include "fix_external.h"
#include "atom.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixExternal::FixExternal(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal fix external command");
+ if (narg != 3) error->all(FLERR,"Illegal fix external command");
callback = NULL;
nmax = 0;
fexternal = NULL;
}
/* ---------------------------------------------------------------------- */
FixExternal::~FixExternal()
{
memory->destroy(fexternal);
}
/* ---------------------------------------------------------------------- */
int FixExternal::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixExternal::init()
{
- if (callback == NULL) error->all("Fix external callback function not set");
+ if (callback == NULL) error->all(FLERR,"Fix external callback function not set");
}
/* ---------------------------------------------------------------------- */
void FixExternal::setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixExternal::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixExternal::post_force(int vflag)
{
if (atom->nlocal > nmax) {
memory->destroy(fexternal);
nmax = atom->nmax;
memory->create(fexternal,nmax,3,"external:fexternal");
}
// invoke the callback in driver program
// it will fill fexternal with forces
(this->callback)(ptr_caller,update->ntimestep,
atom->nlocal,atom->tag,atom->x,fexternal);
// add forces from fexternal to atoms in group
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
f[i][0] += fexternal[i][0];
f[i][1] += fexternal[i][1];
f[i][2] += fexternal[i][2];
}
}
/* ---------------------------------------------------------------------- */
void FixExternal::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
external caller sets a callback function to invoke in post_force()
------------------------------------------------------------------------- */
void FixExternal::set_callback(FnPtr caller_callback, void *caller_ptr)
{
callback = caller_callback;
ptr_caller = caller_ptr;
}
diff --git a/src/fix_gravity.cpp b/src/fix_gravity.cpp
index e3d2ae8ea..09a2e2c7f 100644
--- a/src/fix_gravity.cpp
+++ b/src/fix_gravity.cpp
@@ -1,218 +1,218 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fix_gravity.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{CHUTE,SPHERICAL,GRADIENT,VECTOR};
/* ---------------------------------------------------------------------- */
FixGravity::FixGravity(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix gravity command");
+ if (narg < 5) error->all(FLERR,"Illegal fix gravity command");
time_depend = 1;
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
magnitude = atof(arg[3]);
if (strcmp(arg[4],"chute") == 0) {
- if (narg != 6) error->all("Illegal fix gravity command");
+ if (narg != 6) error->all(FLERR,"Illegal fix gravity command");
style = CHUTE;
phi = 0.0;
theta = 180.0 - atof(arg[5]);
} else if (strcmp(arg[4],"spherical") == 0) {
- if (narg != 7) error->all("Illegal fix gravity command");
+ if (narg != 7) error->all(FLERR,"Illegal fix gravity command");
style = SPHERICAL;
phi = atof(arg[5]);
theta = atof(arg[6]);
} else if (strcmp(arg[4],"gradient") == 0) {
- if (narg != 9) error->all("Illegal fix gravity command");
+ if (narg != 9) error->all(FLERR,"Illegal fix gravity command");
style = GRADIENT;
phi = atof(arg[5]);
theta = atof(arg[6]);
phigrad = atof(arg[7]);
thetagrad = atof(arg[8]);
} else if (strcmp(arg[4],"vector") == 0) {
- if (narg != 8) error->all("Illegal fix gravity command");
+ if (narg != 8) error->all(FLERR,"Illegal fix gravity command");
style = VECTOR;
xdir = atof(arg[5]);
ydir = atof(arg[6]);
zdir = atof(arg[7]);
- } else error->all("Illegal fix gravity command");
+ } else error->all(FLERR,"Illegal fix gravity command");
double PI = 4.0*atan(1.0);
degree2rad = PI/180.0;
if (style == CHUTE || style == SPHERICAL || style == GRADIENT) {
if (domain->dimension == 3) {
xgrav = sin(degree2rad * theta) * cos(degree2rad * phi);
ygrav = sin(degree2rad * theta) * sin(degree2rad * phi);
zgrav = cos(degree2rad * theta);
} else {
xgrav = sin(degree2rad * theta);
ygrav = cos(degree2rad * theta);
zgrav = 0.0;
}
} else if (style == VECTOR) {
if (domain->dimension == 3) {
double length = sqrt(xdir*xdir + ydir*ydir + zdir*zdir);
xgrav = xdir/length;
ygrav = ydir/length;
zgrav = zdir/length;
} else {
double length = sqrt(xdir*xdir + ydir*ydir);
xgrav = xdir/length;
ygrav = ydir/length;
zgrav = 0.0;
}
}
time_origin = update->ntimestep;
eflag = 0;
egrav = 0.0;
}
/* ---------------------------------------------------------------------- */
int FixGravity::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixGravity::init()
{
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
dt = update->dt;
xacc = magnitude*xgrav;
yacc = magnitude*ygrav;
zacc = magnitude*zgrav;
}
/* ---------------------------------------------------------------------- */
void FixGravity::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixGravity::post_force(int vflag)
{
// update direction of gravity vector if gradient style
if (style == GRADIENT) {
if (domain->dimension == 3) {
double phi_current = degree2rad *
(phi + (update->ntimestep - time_origin)*dt*phigrad*360.0);
double theta_current = degree2rad *
(theta + (update->ntimestep - time_origin)*dt*thetagrad*360.0);
xgrav = sin(theta_current) * cos(phi_current);
ygrav = sin(theta_current) * sin(phi_current);
zgrav = cos(theta_current);
} else {
double theta_current = degree2rad *
(theta + (update->ntimestep - time_origin)*dt*thetagrad*360.0);
xgrav = sin(theta_current);
ygrav = cos(theta_current);
}
xacc = magnitude*xgrav;
yacc = magnitude*ygrav;
zacc = magnitude*zgrav;
}
double **x = atom->x;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double massone;
eflag = 0;
egrav = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = rmass[i];
f[i][0] += massone*xacc;
f[i][1] += massone*yacc;
f[i][2] += massone*zacc;
egrav -= massone * (xacc*x[i][0] + yacc*x[i][1] + zacc*x[i][2]);
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = mass[type[i]];
f[i][0] += massone*xacc;
f[i][1] += massone*yacc;
f[i][2] += massone*zacc;
egrav -= massone * (xacc*x[i][0] + yacc*x[i][1] + zacc*x[i][2]);
}
}
}
/* ---------------------------------------------------------------------- */
void FixGravity::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ----------------------------------------------------------------------
potential energy in gravity field
------------------------------------------------------------------------- */
double FixGravity::compute_scalar()
{
// only sum across procs one time
if (eflag == 0) {
MPI_Allreduce(&egrav,&egrav_all,1,MPI_DOUBLE,MPI_SUM,world);
eflag = 1;
}
return egrav_all;
}
diff --git a/src/fix_heat.cpp b/src/fix_heat.cpp
index 450d0bb84..45bd030cc 100644
--- a/src/fix_heat.cpp
+++ b/src/fix_heat.cpp
@@ -1,158 +1,158 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_heat.h"
#include "atom.h"
#include "domain.h"
#include "region.h"
#include "group.h"
#include "force.h"
#include "update.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixHeat::FixHeat(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix heat command");
+ if (narg < 4) error->all(FLERR,"Illegal fix heat command");
scalar_flag = 1;
global_freq = 1;
extscalar = 0;
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix heat command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix heat command");
heat_input = atof(arg[4]);
// optional args
iregion = -1;
idregion = NULL;
int iarg = 5;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix heat command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix heat command");
iregion = domain->find_region(arg[iarg+1]);
- if (iregion == -1) error->all("Region ID for fix heat does not exist");
+ if (iregion == -1) error->all(FLERR,"Region ID for fix heat does not exist");
int n = strlen(arg[iarg+1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix heat command");
+ } else error->all(FLERR,"Illegal fix heat command");
}
scale = 1.0;
}
/* ---------------------------------------------------------------------- */
FixHeat::~FixHeat()
{
delete [] idregion;
}
/* ---------------------------------------------------------------------- */
int FixHeat::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixHeat::init()
{
// set index and check validity of region
if (iregion >= 0) {
iregion = domain->find_region(idregion);
- if (iregion == -1) error->all("Region ID for fix heat does not exist");
+ if (iregion == -1) error->all(FLERR,"Region ID for fix heat does not exist");
}
// cannot have 0 atoms in group
- if (group->count(igroup) == 0) error->all("Fix heat group has no atoms");
+ if (group->count(igroup) == 0) error->all(FLERR,"Fix heat group has no atoms");
masstotal = group->mass(igroup);
}
/* ---------------------------------------------------------------------- */
void FixHeat::end_of_step()
{
double heat,ke;
double vsub[3],vcm[3];
Region *region = NULL;
if (iregion >= 0) region = domain->regions[iregion];
if (iregion < 0) {
heat = heat_input*nevery*update->dt*force->ftm2v;
ke = group->ke(igroup)*force->ftm2v;
group->vcm(igroup,masstotal,vcm);
} else {
masstotal = group->mass(igroup,iregion);
- if (masstotal == 0.0) error->all("Fix heat group has no atoms");
+ if (masstotal == 0.0) error->all(FLERR,"Fix heat group has no atoms");
heat = heat_input*nevery*update->dt*force->ftm2v;
ke = group->ke(igroup,iregion)*force->ftm2v;
group->vcm(igroup,masstotal,vcm,iregion);
}
double vcmsq = vcm[0]*vcm[0] + vcm[1]*vcm[1] + vcm[2]*vcm[2];
double escale = (ke + heat - 0.5*vcmsq*masstotal)/(ke - 0.5*vcmsq*masstotal);
- if (escale < 0.0) error->all("Fix heat kinetic energy went negative");
+ if (escale < 0.0) error->all(FLERR,"Fix heat kinetic energy went negative");
scale = sqrt(escale);
vsub[0] = (scale-1.0) * vcm[0];
vsub[1] = (scale-1.0) * vcm[1];
vsub[2] = (scale-1.0) * vcm[2];
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (iregion < 0) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] = scale*v[i][0] - vsub[0];
v[i][1] = scale*v[i][1] - vsub[1];
v[i][2] = scale*v[i][2] - vsub[2];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
v[i][0] = scale*v[i][0] - vsub[0];
v[i][1] = scale*v[i][1] - vsub[1];
v[i][2] = scale*v[i][2] - vsub[2];
}
}
}
/* ---------------------------------------------------------------------- */
double FixHeat::compute_scalar()
{
return scale;
}
diff --git a/src/fix_indent.cpp b/src/fix_indent.cpp
index dd6f7490e..48f72ac04 100644
--- a/src/fix_indent.cpp
+++ b/src/fix_indent.cpp
@@ -1,520 +1,520 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Ravi Agrawal (Northwestern U)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_indent.h"
#include "atom.h"
#include "input.h"
#include "variable.h"
#include "domain.h"
#include "lattice.h"
#include "update.h"
#include "modify.h"
#include "output.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NONE,SPHERE,CYLINDER,PLANE};
enum{INSIDE,OUTSIDE};
/* ---------------------------------------------------------------------- */
FixIndent::FixIndent(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix indent command");
+ if (narg < 4) error->all(FLERR,"Illegal fix indent command");
scalar_flag = 1;
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extscalar = 1;
extvector = 1;
k = atof(arg[3]);
k3 = k/3.0;
// read options from end of input line
options(narg-4,&arg[4]);
// setup scaling
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix indent with undefined lattice");
+ error->all(FLERR,"Use of fix indent with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// apply scaling factors to geometry
if (istyle == SPHERE || istyle == CYLINDER) {
if (!xstr) xvalue *= xscale;
if (!ystr) yvalue *= yscale;
if (!zstr) zvalue *= zscale;
if (!rstr) rvalue *= xscale;
} else if (istyle == PLANE) {
if (cdim == 0 && !pstr) pvalue *= xscale;
else if (cdim == 1 && !pstr) pvalue *= yscale;
else if (cdim == 2 && !pstr) pvalue *= zscale;
- } else error->all("Illegal fix indent command");
+ } else error->all(FLERR,"Illegal fix indent command");
varflag = 0;
if (xstr || ystr || zstr || rstr || pstr) varflag = 1;
indenter_flag = 0;
indenter[0] = indenter[1] = indenter[2] = indenter[3] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixIndent::~FixIndent()
{
delete [] xstr;
delete [] ystr;
delete [] zstr;
delete [] rstr;
delete [] pstr;
}
/* ---------------------------------------------------------------------- */
int FixIndent::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixIndent::init()
{
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for fix indent does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for fix indent does not exist");
if (!input->variable->equalstyle(xvar))
- error->all("Variable for fix indent is invalid style");
+ error->all(FLERR,"Variable for fix indent is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for fix indent does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for fix indent does not exist");
if (!input->variable->equalstyle(yvar))
- error->all("Variable for fix indent is not equal style");
+ error->all(FLERR,"Variable for fix indent is not equal style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for fix indent does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for fix indent does not exist");
if (!input->variable->equalstyle(zvar))
- error->all("Variable for fix indent is not equal style");
+ error->all(FLERR,"Variable for fix indent is not equal style");
}
if (rstr) {
rvar = input->variable->find(rstr);
- if (rvar < 0) error->all("Variable name for fix indent does not exist");
+ if (rvar < 0) error->all(FLERR,"Variable name for fix indent does not exist");
if (!input->variable->equalstyle(rvar))
- error->all("Variable for fix indent is not equal style");
+ error->all(FLERR,"Variable for fix indent is not equal style");
}
if (pstr) {
pvar = input->variable->find(pstr);
- if (pvar < 0) error->all("Variable name for fix indent does not exist");
+ if (pvar < 0) error->all(FLERR,"Variable name for fix indent does not exist");
if (!input->variable->equalstyle(pvar))
- error->all("Variable for fix indent is not equal style");
+ error->all(FLERR,"Variable for fix indent is not equal style");
}
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixIndent::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixIndent::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixIndent::post_force(int vflag)
{
// indenter values, 0 = energy, 1-3 = force components
// wrap variable evaluations with clear/add
if (varflag) modify->clearstep_compute();
indenter_flag = 0;
indenter[0] = indenter[1] = indenter[2] = indenter[3] = 0.0;
// spherical indenter
if (istyle == SPHERE) {
// ctr = current indenter center
// remap into periodic box
double ctr[3];
if (xstr) ctr[0] = input->variable->compute_equal(xvar);
else ctr[0] = xvalue;
if (ystr) ctr[1] = input->variable->compute_equal(yvar);
else ctr[1] = yvalue;
if (zstr) ctr[2] = input->variable->compute_equal(zvar);
else ctr[2] = zvalue;
domain->remap(ctr);
double radius;
if (rstr) radius = input->variable->compute_equal(rvar);
else radius = rvalue;
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double delx,dely,delz,r,dr,fmag,fx,fy,fz;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
delx = x[i][0] - ctr[0];
dely = x[i][1] - ctr[1];
delz = x[i][2] - ctr[2];
domain->minimum_image(delx,dely,delz);
r = sqrt(delx*delx + dely*dely + delz*delz);
if (side == OUTSIDE) {
dr = r - radius;
fmag = k*dr*dr;
} else {
dr = radius - r;
fmag = -k*dr*dr;
}
if (dr >= 0.0) continue;
fx = delx*fmag/r;
fy = dely*fmag/r;
fz = delz*fmag/r;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
indenter[0] -= k3 * dr*dr*dr;
indenter[1] -= fx;
indenter[2] -= fy;
indenter[3] -= fz;
}
// cylindrical indenter
} else if (istyle == CYLINDER) {
// ctr = current indenter axis
// remap into periodic box
// 3rd coord is just near box for remap(), since isn't used
double ctr[3];
if (cdim == 0) {
ctr[0] = domain->boxlo[0];
if (ystr) ctr[1] = input->variable->compute_equal(yvar);
else ctr[1] = yvalue;
if (zstr) ctr[2] = input->variable->compute_equal(zvar);
else ctr[2] = zvalue;
} else if (cdim == 1) {
if (xstr) ctr[0] = input->variable->compute_equal(xvar);
else ctr[0] = xvalue;
ctr[1] = domain->boxlo[1];
if (zstr) ctr[2] = input->variable->compute_equal(zvar);
else ctr[2] = zvalue;
} else {
if (xstr) ctr[0] = input->variable->compute_equal(xvar);
else ctr[0] = xvalue;
if (ystr) ctr[1] = input->variable->compute_equal(yvar);
else ctr[1] = yvalue;
ctr[2] = domain->boxlo[2];
}
domain->remap(ctr);
double radius;
if (rstr) radius = input->variable->compute_equal(rvar);
else radius = rvalue;
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double delx,dely,delz,r,dr,fmag,fx,fy,fz;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (cdim == 0) {
delx = 0;
dely = x[i][1] - ctr[1];
delz = x[i][2] - ctr[2];
} else if (cdim == 1) {
delx = x[i][0] - ctr[0];
dely = 0;
delz = x[i][2] - ctr[2];
} else {
delx = x[i][0] - ctr[0];
dely = x[i][1] - ctr[1];
delz = 0;
}
domain->minimum_image(delx,dely,delz);
r = sqrt(delx*delx + dely*dely + delz*delz);
if (side == OUTSIDE) {
dr = r - radius;
fmag = k*dr*dr;
} else {
dr = radius - r;
fmag = -k*dr*dr;
}
if (dr >= 0.0) continue;
fx = delx*fmag/r;
fy = dely*fmag/r;
fz = delz*fmag/r;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
indenter[0] -= k3 * dr*dr*dr;
indenter[1] -= fx;
indenter[2] -= fy;
indenter[3] -= fz;
}
// planar indenter
} else {
// plane = current plane position
double plane;
if (pstr) plane = input->variable->compute_equal(pvar);
else plane = pvalue;
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double dr,fatom;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dr = planeside * (plane - x[i][cdim]);
if (dr >= 0.0) continue;
fatom = -planeside * k*dr*dr;
f[i][cdim] += fatom;
indenter[0] -= k3 * dr*dr*dr;
indenter[cdim+1] -= fatom;
}
}
if (varflag) modify->addstep_compute(update->ntimestep + 1);
}
/* ---------------------------------------------------------------------- */
void FixIndent::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixIndent::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
energy of indenter interaction
------------------------------------------------------------------------- */
double FixIndent::compute_scalar()
{
// only sum across procs one time
if (indenter_flag == 0) {
MPI_Allreduce(indenter,indenter_all,4,MPI_DOUBLE,MPI_SUM,world);
indenter_flag = 1;
}
return indenter_all[0];
}
/* ----------------------------------------------------------------------
components of force on indenter
------------------------------------------------------------------------- */
double FixIndent::compute_vector(int n)
{
// only sum across procs one time
if (indenter_flag == 0) {
MPI_Allreduce(indenter,indenter_all,4,MPI_DOUBLE,MPI_SUM,world);
indenter_flag = 1;
}
return indenter_all[n+1];
}
/* ----------------------------------------------------------------------
parse optional parameters at end of input line
------------------------------------------------------------------------- */
void FixIndent::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal fix indent command");
+ if (narg < 0) error->all(FLERR,"Illegal fix indent command");
istyle = NONE;
xstr = ystr = zstr = rstr = pstr = NULL;
xvalue = yvalue = zvalue = rvalue = pvalue = 0.0;
scaleflag = 1;
side = OUTSIDE;
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"sphere") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix indent command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix indent command");
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
int n = strlen(&arg[iarg+1][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[iarg+1][2]);
} else xvalue = atof(arg[iarg+1]);
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[iarg+2][2]);
} else yvalue = atof(arg[iarg+2]);
if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) {
int n = strlen(&arg[iarg+3][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[iarg+3][2]);
} else zvalue = atof(arg[iarg+3]);
if (strstr(arg[iarg+4],"v_") == arg[iarg+4]) {
int n = strlen(&arg[iarg+4][2]) + 1;
rstr = new char[n];
strcpy(rstr,&arg[iarg+4][2]);
} else rvalue = atof(arg[iarg+4]);
istyle = SPHERE;
iarg += 5;
} else if (strcmp(arg[iarg],"cylinder") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix indent command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix indent command");
if (strcmp(arg[iarg+1],"x") == 0) {
cdim = 0;
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[iarg+2][2]);
} else yvalue = atof(arg[iarg+2]);
if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) {
int n = strlen(&arg[iarg+3][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[iarg+3][2]);
} else zvalue = atof(arg[iarg+3]);
} else if (strcmp(arg[iarg+1],"y") == 0) {
cdim = 1;
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[iarg+2][2]);
} else xvalue = atof(arg[iarg+2]);
if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) {
int n = strlen(&arg[iarg+3][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[iarg+3][2]);
} else zvalue = atof(arg[iarg+3]);
} else if (strcmp(arg[iarg+1],"z") == 0) {
cdim = 2;
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[iarg+2][2]);
} else xvalue = atof(arg[iarg+2]);
if (strstr(arg[iarg+3],"v_") == arg[iarg+3]) {
int n = strlen(&arg[iarg+3][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[iarg+3][2]);
} else yvalue = atof(arg[iarg+3]);
- } else error->all("Illegal fix indent command");
+ } else error->all(FLERR,"Illegal fix indent command");
if (strstr(arg[iarg+4],"v_") == arg[iarg+4]) {
int n = strlen(&arg[iarg+4][2]) + 1;
rstr = new char[n];
strcpy(rstr,&arg[iarg+4][2]);
} else rvalue = atof(arg[iarg+4]);
istyle = CYLINDER;
iarg += 5;
} else if (strcmp(arg[iarg],"plane") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix indent command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix indent command");
if (strcmp(arg[iarg+1],"x") == 0) cdim = 0;
else if (strcmp(arg[iarg+1],"y") == 0) cdim = 1;
else if (strcmp(arg[iarg+1],"z") == 0) cdim = 2;
- else error->all("Illegal fix indent command");
+ else error->all(FLERR,"Illegal fix indent command");
if (strstr(arg[iarg+2],"v_") == arg[iarg+2]) {
int n = strlen(&arg[iarg+2][2]) + 1;
pstr = new char[n];
strcpy(pstr,&arg[iarg+2][2]);
} else pvalue = atof(arg[iarg+2]);
if (strcmp(arg[iarg+3],"lo") == 0) planeside = -1;
else if (strcmp(arg[iarg+3],"hi") == 0) planeside = 1;
- else error->all("Illegal fix indent command");
+ else error->all(FLERR,"Illegal fix indent command");
istyle = PLANE;
iarg += 4;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix indent command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix indent command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix indent command");
+ else error->all(FLERR,"Illegal fix indent command");
iarg += 2;
} else if (strcmp(arg[iarg],"side") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix indent command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix indent command");
if (strcmp(arg[iarg+1],"in") == 0) side = INSIDE;
else if (strcmp(arg[iarg+1],"out") == 0) side = OUTSIDE;
- else error->all("Illegal fix indent command");
+ else error->all(FLERR,"Illegal fix indent command");
iarg += 2;
- } else error->all("Illegal fix indent command");
+ } else error->all(FLERR,"Illegal fix indent command");
}
}
diff --git a/src/fix_langevin.cpp b/src/fix_langevin.cpp
index e88792899..d7683d7de 100644
--- a/src/fix_langevin.cpp
+++ b/src/fix_langevin.cpp
@@ -1,715 +1,715 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Carolyn Phillips (U Mich), reservoir energy tally
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_langevin.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "domain.h"
#include "region.h"
#include "respa.h"
#include "comm.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
#include "group.h"
using namespace LAMMPS_NS;
enum{NOBIAS,BIAS};
#define SINERTIA 0.4 // moment of inertia prefactor for sphere
#define EINERTIA 0.2 // moment of inertia prefactor for ellipsoid
/* ---------------------------------------------------------------------- */
FixLangevin::FixLangevin(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal fix langevin command");
+ if (narg < 7) error->all(FLERR,"Illegal fix langevin command");
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
nevery = 1;
t_start = atof(arg[3]);
t_stop = atof(arg[4]);
t_period = atof(arg[5]);
int seed = atoi(arg[6]);
- if (t_period <= 0.0) error->all("Fix langevin period must be > 0.0");
- if (seed <= 0) error->all("Illegal fix langevin command");
+ if (t_period <= 0.0) error->all(FLERR,"Fix langevin period must be > 0.0");
+ if (seed <= 0) error->all(FLERR,"Illegal fix langevin command");
// initialize Marsaglia RNG with processor-unique seed
random = new RanMars(lmp,seed + comm->me);
// allocate per-type arrays for force prefactors
gfactor1 = new double[atom->ntypes+1];
gfactor2 = new double[atom->ntypes+1];
ratio = new double[atom->ntypes+1];
// optional args
for (int i = 1; i <= atom->ntypes; i++) ratio[i] = 1.0;
oflag = aflag = 0;
tally = 0;
zeroflag = 0;
int iarg = 7;
while (iarg < narg) {
if (strcmp(arg[iarg],"angmom") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix langevin command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin command");
if (strcmp(arg[iarg+1],"no") == 0) aflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) aflag = 1;
- else error->all("Illegal fix langevin command");
+ else error->all(FLERR,"Illegal fix langevin command");
iarg += 2;
} else if (strcmp(arg[iarg],"omega") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix langevin command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin command");
if (strcmp(arg[iarg+1],"no") == 0) oflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) oflag = 1;
- else error->all("Illegal fix langevin command");
+ else error->all(FLERR,"Illegal fix langevin command");
iarg += 2;
} else if (strcmp(arg[iarg],"scale") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix langevin command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix langevin command");
int itype = atoi(arg[iarg+1]);
double scale = atof(arg[iarg+2]);
if (itype <= 0 || itype > atom->ntypes)
- error->all("Illegal fix langevin command");
+ error->all(FLERR,"Illegal fix langevin command");
ratio[itype] = scale;
iarg += 3;
} else if (strcmp(arg[iarg],"tally") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix langevin command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin command");
if (strcmp(arg[iarg+1],"no") == 0) tally = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) tally = 1;
- else error->all("Illegal fix langevin command");
+ else error->all(FLERR,"Illegal fix langevin command");
iarg += 2;
} else if (strcmp(arg[iarg],"zero") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix langevin command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix langevin command");
if (strcmp(arg[iarg+1],"no") == 0) zeroflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) zeroflag = 1;
- else error->all("Illegal fix langevin command");
+ else error->all(FLERR,"Illegal fix langevin command");
iarg += 2;
- } else error->all("Illegal fix langevin command");
+ } else error->all(FLERR,"Illegal fix langevin command");
}
// error check
if (aflag) {
avec = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
if (!avec)
- error->all("Fix langevin angmom requires atom style ellipsoid");
+ error->all(FLERR,"Fix langevin angmom requires atom style ellipsoid");
}
// set temperature = NULL, user can override via fix_modify if wants bias
id_temp = NULL;
temperature = NULL;
// flangevin is unallocated until first call to setup()
// compute_scalar checks for this and returns 0.0 if flangevin is NULL
flangevin = NULL;
nmax = 0;
energy = 0.0;
}
/* ---------------------------------------------------------------------- */
FixLangevin::~FixLangevin()
{
delete random;
delete [] gfactor1;
delete [] gfactor2;
delete [] ratio;
delete [] id_temp;
memory->destroy(flangevin);
}
/* ---------------------------------------------------------------------- */
int FixLangevin::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= END_OF_STEP;
mask |= THERMO_ENERGY;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixLangevin::init()
{
if (oflag && !atom->sphere_flag)
- error->all("Fix langevin omega require atom style sphere");
+ error->all(FLERR,"Fix langevin omega require atom style sphere");
if (aflag && !atom->ellipsoid_flag)
- error->all("Fix langevin angmom require atom style ellipsoid");
+ error->all(FLERR,"Fix langevin angmom require atom style ellipsoid");
// if oflag or aflag set, check that all group particles are finite-size
if (oflag) {
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (radius[i] == 0.0)
- error->one("Fix langevin omega requires extended particles");
+ error->one(FLERR,"Fix langevin omega requires extended particles");
}
if (aflag) {
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (ellipsoid[i] < 0)
- error->one("Fix langevin angmom requires extended particles");
+ error->one(FLERR,"Fix langevin angmom requires extended particles");
}
// set force prefactors
if (!atom->rmass) {
for (int i = 1; i <= atom->ntypes; i++) {
gfactor1[i] = -atom->mass[i] / t_period / force->ftm2v;
gfactor2[i] = sqrt(atom->mass[i]) *
sqrt(24.0*force->boltz/t_period/update->dt/force->mvv2e) /
force->ftm2v;
gfactor1[i] *= 1.0/ratio[i];
gfactor2[i] *= 1.0/sqrt(ratio[i]);
}
}
if (temperature && temperature->tempbias) which = BIAS;
else which = NOBIAS;
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixLangevin::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixLangevin::post_force(int vflag)
{
if (tally) post_force_tally();
else post_force_no_tally();
}
/* ---------------------------------------------------------------------- */
void FixLangevin::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixLangevin::post_force_no_tally()
{
double gamma1,gamma2;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
double tsqrt = sqrt(t_target);
// apply damping and thermostat to atoms in group
// for BIAS:
// calculate temperature since some computes require temp
// computed on current nlocal atoms to remove bias
// test v = 0 since some computes mask non-participating atoms via v = 0
// and added force has extra term not multiplied by v = 0
// for ZEROFLAG:
// sum random force over all atoms in group
// subtract sum/count from each atom in group
double fran[3],fsum[3],fsumall[3];
fsum[0] = fsum[1] = fsum[2] = 0.0;
bigint count;
double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;
if (zeroflag) {
count = group->count(igroup);
if (count == 0)
- error->all("Cannot zero Langevin force of 0 atoms");
+ error->all(FLERR,"Cannot zero Langevin force of 0 atoms");
}
if (rmass) {
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = -rmass[i] / t_period / ftm2v;
gamma2 = sqrt(rmass[i]) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
fran[0] = gamma2*(random->uniform()-0.5);
fran[1] = gamma2*(random->uniform()-0.5);
fran[2] = gamma2*(random->uniform()-0.5);
f[i][0] += gamma1*v[i][0] + fran[0];
f[i][1] += gamma1*v[i][1] + fran[1];
f[i][2] += gamma1*v[i][2] + fran[2];
fsum[0] += fran[0];
fsum[1] += fran[1];
fsum[2] += fran[2];
}
}
} else if (which == BIAS) {
temperature->compute_scalar();
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = -rmass[i] / t_period / ftm2v;
gamma2 = sqrt(rmass[i]) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
temperature->remove_bias(i,v[i]);
fran[0] = gamma2*(random->uniform()-0.5);
fran[1] = gamma2*(random->uniform()-0.5);
fran[2] = gamma2*(random->uniform()-0.5);
if (v[i][0] != 0.0)
f[i][0] += gamma1*v[i][0] + fran[0];
if (v[i][1] != 0.0)
f[i][1] += gamma1*v[i][1] + fran[1];
if (v[i][2] != 0.0)
f[i][2] += gamma1*v[i][2] + fran[2];
fsum[0] += fran[0];
fsum[1] += fran[1];
fsum[2] += fran[2];
temperature->restore_bias(i,v[i]);
}
}
}
} else {
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = gfactor1[type[i]];
gamma2 = gfactor2[type[i]] * tsqrt;
fran[0] = gamma2*(random->uniform()-0.5);
fran[1] = gamma2*(random->uniform()-0.5);
fran[2] = gamma2*(random->uniform()-0.5);
f[i][0] += gamma1*v[i][0] + fran[0];
f[i][1] += gamma1*v[i][1] + fran[1];
f[i][2] += gamma1*v[i][2] + fran[2];
fsum[0] += fran[0];
fsum[1] += fran[1];
fsum[2] += fran[2];
}
}
} else if (which == BIAS) {
temperature->compute_scalar();
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = gfactor1[type[i]];
gamma2 = gfactor2[type[i]] * tsqrt;
temperature->remove_bias(i,v[i]);
fran[0] = gamma2*(random->uniform()-0.5);
fran[1] = gamma2*(random->uniform()-0.5);
fran[2] = gamma2*(random->uniform()-0.5);
if (v[i][0] != 0.0)
f[i][0] += gamma1*v[i][0] + fran[0];
if (v[i][1] != 0.0)
f[i][1] += gamma1*v[i][1] + fran[1];
if (v[i][2] != 0.0)
f[i][2] += gamma1*v[i][2] + fran[2];
fsum[0] += fran[0];
fsum[1] += fran[1];
fsum[2] += fran[2];
temperature->restore_bias(i,v[i]);
}
}
}
}
// set total force to zero
if (zeroflag) {
MPI_Allreduce(fsum,fsumall,3,MPI_DOUBLE,MPI_SUM,world);
fsumall[0] /= count;
fsumall[1] /= count;
fsumall[2] /= count;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
f[i][0] -= fsumall[0];
f[i][1] -= fsumall[1];
f[i][2] -= fsumall[2];
}
}
}
// thermostat omega and angmom
if (oflag) omega_thermostat(tsqrt);
if (aflag) angmom_thermostat(tsqrt);
}
/* ---------------------------------------------------------------------- */
void FixLangevin::post_force_tally()
{
double gamma1,gamma2;
// reallocate flangevin if necessary
if (atom->nmax > nmax) {
memory->destroy(flangevin);
nmax = atom->nmax;
memory->create(flangevin,nmax,3,"langevin:flangevin");
}
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
double tsqrt = sqrt(t_target);
// apply damping and thermostat to appropriate atoms
// for BIAS:
// calculate temperature since some computes require temp
// computed on current nlocal atoms to remove bias
// test v = 0 since some computes mask non-participating atoms via v = 0
// and added force has extra term not multiplied by v = 0
double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;
if (rmass) {
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = -rmass[i] / t_period / ftm2v;
gamma2 = sqrt(rmass[i]) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
flangevin[i][0] = gamma1*v[i][0] + gamma2*(random->uniform()-0.5);
flangevin[i][1] = gamma1*v[i][1] + gamma2*(random->uniform()-0.5);
flangevin[i][2] = gamma1*v[i][2] + gamma2*(random->uniform()-0.5);
f[i][0] += flangevin[i][0];
f[i][1] += flangevin[i][1];
f[i][2] += flangevin[i][2];
}
}
} else if (which == BIAS) {
temperature->compute_scalar();
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = -rmass[i] / t_period / ftm2v;
gamma2 = sqrt(rmass[i]) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
temperature->remove_bias(i,v[i]);
flangevin[i][0] = gamma1*v[i][0] + gamma2*(random->uniform()-0.5);
flangevin[i][1] = gamma1*v[i][1] + gamma2*(random->uniform()-0.5);
flangevin[i][2] = gamma1*v[i][2] + gamma2*(random->uniform()-0.5);
if (v[i][0] != 0.0) f[i][0] += flangevin[i][0];
else flangevin[i][0] = 0;
if (v[i][1] != 0.0) f[i][1] += flangevin[i][1];
else flangevin[i][1] = 0;
if (v[i][2] != 0.0) f[i][2] += flangevin[i][2];
else flangevin[i][2] = 0;
temperature->restore_bias(i,v[i]);
}
}
}
} else {
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = gfactor1[type[i]];
gamma2 = gfactor2[type[i]] * tsqrt;
flangevin[i][0] = gamma1*v[i][0] + gamma2*(random->uniform()-0.5);
flangevin[i][1] = gamma1*v[i][1] + gamma2*(random->uniform()-0.5);
flangevin[i][2] = gamma1*v[i][2] + gamma2*(random->uniform()-0.5);
f[i][0] += flangevin[i][0];
f[i][1] += flangevin[i][1];
f[i][2] += flangevin[i][2];
}
}
} else if (which == BIAS) {
temperature->compute_scalar();
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
gamma1 = gfactor1[type[i]];
gamma2 = gfactor2[type[i]] * tsqrt;
temperature->remove_bias(i,v[i]);
flangevin[i][0] = gamma1*v[i][0] + gamma2*(random->uniform()-0.5);
flangevin[i][1] = gamma1*v[i][1] + gamma2*(random->uniform()-0.5);
flangevin[i][2] = gamma1*v[i][2] + gamma2*(random->uniform()-0.5);
if (v[i][0] != 0.0) f[i][0] += flangevin[i][0];
else flangevin[i][0] = 0.0;
if (v[i][1] != 0.0) f[i][1] += flangevin[i][1];
else flangevin[i][1] = 0.0;
if (v[i][2] != 0.0) f[i][2] += flangevin[i][2];
else flangevin[i][2] = 0.0;
temperature->restore_bias(i,v[i]);
}
}
}
}
// thermostat omega and angmom
if (oflag) omega_thermostat(tsqrt);
if (aflag) angmom_thermostat(tsqrt);
}
/* ----------------------------------------------------------------------
thermostat rotational dof via omega
------------------------------------------------------------------------- */
void FixLangevin::omega_thermostat(double tsqrt)
{
double gamma1,gamma2;
double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;
double **torque = atom->torque;
double **omega = atom->omega;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double tran[3];
double inertiaone;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
inertiaone = SINERTIA*radius[i]*radius[i]*rmass[i];
gamma1 = -inertiaone / t_period / ftm2v;
gamma2 = sqrt(inertiaone) * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
tran[0] = gamma2*(random->uniform()-0.5);
tran[1] = gamma2*(random->uniform()-0.5);
tran[2] = gamma2*(random->uniform()-0.5);
torque[i][0] += gamma1*omega[i][0] + tran[0];
torque[i][1] += gamma1*omega[i][1] + tran[1];
torque[i][2] += gamma1*omega[i][2] + tran[2];
}
}
}
/* ----------------------------------------------------------------------
thermostat rotational dof via angmom
------------------------------------------------------------------------- */
void FixLangevin::angmom_thermostat(double tsqrt)
{
double gamma1,gamma2;
double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;
AtomVecEllipsoid::Bonus *bonus = avec->bonus;
double **torque = atom->torque;
double **angmom = atom->angmom;
double *rmass = atom->rmass;
int *ellipsoid = atom->ellipsoid;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double inertia[3],omega[3],tran[3];
double *shape,*quat;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
shape = bonus[ellipsoid[i]].shape;
inertia[0] = EINERTIA*rmass[i] * (shape[1]*shape[1]+shape[2]*shape[2]);
inertia[1] = EINERTIA*rmass[i] * (shape[0]*shape[0]+shape[2]*shape[2]);
inertia[2] = EINERTIA*rmass[i] * (shape[0]*shape[0]+shape[1]*shape[1]);
quat = bonus[ellipsoid[i]].quat;
MathExtra::mq_to_omega(angmom[i],quat,inertia,omega);
gamma1 = -1.0 / t_period / ftm2v;
gamma2 = sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
gamma1 *= 1.0/ratio[type[i]];
gamma2 *= 1.0/sqrt(ratio[type[i]]) * tsqrt;
tran[0] = sqrt(inertia[0])*gamma2*(random->uniform()-0.5);
tran[1] = sqrt(inertia[1])*gamma2*(random->uniform()-0.5);
tran[2] = sqrt(inertia[2])*gamma2*(random->uniform()-0.5);
torque[i][0] += inertia[0]*gamma1*omega[0] + tran[0];
torque[i][1] += inertia[1]*gamma1*omega[1] + tran[1];
torque[i][2] += inertia[2]*gamma1*omega[2] + tran[2];
}
}
}
/* ----------------------------------------------------------------------
tally energy transfer to thermal reservoir
------------------------------------------------------------------------- */
void FixLangevin::end_of_step()
{
if (!tally) return;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
energy_onestep = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
energy_onestep += flangevin[i][0]*v[i][0] + flangevin[i][1]*v[i][1] +
flangevin[i][2]*v[i][2];
energy += energy_onestep*update->dt;
}
/* ---------------------------------------------------------------------- */
void FixLangevin::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
void FixLangevin::reset_dt()
{
if (atom->mass) {
for (int i = 1; i <= atom->ntypes; i++) {
gfactor2[i] = sqrt(atom->mass[i]) *
sqrt(24.0*force->boltz/t_period/update->dt/force->mvv2e) /
force->ftm2v;
gfactor2[i] *= 1.0/sqrt(ratio[i]);
}
}
}
/* ---------------------------------------------------------------------- */
int FixLangevin::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
double FixLangevin::compute_scalar()
{
if (!tally || flangevin == NULL) return 0.0;
// capture the very first energy transfer to thermal reservoir
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (update->ntimestep == update->beginstep) {
energy_onestep = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
energy_onestep += flangevin[i][0]*v[i][0] + flangevin[i][1]*v[i][1] +
flangevin[i][2]*v[i][2];
energy = 0.5*energy_onestep*update->dt;
}
double energy_me = energy - 0.5*energy_onestep*update->dt;
double energy_all;
MPI_Allreduce(&energy_me,&energy_all,1,MPI_DOUBLE,MPI_SUM,world);
return -energy_all;
}
/* ----------------------------------------------------------------------
memory usage of tally array
------------------------------------------------------------------------- */
double FixLangevin::memory_usage()
{
if (!tally) return 0.0;
double bytes = atom->nmax*3 * sizeof(double);
return bytes;
}
diff --git a/src/fix_lineforce.cpp b/src/fix_lineforce.cpp
index 9f3f6b241..f56c28146 100644
--- a/src/fix_lineforce.cpp
+++ b/src/fix_lineforce.cpp
@@ -1,107 +1,107 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_lineforce.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixLineForce::FixLineForce(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal fix lineforce command");
+ if (narg != 6) error->all(FLERR,"Illegal fix lineforce command");
xdir = atof(arg[3]);
ydir = atof(arg[4]);
zdir = atof(arg[5]);
double len = sqrt(xdir*xdir + ydir*ydir + zdir*zdir);
- if (len == 0.0) error->all("Illegal fix lineforce command");
+ if (len == 0.0) error->all(FLERR,"Illegal fix lineforce command");
xdir /= len;
ydir /= len;
zdir /= len;
}
/* ---------------------------------------------------------------------- */
int FixLineForce::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixLineForce::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
int nlevels_respa = ((Respa *) update->integrate)->nlevels;
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
}
}
/* ---------------------------------------------------------------------- */
void FixLineForce::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixLineForce::post_force(int vflag)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double dot;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dot = f[i][0]*xdir + f[i][1]*ydir + f[i][2]*zdir;
f[i][0] = dot * xdir;
f[i][1] = dot * ydir;
f[i][2] = dot * zdir;
}
}
/* ---------------------------------------------------------------------- */
void FixLineForce::post_force_respa(int vflag, int ilevel, int iloop)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixLineForce::min_post_force(int vflag)
{
post_force(vflag);
}
diff --git a/src/fix_momentum.cpp b/src/fix_momentum.cpp
index 400f394c9..8fb7f3ae0 100644
--- a/src/fix_momentum.cpp
+++ b/src/fix_momentum.cpp
@@ -1,142 +1,142 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_momentum.h"
#include "atom.h"
#include "domain.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
Contributing author: Naveen Michaud-Agrawal (Johns Hopkins U)
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
FixMomentum::FixMomentum(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix momentum command");
+ if (narg < 4) error->all(FLERR,"Illegal fix momentum command");
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix momentum command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix momentum command");
linear = angular = 0;
int iarg = 4;
while (iarg < narg) {
if (strcmp(arg[iarg],"linear") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix momentum command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix momentum command");
linear = 1;
xflag = atoi(arg[iarg+1]);
yflag = atoi(arg[iarg+2]);
zflag = atoi(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"angular") == 0) {
angular = 1;
iarg += 1;
- } else error->all("Illegal fix momentum command");
+ } else error->all(FLERR,"Illegal fix momentum command");
}
if (linear == 0 && angular == 0)
- error->all("Illegal fix momentum command");
+ error->all(FLERR,"Illegal fix momentum command");
if (linear)
if (xflag < 0 || xflag > 1 || yflag < 0 || yflag > 1 ||
- zflag < 0 || zflag > 1) error->all("Illegal fix momentum command");
+ zflag < 0 || zflag > 1) error->all(FLERR,"Illegal fix momentum command");
// cannot have 0 atoms in group
if (group->count(igroup) == 0)
- error->all("Fix momentum group has no atoms");
+ error->all(FLERR,"Fix momentum group has no atoms");
}
/* ---------------------------------------------------------------------- */
int FixMomentum::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixMomentum::init()
{
masstotal = group->mass(igroup);
}
/* ---------------------------------------------------------------------- */
void FixMomentum::end_of_step()
{
if (linear) {
double vcm[3];
group->vcm(igroup,masstotal,vcm);
// adjust velocities by vcm to zero linear momentum
// only adjust a component if flag is set
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (xflag) v[i][0] -= vcm[0];
if (yflag) v[i][1] -= vcm[1];
if (zflag) v[i][2] -= vcm[2];
}
}
if (angular) {
double xcm[3],angmom[3],inertia[3][3],omega[3];
group->xcm(igroup,masstotal,xcm);
group->angmom(igroup,xcm,angmom);
group->inertia(igroup,xcm,inertia);
group->omega(angmom,inertia,omega);
// adjust velocities to zero omega
// vnew_i = v_i - w x r_i
// must use unwrapped coords to compute r_i correctly
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - xcm[0];
dy = (x[i][1] + ybox*yprd) - xcm[1];
dz = (x[i][2] + zbox*zprd) - xcm[2];
v[i][0] -= omega[1]*dz - omega[2]*dy;
v[i][1] -= omega[2]*dx - omega[0]*dz;
v[i][2] -= omega[0]*dy - omega[1]*dx;
}
}
}
diff --git a/src/fix_move.cpp b/src/fix_move.cpp
index bb886f8ec..afd087772 100644
--- a/src/fix_move.cpp
+++ b/src/fix_move.cpp
@@ -1,1009 +1,1009 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_move.h"
#include "atom.h"
#include "group.h"
#include "update.h"
#include "modify.h"
#include "force.h"
#include "domain.h"
#include "lattice.h"
#include "comm.h"
#include "respa.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{LINEAR,WIGGLE,ROTATE,VARIABLE};
enum{EQUAL,ATOM};
/* ---------------------------------------------------------------------- */
FixMove::FixMove(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix move command");
+ if (narg < 4) error->all(FLERR,"Illegal fix move command");
restart_global = 1;
restart_peratom = 1;
peratom_flag = 1;
size_peratom_cols = 3;
peratom_freq = 1;
time_integrate = 1;
time_depend = 1;
create_attribute = 1;
// parse args
int iarg;
xvarstr = yvarstr = zvarstr = NULL;
vxvarstr = vyvarstr = vzvarstr = NULL;
if (strcmp(arg[3],"linear") == 0) {
- if (narg < 7) error->all("Illegal fix move command");
+ if (narg < 7) error->all(FLERR,"Illegal fix move command");
iarg = 7;
mstyle = LINEAR;
if (strcmp(arg[4],"NULL") == 0) vxflag = 0;
else {
vxflag = 1;
vx = atof(arg[4]);
}
if (strcmp(arg[5],"NULL") == 0) vyflag = 0;
else {
vyflag = 1;
vy = atof(arg[5]);
}
if (strcmp(arg[6],"NULL") == 0) vzflag = 0;
else {
vzflag = 1;
vz = atof(arg[6]);
}
} else if (strcmp(arg[3],"wiggle") == 0) {
- if (narg < 8) error->all("Illegal fix move command");
+ if (narg < 8) error->all(FLERR,"Illegal fix move command");
iarg = 8;
mstyle = WIGGLE;
if (strcmp(arg[4],"NULL") == 0) axflag = 0;
else {
axflag = 1;
ax = atof(arg[4]);
}
if (strcmp(arg[5],"NULL") == 0) ayflag = 0;
else {
ayflag = 1;
ay = atof(arg[5]);
}
if (strcmp(arg[6],"NULL") == 0) azflag = 0;
else {
azflag = 1;
az = atof(arg[6]);
}
period = atof(arg[7]);
} else if (strcmp(arg[3],"rotate") == 0) {
- if (narg < 11) error->all("Illegal fix move command");
+ if (narg < 11) error->all(FLERR,"Illegal fix move command");
iarg = 11;
mstyle = ROTATE;
point[0] = atof(arg[4]);
point[1] = atof(arg[5]);
point[2] = atof(arg[6]);
axis[0] = atof(arg[7]);
axis[1] = atof(arg[8]);
axis[2] = atof(arg[9]);
period = atof(arg[10]);
} else if (strcmp(arg[3],"variable") == 0) {
- if (narg < 10) error->all("Illegal fix move command");
+ if (narg < 10) error->all(FLERR,"Illegal fix move command");
iarg = 10;
mstyle = VARIABLE;
if (strcmp(arg[4],"NULL") == 0) xvarstr = NULL;
else if (strstr(arg[4],"v_") == arg[4]) {
int n = strlen(&arg[4][2]) + 1;
xvarstr = new char[n];
strcpy(xvarstr,&arg[4][2]);
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
if (strcmp(arg[5],"NULL") == 0) yvarstr = NULL;
else if (strstr(arg[5],"v_") == arg[5]) {
int n = strlen(&arg[5][2]) + 1;
yvarstr = new char[n];
strcpy(yvarstr,&arg[5][2]);
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
if (strcmp(arg[6],"NULL") == 0) zvarstr = NULL;
else if (strstr(arg[6],"v_") == arg[6]) {
int n = strlen(&arg[6][2]) + 1;
zvarstr = new char[n];
strcpy(zvarstr,&arg[6][2]);
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
if (strcmp(arg[7],"NULL") == 0) vxvarstr = NULL;
else if (strstr(arg[7],"v_") == arg[7]) {
int n = strlen(&arg[7][2]) + 1;
vxvarstr = new char[n];
strcpy(vxvarstr,&arg[7][2]);
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
if (strcmp(arg[8],"NULL") == 0) vyvarstr = NULL;
else if (strstr(arg[8],"v_") == arg[8]) {
int n = strlen(&arg[8][2]) + 1;
vyvarstr = new char[n];
strcpy(vyvarstr,&arg[8][2]);
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
if (strcmp(arg[9],"NULL") == 0) vzvarstr = NULL;
else if (strstr(arg[9],"v_") == arg[9]) {
int n = strlen(&arg[9][2]) + 1;
vzvarstr = new char[n];
strcpy(vzvarstr,&arg[9][2]);
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
// optional args
int scaleflag = 1;
while (iarg < narg) {
if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix move command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix move command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix move command");
+ else error->all(FLERR,"Illegal fix move command");
iarg += 2;
- } else error->all("Illegal fix move command");
+ } else error->all(FLERR,"Illegal fix move command");
}
// error checks and warnings
if (domain->dimension == 2) {
if (mstyle == LINEAR && vzflag && vz != 0.0)
- error->all("Fix move cannot set linear z motion for 2d problem");
+ error->all(FLERR,"Fix move cannot set linear z motion for 2d problem");
if (mstyle == WIGGLE && azflag && az != 0.0)
- error->all("Fix move cannot set wiggle z motion for 2d problem");
+ error->all(FLERR,"Fix move cannot set wiggle z motion for 2d problem");
if (mstyle == ROTATE && (axis[0] != 0.0 || axis[1] != 0.0))
- error->all("Fix move cannot rotate aroung non z-axis for 2d problem");
+ error->all(FLERR,"Fix move cannot rotate aroung non z-axis for 2d problem");
if (mstyle == VARIABLE && (zvarstr || vzvarstr))
- error->all("Fix move cannot define z or vz variable for 2d problem");
+ error->all(FLERR,"Fix move cannot define z or vz variable for 2d problem");
}
if (atom->angmom_flag && comm->me == 0)
- error->warning("Fix move does not update angular momentum");
+ error->warning(FLERR,"Fix move does not update angular momentum");
if (atom->ellipsoid_flag && comm->me == 0)
- error->warning("Fix move does not update quaternions");
+ error->warning(FLERR,"Fix move does not update quaternions");
// setup scaling and apply scaling factors to velocity & amplitude
if ((mstyle == LINEAR || mstyle == WIGGLE || mstyle == ROTATE) &&
scaleflag) {
if (domain->lattice == NULL)
- error->all("Use of fix move with undefined lattice");
+ error->all(FLERR,"Use of fix move with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
if (mstyle == LINEAR) {
if (vxflag) vx *= xscale;
if (vyflag) vy *= yscale;
if (vzflag) vz *= zscale;
} else if (mstyle == WIGGLE) {
if (axflag) ax *= xscale;
if (ayflag) ay *= yscale;
if (azflag) az *= zscale;
} else if (mstyle == ROTATE) {
point[0] *= xscale;
point[1] *= yscale;
point[2] *= zscale;
}
}
// set omega_rotate from period
if (mstyle == WIGGLE || mstyle == ROTATE) {
double PI = 4.0 * atan(1.0);
omega_rotate = 2.0*PI / period;
}
// runit = unit vector along rotation axis
if (mstyle == ROTATE) {
double len = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
if (len == 0.0)
- error->all("Fix move cannot have 0 length rotation vector");
+ error->all(FLERR,"Fix move cannot have 0 length rotation vector");
runit[0] = axis[0]/len;
runit[1] = axis[1]/len;
runit[2] = axis[2]/len;
}
// set omega_flag if particles store omega
omega_flag = atom->omega_flag;
// perform initial allocation of atom-based array
// register with Atom class
xoriginal = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
atom->add_callback(1);
maxatom = 0;
displace = velocity = NULL;
// xoriginal = initial unwrapped positions of atoms
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) domain->unmap(x[i],image[i],xoriginal[i]);
else xoriginal[i][0] = xoriginal[i][1] = xoriginal[i][2] = 0.0;
}
time_origin = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
FixMove::~FixMove()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
atom->delete_callback(id,1);
// delete locally stored arrays
memory->destroy(xoriginal);
memory->destroy(displace);
memory->destroy(velocity);
delete [] xvarstr;
delete [] yvarstr;
delete [] zvarstr;
delete [] vxvarstr;
delete [] vyvarstr;
delete [] vzvarstr;
}
/* ---------------------------------------------------------------------- */
int FixMove::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixMove::init()
{
dt = update->dt;
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
// set indices and style of all variables
if (mstyle == VARIABLE) {
if (xvarstr) {
xvar = input->variable->find(xvarstr);
- if (xvar < 0) error->all("Variable name for fix move does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for fix move does not exist");
if (input->variable->equalstyle(xvar)) xvarstyle = EQUAL;
else if (input->variable->atomstyle(xvar)) xvarstyle = ATOM;
- else error->all("Variable for fix move is invalid style");
+ else error->all(FLERR,"Variable for fix move is invalid style");
}
if (yvarstr) {
yvar = input->variable->find(yvarstr);
- if (yvar < 0) error->all("Variable name for fix move does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for fix move does not exist");
if (input->variable->equalstyle(yvar)) yvarstyle = EQUAL;
else if (input->variable->atomstyle(yvar)) yvarstyle = ATOM;
- else error->all("Variable for fix move is invalid style");
+ else error->all(FLERR,"Variable for fix move is invalid style");
}
if (zvarstr) {
zvar = input->variable->find(zvarstr);
- if (zvar < 0) error->all("Variable name for fix move does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for fix move does not exist");
if (input->variable->equalstyle(zvar)) zvarstyle = EQUAL;
else if (input->variable->atomstyle(zvar)) zvarstyle = ATOM;
- else error->all("Variable for fix move is invalid style");
+ else error->all(FLERR,"Variable for fix move is invalid style");
}
if (vxvarstr) {
vxvar = input->variable->find(vxvarstr);
- if (vxvar < 0) error->all("Variable name for fix move does not exist");
+ if (vxvar < 0) error->all(FLERR,"Variable name for fix move does not exist");
if (input->variable->equalstyle(vxvar)) vxvarstyle = EQUAL;
else if (input->variable->atomstyle(vxvar)) vxvarstyle = ATOM;
- else error->all("Variable for fix move is invalid style");
+ else error->all(FLERR,"Variable for fix move is invalid style");
}
if (vyvarstr) {
vyvar = input->variable->find(vyvarstr);
- if (vyvar < 0) error->all("Variable name for fix move does not exist");
+ if (vyvar < 0) error->all(FLERR,"Variable name for fix move does not exist");
if (input->variable->equalstyle(vyvar)) vyvarstyle = EQUAL;
else if (input->variable->atomstyle(vyvar)) vyvarstyle = ATOM;
- else error->all("Variable for fix move is invalid style");
+ else error->all(FLERR,"Variable for fix move is invalid style");
}
if (vzvarstr) {
vzvar = input->variable->find(vzvarstr);
- if (vzvar < 0) error->all("Variable name for fix move does not exist");
+ if (vzvar < 0) error->all(FLERR,"Variable name for fix move does not exist");
if (input->variable->equalstyle(vzvar)) vzvarstyle = EQUAL;
else if (input->variable->atomstyle(vzvar)) vzvarstyle = ATOM;
- else error->all("Variable for fix move is invalid style");
+ else error->all(FLERR,"Variable for fix move is invalid style");
}
displaceflag = velocityflag = 0;
if (xvarstr && xvarstyle == ATOM) displaceflag = 1;
if (yvarstr && yvarstyle == ATOM) displaceflag = 1;
if (zvarstr && zvarstyle == ATOM) displaceflag = 1;
if (vxvarstr && vxvarstyle == ATOM) velocityflag = 1;
if (vyvarstr && vyvarstyle == ATOM) velocityflag = 1;
if (vzvarstr && vzvarstyle == ATOM) velocityflag = 1;
}
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ----------------------------------------------------------------------
set x,v of particles
------------------------------------------------------------------------- */
void FixMove::initial_integrate(int vflag)
{
double dtfm;
double xold[3],a[3],b[3],c[3],d[3],disp[3];
double ddotr,dx,dy,dz;
double delta = (update->ntimestep - time_origin) * dt;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// for linear: X = X0 + V*dt
if (mstyle == LINEAR) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xold[0] = x[i][0];
xold[1] = x[i][1];
xold[2] = x[i][2];
if (vxflag) {
v[i][0] = vx;
x[i][0] = xoriginal[i][0] + vx*delta;
} else if (rmass) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
x[i][0] += dtv * v[i][0];
} else {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
x[i][0] += dtv * v[i][0];
}
if (vyflag) {
v[i][1] = vy;
x[i][1] = xoriginal[i][1] + vy*delta;
} else if (rmass) {
dtfm = dtf / rmass[i];
v[i][1] += dtfm * f[i][1];
x[i][1] += dtv * v[i][1];
} else {
dtfm = dtf / mass[type[i]];
v[i][1] += dtfm * f[i][1];
x[i][1] += dtv * v[i][1];
}
if (vzflag) {
v[i][2] = vz;
x[i][2] = xoriginal[i][2] + vz*delta;
} else if (rmass) {
dtfm = dtf / rmass[i];
v[i][2] += dtfm * f[i][2];
x[i][2] += dtv * v[i][2];
} else {
dtfm = dtf / mass[type[i]];
v[i][2] += dtfm * f[i][2];
x[i][2] += dtv * v[i][2];
}
domain->remap_near(x[i],xold);
}
}
// for wiggle: X = X0 + A sin(w*dt)
} else if (mstyle == WIGGLE) {
double arg = omega_rotate * delta;
double sine = sin(arg);
double cosine = cos(arg);
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xold[0] = x[i][0];
xold[1] = x[i][1];
xold[2] = x[i][2];
if (axflag) {
v[i][0] = ax*omega_rotate*cosine;
x[i][0] = xoriginal[i][0] + ax*sine;
} else if (rmass) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
x[i][0] += dtv * v[i][0];
} else {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
x[i][0] += dtv * v[i][0];
}
if (ayflag) {
v[i][1] = ay*omega_rotate*cosine;
x[i][1] = xoriginal[i][1] + ay*sine;
} else if (rmass) {
dtfm = dtf / rmass[i];
v[i][1] += dtfm * f[i][1];
x[i][1] += dtv * v[i][1];
} else {
dtfm = dtf / mass[type[i]];
v[i][1] += dtfm * f[i][1];
x[i][1] += dtv * v[i][1];
}
if (azflag) {
v[i][2] = az*omega_rotate*cosine;
x[i][2] = xoriginal[i][2] + az*sine;
} else if (rmass) {
dtfm = dtf / rmass[i];
v[i][2] += dtfm * f[i][2];
x[i][2] += dtv * v[i][2];
} else {
dtfm = dtf / mass[type[i]];
v[i][2] += dtfm * f[i][2];
x[i][2] += dtv * v[i][2];
}
domain->remap_near(x[i],xold);
}
}
// for rotate by right-hand rule around omega:
// P = point = vector = point of rotation
// R = vector = axis of rotation
// w = omega of rotation (from period)
// X0 = xoriginal = initial coord of atom
// R0 = runit = unit vector for R
// D = X0 - P = vector from P to X0
// C = (D dot R0) R0 = projection of atom coord onto R line
// A = D - C = vector from R line to X0
// B = R0 cross A = vector perp to A in plane of rotation
// A,B define plane of circular rotation around R line
// X = P + C + A cos(w*dt) + B sin(w*dt)
// V = w R0 cross (A cos(w*dt) + B sin(w*dt))
} else if (mstyle == ROTATE) {
double arg = omega_rotate * delta;
double sine = sin(arg);
double cosine = cos(arg);
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xold[0] = x[i][0];
xold[1] = x[i][1];
xold[2] = x[i][2];
d[0] = xoriginal[i][0] - point[0];
d[1] = xoriginal[i][1] - point[1];
d[2] = xoriginal[i][2] - point[2];
ddotr = d[0]*runit[0] + d[1]*runit[1] + d[2]*runit[2];
c[0] = ddotr*runit[0];
c[1] = ddotr*runit[1];
c[2] = ddotr*runit[2];
a[0] = d[0] - c[0];
a[1] = d[1] - c[1];
a[2] = d[2] - c[2];
b[0] = runit[1]*a[2] - runit[2]*a[1];
b[1] = runit[2]*a[0] - runit[0]*a[2];
b[2] = runit[0]*a[1] - runit[1]*a[0];
disp[0] = a[0]*cosine + b[0]*sine;
disp[1] = a[1]*cosine + b[1]*sine;
disp[2] = a[2]*cosine + b[2]*sine;
x[i][0] = point[0] + c[0] + disp[0];
x[i][1] = point[1] + c[1] + disp[1];
x[i][2] = point[2] + c[2] + disp[2];
v[i][0] = omega_rotate * (runit[1]*disp[2] - runit[2]*disp[1]);
v[i][1] = omega_rotate * (runit[2]*disp[0] - runit[0]*disp[2]);
v[i][2] = omega_rotate * (runit[0]*disp[1] - runit[1]*disp[0]);
if (omega_flag) {
omega[i][0] = omega_rotate*runit[0];
omega[i][1] = omega_rotate*runit[1];
omega[i][2] = omega_rotate*runit[2];
}
domain->remap_near(x[i],xold);
}
}
// for variable: compute x,v from variables
} else if (mstyle == VARIABLE) {
// reallocate displace and velocity arrays as necessary
if ((displaceflag || velocityflag) && nlocal > maxatom) {
maxatom = atom->nmax;
if (displaceflag) {
memory->destroy(displace);
memory->create(displace,maxatom,3,"move:displace");
}
if (velocityflag) {
memory->destroy(velocity);
memory->create(velocity,maxatom,3,"move:velocity");
}
}
// pre-compute variable values, wrap with clear/add
modify->clearstep_compute();
if (xvarstr) {
if (xvarstyle == EQUAL) dx = input->variable->compute_equal(xvar);
else if (displace)
input->variable->compute_atom(xvar,igroup,&displace[0][0],3,0);
}
if (yvarstr) {
if (yvarstyle == EQUAL) dy = input->variable->compute_equal(yvar);
else if (displace)
input->variable->compute_atom(yvar,igroup,&displace[0][1],3,0);
}
if (zvarstr) {
if (zvarstyle == EQUAL) dz = input->variable->compute_equal(zvar);
else if (displace)
input->variable->compute_atom(zvar,igroup,&displace[0][2],3,0);
}
if (vxvarstr) {
if (vxvarstyle == EQUAL) vx = input->variable->compute_equal(vxvar);
else if (velocity)
input->variable->compute_atom(vxvar,igroup,&velocity[0][0],3,0);
}
if (vyvarstr) {
if (vyvarstyle == EQUAL) vy = input->variable->compute_equal(vyvar);
else if (velocity)
input->variable->compute_atom(vyvar,igroup,&velocity[0][1],3,0);
}
if (vzvarstr) {
if (vzvarstyle == EQUAL) vz = input->variable->compute_equal(vzvar);
else if (velocity)
input->variable->compute_atom(vzvar,igroup,&velocity[0][2],3,0);
}
modify->addstep_compute(update->ntimestep + 1);
// update x,v
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xold[0] = x[i][0];
xold[1] = x[i][1];
xold[2] = x[i][2];
if (xvarstr && vxvarstr) {
if (vxvarstyle == EQUAL) v[i][0] = vx;
else v[i][0] = velocity[i][0];
if (xvarstyle == EQUAL) x[i][0] = xoriginal[i][0] + dx;
else x[i][0] = xoriginal[i][0] + displace[i][0];
} else if (xvarstr) {
if (xvarstyle == EQUAL) x[i][0] = xoriginal[i][0] + dx;
else x[i][0] = xoriginal[i][0] + displace[i][0];
} else if (vxvarstr) {
if (vxvarstyle == EQUAL) v[i][0] = vx;
else v[i][0] = velocity[i][0];
if (rmass) {
dtfm = dtf / rmass[i];
x[i][0] += dtv * v[i][0];
} else {
dtfm = dtf / mass[type[i]];
x[i][0] += dtv * v[i][0];
}
} else {
if (rmass) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
x[i][0] += dtv * v[i][0];
} else {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
x[i][0] += dtv * v[i][0];
}
}
if (yvarstr && vyvarstr) {
if (vyvarstyle == EQUAL) v[i][1] = vy;
else v[i][1] = velocity[i][1];
if (yvarstyle == EQUAL) x[i][1] = xoriginal[i][1] + dy;
else x[i][1] = xoriginal[i][1] + displace[i][1];
} else if (yvarstr) {
if (yvarstyle == EQUAL) x[i][1] = xoriginal[i][1] + dy;
else x[i][1] = xoriginal[i][1] + displace[i][1];
} else if (vyvarstr) {
if (vyvarstyle == EQUAL) v[i][1] = vy;
else v[i][1] = velocity[i][1];
if (rmass) {
dtfm = dtf / rmass[i];
x[i][1] += dtv * v[i][1];
} else {
dtfm = dtf / mass[type[i]];
x[i][1] += dtv * v[i][1];
}
} else {
if (rmass) {
dtfm = dtf / rmass[i];
v[i][1] += dtfm * f[i][1];
x[i][1] += dtv * v[i][1];
} else {
dtfm = dtf / mass[type[i]];
v[i][1] += dtfm * f[i][1];
x[i][1] += dtv * v[i][1];
}
}
if (zvarstr && vzvarstr) {
if (vzvarstyle == EQUAL) v[i][2] = vz;
else v[i][2] = velocity[i][2];
if (zvarstyle == EQUAL) x[i][2] = xoriginal[i][2] + dz;
else x[i][2] = xoriginal[i][2] + displace[i][2];
} else if (zvarstr) {
if (zvarstyle == EQUAL) x[i][2] = xoriginal[i][2] + dz;
else x[i][2] = xoriginal[i][2] + displace[i][2];
} else if (vzvarstr) {
if (vzvarstyle == EQUAL) v[i][2] = vz;
else v[i][2] = velocity[i][2];
if (rmass) {
dtfm = dtf / rmass[i];
x[i][2] += dtv * v[i][2];
} else {
dtfm = dtf / mass[type[i]];
x[i][2] += dtv * v[i][2];
}
} else {
if (rmass) {
dtfm = dtf / rmass[i];
v[i][2] += dtfm * f[i][2];
x[i][2] += dtv * v[i][2];
} else {
dtfm = dtf / mass[type[i]];
v[i][2] += dtfm * f[i][2];
x[i][2] += dtv * v[i][2];
}
}
domain->remap_near(x[i],xold);
}
}
}
}
/* ----------------------------------------------------------------------
final NVE of particles with NULL components
------------------------------------------------------------------------- */
void FixMove::final_integrate()
{
double dtfm;
int xflag = 1;
if (mstyle == LINEAR && vxflag) xflag = 0;
else if (mstyle == WIGGLE && axflag) xflag = 0;
else if (mstyle == ROTATE) xflag = 0;
else if (mstyle == VARIABLE && (xvarstr || vxvarstr)) xflag = 0;
int yflag = 1;
if (mstyle == LINEAR && vyflag) yflag = 0;
else if (mstyle == WIGGLE && ayflag) yflag = 0;
else if (mstyle == ROTATE) yflag = 0;
else if (mstyle == VARIABLE && (yvarstr || vyvarstr)) yflag = 0;
int zflag = 1;
if (mstyle == LINEAR && vzflag) zflag = 0;
else if (mstyle == WIGGLE && azflag) zflag = 0;
else if (mstyle == ROTATE) zflag = 0;
else if (mstyle == VARIABLE && (zvarstr || vzvarstr)) zflag = 0;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (xflag)
if (rmass) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
} else {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
}
if (yflag)
if (rmass) {
dtfm = dtf / rmass[i];
v[i][1] += dtfm * f[i][1];
} else {
dtfm = dtf / mass[type[i]];
v[i][1] += dtfm * f[i][1];
}
if (zflag)
if (rmass) {
dtfm = dtf / rmass[i];
v[i][2] += dtfm * f[i][2];
} else {
dtfm = dtf / mass[type[i]];
v[i][2] += dtfm * f[i][2];
}
}
}
}
/* ---------------------------------------------------------------------- */
void FixMove::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
// outermost level - update v and x
// all other levels - nothing
if (ilevel == nlevels_respa-1) initial_integrate(vflag);
}
/* ---------------------------------------------------------------------- */
void FixMove::final_integrate_respa(int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) final_integrate();
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixMove::memory_usage()
{
double bytes = atom->nmax*3 * sizeof(double);
if (displaceflag) bytes += atom->nmax*3 * sizeof(double);
if (velocityflag) bytes += atom->nmax*3 * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixMove::write_restart(FILE *fp)
{
int n = 0;
double list[1];
list[n++] = time_origin;
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),n,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixMove::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
time_origin = static_cast<int> (list[n++]);
}
/* ----------------------------------------------------------------------
allocate atom-based array
------------------------------------------------------------------------- */
void FixMove::grow_arrays(int nmax)
{
memory->grow(xoriginal,nmax,3,"move:xoriginal");
array_atom = xoriginal;
}
/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */
void FixMove::copy_arrays(int i, int j)
{
xoriginal[j][0] = xoriginal[i][0];
xoriginal[j][1] = xoriginal[i][1];
xoriginal[j][2] = xoriginal[i][2];
}
/* ----------------------------------------------------------------------
initialize one atom's array values, called when atom is created
------------------------------------------------------------------------- */
void FixMove::set_arrays(int i)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
// particle not in group
if (!(mask[i] & groupbit)) {
xoriginal[i][0] = xoriginal[i][1] = xoriginal[i][2] = 0.0;
return;
}
// current time still equal fix creation time
if (update->ntimestep == time_origin) {
domain->unmap(x[i],image[i],xoriginal[i]);
return;
}
// backup particle to time_origin
if (mstyle == VARIABLE)
- error->all("Cannot add atoms to fix move variable");
+ error->all(FLERR,"Cannot add atoms to fix move variable");
domain->unmap(x[i],image[i],xoriginal[i]);
double delta = (update->ntimestep - time_origin) * update->dt;
if (mstyle == LINEAR) {
if (vxflag) xoriginal[i][0] -= vx * delta;
if (vyflag) xoriginal[i][1] -= vy * delta;
if (vzflag) xoriginal[i][2] -= vz * delta;
} else if (mstyle == WIGGLE) {
double arg = omega_rotate * delta;
double sine = sin(arg);
if (axflag) xoriginal[i][0] -= ax*sine;
if (ayflag) xoriginal[i][1] -= ay*sine;
if (azflag) xoriginal[i][2] -= az*sine;
} else if (mstyle == ROTATE) {
double a[3],b[3],c[3],d[3],disp[3],ddotr;
double arg = - omega_rotate * delta;
double sine = sin(arg);
double cosine = cos(arg);
d[0] = x[i][0] - point[0];
d[1] = x[i][1] - point[1];
d[2] = x[i][2] - point[2];
ddotr = d[0]*runit[0] + d[1]*runit[1] + d[2]*runit[2];
c[0] = ddotr*runit[0];
c[1] = ddotr*runit[1];
c[2] = ddotr*runit[2];
a[0] = d[0] - c[0];
a[1] = d[1] - c[1];
a[2] = d[2] - c[2];
b[0] = runit[1]*a[2] - runit[2]*a[1];
b[1] = runit[2]*a[0] - runit[0]*a[2];
b[2] = runit[0]*a[1] - runit[1]*a[0];
disp[0] = a[0]*cosine + b[0]*sine;
disp[1] = a[1]*cosine + b[1]*sine;
disp[2] = a[2]*cosine + b[2]*sine;
xoriginal[i][0] = point[0] + c[0] + disp[0];
xoriginal[i][1] = point[1] + c[1] + disp[1];
xoriginal[i][2] = point[2] + c[2] + disp[2];
}
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixMove::pack_exchange(int i, double *buf)
{
buf[0] = xoriginal[i][0];
buf[1] = xoriginal[i][1];
buf[2] = xoriginal[i][2];
return 3;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixMove::unpack_exchange(int nlocal, double *buf)
{
xoriginal[nlocal][0] = buf[0];
xoriginal[nlocal][1] = buf[1];
xoriginal[nlocal][2] = buf[2];
return 3;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixMove::pack_restart(int i, double *buf)
{
buf[0] = 4;
buf[1] = xoriginal[i][0];
buf[2] = xoriginal[i][1];
buf[3] = xoriginal[i][2];
return 4;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixMove::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
xoriginal[nlocal][0] = extra[nlocal][m++];
xoriginal[nlocal][1] = extra[nlocal][m++];
xoriginal[nlocal][2] = extra[nlocal][m++];
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixMove::maxsize_restart()
{
return 4;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixMove::size_restart(int nlocal)
{
return 4;
}
/* ---------------------------------------------------------------------- */
void FixMove::reset_dt()
{
- error->all("Resetting timestep is not allowed with fix move");
+ error->all(FLERR,"Resetting timestep is not allowed with fix move");
}
diff --git a/src/fix_nh.cpp b/src/fix_nh.cpp
index 285489305..2bf3df8a8 100644
--- a/src/fix_nh.cpp
+++ b/src/fix_nh.cpp
@@ -1,2180 +1,2177 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Mark Stevens (SNL), Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_nh.h"
#include "math_extra.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "irregular.h"
#include "modify.h"
#include "fix_deform.h"
#include "compute.h"
#include "kspace.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTAFLIP 0.1
#define TILTMAX 1.5
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
enum{NOBIAS,BIAS};
enum{NONE,XYZ,XY,YZ,XZ};
enum{ISO,ANISO,TRICLINIC};
/* ----------------------------------------------------------------------
NVT,NPH,NPT integrators for improved Nose-Hoover equations of motion
---------------------------------------------------------------------- */
FixNH::FixNH(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix nvt/npt/nph command");
+ if (narg < 4) error->all(FLERR,"Illegal fix nvt/npt/nph command");
restart_global = 1;
time_integrate = 1;
scalar_flag = 1;
vector_flag = 1;
global_freq = 1;
extscalar = 1;
extvector = 0;
// default values
pcouple = NONE;
drag = 0.0;
allremap = 1;
mtchain = mpchain = 3;
nc_tchain = nc_pchain = 1;
mtk_flag = 1;
deviatoric_flag = 0;
nreset_h0 = 0;
eta_mass_flag = 1;
omega_mass_flag = 0;
etap_mass_flag = 0;
// turn on tilt factor scaling, whenever applicable
dimension = domain->dimension;
scaleyz = scalexz = scalexy = 0;
if (domain->yperiodic && domain->xy != 0.0) scalexy = 1;
if (domain->zperiodic && dimension == 3) {
if (domain->yz != 0.0) scaleyz = 1;
if (domain->xz != 0.0) scalexz = 1;
}
// Used by FixNVTSllod to preserve non-default value
mtchain_default_flag = 1;
tstat_flag = 0;
double t_period = 0.0;
double p_period[6];
for (int i = 0; i < 6; i++) {
p_start[i] = p_stop[i] = p_period[i] = p_target[i] = 0.0;
p_flag[i] = 0;
}
// process keywords
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
tstat_flag = 1;
t_start = atof(arg[iarg+1]);
t_stop = atof(arg[iarg+2]);
t_period = atof(arg[iarg+3]);
if (t_start < 0.0 || t_stop <= 0.0)
- error->all("Target temperature for fix nvt/npt/nph cannot be 0.0");
+ error->all(FLERR,"Target temperature for fix nvt/npt/nph cannot be 0.0");
iarg += 4;
} else if (strcmp(arg[iarg],"iso") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
pcouple = XYZ;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"aniso") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
pcouple = NONE;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"tri") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
pcouple = NONE;
scalexy = scalexz = scaleyz = 0;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
p_start[3] = p_start[4] = p_start[5] = 0.0;
p_stop[3] = p_stop[4] = p_stop[5] = 0.0;
p_period[3] = p_period[4] = p_period[5] = atof(arg[iarg+3]);
p_flag[3] = p_flag[4] = p_flag[5] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
p_start[3] = p_stop[3] = p_period[3] = 0.0;
p_flag[3] = 0;
p_start[4] = p_stop[4] = p_period[4] = 0.0;
p_flag[4] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"x") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[0] = atof(arg[iarg+1]);
p_stop[0] = atof(arg[iarg+2]);
p_period[0] = atof(arg[iarg+3]);
p_flag[0] = 1;
deviatoric_flag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"y") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[1] = atof(arg[iarg+1]);
p_stop[1] = atof(arg[iarg+2]);
p_period[1] = atof(arg[iarg+3]);
p_flag[1] = 1;
deviatoric_flag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"z") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[2] = atof(arg[iarg+1]);
p_stop[2] = atof(arg[iarg+2]);
p_period[2] = atof(arg[iarg+3]);
p_flag[2] = 1;
deviatoric_flag = 1;
iarg += 4;
if (dimension == 2)
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
} else if (strcmp(arg[iarg],"yz") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
scaleyz = 0;
p_start[3] = atof(arg[iarg+1]);
p_stop[3] = atof(arg[iarg+2]);
p_period[3] = atof(arg[iarg+3]);
p_flag[3] = 1;
deviatoric_flag = 1;
iarg += 4;
if (dimension == 2)
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
} else if (strcmp(arg[iarg],"xz") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
scalexz = 0;
p_start[4] = atof(arg[iarg+1]);
p_stop[4] = atof(arg[iarg+2]);
p_period[4] = atof(arg[iarg+3]);
p_flag[4] = 1;
deviatoric_flag = 1;
iarg += 4;
if (dimension == 2)
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
} else if (strcmp(arg[iarg],"xy") == 0) {
scalexy = 0;
- if (iarg+4 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
p_start[5] = atof(arg[iarg+1]);
p_stop[5] = atof(arg[iarg+2]);
p_period[5] = atof(arg[iarg+3]);
p_flag[5] = 1;
deviatoric_flag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"couple") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"xyz") == 0) pcouple = XYZ;
else if (strcmp(arg[iarg+1],"xy") == 0) pcouple = XY;
else if (strcmp(arg[iarg+1],"yz") == 0) pcouple = YZ;
else if (strcmp(arg[iarg+1],"xz") == 0) pcouple = XZ;
else if (strcmp(arg[iarg+1],"none") == 0) pcouple = NONE;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"drag") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
drag = atof(arg[iarg+1]);
- if (drag < 0.0) error->all("Illegal fix nvt/npt/nph command");
+ if (drag < 0.0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"dilate") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"all") == 0) allremap = 1;
else if (strcmp(arg[iarg+1],"partial") == 0) allremap = 0;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"tchain") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
mtchain = atoi(arg[iarg+1]);
// used by FixNVTSllod to preserve non-default value
mtchain_default_flag = 0;
- if (mtchain < 1) error->all("Illegal fix nvt/npt/nph command");
+ if (mtchain < 1) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"pchain") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
mpchain = atoi(arg[iarg+1]);
- if (mpchain < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (mpchain < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"mtk") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"yes") == 0) mtk_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) mtk_flag = 0;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"tloop") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
nc_tchain = atoi(arg[iarg+1]);
- if (nc_tchain < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (nc_tchain < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"ploop") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
nc_pchain = atoi(arg[iarg+1]);
- if (nc_pchain < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (nc_pchain < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"nreset") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
nreset_h0 = atoi(arg[iarg+1]);
- if (nreset_h0 < 0) error->all("Illegal fix nvt/npt/nph command");
+ if (nreset_h0 < 0) error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"scalexy") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"yes") == 0) scalexy = 1;
else if (strcmp(arg[iarg+1],"no") == 0) scalexy = 0;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"scalexz") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"yes") == 0) scalexz = 1;
else if (strcmp(arg[iarg+1],"no") == 0) scalexz = 0;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
} else if (strcmp(arg[iarg],"scaleyz") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nvt/npt/nph command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nvt/npt/nph command");
if (strcmp(arg[iarg+1],"yes") == 0) scaleyz = 1;
else if (strcmp(arg[iarg+1],"no") == 0) scaleyz = 0;
- else error->all("Illegal fix nvt/npt/nph command");
+ else error->all(FLERR,"Illegal fix nvt/npt/nph command");
iarg += 2;
- } else error->all("Illegal fix nvt/npt/nph command");
+ } else error->all(FLERR,"Illegal fix nvt/npt/nph command");
}
// error checks
if (dimension == 2 && (p_flag[2] || p_flag[3] || p_flag[4]))
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
if (dimension == 2 && (pcouple == YZ || pcouple == XZ))
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
if (dimension == 2 && (scalexz == 1 || scaleyz == 1 ))
- error->all("Invalid fix nvt/npt/nph command for a 2d simulation");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command for a 2d simulation");
if (pcouple == XYZ && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == XYZ && dimension == 3 && p_flag[2] == 0)
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == XY && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == YZ && (p_flag[1] == 0 || p_flag[2] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (pcouple == XZ && (p_flag[0] == 0 || p_flag[2] == 0))
- error->all("Invalid fix nvt/npt/nph command pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph command pressure settings");
if (p_flag[0] && domain->xperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a non-periodic dimension");
if (p_flag[1] && domain->yperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a non-periodic dimension");
if (p_flag[2] && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a non-periodic dimension");
if (p_flag[3] && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
if (p_flag[4] && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
if (p_flag[5] && domain->yperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
+ error->all(FLERR,"Cannot use fix nvt/npt/nph on a 2nd non-periodic dimension");
if (scaleyz == 1 && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph "
+ error->all(FLERR,"Cannot use fix nvt/npt/nph "
"with yz dynamics when z is non-periodic dimension");
if (scalexz == 1 && domain->zperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph "
+ error->all(FLERR,"Cannot use fix nvt/npt/nph "
"with xz dynamics when z is non-periodic dimension");
if (scalexy == 1 && domain->yperiodic == 0)
- error->all("Cannot use fix nvt/npt/nph "
+ error->all(FLERR,"Cannot use fix nvt/npt/nph "
"with xy dynamics when y is non-periodic dimension");
if (p_flag[3] && scaleyz == 1)
- error->all("Cannot use fix nvt/npt/nph with"
+ error->all(FLERR,"Cannot use fix nvt/npt/nph with"
"both yz dynamics and yz scaling");
if (p_flag[4] && scalexz == 1)
- error->all("Cannot use fix nvt/npt/nph with "
+ error->all(FLERR,"Cannot use fix nvt/npt/nph with "
"both xz dynamics and xz scaling");
if (p_flag[5] && scalexy == 1)
- error->all("Cannot use fix nvt/npt/nph with "
+ error->all(FLERR,"Cannot use fix nvt/npt/nph with "
"both xy dynamics and xy scaling");
if (!domain->triclinic && (p_flag[3] || p_flag[4] || p_flag[5]))
- error->all("Can not specify Pxy/Pxz/Pyz in "
+ error->all(FLERR,"Can not specify Pxy/Pxz/Pyz in "
"fix nvt/npt/nph with non-triclinic box");
if (pcouple == XYZ && dimension == 3 &&
(p_start[0] != p_start[1] || p_start[0] != p_start[2] ||
p_stop[0] != p_stop[1] || p_stop[0] != p_stop[2] ||
p_period[0] != p_period[1] || p_period[0] != p_period[2]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == XYZ && dimension == 2 &&
(p_start[0] != p_start[1] || p_stop[0] != p_stop[1] ||
p_period[0] != p_period[1]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == XY &&
(p_start[0] != p_start[1] || p_stop[0] != p_stop[1] ||
p_period[0] != p_period[1]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == YZ &&
(p_start[1] != p_start[2] || p_stop[1] != p_stop[2] ||
p_period[1] != p_period[2]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if (pcouple == XZ &&
(p_start[0] != p_start[2] || p_stop[0] != p_stop[2] ||
p_period[0] != p_period[2]))
- error->all("Invalid fix nvt/npt/nph pressure settings");
+ error->all(FLERR,"Invalid fix nvt/npt/nph pressure settings");
if ((tstat_flag && t_period <= 0.0) ||
(p_flag[0] && p_period[0] <= 0.0) ||
(p_flag[1] && p_period[1] <= 0.0) ||
(p_flag[2] && p_period[2] <= 0.0) ||
(p_flag[3] && p_period[3] <= 0.0) ||
(p_flag[4] && p_period[4] <= 0.0) ||
(p_flag[5] && p_period[5] <= 0.0))
- error->all("Fix nvt/npt/nph damping parameters must be > 0.0");
+ error->all(FLERR,"Fix nvt/npt/nph damping parameters must be > 0.0");
// set pstat_flag and box change and restart_pbc variables
pstat_flag = 0;
for (int i = 0; i < 6; i++)
if (p_flag[i]) pstat_flag = 1;
if (pstat_flag) {
box_change = 1;
if (p_flag[0] || p_flag[1] || p_flag[2]) box_change_size = 1;
if (p_flag[3] || p_flag[4] || p_flag[5]) box_change_shape = 1;
no_change_box = 1;
if (allremap == 0) restart_pbc = 1;
}
// pstyle = TRICLINIC if any off-diagonal term is controlled -> 6 dof
// else pstyle = ISO if XYZ coupling or XY coupling in 2d -> 1 dof
// else pstyle = ANISO -> 3 dof
if (p_flag[3] || p_flag[4] || p_flag[5]) pstyle = TRICLINIC;
else if (pcouple == XYZ || (dimension == 2 && pcouple == XY)) pstyle = ISO;
else pstyle = ANISO;
// reneighboring only forced if flips will occur due to shape changes
if (p_flag[3] || p_flag[4] || p_flag[5]) force_reneighbor = 1;
if (scaleyz || scalexz || scalexy) force_reneighbor = 1;
// convert input periods to frequencies
t_freq = 0.0;
p_freq[0] = p_freq[1] = p_freq[2] = p_freq[3] = p_freq[4] = p_freq[5] = 0.0;
if (tstat_flag) t_freq = 1.0 / t_period;
if (p_flag[0]) p_freq[0] = 1.0 / p_period[0];
if (p_flag[1]) p_freq[1] = 1.0 / p_period[1];
if (p_flag[2]) p_freq[2] = 1.0 / p_period[2];
if (p_flag[3]) p_freq[3] = 1.0 / p_period[3];
if (p_flag[4]) p_freq[4] = 1.0 / p_period[4];
if (p_flag[5]) p_freq[5] = 1.0 / p_period[5];
// Nose/Hoover temp and pressure init
size_vector = 0;
if (tstat_flag) {
int ich;
eta = new double[mtchain];
// add one extra dummy thermostat, set to zero
eta_dot = new double[mtchain+1];
eta_dot[mtchain] = 0.0;
eta_dotdot = new double[mtchain];
for (ich = 0; ich < mtchain; ich++) {
eta[ich] = eta_dot[ich] = eta_dotdot[ich] = 0.0;
}
eta_mass = new double[mtchain];
size_vector += 2*2*mtchain;
}
if (pstat_flag) {
omega[0] = omega[1] = omega[2] = 0.0;
omega_dot[0] = omega_dot[1] = omega_dot[2] = 0.0;
omega_mass[0] = omega_mass[1] = omega_mass[2] = 0.0;
omega[3] = omega[4] = omega[5] = 0.0;
omega_dot[3] = omega_dot[4] = omega_dot[5] = 0.0;
omega_mass[3] = omega_mass[4] = omega_mass[5] = 0.0;
if (pstyle == ISO) size_vector += 2*2*1;
else if (pstyle == ANISO) size_vector += 2*2*3;
else if (pstyle == TRICLINIC) size_vector += 2*2*6;
if (mpchain) {
int ich;
etap = new double[mpchain];
// add one extra dummy thermostat, set to zero
etap_dot = new double[mpchain+1];
etap_dot[mpchain] = 0.0;
etap_dotdot = new double[mpchain];
for (ich = 0; ich < mpchain; ich++) {
etap[ich] = etap_dot[ich] =
etap_dotdot[ich] = 0.0;
}
etap_mass = new double[mpchain];
size_vector += 2*2*mpchain;
}
if (deviatoric_flag) size_vector += 1;
}
nrigid = 0;
rfix = NULL;
if (force_reneighbor) irregular = new Irregular(lmp);
else irregular = NULL;
// initialize vol0,t0 to zero to signal uninitialized
// values then assigned in init(), if necessary
vol0 = t0 = 0.0;
}
/* ---------------------------------------------------------------------- */
FixNH::~FixNH()
{
delete [] rfix;
delete irregular;
// delete temperature and pressure if fix created them
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
if (tstat_flag) {
delete [] eta;
delete [] eta_dot;
delete [] eta_dotdot;
delete [] eta_mass;
}
if (pstat_flag) {
if (pflag) modify->delete_compute(id_press);
delete [] id_press;
if (mpchain) {
delete [] etap;
delete [] etap_dot;
delete [] etap_dotdot;
delete [] etap_mass;
}
}
}
/* ---------------------------------------------------------------------- */
int FixNH::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= THERMO_ENERGY;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
if (force_reneighbor) mask |= PRE_EXCHANGE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNH::init()
{
// ensure no conflict with fix deform
if (pstat_flag)
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
int *dimflag = ((FixDeform *) modify->fix[i])->dimflag;
if ((p_flag[0] && dimflag[0]) || (p_flag[1] && dimflag[1]) ||
(p_flag[2] && dimflag[2]) || (p_flag[3] && dimflag[3]) ||
(p_flag[4] && dimflag[4]) || (p_flag[5] && dimflag[5]))
- error->all("Cannot use fix npt and fix deform on "
+ error->all(FLERR,"Cannot use fix npt and fix deform on "
"same component of stress tensor");
}
// set temperature and pressure ptrs
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix nvt/nph/npt does not exist");
+ error->all(FLERR,"Temperature ID for fix nvt/nph/npt does not exist");
temperature = modify->compute[icompute];
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
if (pstat_flag) {
icompute = modify->find_compute(id_press);
- if (icompute < 0) error->all("Pressure ID for fix npt/nph does not exist");
+ if (icompute < 0) error->all(FLERR,"Pressure ID for fix npt/nph does not exist");
pressure = modify->compute[icompute];
}
// set timesteps and frequencies
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dthalf = 0.5 * update->dt;
dt4 = 0.25 * update->dt;
dt8 = 0.125 * update->dt;
dto = dthalf;
p_freq_max = 0.0;
if (pstat_flag) {
p_freq_max = MAX(p_freq[0],p_freq[1]);
p_freq_max = MAX(p_freq_max,p_freq[2]);
if (pstyle == TRICLINIC) {
p_freq_max = MAX(p_freq_max,p_freq[3]);
p_freq_max = MAX(p_freq_max,p_freq[4]);
p_freq_max = MAX(p_freq_max,p_freq[5]);
}
pdrag_factor = 1.0 - (update->dt * p_freq_max * drag / nc_pchain);
}
if (tstat_flag)
tdrag_factor = 1.0 - (update->dt * t_freq * drag / nc_tchain);
// tally the number of dimensions that are barostatted
// set initial volume and reference cell, if not already done
if (pstat_flag) {
pdim = p_flag[0] + p_flag[1] + p_flag[2];
if (vol0 == 0.0) {
if (dimension == 3) vol0 = domain->xprd * domain->yprd * domain->zprd;
else vol0 = domain->xprd * domain->yprd;
h0_inv[0] = domain->h_inv[0];
h0_inv[1] = domain->h_inv[1];
h0_inv[2] = domain->h_inv[2];
h0_inv[3] = domain->h_inv[3];
h0_inv[4] = domain->h_inv[4];
h0_inv[5] = domain->h_inv[5];
}
}
boltz = force->boltz;
nktv2p = force->nktv2p;
if (force->kspace) kspace_flag = 1;
else kspace_flag = 0;
if (strstr(update->integrate_style,"respa")) {
nlevels_respa = ((Respa *) update->integrate)->nlevels;
step_respa = ((Respa *) update->integrate)->step;
dto = 0.5*step_respa[0];
}
// detect if any rigid fixes exist so rigid bodies move when box is remapped
// rfix[] = indices to each fix rigid
delete [] rfix;
nrigid = 0;
rfix = NULL;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) nrigid++;
if (nrigid) {
rfix = new int[nrigid];
nrigid = 0;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) rfix[nrigid++] = i;
}
}
/* ----------------------------------------------------------------------
compute T,P before integrator starts
------------------------------------------------------------------------- */
void FixNH::setup(int vflag)
{
// initialize some quantities that were not available earlier
tdof = temperature->dof;
// t_target is needed by NPH and NPT in compute_scalar()
// If no thermostat or using fix nphug,
// t_target must be defined by other means.
if (tstat_flag && strcmp(style,"nphug") != 0) {
compute_temp_target();
} else if (pstat_flag) {
// t0 = reference temperature for masses
// cannot be done in init() b/c temperature cannot be called there
// is b/c Modify::init() inits computes after fixes due to dof dependence
// guesstimate a unit-dependent t0 if actual T = 0.0
// if it was read in from a restart file, leave it be
if (t0 == 0.0) {
t0 = temperature->compute_scalar();
if (t0 == 0.0) {
if (strcmp(update->unit_style,"lj") == 0) t0 = 1.0;
else t0 = 300.0;
}
}
t_target = t0;
}
if (pstat_flag) compute_press_target();
t_current = temperature->compute_scalar();
if (pstat_flag) {
if (pstyle == ISO) pressure->compute_scalar();
else pressure->compute_vector();
couple();
pressure->addstep(update->ntimestep+1);
}
// masses and initial forces on thermostat variables
if (tstat_flag) {
eta_mass[0] = tdof * boltz * t_target / (t_freq*t_freq);
for (int ich = 1; ich < mtchain; ich++)
eta_mass[ich] = boltz * t_target / (t_freq*t_freq);
for (int ich = 1; ich < mtchain; ich++) {
eta_dotdot[ich] = (eta_mass[ich-1]*eta_dot[ich-1]*eta_dot[ich-1] -
boltz * t_target) / eta_mass[ich];
}
}
// masses and initial forces on barostat variables
if (pstat_flag) {
double kt = boltz * t_target;
double nkt = atom->natoms * kt;
for (int i = 0; i < 3; i++)
if (p_flag[i])
omega_mass[i] = nkt/(p_freq[i]*p_freq[i]);
if (pstyle == TRICLINIC) {
for (int i = 3; i < 6; i++)
if (p_flag[i]) omega_mass[i] = nkt/(p_freq[i]*p_freq[i]);
}
// masses and initial forces on barostat thermostat variables
if (mpchain) {
etap_mass[0] = boltz * t_target / (p_freq_max*p_freq_max);
for (int ich = 1; ich < mpchain; ich++)
etap_mass[ich] = boltz * t_target / (p_freq_max*p_freq_max);
for (int ich = 1; ich < mpchain; ich++)
etap_dotdot[ich] =
(etap_mass[ich-1]*etap_dot[ich-1]*etap_dot[ich-1] -
boltz * t_target) / etap_mass[ich];
}
}
}
/* ----------------------------------------------------------------------
1st half of Verlet update
------------------------------------------------------------------------- */
void FixNH::initial_integrate(int vflag)
{
// update eta_press_dot
if (pstat_flag && mpchain) nhc_press_integrate();
// update eta_dot
if (tstat_flag) {
compute_temp_target();
nhc_temp_integrate();
}
// need to recompute pressure to account for change in KE
// t_current is up-to-date, but compute_temperature is not
// compute appropriately coupled elements of mvv_current
if (pstat_flag) {
if (pstyle == ISO) {
temperature->compute_scalar();
pressure->compute_scalar();
} else {
temperature->compute_vector();
pressure->compute_vector();
}
couple();
pressure->addstep(update->ntimestep+1);
}
if (pstat_flag) {
compute_press_target();
nh_omega_dot();
nh_v_press();
}
nve_v();
// remap simulation box by 1/2 step
if (pstat_flag) remap();
nve_x();
// remap simulation box by 1/2 step
// redo KSpace coeffs since volume has changed
if (pstat_flag) {
remap();
if (kspace_flag) force->kspace->setup();
}
}
/* ----------------------------------------------------------------------
2nd half of Verlet update
------------------------------------------------------------------------- */
void FixNH::final_integrate()
{
nve_v();
if (pstat_flag) nh_v_press();
// compute new T,P
// compute appropriately coupled elements of mvv_current
t_current = temperature->compute_scalar();
if (pstat_flag) {
if (pstyle == ISO) pressure->compute_scalar();
else pressure->compute_vector();
couple();
pressure->addstep(update->ntimestep+1);
}
if (pstat_flag) nh_omega_dot();
// update eta_dot
// update eta_press_dot
if (tstat_flag) nhc_temp_integrate();
if (pstat_flag && mpchain) nhc_press_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNH::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
// set timesteps by level
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
dthalf = 0.5 * step_respa[ilevel];
// outermost level - update eta_dot and omega_dot, apply to v
// all other levels - NVE update of v
// x,v updates only performed for atoms in group
if (ilevel == nlevels_respa-1) {
// update eta_press_dot
if (pstat_flag && mpchain) nhc_press_integrate();
// update eta_dot
if (tstat_flag) {
compute_temp_target();
nhc_temp_integrate();
}
// recompute pressure to account for change in KE
// t_current is up-to-date, but compute_temperature is not
// compute appropriately coupled elements of mvv_current
if (pstat_flag) {
if (pstyle == ISO) {
temperature->compute_scalar();
pressure->compute_scalar();
} else {
temperature->compute_vector();
pressure->compute_vector();
}
couple();
pressure->addstep(update->ntimestep+1);
}
if (pstat_flag) {
compute_press_target();
nh_omega_dot();
nh_v_press();
}
nve_v();
} else nve_v();
// innermost level - also update x only for atoms in group
// if barostat, perform 1/2 step remap before and after
if (ilevel == 0) {
if (pstat_flag) remap();
nve_x();
if (pstat_flag) remap();
}
// if barostat, redo KSpace coeffs at outermost level,
// since volume has changed
if (ilevel == nlevels_respa-1 && kspace_flag && pstat_flag)
force->kspace->setup();
}
/* ---------------------------------------------------------------------- */
void FixNH::final_integrate_respa(int ilevel, int iloop)
{
// set timesteps by level
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
dthalf = 0.5 * step_respa[ilevel];
// outermost level - update eta_dot and omega_dot, apply via final_integrate
// all other levels - NVE update of v
if (ilevel == nlevels_respa-1) final_integrate();
else nve_v();
}
/* ---------------------------------------------------------------------- */
void FixNH::couple()
{
double *tensor = pressure->vector;
if (pstyle == ISO)
p_current[0] = p_current[1] = p_current[2] = pressure->scalar;
else if (pcouple == XYZ) {
double ave = 1.0/3.0 * (tensor[0] + tensor[1] + tensor[2]);
p_current[0] = p_current[1] = p_current[2] = ave;
} else if (pcouple == XY) {
double ave = 0.5 * (tensor[0] + tensor[1]);
p_current[0] = p_current[1] = ave;
p_current[2] = tensor[2];
} else if (pcouple == YZ) {
double ave = 0.5 * (tensor[1] + tensor[2]);
p_current[1] = p_current[2] = ave;
p_current[0] = tensor[0];
} else if (pcouple == XZ) {
double ave = 0.5 * (tensor[0] + tensor[2]);
p_current[0] = p_current[2] = ave;
p_current[1] = tensor[1];
} else {
p_current[0] = tensor[0];
p_current[1] = tensor[1];
p_current[2] = tensor[2];
}
// switch order from xy-xz-yz to Voigt
if (pstyle == TRICLINIC) {
p_current[3] = tensor[5];
p_current[4] = tensor[4];
p_current[5] = tensor[3];
}
}
/* ----------------------------------------------------------------------
change box size
remap all atoms or fix group atoms depending on allremap flag
if rigid bodies exist, scale rigid body centers-of-mass
------------------------------------------------------------------------- */
void FixNH::remap()
{
int i;
double oldlo,oldhi,ctr;
double expfac;
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
// omega is not used, except for book-keeping
for (int i = 0; i < 6; i++) omega[i] += dto*omega_dot[i];
// convert pertinent atoms and rigid bodies to lamda coords
if (allremap) domain->x2lamda(nlocal);
else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->x2lamda(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(0);
// reset global and local box to new size/shape
// this operation corresponds to applying the
// translate and scale operations
// corresponding to the solution of the following ODE:
//
// h_dot = omega_dot * h
//
// where h_dot, omega_dot and h are all upper-triangular
// 3x3 tensors. In Voigt notation, the elements of the
// RHS product tensor are:
// h_dot = [0*0, 1*1, 2*2, 1*3+3*2, 0*4+5*3+4*2, 0*5+5*1]
//
// Ordering of operations preserves time symmetry.
double dto2 = dto/2.0;
double dto4 = dto/4.0;
double dto8 = dto/8.0;
// off-diagonal components, first half
if (pstyle == TRICLINIC) {
if (p_flag[4]) {
expfac = exp(dto8*omega_dot[0]);
h[4] *= expfac;
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= expfac;
}
if (p_flag[3]) {
expfac = exp(dto4*omega_dot[1]);
h[3] *= expfac;
h[3] += dto2*(omega_dot[3]*h[2]);
h[3] *= expfac;
}
if (p_flag[5]) {
expfac = exp(dto4*omega_dot[0]);
h[5] *= expfac;
h[5] += dto2*(omega_dot[5]*h[1]);
h[5] *= expfac;
}
if (p_flag[4]) {
expfac = exp(dto8*omega_dot[0]);
h[4] *= expfac;
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= expfac;
}
}
// scale diagonal components
// scale tilt factors with cell, if set
if (p_flag[0]) {
oldlo = domain->boxlo[0];
oldhi = domain->boxhi[0];
ctr = 0.5 * (oldlo + oldhi);
expfac = exp(dto*omega_dot[0]);
domain->boxlo[0] = (oldlo-ctr)*expfac + ctr;
domain->boxhi[0] = (oldhi-ctr)*expfac + ctr;
}
if (p_flag[1]) {
oldlo = domain->boxlo[1];
oldhi = domain->boxhi[1];
ctr = 0.5 * (oldlo + oldhi);
expfac = exp(dto*omega_dot[1]);
domain->boxlo[1] = (oldlo-ctr)*expfac + ctr;
domain->boxhi[1] = (oldhi-ctr)*expfac + ctr;
if (scalexy) h[5] *= expfac;
}
if (p_flag[2]) {
oldlo = domain->boxlo[2];
oldhi = domain->boxhi[2];
ctr = 0.5 * (oldlo + oldhi);
expfac = exp(dto*omega_dot[2]);
domain->boxlo[2] = (oldlo-ctr)*expfac + ctr;
domain->boxhi[2] = (oldhi-ctr)*expfac + ctr;
if (scalexz) h[4] *= expfac;
if (scaleyz) h[3] *= expfac;
}
// off-diagonal components, second half
if (pstyle == TRICLINIC) {
if (p_flag[4]) {
expfac = exp(dto8*omega_dot[0]);
h[4] *= expfac;
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= expfac;
}
if (p_flag[3]) {
expfac = exp(dto4*omega_dot[1]);
h[3] *= expfac;
h[3] += dto2*(omega_dot[3]*h[2]);
h[3] *= expfac;
}
if (p_flag[5]) {
expfac = exp(dto4*omega_dot[0]);
h[5] *= expfac;
h[5] += dto2*(omega_dot[5]*h[1]);
h[5] *= expfac;
}
if (p_flag[4]) {
expfac = exp(dto8*omega_dot[0]);
h[4] *= expfac;
h[4] += dto4*(omega_dot[5]*h[3]+omega_dot[4]*h[2]);
h[4] *= expfac;
}
}
domain->yz = h[3];
domain->xz = h[4];
domain->xy = h[5];
// tilt factor to cell length ratio can not exceed TILTMAX
// in one step
if (domain->yz < -TILTMAX*domain->yprd || domain->yz > TILTMAX*domain->yprd ||
domain->xz < -TILTMAX*domain->xprd || domain->xz > TILTMAX*domain->xprd ||
domain->xy < -TILTMAX*domain->xprd || domain->xy > TILTMAX*domain->xprd)
- error->all("Fix npt/nph has tilted box too far in one step - "
+ error->all(FLERR,"Fix npt/nph has tilted box too far in one step - "
"periodic cell is too far from equilibrium state");
domain->set_global_box();
domain->set_local_box();
// convert pertinent atoms and rigid bodies back to box coords
if (allremap) domain->lamda2x(nlocal);
else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->lamda2x(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(1);
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixNH::write_restart(FILE *fp)
{
int nsize = size_restart_global();
double *list;
memory->create(list,nsize,"nh:list");
int n = pack_restart_data(list);
if (comm->me == 0) {
int size = nsize * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),nsize,fp);
}
memory->destroy(list);
}
/* ----------------------------------------------------------------------
calculate the number of data to be packed
------------------------------------------------------------------------- */
int FixNH::size_restart_global()
{
int nsize = 2;
if (tstat_flag) nsize += 1 + 2*mtchain;
if (pstat_flag) {
nsize += 16 + 2*mpchain;
if (deviatoric_flag) nsize += 6;
}
return nsize;
}
/* ----------------------------------------------------------------------
pack restart data
------------------------------------------------------------------------- */
int FixNH::pack_restart_data(double *list)
{
int n = 0;
list[n++] = tstat_flag;
if (tstat_flag) {
list[n++] = mtchain;
for (int ich = 0; ich < mtchain; ich++)
list[n++] = eta[ich];
for (int ich = 0; ich < mtchain; ich++)
list[n++] = eta_dot[ich];
}
list[n++] = pstat_flag;
if (pstat_flag) {
list[n++] = omega[0];
list[n++] = omega[1];
list[n++] = omega[2];
list[n++] = omega[3];
list[n++] = omega[4];
list[n++] = omega[5];
list[n++] = omega_dot[0];
list[n++] = omega_dot[1];
list[n++] = omega_dot[2];
list[n++] = omega_dot[3];
list[n++] = omega_dot[4];
list[n++] = omega_dot[5];
list[n++] = vol0;
list[n++] = t0;
list[n++] = mpchain;
if (mpchain) {
for (int ich = 0; ich < mpchain; ich++)
list[n++] = etap[ich];
for (int ich = 0; ich < mpchain; ich++)
list[n++] = etap_dot[ich];
}
list[n++] = deviatoric_flag;
if (deviatoric_flag) {
list[n++] = h0_inv[0];
list[n++] = h0_inv[1];
list[n++] = h0_inv[2];
list[n++] = h0_inv[3];
list[n++] = h0_inv[4];
list[n++] = h0_inv[5];
}
}
return n;
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixNH::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
int flag = static_cast<int> (list[n++]);
if (flag) {
int m = static_cast<int> (list[n++]);
if (tstat_flag && m == mtchain) {
for (int ich = 0; ich < mtchain; ich++)
eta[ich] = list[n++];
for (int ich = 0; ich < mtchain; ich++)
eta_dot[ich] = list[n++];
} else n += 2*m;
}
flag = static_cast<int> (list[n++]);
if (flag) {
omega[0] = list[n++];
omega[1] = list[n++];
omega[2] = list[n++];
omega[3] = list[n++];
omega[4] = list[n++];
omega[5] = list[n++];
omega_dot[0] = list[n++];
omega_dot[1] = list[n++];
omega_dot[2] = list[n++];
omega_dot[3] = list[n++];
omega_dot[4] = list[n++];
omega_dot[5] = list[n++];
vol0 = list[n++];
t0 = list[n++];
int m = static_cast<int> (list[n++]);
if (pstat_flag && m == mpchain) {
for (int ich = 0; ich < mpchain; ich++)
etap[ich] = list[n++];
for (int ich = 0; ich < mpchain; ich++)
etap_dot[ich] = list[n++];
} else n+=2*m;
flag = static_cast<int> (list[n++]);
if (flag) {
h0_inv[0] = list[n++];
h0_inv[1] = list[n++];
h0_inv[2] = list[n++];
h0_inv[3] = list[n++];
h0_inv[4] = list[n++];
h0_inv[5] = list[n++];
}
}
}
/* ---------------------------------------------------------------------- */
int FixNH::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != 0 && comm->me == 0)
- error->warning("Temperature for fix modify is not for group all");
+ error->warning(FLERR,"Temperature for fix modify is not for group all");
// reset id_temp of pressure to new temperature ID
if (pstat_flag) {
icompute = modify->find_compute(id_press);
if (icompute < 0)
- error->all("Pressure ID for fix modify does not exist");
+ error->all(FLERR,"Pressure ID for fix modify does not exist");
modify->compute[icompute]->reset_extra_compute_fix(id_temp);
}
return 2;
} else if (strcmp(arg[0],"press") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
- if (!pstat_flag) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
+ if (!pstat_flag) error->all(FLERR,"Illegal fix_modify command");
if (pflag) {
modify->delete_compute(id_press);
pflag = 0;
}
delete [] id_press;
int n = strlen(arg[1]) + 1;
id_press = new char[n];
strcpy(id_press,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify pressure ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify pressure ID");
pressure = modify->compute[icompute];
if (pressure->pressflag == 0)
- error->all("Fix_modify pressure ID does not compute pressure");
+ error->all(FLERR,"Fix_modify pressure ID does not compute pressure");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
double FixNH::compute_scalar()
{
int i;
double volume;
double energy;
double kt = boltz * t_target;
double lkt_press = kt;
int ich;
if (dimension == 3) volume = domain->xprd * domain->yprd * domain->zprd;
else volume = domain->xprd * domain->yprd;
energy = 0.0;
// thermostat chain energy is equivalent to Eq. (2) in
// Martyna, Tuckerman, Tobias, Klein, Mol Phys, 87, 1117
// Sum(0.5*p_eta_k^2/Q_k,k=1,M) + L*k*T*eta_1 + Sum(k*T*eta_k,k=2,M),
// where L = tdof
// M = mtchain
// p_eta_k = Q_k*eta_dot[k-1]
// Q_1 = L*k*T/t_freq^2
// Q_k = k*T/t_freq^2, k > 1
if (tstat_flag) {
energy += ke_target * eta[0] + 0.5*eta_mass[0]*eta_dot[0]*eta_dot[0];
for (ich = 1; ich < mtchain; ich++)
energy += kt * eta[ich] + 0.5*eta_mass[ich]*eta_dot[ich]*eta_dot[ich];
}
// barostat energy is equivalent to Eq. (8) in
// Martyna, Tuckerman, Tobias, Klein, Mol Phys, 87, 1117
// Sum(0.5*p_omega^2/W + P*V),
// where N = natoms
// p_omega = W*omega_dot
// W = N*k*T/p_freq^2
// sum is over barostatted dimensions
if (pstat_flag) {
for (i = 0; i < 3; i++)
if (p_flag[i])
energy += 0.5*omega_dot[i]*omega_dot[i]*omega_mass[i] +
p_hydro*(volume-vol0) / (pdim*nktv2p);
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i])
energy += 0.5*omega_dot[i]*omega_dot[i]*omega_mass[i];
}
// extra contributions from thermostat chain for barostat
if (mpchain) {
energy += lkt_press * etap[0] + 0.5*etap_mass[0]*etap_dot[0]*etap_dot[0];
for (ich = 1; ich < mpchain; ich++)
energy += kt * etap[ich] +
0.5*etap_mass[ich]*etap_dot[ich]*etap_dot[ich];
}
// extra contribution from strain energy
if (deviatoric_flag) energy += compute_strain_energy();
}
return energy;
}
/* ----------------------------------------------------------------------
return a single element of the following vectors, in this order:
eta[tchain], eta_dot[tchain], omega[ndof], omega_dot[ndof]
etap[pchain], etap_dot[pchain], PE_eta[tchain], KE_eta_dot[tchain]
PE_omega[ndof], KE_omega_dot[ndof], PE_etap[pchain], KE_etap_dot[pchain]
PE_strain[1]
if no thermostat exists, related quantities are omitted from the list
if no barostat exists, related quantities are omitted from the list
ndof = 1,3,6 degrees of freedom for pstyle = ISO,ANISO,TRI
------------------------------------------------------------------------- */
double FixNH::compute_vector(int n)
{
int ilen;
if (tstat_flag) {
ilen = mtchain;
if (n < ilen) return eta[n];
n -= ilen;
ilen = mtchain;
if (n < ilen) return eta_dot[n];
n -= ilen;
}
if (pstat_flag) {
if (pstyle == ISO) {
ilen = 1;
if (n < ilen) return omega[n];
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen) return omega[n];
n -= ilen;
} else {
ilen = 6;
if (n < ilen) return omega[n];
n -= ilen;
}
if (pstyle == ISO) {
ilen = 1;
if (n < ilen) return omega_dot[n];
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen) return omega_dot[n];
n -= ilen;
} else {
ilen = 6;
if (n < ilen) return omega_dot[n];
n -= ilen;
}
if (mpchain) {
ilen = mpchain;
if (n < ilen) return etap[n];
n -= ilen;
ilen = mpchain;
if (n < ilen) return etap_dot[n];
n -= ilen;
}
}
double volume;
double kt = boltz * t_target;
double lkt_press = kt;
int ich;
if (dimension == 3) volume = domain->xprd * domain->yprd * domain->zprd;
else volume = domain->xprd * domain->yprd;
if (tstat_flag) {
ilen = mtchain;
if (n < ilen) {
ich = n;
if (ich == 0)
return ke_target * eta[0];
else
return kt * eta[ich];
}
n -= ilen;
ilen = mtchain;
if (n < ilen) {
ich = n;
if (ich == 0)
return 0.5*eta_mass[0]*eta_dot[0]*eta_dot[0];
else
return 0.5*eta_mass[ich]*eta_dot[ich]*eta_dot[ich];
}
n -= ilen;
}
if (pstat_flag) {
if (pstyle == ISO) {
ilen = 1;
if (n < ilen)
return p_hydro*(volume-vol0) / nktv2p;
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen)
if (p_flag[n])
return p_hydro*(volume-vol0) / (pdim*nktv2p);
else
return 0.0;
n -= ilen;
} else {
ilen = 6;
if (n < ilen)
if (n > 2) return 0.0;
else if (p_flag[n])
return p_hydro*(volume-vol0) / (pdim*nktv2p);
else
return 0.0;
n -= ilen;
}
if (pstyle == ISO) {
ilen = 1;
if (n < ilen)
return pdim*0.5*omega_dot[n]*omega_dot[n]*omega_mass[n];
n -= ilen;
} else if (pstyle == ANISO) {
ilen = 3;
if (n < ilen)
if (p_flag[n])
return 0.5*omega_dot[n]*omega_dot[n]*omega_mass[n];
else return 0.0;
n -= ilen;
} else {
ilen = 6;
if (n < ilen)
if (p_flag[n])
return 0.5*omega_dot[n]*omega_dot[n]*omega_mass[n];
else return 0.0;
n -= ilen;
}
if (mpchain) {
ilen = mpchain;
if (n < ilen) {
ich = n;
if (ich == 0) return lkt_press * etap[0];
else return kt * etap[ich];
}
n -= ilen;
ilen = mpchain;
if (n < ilen) {
ich = n;
if (ich == 0)
return 0.5*etap_mass[0]*etap_dot[0]*etap_dot[0];
else
return 0.5*etap_mass[ich]*etap_dot[ich]*etap_dot[ich];
}
n -= ilen;
}
if (deviatoric_flag) {
ilen = 1;
if (n < ilen)
return compute_strain_energy();
n -= ilen;
}
}
return 0.0;
}
/* ---------------------------------------------------------------------- */
void FixNH::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
void FixNH::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dthalf = 0.5 * update->dt;
dt4 = 0.25 * update->dt;
dt8 = 0.125 * update->dt;
dto = dthalf;
// If using respa, then remap is performed in innermost level
if (strstr(update->integrate_style,"respa"))
dto = 0.5*step_respa[0];
if (pstat_flag)
pdrag_factor = 1.0 - (update->dt * p_freq_max * drag / nc_pchain);
if (tstat_flag)
tdrag_factor = 1.0 - (update->dt * t_freq * drag / nc_tchain);
}
/* ----------------------------------------------------------------------
perform half-step update of chain thermostat variables
------------------------------------------------------------------------- */
void FixNH::nhc_temp_integrate()
{
int ich;
double expfac;
double kecurrent = tdof * boltz * t_current;
// Update masses, to preserve initial freq, if flag set
if (eta_mass_flag) {
eta_mass[0] = tdof * boltz * t_target / (t_freq*t_freq);
for (int ich = 1; ich < mtchain; ich++)
eta_mass[ich] = boltz * t_target / (t_freq*t_freq);
}
eta_dotdot[0] = (kecurrent - ke_target)/eta_mass[0];
double ncfac = 1.0/nc_tchain;
for (int iloop = 0; iloop < nc_tchain; iloop++) {
for (ich = mtchain-1; ich > 0; ich--) {
expfac = exp(-ncfac*dt8*eta_dot[ich+1]);
eta_dot[ich] *= expfac;
eta_dot[ich] += eta_dotdot[ich] * ncfac*dt4;
eta_dot[ich] *= tdrag_factor;
eta_dot[ich] *= expfac;
}
expfac = exp(-ncfac*dt8*eta_dot[1]);
eta_dot[0] *= expfac;
eta_dot[0] += eta_dotdot[0] * ncfac*dt4;
eta_dot[0] *= tdrag_factor;
eta_dot[0] *= expfac;
factor_eta = exp(-ncfac*dthalf*eta_dot[0]);
nh_v_temp();
// rescale temperature due to velocity scaling
// should not be necessary to explicitly recompute the temperature
t_current *= factor_eta*factor_eta;
kecurrent = tdof * boltz * t_current;
eta_dotdot[0] = (kecurrent - ke_target)/eta_mass[0];
for (ich = 0; ich < mtchain; ich++)
eta[ich] += ncfac*dthalf*eta_dot[ich];
eta_dot[0] *= expfac;
eta_dot[0] += eta_dotdot[0] * ncfac*dt4;
eta_dot[0] *= expfac;
for (ich = 1; ich < mtchain; ich++) {
expfac = exp(-ncfac*dt8*eta_dot[ich+1]);
eta_dot[ich] *= expfac;
eta_dotdot[ich] = (eta_mass[ich-1]*eta_dot[ich-1]*eta_dot[ich-1]
- boltz * t_target)/eta_mass[ich];
eta_dot[ich] += eta_dotdot[ich] * ncfac*dt4;
eta_dot[ich] *= expfac;
}
}
}
/* ----------------------------------------------------------------------
perform half-step update of chain thermostat variables for barostat
scale barostat velocities
------------------------------------------------------------------------- */
void FixNH::nhc_press_integrate()
{
int ich,i;
double expfac,factor_etap,kecurrent;
double kt = boltz * t_target;
double lkt_press = kt;
// Update masses, to preserve initial freq, if flag set
if (omega_mass_flag) {
double nkt = atom->natoms * kt;
for (int i = 0; i < 3; i++)
if (p_flag[i])
omega_mass[i] = nkt/(p_freq[i]*p_freq[i]);
if (pstyle == TRICLINIC) {
for (int i = 3; i < 6; i++)
if (p_flag[i]) omega_mass[i] = nkt/(p_freq[i]*p_freq[i]);
}
}
if (etap_mass_flag) {
if (mpchain) {
etap_mass[0] = boltz * t_target / (p_freq_max*p_freq_max);
for (int ich = 1; ich < mpchain; ich++)
etap_mass[ich] = boltz * t_target / (p_freq_max*p_freq_max);
for (int ich = 1; ich < mpchain; ich++)
etap_dotdot[ich] =
(etap_mass[ich-1]*etap_dot[ich-1]*etap_dot[ich-1] -
boltz * t_target) / etap_mass[ich];
}
}
kecurrent = 0.0;
for (i = 0; i < 3; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
}
etap_dotdot[0] = (kecurrent - lkt_press)/etap_mass[0];
double ncfac = 1.0/nc_pchain;
for (int iloop = 0; iloop < nc_pchain; iloop++) {
for (ich = mpchain-1; ich > 0; ich--) {
expfac = exp(-ncfac*dt8*etap_dot[ich+1]);
etap_dot[ich] *= expfac;
etap_dot[ich] += etap_dotdot[ich] * ncfac*dt4;
etap_dot[ich] *= pdrag_factor;
etap_dot[ich] *= expfac;
}
expfac = exp(-ncfac*dt8*etap_dot[1]);
etap_dot[0] *= expfac;
etap_dot[0] += etap_dotdot[0] * ncfac*dt4;
etap_dot[0] *= pdrag_factor;
etap_dot[0] *= expfac;
for (ich = 0; ich < mpchain; ich++)
etap[ich] += ncfac*dthalf*etap_dot[ich];
factor_etap = exp(-ncfac*dthalf*etap_dot[0]);
for (i = 0; i < 3; i++)
if (p_flag[i]) omega_dot[i] *= factor_etap;
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i]) omega_dot[i] *= factor_etap;
}
kecurrent = 0.0;
for (i = 0; i < 3; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
if (pstyle == TRICLINIC) {
for (i = 3; i < 6; i++)
if (p_flag[i]) kecurrent += omega_mass[i]*omega_dot[i]*omega_dot[i];
}
etap_dotdot[0] = (kecurrent - lkt_press)/etap_mass[0];
etap_dot[0] *= expfac;
etap_dot[0] += etap_dotdot[0] * ncfac*dt4;
etap_dot[0] *= expfac;
for (ich = 1; ich < mpchain; ich++) {
expfac = exp(-ncfac*dt8*etap_dot[ich+1]);
etap_dot[ich] *= expfac;
etap_dotdot[ich] =
(etap_mass[ich-1]*etap_dot[ich-1]*etap_dot[ich-1] - boltz*t_target) /
etap_mass[ich];
etap_dot[ich] += etap_dotdot[ich] * ncfac*dt4;
etap_dot[ich] *= expfac;
}
}
}
/* ----------------------------------------------------------------------
perform half-step barostat scaling of velocities
-----------------------------------------------------------------------*/
void FixNH::nh_v_press()
{
double factor[3];
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
factor[0] = exp(-dt4*(omega_dot[0]+mtk_term2));
factor[1] = exp(-dt4*(omega_dot[1]+mtk_term2));
factor[2] = exp(-dt4*(omega_dot[2]+mtk_term2));
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
if (pstyle == TRICLINIC) {
v[i][0] += -dthalf*(v[i][1]*omega_dot[5] + v[i][2]*omega_dot[4]);
v[i][1] += -dthalf*v[i][2]*omega_dot[3];
}
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
}
}
} else if (which == BIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
if (pstyle == TRICLINIC) {
v[i][0] += -dthalf*(v[i][1]*omega_dot[5] + v[i][2]*omega_dot[4]);
v[i][1] += -dthalf*v[i][2]*omega_dot[3];
}
v[i][0] *= factor[0];
v[i][1] *= factor[1];
v[i][2] *= factor[2];
temperature->restore_bias(i,v[i]);
}
}
}
}
/* ----------------------------------------------------------------------
perform half-step update of velocities
-----------------------------------------------------------------------*/
void FixNH::nve_v()
{
double dtfm;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm*f[i][0];
v[i][1] += dtfm*f[i][1];
v[i][2] += dtfm*f[i][2];
}
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm*f[i][0];
v[i][1] += dtfm*f[i][1];
v[i][2] += dtfm*f[i][2];
}
}
}
}
/* ----------------------------------------------------------------------
perform full-step update of positions
-----------------------------------------------------------------------*/
void FixNH::nve_x()
{
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// x update by full step only for atoms in group
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
}
/* ----------------------------------------------------------------------
perform half-step thermostat scaling of velocities
-----------------------------------------------------------------------*/
void FixNH::nh_v_temp()
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] *= factor_eta;
v[i][1] *= factor_eta;
v[i][2] *= factor_eta;
}
}
} else if (which == BIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= factor_eta;
v[i][1] *= factor_eta;
v[i][2] *= factor_eta;
temperature->restore_bias(i,v[i]);
}
}
}
}
/* ----------------------------------------------------------------------
compute sigma tensor
needed whenever p_target or h0_inv changes
-----------------------------------------------------------------------*/
void FixNH::compute_sigma()
{
// if nreset_h0 > 0, reset vol0 and h0_inv
// every nreset_h0 timesteps
if (nreset_h0 > 0) {
int delta = update->ntimestep - update->beginstep;
if (delta % nreset_h0 == 0) {
if (dimension == 3) vol0 = domain->xprd * domain->yprd * domain->zprd;
else vol0 = domain->xprd * domain->yprd;
h0_inv[0] = domain->h_inv[0];
h0_inv[1] = domain->h_inv[1];
h0_inv[2] = domain->h_inv[2];
h0_inv[3] = domain->h_inv[3];
h0_inv[4] = domain->h_inv[4];
h0_inv[5] = domain->h_inv[5];
}
}
// generate upper-triangular half of
// sigma = vol0*h0inv*(p_target-p_hydro)*h0inv^t
// units of sigma are are PV/L^2 e.g. atm.A
//
// [ 0 5 4 ] [ 0 5 4 ] [ 0 5 4 ] [ 0 - - ]
// [ 5 1 3 ] = [ - 1 3 ] [ 5 1 3 ] [ 5 1 - ]
// [ 4 3 2 ] [ - - 2 ] [ 4 3 2 ] [ 4 3 2 ]
sigma[0] =
vol0*(h0_inv[0]*((p_target[0]-p_hydro)*h0_inv[0] +
p_target[5]*h0_inv[5]+p_target[4]*h0_inv[4]) +
h0_inv[5]*(p_target[5]*h0_inv[0] +
(p_target[1]-p_hydro)*h0_inv[5]+p_target[3]*h0_inv[4]) +
h0_inv[4]*(p_target[4]*h0_inv[0]+p_target[3]*h0_inv[5] +
(p_target[2]-p_hydro)*h0_inv[4]));
sigma[1] =
vol0*(h0_inv[1]*((p_target[1]-p_hydro)*h0_inv[1] +
p_target[3]*h0_inv[3]) +
h0_inv[3]*(p_target[3]*h0_inv[1] +
(p_target[2]-p_hydro)*h0_inv[3]));
sigma[2] =
vol0*(h0_inv[2]*((p_target[2]-p_hydro)*h0_inv[2]));
sigma[3] =
vol0*(h0_inv[1]*(p_target[3]*h0_inv[2]) +
h0_inv[3]*((p_target[2]-p_hydro)*h0_inv[2]));
sigma[4] =
vol0*(h0_inv[0]*(p_target[4]*h0_inv[2]) +
h0_inv[5]*(p_target[3]*h0_inv[2]) +
h0_inv[4]*((p_target[2]-p_hydro)*h0_inv[2]));
sigma[5] =
vol0*(h0_inv[0]*(p_target[5]*h0_inv[1]+p_target[4]*h0_inv[3]) +
h0_inv[5]*((p_target[1]-p_hydro)*h0_inv[1]+p_target[3]*h0_inv[3]) +
h0_inv[4]*(p_target[3]*h0_inv[1]+(p_target[2]-p_hydro)*h0_inv[3]));
}
/* ----------------------------------------------------------------------
compute strain energy
-----------------------------------------------------------------------*/
double FixNH::compute_strain_energy()
{
// compute strain energy = 0.5*Tr(sigma*h*h^t) in energy units
double* h = domain->h;
double d0,d1,d2;
d0 =
sigma[0]*(h[0]*h[0]+h[5]*h[5]+h[4]*h[4]) +
sigma[5]*( h[1]*h[5]+h[3]*h[4]) +
sigma[4]*( h[2]*h[4]);
d1 =
sigma[5]*( h[5]*h[1]+h[4]*h[3]) +
sigma[1]*( h[1]*h[1]+h[3]*h[3]) +
sigma[3]*( h[2]*h[3]);
d2 =
sigma[4]*( h[4]*h[2]) +
sigma[3]*( h[3]*h[2]) +
sigma[2]*( h[2]*h[2]);
double energy = 0.5*(d0+d1+d2)/nktv2p;
return energy;
}
/* ----------------------------------------------------------------------
compute deviatoric barostat force = h*sigma*h^t
-----------------------------------------------------------------------*/
void FixNH::compute_deviatoric()
{
// generate upper-triangular part of h*sigma*h^t
// units of fdev are are PV, e.g. atm*A^3
// [ 0 5 4 ] [ 0 5 4 ] [ 0 5 4 ] [ 0 - - ]
// [ 5 1 3 ] = [ - 1 3 ] [ 5 1 3 ] [ 5 1 - ]
// [ 4 3 2 ] [ - - 2 ] [ 4 3 2 ] [ 4 3 2 ]
double* h = domain->h;
fdev[0] =
h[0]*(sigma[0]*h[0]+sigma[5]*h[5]+sigma[4]*h[4]) +
h[5]*(sigma[5]*h[0]+sigma[1]*h[5]+sigma[3]*h[4]) +
h[4]*(sigma[4]*h[0]+sigma[3]*h[5]+sigma[2]*h[4]);
fdev[1] =
h[1]*( sigma[1]*h[1]+sigma[3]*h[3]) +
h[3]*( sigma[3]*h[1]+sigma[2]*h[3]);
fdev[2] =
h[2]*( sigma[2]*h[2]);
fdev[3] =
h[1]*( sigma[3]*h[2]) +
h[3]*( sigma[2]*h[2]);
fdev[4] =
h[0]*( sigma[4]*h[2]) +
h[5]*( sigma[3]*h[2]) +
h[4]*( sigma[2]*h[2]);
fdev[5] =
h[0]*( sigma[5]*h[1]+sigma[4]*h[3]) +
h[5]*( sigma[1]*h[1]+sigma[3]*h[3]) +
h[4]*( sigma[3]*h[1]+sigma[2]*h[3]);
}
/* ----------------------------------------------------------------------
compute target temperature and kinetic energy
-----------------------------------------------------------------------*/
void FixNH::compute_temp_target()
{
double delta = update->ntimestep - update->beginstep;
if (update->endstep > update->beginstep)
delta /= update->endstep - update->beginstep;
else delta = 0.0;
t_target = t_start + delta * (t_stop-t_start);
ke_target = tdof * boltz * t_target;
}
/* ----------------------------------------------------------------------
compute hydrostatic target pressure
-----------------------------------------------------------------------*/
void FixNH::compute_press_target()
{
double delta = update->ntimestep - update->beginstep;
if (update->endstep > update->beginstep)
delta /= update->endstep - update->beginstep;
else delta = 0.0;
p_hydro = 0.0;
for (int i = 0; i < 3; i++)
if (p_flag[i]) {
p_target[i] = p_start[i] + delta * (p_stop[i]-p_start[i]);
p_hydro += p_target[i];
}
p_hydro /= pdim;
if (pstyle == TRICLINIC)
for (int i = 3; i < 6; i++)
p_target[i] = p_start[i] + delta * (p_stop[i]-p_start[i]);
// if deviatoric, recompute sigma each time p_target changes
if (deviatoric_flag) compute_sigma();
}
/* ----------------------------------------------------------------------
update omega_dot, omega
-----------------------------------------------------------------------*/
void FixNH::nh_omega_dot()
{
double f_omega,volume;
if (dimension == 3) volume = domain->xprd*domain->yprd*domain->zprd;
else volume = domain->xprd*domain->yprd;
if (deviatoric_flag) compute_deviatoric();
mtk_term1 = 0.0;
if (mtk_flag)
if (pstyle == ISO) {
mtk_term1 = tdof * boltz * t_current;
mtk_term1 /= pdim * atom->natoms;
} else {
double *mvv_current = temperature->vector;
for (int i = 0; i < 3; i++)
if (p_flag[i])
mtk_term1 += mvv_current[i];
mtk_term1 /= pdim * atom->natoms;
}
for (int i = 0; i < 3; i++)
if (p_flag[i]) {
f_omega = (p_current[i]-p_hydro)*volume /
(omega_mass[i] * nktv2p) + mtk_term1 / omega_mass[i];
if (deviatoric_flag) f_omega -= fdev[i]/(omega_mass[i] * nktv2p);
omega_dot[i] += f_omega*dthalf;
omega_dot[i] *= pdrag_factor;
}
mtk_term2 = 0.0;
if (mtk_flag) {
for (int i = 0; i < 3; i++)
if (p_flag[i])
mtk_term2 += omega_dot[i];
mtk_term2 /= pdim * atom->natoms;
}
if (pstyle == TRICLINIC) {
for (int i = 3; i < 6; i++) {
if (p_flag[i]) {
f_omega = p_current[i]*volume/(omega_mass[i] * nktv2p);
if (deviatoric_flag)
f_omega -= fdev[i]/(omega_mass[i] * nktv2p);
omega_dot[i] += f_omega*dthalf;
omega_dot[i] *= pdrag_factor;
}
}
}
}
/* ----------------------------------------------------------------------
if box tilt exceeds limits,
create new box in domain
remap to put far-away atoms back into new box
perform irregular on atoms in lamda coords to get atoms to new procs
force reneighboring on next timestep
------------------------------------------------------------------------- */
void FixNH::pre_exchange()
{
double xprd = domain->xprd;
double yprd = domain->yprd;
// flip is triggered when tilt exceeds 0.5 by
// an amount DELTAFLIP that is somewhat arbitrary
double xtiltmax = (0.5+DELTAFLIP)*xprd;
double ytiltmax = (0.5+DELTAFLIP)*yprd;
int flip = 0;
if (domain->yz < -ytiltmax) {
flip = 1;
domain->yz += yprd;
domain->xz += domain->xy;
} else if (domain->yz >= ytiltmax) {
flip = 1;
domain->yz -= yprd;
domain->xz -= domain->xy;
}
if (domain->xz < -xtiltmax) {
flip = 1;
domain->xz += xprd;
} else if (domain->xz >= xtiltmax) {
flip = 1;
domain->xz -= xprd;
}
if (domain->xy < -xtiltmax) {
flip = 1;
domain->xy += xprd;
} else if (domain->xy >= xtiltmax) {
flip = 1;
domain->xy -= xprd;
}
if (flip) {
domain->set_global_box();
domain->set_local_box();
double **x = atom->x;
int *image = atom->image;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) domain->remap(x[i],image[i]);
domain->x2lamda(atom->nlocal);
irregular->migrate_atoms();
domain->lamda2x(atom->nlocal);
}
}
diff --git a/src/fix_nh_sphere.cpp b/src/fix_nh_sphere.cpp
index ed414e511..7bdbcee26 100644
--- a/src/fix_nh_sphere.cpp
+++ b/src/fix_nh_sphere.cpp
@@ -1,115 +1,115 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mike Brown (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "fix_nh_sphere.h"
#include "atom.h"
#include "atom_vec.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
#define INERTIA 0.4 // moment of inertia prefactor for sphere
/* ---------------------------------------------------------------------- */
FixNHSphere::FixNHSphere(LAMMPS *lmp, int narg, char **arg) :
FixNH(lmp, narg, arg)
{
if (!atom->sphere_flag)
- error->all("Fix nvt/nph/npt sphere requires atom style sphere");
+ error->all(FLERR,"Fix nvt/nph/npt sphere requires atom style sphere");
}
/* ---------------------------------------------------------------------- */
void FixNHSphere::init()
{
// check that all particles are finite-size
// no point particles allowed
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (radius[i] == 0.0)
- error->one("Fix nvt/sphere requires extended particles");
+ error->one(FLERR,"Fix nvt/sphere requires extended particles");
FixNH::init();
}
/* ----------------------------------------------------------------------
perform half-step update of rotational velocities
-----------------------------------------------------------------------*/
void FixNHSphere::nve_v()
{
// standard nve_v velocity update
FixNH::nve_v();
double **omega = atom->omega;
double **torque = atom->torque;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// set timestep here since dt may have changed or come via rRESPA
double dtfrotate = dtf / INERTIA;
double dtirotate;
// update omega for all particles
// d_omega/dt = torque / inertia
// 4 cases depending on radius vs shape and rmass vs mass
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtirotate = dtfrotate / (radius[i]*radius[i]*rmass[i]);
omega[i][0] += dtirotate*torque[i][0];
omega[i][1] += dtirotate*torque[i][1];
omega[i][2] += dtirotate*torque[i][2];
}
}
/* ----------------------------------------------------------------------
perform half-step scaling of rotatonal velocities
-----------------------------------------------------------------------*/
void FixNHSphere::nh_v_temp()
{
// standard nh_v_temp scaling
FixNH::nh_v_temp();
double **omega = atom->omega;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
omega[i][0] *= factor_eta;
omega[i][1] *= factor_eta;
omega[i][2] *= factor_eta;
}
}
}
diff --git a/src/fix_nph.cpp b/src/fix_nph.cpp
index b863be12a..e65da3658 100644
--- a/src/fix_nph.cpp
+++ b/src/fix_nph.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_nph.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPH::FixNPH(LAMMPS *lmp, int narg, char **arg) :
FixNH(lmp, narg, arg)
{
if (tstat_flag)
- error->all("Temperature control can not be used with fix nph");
+ error->all(FLERR,"Temperature control can not be used with fix nph");
if (!pstat_flag)
- error->all("Pressure control must be used with fix nph");
+ error->all(FLERR,"Pressure control must be used with fix nph");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/fix_nph_sphere.cpp b/src/fix_nph_sphere.cpp
index bc0e23a3b..550dd8f5b 100644
--- a/src/fix_nph_sphere.cpp
+++ b/src/fix_nph_sphere.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_nph_sphere.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPHSphere::FixNPHSphere(LAMMPS *lmp, int narg, char **arg) :
FixNHSphere(lmp, narg, arg)
{
if (tstat_flag)
- error->all("Temperature control can not be used with fix nph/sphere");
+ error->all(FLERR,"Temperature control can not be used with fix nph/sphere");
if (!pstat_flag)
- error->all("Pressure control must be used with fix nph/sphere");
+ error->all(FLERR,"Pressure control must be used with fix nph/sphere");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp/sphere";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/fix_npt.cpp b/src/fix_npt.cpp
index 3963e69eb..84522560a 100644
--- a/src/fix_npt.cpp
+++ b/src/fix_npt.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_npt.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPT::FixNPT(LAMMPS *lmp, int narg, char **arg) :
FixNH(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix npt");
+ error->all(FLERR,"Temperature control must be used with fix npt");
if (!pstat_flag)
- error->all("Pressure control must be used with fix npt");
+ error->all(FLERR,"Pressure control must be used with fix npt");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/fix_npt_sphere.cpp b/src/fix_npt_sphere.cpp
index 2e250fad8..b58971f55 100644
--- a/src/fix_npt_sphere.cpp
+++ b/src/fix_npt_sphere.cpp
@@ -1,67 +1,67 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_npt_sphere.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNPTSphere::FixNPTSphere(LAMMPS *lmp, int narg, char **arg) :
FixNHSphere(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix npt/sphere");
+ error->all(FLERR,"Temperature control must be used with fix npt/sphere");
if (!pstat_flag)
- error->all("Pressure control must be used with fix npt/sphere");
+ error->all(FLERR,"Pressure control must be used with fix npt/sphere");
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp/sphere";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
}
diff --git a/src/fix_nve.cpp b/src/fix_nve.cpp
index bb500561a..ce4e25306 100644
--- a/src/fix_nve.cpp
+++ b/src/fix_nve.cpp
@@ -1,170 +1,170 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdio.h"
#include "string.h"
#include "fix_nve.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVE::FixNVE(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
if (strcmp(style,"nve/sphere") != 0 && narg < 3)
- error->all("Illegal fix nve command");
+ error->all(FLERR,"Illegal fix nve command");
time_integrate = 1;
}
/* ---------------------------------------------------------------------- */
int FixNVE::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVE::init()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixNVE::initial_integrate(int vflag)
{
double dtfm;
// update v and x of atoms in group
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVE::final_integrate()
{
double dtfm;
// update v of atoms in group
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVE::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
// innermost level - NVE update of v and x
// all other levels - NVE update of v
if (ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVE::final_integrate_respa(int ilevel, int iloop)
{
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVE::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
}
diff --git a/src/fix_nve_limit.cpp b/src/fix_nve_limit.cpp
index 2fed70c49..a5e2b2894 100644
--- a/src/fix_nve_limit.cpp
+++ b/src/fix_nve_limit.cpp
@@ -1,228 +1,228 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fix_nve_limit.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVELimit::FixNVELimit(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal fix nve/limit command");
+ if (narg != 4) error->all(FLERR,"Illegal fix nve/limit command");
time_integrate = 1;
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
xlimit = atof(arg[3]);
ncount = 0;
}
/* ---------------------------------------------------------------------- */
int FixNVELimit::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVELimit::init()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
vlimitsq = (xlimit/dtv) * (xlimit/dtv);
ncount = 0;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
}
/* ----------------------------------------------------------------------
allow for both per-type and per-atom mass
------------------------------------------------------------------------- */
void FixNVELimit::initial_integrate(int vflag)
{
double dtfm,vsq,scale;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vlimitsq) {
ncount++;
scale = sqrt(vlimitsq/vsq);
v[i][0] *= scale;
v[i][1] *= scale;
v[i][2] *= scale;
}
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vlimitsq) {
ncount++;
scale = sqrt(vlimitsq/vsq);
v[i][0] *= scale;
v[i][1] *= scale;
v[i][2] *= scale;
}
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVELimit::final_integrate()
{
double dtfm,vsq,scale;
double **v = atom->v;
double **f = atom->f;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vlimitsq) {
ncount++;
scale = sqrt(vlimitsq/vsq);
v[i][0] *= scale;
v[i][1] *= scale;
v[i][2] *= scale;
}
}
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > vlimitsq) {
ncount++;
scale = sqrt(vlimitsq/vsq);
v[i][0] *= scale;
v[i][1] *= scale;
v[i][2] *= scale;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVELimit::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
if (ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVELimit::final_integrate_respa(int ilevel, int iloop)
{
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixNVELimit::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
vlimitsq = (xlimit/dtv) * (xlimit/dtv);
}
/* ----------------------------------------------------------------------
energy of indenter interaction
------------------------------------------------------------------------- */
double FixNVELimit::compute_scalar()
{
double one = ncount;
double all;
MPI_Allreduce(&one,&all,1,MPI_DOUBLE,MPI_SUM,world);
return all;
}
diff --git a/src/fix_nve_noforce.cpp b/src/fix_nve_noforce.cpp
index b0095ab18..b4d67be75 100644
--- a/src/fix_nve_noforce.cpp
+++ b/src/fix_nve_noforce.cpp
@@ -1,89 +1,89 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdio.h"
#include "string.h"
#include "fix_nve_noforce.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVENoforce::FixNVENoforce(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 3) error->all("Illegal fix nve/noforce command");
+ if (narg != 3) error->all(FLERR,"Illegal fix nve/noforce command");
time_integrate = 1;
}
/* ---------------------------------------------------------------------- */
int FixNVENoforce::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVENoforce::init()
{
dtv = update->dt;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
}
/* ---------------------------------------------------------------------- */
void FixNVENoforce::initial_integrate(int vflag)
{
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVENoforce::initial_integrate_respa(int vflag, int ilevel, int flag)
{
if (flag) return; // only used by NPT,NPH
dtv = step_respa[ilevel];
if (ilevel == 0) initial_integrate(vflag);
}
/* ---------------------------------------------------------------------- */
void FixNVENoforce::reset_dt()
{
dtv = update->dt;
}
diff --git a/src/fix_nve_sphere.cpp b/src/fix_nve_sphere.cpp
index 935c9f069..c81452994 100644
--- a/src/fix_nve_sphere.cpp
+++ b/src/fix_nve_sphere.cpp
@@ -1,191 +1,191 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "string.h"
#include "fix_nve_sphere.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "respa.h"
#include "force.h"
#include "error.h"
using namespace LAMMPS_NS;
#define INERTIA 0.4 // moment of inertia prefactor for sphere
enum{NONE,DIPOLE};
/* ---------------------------------------------------------------------- */
FixNVESphere::FixNVESphere(LAMMPS *lmp, int narg, char **arg) :
FixNVE(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal fix nve/sphere command");
+ if (narg < 3) error->all(FLERR,"Illegal fix nve/sphere command");
time_integrate = 1;
// process extra keywords
extra = NONE;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"update") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix nve/sphere command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix nve/sphere command");
if (strcmp(arg[iarg+1],"dipole") == 0) extra = DIPOLE;
- else error->all("Illegal fix nve/sphere command");
+ else error->all(FLERR,"Illegal fix nve/sphere command");
iarg += 2;
- } else error->all("Illegal fix nve/sphere command");
+ } else error->all(FLERR,"Illegal fix nve/sphere command");
}
// error checks
if (!atom->sphere_flag)
- error->all("Fix nve/sphere requires atom style sphere");
+ error->all(FLERR,"Fix nve/sphere requires atom style sphere");
if (extra == DIPOLE && !atom->mu_flag)
- error->all("Fix nve/sphere requires atom attribute mu");
+ error->all(FLERR,"Fix nve/sphere requires atom attribute mu");
}
/* ---------------------------------------------------------------------- */
int FixNVESphere::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixNVESphere::init()
{
// check that all particles are finite-size
// no point particles allowed
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (radius[i] == 0.0)
- error->one("Fix nve/sphere requires extended particles");
+ error->one(FLERR,"Fix nve/sphere requires extended particles");
FixNVE::init();
}
/* ---------------------------------------------------------------------- */
void FixNVESphere::initial_integrate(int vflag)
{
double dtfm,dtirotate,msq,scale;
double g[3];
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *radius = atom->radius;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// set timestep here since dt may have changed or come via rRESPA
double dtfrotate = dtf / INERTIA;
// update v,x,omega for all particles
// d_omega/dt = torque / inertia
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
dtirotate = dtfrotate / (radius[i]*radius[i]*rmass[i]);
omega[i][0] += dtirotate * torque[i][0];
omega[i][1] += dtirotate * torque[i][1];
omega[i][2] += dtirotate * torque[i][2];
}
}
// update mu for dipoles
// d_mu/dt = omega cross mu
// renormalize mu to dipole length
if (extra == DIPOLE) {
double **mu = atom->mu;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (mu[i][3] > 0.0) {
g[0] = mu[i][0] + dtv * (omega[i][1]*mu[i][2]-omega[i][2]*mu[i][1]);
g[1] = mu[i][1] + dtv * (omega[i][2]*mu[i][0]-omega[i][0]*mu[i][2]);
g[2] = mu[i][2] + dtv * (omega[i][0]*mu[i][1]-omega[i][1]*mu[i][0]);
msq = g[0]*g[0] + g[1]*g[1] + g[2]*g[2];
scale = mu[i][3]/sqrt(msq);
mu[i][0] = g[0]*scale;
mu[i][1] = g[1]*scale;
mu[i][2] = g[2]*scale;
}
}
}
/* ---------------------------------------------------------------------- */
void FixNVESphere::final_integrate()
{
double dtfm,dtirotate;
double **v = atom->v;
double **f = atom->f;
double **omega = atom->omega;
double **torque = atom->torque;
double *rmass = atom->rmass;
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
// set timestep here since dt may have changed or come via rRESPA
double dtfrotate = dtf / INERTIA;
// update v,omega for all particles
// d_omega/dt = torque / inertia
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dtfm = dtf / rmass[i];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
dtirotate = dtfrotate / (radius[i]*radius[i]*rmass[i]);
omega[i][0] += dtirotate * torque[i][0];
omega[i][1] += dtirotate * torque[i][1];
omega[i][2] += dtirotate * torque[i][2];
}
}
diff --git a/src/fix_nvt.cpp b/src/fix_nvt.cpp
index 7817113b0..60478e6c4 100644
--- a/src/fix_nvt.cpp
+++ b/src/fix_nvt.cpp
@@ -1,48 +1,48 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_nvt.h"
#include "group.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVT::FixNVT(LAMMPS *lmp, int narg, char **arg) :
FixNH(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix nvt");
+ error->all(FLERR,"Temperature control must be used with fix nvt");
if (pstat_flag)
- error->all("Pressure control can not be used with fix nvt");
+ error->all(FLERR,"Pressure control can not be used with fix nvt");
// create a new compute temp style
// id = fix-ID + temp
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
diff --git a/src/fix_nvt_sllod.cpp b/src/fix_nvt_sllod.cpp
index 576d06440..ab5c876ad 100644
--- a/src/fix_nvt_sllod.cpp
+++ b/src/fix_nvt_sllod.cpp
@@ -1,129 +1,129 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
www.cs.sandia.gov/~sjplimp/lammps.html
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "fix_nvt_sllod.h"
#include "math_extra.h"
#include "atom.h"
#include "domain.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "fix_deform.h"
#include "compute.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp
/* ---------------------------------------------------------------------- */
FixNVTSllod::FixNVTSllod(LAMMPS *lmp, int narg, char **arg) :
FixNH(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix nvt/sllod");
+ error->all(FLERR,"Temperature control must be used with fix nvt/sllod");
if (pstat_flag)
- error->all("Pressure control can not be used with fix nvt/sllod");
+ error->all(FLERR,"Pressure control can not be used with fix nvt/sllod");
// default values
if (mtchain_default_flag) mtchain = 1;
// create a new compute temp style
// id = fix-ID + temp
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/deform";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
/* ---------------------------------------------------------------------- */
void FixNVTSllod::init()
{
FixNH::init();
if (!temperature->tempbias)
- error->all("Temperature for fix nvt/sllod does not have a bias");
+ error->all(FLERR,"Temperature for fix nvt/sllod does not have a bias");
nondeformbias = 0;
if (strcmp(temperature->style,"temp/deform") != 0) nondeformbias = 1;
// check fix deform remap settings
int i;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
if (((FixDeform *) modify->fix[i])->remapflag != V_REMAP)
- error->all("Using fix nvt/sllod with inconsistent fix deform "
+ error->all(FLERR,"Using fix nvt/sllod with inconsistent fix deform "
"remap option");
break;
}
if (i == modify->nfix)
- error->all("Using fix nvt/sllod with no fix deform defined");
+ error->all(FLERR,"Using fix nvt/sllod with no fix deform defined");
}
/* ----------------------------------------------------------------------
perform half-step scaling of velocities
-----------------------------------------------------------------------*/
void FixNVTSllod::nh_v_temp()
{
// remove and restore bias = streaming velocity = Hrate*lamda + Hratelo
// thermostat thermal velocity only
// vdelu = SLLOD correction = Hrate*Hinv*vthermal
// for non temp/deform BIAS:
// calculate temperature since some computes require temp
// computed on current nlocal atoms to remove bias
if (nondeformbias) temperature->compute_scalar();
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
double h_two[6],vdelu[3];
MathExtra::multiply_shape_shape(domain->h_rate,domain->h_inv,h_two);
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
vdelu[0] = h_two[0]*v[i][0] + h_two[5]*v[i][1] + h_two[4]*v[i][2];
vdelu[1] = h_two[1]*v[i][1] + h_two[3]*v[i][2];
vdelu[2] = h_two[2]*v[i][2];
temperature->remove_bias(i,v[i]);
v[i][0] = v[i][0]*factor_eta - dthalf*vdelu[0];
v[i][1] = v[i][1]*factor_eta - dthalf*vdelu[1];
v[i][2] = v[i][2]*factor_eta - dthalf*vdelu[2];
temperature->restore_bias(i,v[i]);
}
}
}
diff --git a/src/fix_nvt_sphere.cpp b/src/fix_nvt_sphere.cpp
index 9873917c9..84c4a6bbc 100644
--- a/src/fix_nvt_sphere.cpp
+++ b/src/fix_nvt_sphere.cpp
@@ -1,48 +1,48 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_nvt_sphere.h"
#include "group.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixNVTSphere::FixNVTSphere(LAMMPS *lmp, int narg, char **arg) :
FixNHSphere(lmp, narg, arg)
{
if (!tstat_flag)
- error->all("Temperature control must be used with fix nvt/sphere");
+ error->all(FLERR,"Temperature control must be used with fix nvt/sphere");
if (pstat_flag)
- error->all("Pressure control can not be used with fix nvt/sphere");
+ error->all(FLERR,"Pressure control can not be used with fix nvt/sphere");
// create a new compute temp style
// id = fix-ID + temp
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp/sphere";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
}
diff --git a/src/fix_orient_fcc.cpp b/src/fix_orient_fcc.cpp
index 088c01785..d0269acdd 100644
--- a/src/fix_orient_fcc.cpp
+++ b/src/fix_orient_fcc.cpp
@@ -1,593 +1,590 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Koenraad Janssens and David Olmsted (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "mpi.h"
#include "fix_orient_fcc.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "comm.h"
#include "output.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1000000000
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixOrientFCC::FixOrientFCC(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
MPI_Comm_rank(world,&me);
- if (narg != 11) error->all("Illegal fix orient/fcc command");
+ if (narg != 11) error->all(FLERR,"Illegal fix orient/fcc command");
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
peratom_flag = 1;
size_peratom_cols = 2;
peratom_freq = 1;
nstats = atoi(arg[3]);
direction_of_motion = atoi(arg[4]);
a = atof(arg[5]);
Vxi = atof(arg[6]);
uxif_low = atof(arg[7]);
uxif_high = atof(arg[8]);
if (direction_of_motion == 0) {
int n = strlen(arg[9]) + 1;
chifilename = new char[n];
strcpy(chifilename,arg[9]);
n = strlen(arg[10]) + 1;
xifilename = new char[n];
strcpy(xifilename,arg[10]);
} else if (direction_of_motion == 1) {
int n = strlen(arg[9]) + 1;
xifilename = new char[n];
strcpy(xifilename,arg[9]);
n = strlen(arg[10]) + 1;
chifilename = new char[n];
strcpy(chifilename,arg[10]);
- } else error->all("Illegal fix orient/fcc command");
+ } else error->all(FLERR,"Illegal fix orient/fcc command");
// initializations
PI = 4.0*atan(1.0);
half_fcc_nn = 6;
use_xismooth = false;
double xicutoff = 1.57;
xicutoffsq = xicutoff * xicutoff;
cutsq = 0.5 * a*a*xicutoffsq;
nmax = 0;
// read xi and chi reference orientations from files
if (me == 0) {
char line[512];
char *result;
int count;
FILE *infile = fopen(xifilename,"r");
- if (infile == NULL) error->one("Fix orient/fcc file open failed");
+ if (infile == NULL) error->one(FLERR,"Fix orient/fcc file open failed");
for (int i = 0; i < 6; i++) {
result = fgets(line,512,infile);
- if (!result) error->one("Fix orient/fcc file read failed");
+ if (!result) error->one(FLERR,"Fix orient/fcc file read failed");
count = sscanf(line,"%lg %lg %lg",&Rxi[i][0],&Rxi[i][1],&Rxi[i][2]);
- if (count != 3) error->one("Fix orient/fcc file read failed");
+ if (count != 3) error->one(FLERR,"Fix orient/fcc file read failed");
}
fclose(infile);
infile = fopen(chifilename,"r");
- if (infile == NULL) error->one("Fix orient/fcc file open failed");
+ if (infile == NULL) error->one(FLERR,"Fix orient/fcc file open failed");
for (int i = 0; i < 6; i++) {
result = fgets(line,512,infile);
- if (!result) error->one("Fix orient/fcc file read failed");
+ if (!result) error->one(FLERR,"Fix orient/fcc file read failed");
count = sscanf(line,"%lg %lg %lg",&Rchi[i][0],&Rchi[i][1],&Rchi[i][2]);
- if (count != 3) error->one("Fix orient/fcc file read failed");
+ if (count != 3) error->one(FLERR,"Fix orient/fcc file read failed");
}
fclose(infile);
}
MPI_Bcast(&Rxi[0][0],18,MPI_DOUBLE,0,world);
MPI_Bcast(&Rchi[0][0],18,MPI_DOUBLE,0,world);
// make copy of the reference vectors
for (int i = 0; i < 6; i++)
for (int j = 0; j < 3; j++) {
half_xi_chi_vec[0][i][j] = Rxi[i][j];
half_xi_chi_vec[1][i][j] = Rchi[i][j];
}
// compute xiid,xi0,xi1 for all 12 neighbors
// xi is the favored crystal
// want order parameter when actual is Rchi
double xi_sq,dxi[3],rchi[3];
xiid = 0.0;
for (int i = 0; i < 6; i++) {
rchi[0] = Rchi[i][0];
rchi[1] = Rchi[i][1];
rchi[2] = Rchi[i][2];
find_best_ref(rchi,0,xi_sq,dxi);
xiid += sqrt(xi_sq);
for (int j = 0; j < 3; j++) rchi[j] = -rchi[j];
find_best_ref(rchi,0,xi_sq,dxi);
xiid += sqrt(xi_sq);
}
xiid /= 12.0;
xi0 = uxif_low * xiid;
xi1 = uxif_high * xiid;
// set comm size needed by this Fix
// NOTE: doesn't seem that use_xismooth is ever true
if (use_xismooth) comm_forward = 62;
else comm_forward = 50;
added_energy = 0.0;
nmax = atom->nmax;
nbr = (Nbr *) memory->smalloc(nmax*sizeof(Nbr),"orient/fcc:nbr");
memory->create(order,nmax,2,"orient/fcc:order");
array_atom = order;
// zero the array since a variable may access it before first run
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) order[i][0] = order[i][1] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixOrientFCC::~FixOrientFCC()
{
delete [] xifilename;
delete [] chifilename;
memory->sfree(nbr);
memory->destroy(order);
}
/* ---------------------------------------------------------------------- */
int FixOrientFCC::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixOrientFCC::init()
{
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
// need a full neighbor list, built whenever re-neighboring occurs
int irequest = neighbor->request((void *) this);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
}
/* ---------------------------------------------------------------------- */
void FixOrientFCC::init_list(int id, NeighList *ptr)
{
list = ptr;
}
/* ---------------------------------------------------------------------- */
void FixOrientFCC::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixOrientFCC::post_force(int vflag)
{
int i,j,k,ii,jj,inum,jnum,m,n,nn,nsort,id_self;
int *ilist,*jlist,*numneigh,**firstneigh;
double edelta,omega;
double dx,dy,dz,rsq,xismooth,xi_sq,duxi,duxi_other;
double dxi[3];
double *dxiptr;
bool found_myself;
// set local ptrs
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int *tag = atom->tag;
int nlocal = atom->nlocal;
int nall = atom->nlocal + atom->nghost;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
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/fcc:nbr");
memory->create(order,nmax,2,"orient/fcc:order");
array_atom = order;
}
// loop over owned atoms and build Nbr data structure of neighbors
// use full neighbor list
added_energy = 0.0;
int count = 0;
int mincount = BIG;
int maxcount = 0;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
jlist = firstneigh[i];
jnum = numneigh[i];
if (jnum < mincount) mincount = jnum;
if (jnum > maxcount) {
if (maxcount) delete [] sort;
sort = new Sort[jnum];
maxcount = jnum;
}
// loop over all neighbors of atom i
// for those within cutsq, build sort data structure
// store local id, rsq, delta vector, xismooth (if included)
nsort = 0;
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
count++;
dx = x[i][0] - x[j][0];
dy = x[i][1] - x[j][1];
dz = x[i][2] - x[j][2];
rsq = dx*dx + dy*dy + dz*dz;
if (rsq < cutsq) {
sort[nsort].id = j;
sort[nsort].rsq = rsq;
sort[nsort].delta[0] = dx;
sort[nsort].delta[1] = dy;
sort[nsort].delta[2] = dz;
if (use_xismooth) {
xismooth = (xicutoffsq - 2.0*rsq/(a*a)) / (xicutoffsq - 1.0);
sort[nsort].xismooth = 1.0 - fabs(1.0-xismooth);
}
nsort++;
}
}
// sort neighbors by rsq distance
// no need to sort if nsort <= 12
if (nsort > 12) qsort(sort,nsort,sizeof(Sort),compare);
// copy up to 12 nearest neighbors into nbr data structure
// operate on delta vector via find_best_ref() to compute dxi
n = MIN(12,nsort);
nbr[i].n = n;
if (n == 0) continue;
double xi_total = 0.0;
for (j = 0; j < n; j++) {
find_best_ref(sort[j].delta,0,xi_sq,dxi);
xi_total += sqrt(xi_sq);
nbr[i].id[j] = sort[j].id;
nbr[i].dxi[j][0] = dxi[0]/n;
nbr[i].dxi[j][1] = dxi[1]/n;
nbr[i].dxi[j][2] = dxi[2]/n;
if (use_xismooth) nbr[i].xismooth[j] = sort[j].xismooth;
}
xi_total /= n;
order[i][0] = xi_total;
// compute potential derivative to xi
if (xi_total < xi0) {
nbr[i].duxi = 0.0;
edelta = 0.0;
order[i][1] = 0.0;
} else if (xi_total > xi1) {
nbr[i].duxi = 0.0;
edelta = Vxi;
order[i][1] = 1.0;
} else {
omega = (0.5*PI)*(xi_total-xi0) / (xi1-xi0);
nbr[i].duxi = PI*Vxi*sin(2.0*omega) / (2.0*(xi1-xi0));
edelta = Vxi*(1 - cos(2.0*omega)) / 2.0;
order[i][1] = omega / (0.5*PI);
}
added_energy += edelta;
}
if (maxcount) delete [] sort;
// communicate to acquire nbr data for ghost atoms
comm->forward_comm_fix(this);
// compute grain boundary force on each owned atom
// skip atoms not in group
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
if (!(mask[i] & groupbit)) continue;
n = nbr[i].n;
duxi = nbr[i].duxi;
for (j = 0; j < n; j++) {
dxiptr = &nbr[i].dxi[j][0];
if (use_xismooth) {
xismooth = nbr[i].xismooth[j];
f[i][0] += duxi * dxiptr[0] * xismooth;
f[i][1] += duxi * dxiptr[1] * xismooth;
f[i][2] += duxi * dxiptr[2] * xismooth;
} else {
f[i][0] += duxi * dxiptr[0];
f[i][1] += duxi * dxiptr[1];
f[i][2] += duxi * dxiptr[2];
}
// m = local index of neighbor
// id_self = ID for atom I in atom M's neighbor list
// if M is local atom, id_self will be local ID of atom I
// if M is ghost atom, id_self will be global ID of atom I
m = nbr[i].id[j];
if (m < nlocal) id_self = i;
else id_self = tag[i];
found_myself = false;
nn = nbr[m].n;
for (k = 0; k < nn; k++) {
if (id_self == nbr[m].id[k]) {
- if (found_myself) error->one("Fix orient/fcc found self twice");
+ if (found_myself) error->one(FLERR,"Fix orient/fcc found self twice");
found_myself = true;
duxi_other = nbr[m].duxi;
dxiptr = &nbr[m].dxi[k][0];
if (use_xismooth) {
xismooth = nbr[m].xismooth[k];
f[i][0] -= duxi_other * dxiptr[0] * xismooth;
f[i][1] -= duxi_other * dxiptr[1] * xismooth;
f[i][2] -= duxi_other * dxiptr[2] * xismooth;
} else {
f[i][0] -= duxi_other * dxiptr[0];
f[i][1] -= duxi_other * dxiptr[1];
f[i][2] -= duxi_other * dxiptr[2];
}
}
}
}
}
// print statistics every nstats timesteps
if (nstats && update->ntimestep % nstats == 0) {
int total;
MPI_Allreduce(&count,&total,1,MPI_INT,MPI_SUM,world);
double ave = total/atom->natoms;
int min,max;
MPI_Allreduce(&mincount,&min,1,MPI_INT,MPI_MIN,world);
MPI_Allreduce(&maxcount,&max,1,MPI_INT,MPI_MAX,world);
if (me == 0) {
if (screen) fprintf(screen,
"orient step " BIGINT_FORMAT ": " BIGINT_FORMAT
" atoms have %d neighbors\n",
update->ntimestep,atom->natoms,total);
if (logfile) fprintf(logfile,
"orient step " BIGINT_FORMAT ": " BIGINT_FORMAT
" atoms have %d neighbors\n",
update->ntimestep,atom->natoms,total);
if (screen)
fprintf(screen," neighs: min = %d, max = %d, ave = %g\n",
min,max,ave);
if (logfile)
fprintf(logfile," neighs: min = %d, max = %d, ave = %g\n",
min,max,ave);
}
}
}
/* ---------------------------------------------------------------------- */
void FixOrientFCC::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
double FixOrientFCC::compute_scalar()
{
double added_energy_total;
MPI_Allreduce(&added_energy,&added_energy_total,1,MPI_DOUBLE,MPI_SUM,world);
return added_energy_total;
}
/* ---------------------------------------------------------------------- */
int FixOrientFCC::pack_comm(int n, int *list, double *buf,
int pbc_flag, int *pbc)
{
int i,j,k,id,num;
int *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].duxi;
for (j = 0; j < num; j++) {
if (use_xismooth) buf[m++] = nbr[m].xismooth[j];
buf[m++] = nbr[k].dxi[j][0];
buf[m++] = nbr[k].dxi[j][1];
buf[m++] = nbr[k].dxi[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 = nbr[k].id[j];
if (k < nlocal) id = tag[id];
buf[m++] = id;
}
m += (12-num) * 3;
if (use_xismooth) m += 12-num;
}
if (use_xismooth) return 62;
return 50;
}
/* ---------------------------------------------------------------------- */
void FixOrientFCC::unpack_comm(int n, int first, double *buf)
{
int i,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].duxi = buf[m++];
for (j = 0; j < num; j++) {
if (use_xismooth) nbr[i].xismooth[j] = buf[m++];
nbr[i].dxi[j][0] = buf[m++];
nbr[i].dxi[j][1] = buf[m++];
nbr[i].dxi[j][2] = buf[m++];
nbr[i].id[j] = static_cast<int> (buf[m++]);
}
m += (12-num) * 3;
if (use_xismooth) m += 12-num;
}
}
/* ---------------------------------------------------------------------- */
void FixOrientFCC::find_best_ref(double *displs, int which_crystal,
double &xi_sq, double *dxi)
{
int i;
double dot,tmp;
double best_dot = -1.0; // best is biggest (smallest angle)
int best_i = -1;
int best_sign = 0;
for (i = 0; i < half_fcc_nn; i++) {
dot = displs[0] * half_xi_chi_vec[which_crystal][i][0] +
displs[1] * half_xi_chi_vec[which_crystal][i][1] +
displs[2] * half_xi_chi_vec[which_crystal][i][2];
if (fabs(dot) > best_dot) {
best_dot = fabs(dot);
best_i = i;
if (dot < 0.0) best_sign = -1;
else best_sign = 1;
}
}
xi_sq = 0.0;
for (i = 0; i < 3; i++) {
tmp = displs[i] - best_sign * half_xi_chi_vec[which_crystal][best_i][i];
xi_sq += tmp*tmp;
}
if (xi_sq > 0.0) {
double xi = sqrt(xi_sq);
for (i = 0; i < 3; i++)
dxi[i] = (best_sign * half_xi_chi_vec[which_crystal][best_i][i] -
displs[i]) / xi;
} else dxi[0] = dxi[1] = dxi[2] = 0.0;
}
/* ----------------------------------------------------------------------
compare two neighbors I and J in sort data structure
called via qsort in post_force() method
is a static method so can't access sort data structure directly
return -1 if I < J, 0 if I = J, 1 if I > J
do comparison based on rsq distance
------------------------------------------------------------------------- */
int FixOrientFCC::compare(const void *pi, const void *pj)
{
FixOrientFCC::Sort *ineigh = (FixOrientFCC::Sort *) pi;
FixOrientFCC::Sort *jneigh = (FixOrientFCC::Sort *) pj;
if (ineigh->rsq < jneigh->rsq) return -1;
else if (ineigh->rsq > jneigh->rsq) return 1;
return 0;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixOrientFCC::memory_usage()
{
double bytes = nmax * sizeof(Nbr);
bytes += 2*nmax * sizeof(double);
return bytes;
}
diff --git a/src/fix_planeforce.cpp b/src/fix_planeforce.cpp
index 0cf0ee2b9..5b7a0cfbe 100644
--- a/src/fix_planeforce.cpp
+++ b/src/fix_planeforce.cpp
@@ -1,107 +1,107 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_planeforce.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixPlaneForce::FixPlaneForce(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal fix planeforce command");
+ if (narg != 6) error->all(FLERR,"Illegal fix planeforce command");
xdir = atof(arg[3]);
ydir = atof(arg[4]);
zdir = atof(arg[5]);
double len = sqrt(xdir*xdir + ydir*ydir + zdir*zdir);
- if (len == 0.0) error->all("Illegal fix planeforce command");
+ if (len == 0.0) error->all(FLERR,"Illegal fix planeforce command");
xdir /= len;
ydir /= len;
zdir /= len;
}
/* ---------------------------------------------------------------------- */
int FixPlaneForce::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPlaneForce::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
int nlevels_respa = ((Respa *) update->integrate)->nlevels;
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
}
}
/* ---------------------------------------------------------------------- */
void FixPlaneForce::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixPlaneForce::post_force(int vflag)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double dot;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
dot = f[i][0]*xdir + f[i][1]*ydir + f[i][2]*zdir;
f[i][0] -= dot * xdir;
f[i][1] -= dot * ydir;
f[i][2] -= dot * zdir;
}
}
/* ---------------------------------------------------------------------- */
void FixPlaneForce::post_force_respa(int vflag, int ilevel, int iloop)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixPlaneForce::min_post_force(int vflag)
{
post_force(vflag);
}
diff --git a/src/fix_press_berendsen.cpp b/src/fix_press_berendsen.cpp
index 2da7bde7b..36abc158b 100644
--- a/src/fix_press_berendsen.cpp
+++ b/src/fix_press_berendsen.cpp
@@ -1,513 +1,510 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_press_berendsen.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "modify.h"
#include "fix_deform.h"
#include "compute.h"
#include "kspace.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
enum{NOBIAS,BIAS};
enum{NONE,XYZ,XY,YZ,XZ};
enum{ISO,ANISO};
/* ---------------------------------------------------------------------- */
FixPressBerendsen::FixPressBerendsen(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix press/berendsen command");
+ if (narg < 5) error->all(FLERR,"Illegal fix press/berendsen command");
box_change = 1;
box_change_size = 1;
// Berendsen barostat applied every step
nevery = 1;
// default values
pcouple = NONE;
bulkmodulus = 10.0;
allremap = 1;
for (int i = 0; i < 3; i++) {
p_start[i] = p_stop[i] = p_period[i] = 0.0;
p_flag[i] = 0;
p_period[i] = 0.0;
}
// process keywords
dimension = domain->dimension;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"iso") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
pcouple = XYZ;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"aniso") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
pcouple = NONE;
p_start[0] = p_start[1] = p_start[2] = atof(arg[iarg+1]);
p_stop[0] = p_stop[1] = p_stop[2] = atof(arg[iarg+2]);
p_period[0] = p_period[1] = p_period[2] = atof(arg[iarg+3]);
p_flag[0] = p_flag[1] = p_flag[2] = 1;
if (dimension == 2) {
p_start[2] = p_stop[2] = p_period[2] = 0.0;
p_flag[2] = 0;
}
iarg += 4;
} else if (strcmp(arg[iarg],"x") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
p_start[0] = atof(arg[iarg+1]);
p_stop[0] = atof(arg[iarg+2]);
p_period[0] = atof(arg[iarg+3]);
p_flag[0] = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"y") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
p_start[1] = atof(arg[iarg+1]);
p_stop[1] = atof(arg[iarg+2]);
p_period[1] = atof(arg[iarg+3]);
p_flag[1] = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"z") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
p_start[2] = atof(arg[iarg+1]);
p_stop[2] = atof(arg[iarg+2]);
p_period[2] = atof(arg[iarg+3]);
p_flag[2] = 1;
iarg += 4;
if (dimension == 2)
- error->all("Invalid fix press/berendsen for a 2d simulation");
+ error->all(FLERR,"Invalid fix press/berendsen for a 2d simulation");
} else if (strcmp(arg[iarg],"couple") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
if (strcmp(arg[iarg+1],"xyz") == 0) pcouple = XYZ;
else if (strcmp(arg[iarg+1],"xy") == 0) pcouple = XY;
else if (strcmp(arg[iarg+1],"yz") == 0) pcouple = YZ;
else if (strcmp(arg[iarg+1],"xz") == 0) pcouple = XZ;
else if (strcmp(arg[iarg+1],"none") == 0) pcouple = NONE;
- else error->all("Illegal fix press/berendsen command");
+ else error->all(FLERR,"Illegal fix press/berendsen command");
iarg += 2;
} else if (strcmp(arg[iarg],"modulus") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
bulkmodulus = atof(arg[iarg+1]);
if (bulkmodulus <= 0.0)
- error->all("Illegal fix press/berendsen command");
+ error->all(FLERR,"Illegal fix press/berendsen command");
iarg += 2;
} else if (strcmp(arg[iarg],"dilate") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix press/berendsen command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix press/berendsen command");
if (strcmp(arg[iarg+1],"all") == 0) allremap = 1;
else if (strcmp(arg[iarg+1],"partial") == 0) allremap = 0;
- else error->all("Illegal fix press/berendsen command");
+ else error->all(FLERR,"Illegal fix press/berendsen command");
iarg += 2;
- } else error->all("Illegal fix press/berendsen command");
+ } else error->all(FLERR,"Illegal fix press/berendsen command");
}
if (allremap == 0) restart_pbc = 1;
// error checks
if (dimension == 2 && p_flag[2])
- error->all("Invalid fix press/berendsen for a 2d simulation");
+ error->all(FLERR,"Invalid fix press/berendsen for a 2d simulation");
if (dimension == 2 && (pcouple == YZ || pcouple == XZ))
- error->all("Invalid fix press/berendsen for a 2d simulation");
+ error->all(FLERR,"Invalid fix press/berendsen for a 2d simulation");
if (pcouple == XYZ && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == XYZ && dimension == 3 && p_flag[2] == 0)
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == XY && (p_flag[0] == 0 || p_flag[1] == 0))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == YZ && (p_flag[1] == 0 || p_flag[2] == 0))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == XZ && (p_flag[0] == 0 || p_flag[2] == 0))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (p_flag[0] && domain->xperiodic == 0)
- error->all("Cannot use fix press/berendsen on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix press/berendsen on a non-periodic dimension");
if (p_flag[1] && domain->yperiodic == 0)
- error->all("Cannot use fix press/berendsen on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix press/berendsen on a non-periodic dimension");
if (p_flag[2] && domain->zperiodic == 0)
- error->all("Cannot use fix press/berendsen on a non-periodic dimension");
+ error->all(FLERR,"Cannot use fix press/berendsen on a non-periodic dimension");
if (pcouple == XYZ && dimension == 3 &&
(p_start[0] != p_start[1] || p_start[0] != p_start[2] ||
p_stop[0] != p_stop[1] || p_stop[0] != p_stop[2] ||
p_period[0] != p_period[1] || p_period[0] != p_period[2]))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == XYZ && dimension == 2 &&
(p_start[0] != p_start[1] || p_stop[0] != p_stop[1] ||
p_period[0] != p_period[1]))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == XY &&
(p_start[0] != p_start[1] || p_stop[0] != p_stop[1] ||
p_period[0] != p_period[1]))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == YZ &&
(p_start[1] != p_start[2] || p_stop[1] != p_stop[2] ||
p_period[1] != p_period[2]))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if (pcouple == XZ &&
(p_start[0] != p_start[2] || p_stop[0] != p_stop[2] ||
p_period[0] != p_period[2]))
- error->all("Invalid fix press/berendsen pressure settings");
+ error->all(FLERR,"Invalid fix press/berendsen pressure settings");
if ((p_flag[0] && p_period[0] <= 0.0) ||
(p_flag[1] && p_period[1] <= 0.0) ||
(p_flag[2] && p_period[2] <= 0.0))
- error->all("Fix press/berendsen damping parameters must be > 0.0");
+ error->all(FLERR,"Fix press/berendsen damping parameters must be > 0.0");
// pstyle = ISO if XYZ coupling or XY coupling in 2d -> 1 dof
// else pstyle = ANISO -> 3 dof
if (pcouple == XYZ || (dimension == 2 && pcouple == XY)) pstyle = ISO;
else pstyle = ANISO;
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n = strlen(id) + 7;
id_press = new char[n];
strcpy(id_press,id);
strcat(id_press,"_press");
newarg = new char*[4];
newarg[0] = id_press;
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = id_temp;
modify->add_compute(4,newarg);
delete [] newarg;
pflag = 1;
nrigid = 0;
rfix = NULL;
}
/* ---------------------------------------------------------------------- */
FixPressBerendsen::~FixPressBerendsen()
{
delete [] rfix;
// delete temperature and pressure if fix created them
if (tflag) modify->delete_compute(id_temp);
if (pflag) modify->delete_compute(id_press);
delete [] id_temp;
delete [] id_press;
}
/* ---------------------------------------------------------------------- */
int FixPressBerendsen::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPressBerendsen::init()
{
if (domain->triclinic)
- error->all("Cannot use fix press/berendsen with triclinic box");
+ error->all(FLERR,"Cannot use fix press/berendsen with triclinic box");
// insure no conflict with fix deform
for (int i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"deform") == 0) {
int *dimflag = ((FixDeform *) modify->fix[i])->dimflag;
if ((p_flag[0] && dimflag[0]) || (p_flag[1] && dimflag[1]) ||
(p_flag[2] && dimflag[2]))
- error->all("Cannot use fix press/berendsen and "
+ error->all(FLERR,"Cannot use fix press/berendsen and "
"fix deform on same component of stress tensor");
}
// set temperature and pressure ptrs
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix press/berendsen does not exist");
+ error->all(FLERR,"Temperature ID for fix press/berendsen does not exist");
temperature = modify->compute[icompute];
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
icompute = modify->find_compute(id_press);
if (icompute < 0)
- error->all("Pressure ID for fix press/berendsen does not exist");
+ error->all(FLERR,"Pressure ID for fix press/berendsen does not exist");
pressure = modify->compute[icompute];
// Kspace setting
if (force->kspace) kspace_flag = 1;
else kspace_flag = 0;
// detect if any rigid fixes exist so rigid bodies move when box is remapped
// rfix[] = indices to each fix rigid
delete [] rfix;
nrigid = 0;
rfix = NULL;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) nrigid++;
if (nrigid) {
rfix = new int[nrigid];
nrigid = 0;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) rfix[nrigid++] = i;
}
}
/* ----------------------------------------------------------------------
compute T,P before integrator starts
------------------------------------------------------------------------- */
void FixPressBerendsen::setup(int vflag)
{
// trigger virial computation on next timestep
pressure->addstep(update->ntimestep+1);
}
/* ---------------------------------------------------------------------- */
void FixPressBerendsen::end_of_step()
{
// compute new T,P
if (pstyle == ISO) {
double tmp = temperature->compute_scalar();
tmp = pressure->compute_scalar();
} else {
temperature->compute_vector();
pressure->compute_vector();
}
couple();
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
for (int i = 0; i < 3; i++) {
if (p_flag[i]) {
p_target[i] = p_start[i] + delta * (p_stop[i]-p_start[i]);
dilation[i] =
pow(1.0 - update->dt/p_period[i] *
(p_target[i]-p_current[i])/bulkmodulus,1.0/3.0);
}
}
// remap simulation box and atoms
// redo KSpace coeffs since volume has changed
remap();
if (kspace_flag) force->kspace->setup();
// trigger virial computation on next timestep
pressure->addstep(update->ntimestep+1);
}
/* ---------------------------------------------------------------------- */
void FixPressBerendsen::couple()
{
double *tensor = pressure->vector;
if (pstyle == ISO)
p_current[0] = p_current[1] = p_current[2] = pressure->scalar;
else if (pcouple == XYZ) {
double ave = 1.0/3.0 * (tensor[0] + tensor[1] + tensor[2]);
p_current[0] = p_current[1] = p_current[2] = ave;
} else if (pcouple == XY) {
double ave = 0.5 * (tensor[0] + tensor[1]);
p_current[0] = p_current[1] = ave;
p_current[2] = tensor[2];
} else if (pcouple == YZ) {
double ave = 0.5 * (tensor[1] + tensor[2]);
p_current[1] = p_current[2] = ave;
p_current[0] = tensor[0];
} else if (pcouple == XZ) {
double ave = 0.5 * (tensor[0] + tensor[2]);
p_current[0] = p_current[2] = ave;
p_current[1] = tensor[1];
} else {
p_current[0] = tensor[0];
p_current[1] = tensor[1];
p_current[2] = tensor[2];
}
}
/* ----------------------------------------------------------------------
change box size
remap all atoms or fix group atoms depending on allremap flag
if rigid bodies exist, scale rigid body centers-of-mass
------------------------------------------------------------------------- */
void FixPressBerendsen::remap()
{
int i;
double oldlo,oldhi,ctr;
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// convert pertinent atoms and rigid bodies to lamda coords
if (allremap) domain->x2lamda(nlocal);
else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->x2lamda(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(0);
// reset global and local box to new size/shape
for (i = 0; i < 3; i++) {
if (p_flag[i]) {
oldlo = domain->boxlo[i];
oldhi = domain->boxhi[i];
ctr = 0.5 * (oldlo + oldhi);
domain->boxlo[i] = (oldlo-ctr)*dilation[i] + ctr;
domain->boxhi[i] = (oldhi-ctr)*dilation[i] + ctr;
}
}
domain->set_global_box();
domain->set_local_box();
// convert pertinent atoms and rigid bodies back to box coords
if (allremap) domain->lamda2x(nlocal);
else {
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
domain->lamda2x(x[i],x[i]);
}
if (nrigid)
for (i = 0; i < nrigid; i++)
modify->fix[rfix[i]]->deform(1);
}
/* ---------------------------------------------------------------------- */
int FixPressBerendsen::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != 0 && comm->me == 0)
- error->warning("Temperature for NPT is not for group all");
+ error->warning(FLERR,"Temperature for NPT is not for group all");
// reset id_temp of pressure to new temperature ID
icompute = modify->find_compute(id_press);
if (icompute < 0)
- error->all("Pressure ID for fix press/berendsen does not exist");
+ error->all(FLERR,"Pressure ID for fix press/berendsen does not exist");
modify->compute[icompute]->reset_extra_compute_fix(id_temp);
return 2;
} else if (strcmp(arg[0],"press") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (pflag) {
modify->delete_compute(id_press);
pflag = 0;
}
delete [] id_press;
int n = strlen(arg[1]) + 1;
id_press = new char[n];
strcpy(id_press,arg[1]);
int icompute = modify->find_compute(arg[1]);
- if (icompute < 0) error->all("Could not find fix_modify pressure ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify pressure ID");
pressure = modify->compute[icompute];
if (pressure->pressflag == 0)
- error->all("Fix_modify pressure ID does not compute pressure");
+ error->all(FLERR,"Fix_modify pressure ID does not compute pressure");
return 2;
}
return 0;
}
diff --git a/src/fix_print.cpp b/src/fix_print.cpp
index 682c7b1b5..c38945a8c 100644
--- a/src/fix_print.cpp
+++ b/src/fix_print.cpp
@@ -1,143 +1,143 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_print.h"
#include "update.h"
#include "input.h"
#include "modify.h"
#include "variable.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
FixPrint::FixPrint(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix print command");
+ if (narg < 5) error->all(FLERR,"Illegal fix print command");
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix print command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix print command");
MPI_Comm_rank(world,&me);
int n = strlen(arg[4]) + 1;
string = new char[n];
strcpy(string,arg[4]);
// parse optional args
fp = NULL;
screenflag = 1;
char *title = NULL;
int iarg = 5;
while (iarg < narg) {
if (strcmp(arg[iarg],"file") == 0 || strcmp(arg[iarg],"append") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix print command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix print command");
if (me == 0) {
if (strcmp(arg[iarg],"file") == 0) fp = fopen(arg[iarg+1],"w");
else fp = fopen(arg[iarg+1],"a");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix print file %s",arg[iarg+1]);
- error->one(str);
+ error->one(FLERR,str);
}
}
iarg += 2;
} else if (strcmp(arg[iarg],"screen") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix print command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix print command");
if (strcmp(arg[iarg+1],"yes") == 0) screenflag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) screenflag = 0;
- else error->all("Illegal fix print command");
+ else error->all(FLERR,"Illegal fix print command");
iarg += 2;
} else if (strcmp(arg[iarg],"title") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix print command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix print command");
delete [] title;
int n = strlen(arg[iarg+1]) + 1;
title = new char[n];
strcpy(title,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix print command");
+ } else error->all(FLERR,"Illegal fix print command");
}
// print file comment line
if (fp && me == 0) {
if (title) fprintf(fp,"%s\n",title);
else fprintf(fp,"# Fix print output for fix %s\n",id);
}
delete [] title;
copy = new char[MAXLINE];
work = new char[MAXLINE];
// add nfirst to all computes that store invocation times
// since don't know a priori which are invoked via variables by this fix
// once in end_of_step() can set timestep for ones actually invoked
int nfirst = (update->ntimestep/nevery)*nevery + nevery;
modify->addstep_compute_all(nfirst);
}
/* ---------------------------------------------------------------------- */
FixPrint::~FixPrint()
{
delete [] string;
delete [] copy;
delete [] work;
if (fp && me == 0) fclose(fp);
}
/* ---------------------------------------------------------------------- */
int FixPrint::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixPrint::end_of_step()
{
// make a copy of string to work on
// substitute for $ variables (no printing)
// append a newline and print final copy
// variable evaluation may invoke computes so wrap with clear/add
modify->clearstep_compute();
strcpy(copy,string);
input->substitute(copy,0);
strcat(copy,"\n");
modify->addstep_compute(update->ntimestep + nevery);
if (me == 0) {
if (screenflag && screen) fprintf(screen,copy);
if (screenflag && logfile) fprintf(logfile,copy);
if (fp) {
fprintf(fp,copy);
fflush(fp);
}
}
}
diff --git a/src/fix_recenter.cpp b/src/fix_recenter.cpp
index cd2b311c9..ac752b99c 100644
--- a/src/fix_recenter.cpp
+++ b/src/fix_recenter.cpp
@@ -1,187 +1,187 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Naveen Michaud-Agrawal (Johns Hopkins U)
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_recenter.h"
#include "atom.h"
#include "group.h"
#include "domain.h"
#include "lattice.h"
#include "modify.h"
#include "comm.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{BOX,LATTICE,FRACTION};
/* ---------------------------------------------------------------------- */
FixRecenter::FixRecenter(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix recenter command");
+ if (narg < 6) error->all(FLERR,"Illegal fix recenter command");
xcom = ycom = zcom = 0.0;
xflag = yflag = zflag = 1;
xinitflag = yinitflag = zinitflag = 0;
if (strcmp(arg[3],"NULL") == 0) xflag = 0;
else if (strcmp(arg[3],"INIT") == 0) xinitflag = 1;
else xcom = atof(arg[3]);
if (strcmp(arg[4],"NULL") == 0) yflag = 0;
else if (strcmp(arg[4],"INIT") == 0) yinitflag = 1;
else ycom = atof(arg[4]);
if (strcmp(arg[5],"NULL") == 0) zflag = 0;
else if (strcmp(arg[5],"INIT") == 0) zinitflag = 1;
else zcom = atof(arg[5]);
// optional args
group2bit = groupbit;
scaleflag = LATTICE;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"shift") == 0) {
int igroup2 = group->find(arg[iarg+1]);
- if (igroup2 < 0) error->all("Could not find fix recenter group ID");
+ if (igroup2 < 0) error->all(FLERR,"Could not find fix recenter group ID");
group2bit = group->bitmask[igroup2];
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = BOX;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = LATTICE;
else if (strcmp(arg[iarg+1],"fraction") == 0) scaleflag = FRACTION;
- else error->all("Illegal fix recenter command");
+ else error->all(FLERR,"Illegal fix recenter command");
iarg += 2;
- } else error->all("Illegal fix recenter command");
+ } else error->all(FLERR,"Illegal fix recenter command");
}
// scale xcom,ycom,zcom
if (scaleflag == LATTICE && domain->lattice == NULL)
- error->all("Use of fix recenter with undefined lattice");
+ error->all(FLERR,"Use of fix recenter with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag == LATTICE) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
xcom *= xscale;
ycom *= yscale;
zcom *= zscale;
// cannot have 0 atoms in group
if (group->count(igroup) == 0)
- error->all("Fix recenter group has no atoms");
+ error->all(FLERR,"Fix recenter group has no atoms");
}
/* ---------------------------------------------------------------------- */
int FixRecenter::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixRecenter::init()
{
// warn if any integrate fix comes after this one
int after = 0;
int flag = 0;
for (int i = 0; i < modify->nfix; i++) {
if (strcmp(id,modify->fix[i]->id) == 0) after = 1;
else if ((modify->fmask[i] & INITIAL_INTEGRATE) && after) flag = 1;
}
if (flag && comm->me == 0)
- error->warning("Fix recenter should come after all other integration fixes");
+ error->warning(FLERR,"Fix recenter should come after all other integration fixes");
masstotal = group->mass(igroup);
// if any components of requested COM were INIT, store initial COM
if (xinitflag || yinitflag || zinitflag) {
double xcm[3];
group->xcm(igroup,masstotal,xcm);
xinit = xcm[0];
yinit = xcm[1];
zinit = xcm[2];
}
}
/* ---------------------------------------------------------------------- */
void FixRecenter::initial_integrate(int vflag)
{
// target COM
// bounding box around domain works for both orthogonal and triclinic
double xtarget,ytarget,ztarget;
double *bboxlo,*bboxhi;
if (scaleflag == FRACTION) {
if (domain->triclinic == 0) {
bboxlo = domain->boxlo;
bboxhi = domain->boxhi;
} else {
bboxlo = domain->boxlo_bound;
bboxhi = domain->boxhi_bound;
}
}
if (xinitflag) xtarget = xinit;
else if (scaleflag == FRACTION)
xtarget = bboxlo[0] + xcom*(bboxhi[0] - bboxlo[0]);
else xtarget = xcom;
if (yinitflag) ytarget = yinit;
else if (scaleflag == FRACTION)
ytarget = bboxlo[1] + ycom*(bboxhi[1] - bboxlo[1]);
else ytarget = ycom;
if (zinitflag) ztarget = zinit;
else if (scaleflag == FRACTION)
ztarget = bboxlo[2] + zcom*(bboxhi[2] - bboxlo[2]);
else ztarget = zcom;
// current COM
double xcm[3];
group->xcm(igroup,masstotal,xcm);
// shift coords by difference between actual COM and requested COM
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & group2bit) {
if (xflag) x[i][0] += xtarget - xcm[0];
if (yflag) x[i][1] += ytarget - xcm[1];
if (zflag) x[i][2] += ztarget - xcm[2];
}
}
diff --git a/src/fix_restrain.cpp b/src/fix_restrain.cpp
index b9e16c7a4..43f7f6108 100644
--- a/src/fix_restrain.cpp
+++ b/src/fix_restrain.cpp
@@ -1,401 +1,401 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Craig Tenney (University of Notre Dame)
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_restrain.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "domain.h"
#include "comm.h"
#include "respa.h"
#include "input.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{DIHEDRAL};
#define TOLERANCE 0.05
/* ---------------------------------------------------------------------- */
FixRestrain::FixRestrain(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
int iarg = 6;
- if (narg < iarg) error->all("Illegal fix restrain command");
+ if (narg < iarg) error->all(FLERR,"Illegal fix restrain command");
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
time_depend = 1;
// parse standard arguments
int n_atoms;
k_start = force->numeric(arg[3]);
k_stop = force->numeric(arg[4]);
if (strcmp(arg[5], "dihedral") == 0) {
rstyle = DIHEDRAL;
n_atoms = 4;
- } else error->all("Illegal fix restrain command");
+ } else error->all(FLERR,"Illegal fix restrain command");
n_bonds = (narg - iarg) / (n_atoms + 1);
if (narg != iarg + n_bonds * (n_atoms + 1))
- error->all("Illegal fix restrain command");
+ error->all(FLERR,"Illegal fix restrain command");
// allocate arrays
memory->create(atom_id,n_bonds,n_atoms,"restrain:atom_id");
memory->create(target,n_bonds,"restrain:taret");
// grab atom_ids and restraint target values
int ibond = 0;
while (iarg < narg) {
for (int i = 0; i < n_atoms; i++) {
atom_id[ibond][i] = force->inumeric(arg[iarg]);
iarg++;
}
target[ibond] = force->numeric(arg[iarg]);
iarg++;
ibond++;
}
// special treatment for dihedral restraints
if (rstyle == DIHEDRAL) {
double PI = 4.0*atan(1.0);
cos_shift = (double *)
memory->smalloc(n_bonds * sizeof(double), "restrain:cos_shift");
sin_shift = (double *)
memory->smalloc(n_bonds * sizeof(double), "restrain:sin_shift");
for (ibond = 0; ibond < n_bonds; ibond++) {
double my_arg = PI * (180.0 + target[ibond]) / 180.0;
cos_shift[ibond] = cos(my_arg);
sin_shift[ibond] = sin(my_arg);
}
}
// require atom map to lookup atom IDs
if (atom->map_style == 0)
- error->all("Fix restrain requires an atom map, see atom_modify");
+ error->all(FLERR,"Fix restrain requires an atom map, see atom_modify");
}
/* ---------------------------------------------------------------------- */
FixRestrain::~FixRestrain()
{
memory->destroy(atom_id);
memory->destroy(target);
if (rstyle == DIHEDRAL) {
memory->sfree(cos_shift);
memory->sfree(sin_shift);
}
}
/* ---------------------------------------------------------------------- */
int FixRestrain::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixRestrain::init()
{
if (strcmp(update->integrate_style,"respa") == 0)
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixRestrain::setup(int vflag)
{
if (strcmp(update->integrate_style,"verlet") == 0)
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixRestrain::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixRestrain::post_force(int vflag)
{
energy = 0.0;
if (rstyle == DIHEDRAL) restrain_dihedral();
}
/* ---------------------------------------------------------------------- */
void FixRestrain::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixRestrain::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
apply dihedral restraints
adopted from dihedral_charmm
---------------------------------------------------------------------- */
void FixRestrain::restrain_dihedral()
{
int i1,i2,i3,i4,i,m,n;
double vb1x,vb1y,vb1z,vb2x,vb2y,vb2z,vb3x,vb3y,vb3z,vb2xm,vb2ym,vb2zm;
double f1[3],f2[3],f3[3],f4[3];
double ax,ay,az,bx,by,bz,rasq,rbsq,rgsq,rg,rginv,ra2inv,rb2inv,rabinv;
double df,df1,ddf1,fg,hg,fga,hgb,gaa,gbb;
double dtfx,dtfy,dtfz,dtgx,dtgy,dtgz,dthx,dthy,dthz;
double c,s,p,sx2,sy2,sz2;
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
int newton_bond = force->newton_bond;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double k_step = k_start + delta * (k_stop - k_start);
for (n = 0; n < n_bonds; n++) {
i1 = atom->map(atom_id[n][0]);
i2 = atom->map(atom_id[n][1]);
i3 = atom->map(atom_id[n][2]);
i4 = atom->map(atom_id[n][3]);
// insure exactly one processor computes restraint
if (newton_bond) {
if (i2 == -1 || i2 >= nlocal) continue;
if (i1 == -1 || i3 == -1 || i4 == -1) {
char str[128];
sprintf(str,
"Restrain atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
atom_id[n][0],atom_id[n][1],atom_id[n][2],atom_id[n][3],
comm->me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
} else {
if ((i1 == -1 || i1 >= nlocal) && (i2 == -1 || i2 >= nlocal) &&
(i3 == -1 || i3 >= nlocal) && (i4 == -1 || i3 >= nlocal)) continue;
if (i1 == -1 || i2 == -1 || i3 == -1 || i4 == -1) {
char str[128];
sprintf(str,
"Restrain atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
atom_id[n][0],atom_id[n][1],atom_id[n][2],atom_id[n][3],
comm->me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
}
// 1st bond
vb1x = x[i1][0] - x[i2][0];
vb1y = x[i1][1] - x[i2][1];
vb1z = x[i1][2] - x[i2][2];
domain->minimum_image(vb1x,vb1y,vb1z);
// 2nd bond
vb2x = x[i3][0] - x[i2][0];
vb2y = x[i3][1] - x[i2][1];
vb2z = x[i3][2] - x[i2][2];
domain->minimum_image(vb2x,vb2y,vb2z);
vb2xm = -vb2x;
vb2ym = -vb2y;
vb2zm = -vb2z;
domain->minimum_image(vb2xm,vb2ym,vb2zm);
// 3rd bond
vb3x = x[i4][0] - x[i3][0];
vb3y = x[i4][1] - x[i3][1];
vb3z = x[i4][2] - x[i3][2];
domain->minimum_image(vb3x,vb3y,vb3z);
ax = vb1y*vb2zm - vb1z*vb2ym;
ay = vb1z*vb2xm - vb1x*vb2zm;
az = vb1x*vb2ym - vb1y*vb2xm;
bx = vb3y*vb2zm - vb3z*vb2ym;
by = vb3z*vb2xm - vb3x*vb2zm;
bz = vb3x*vb2ym - vb3y*vb2xm;
rasq = ax*ax + ay*ay + az*az;
rbsq = bx*bx + by*by + bz*bz;
rgsq = vb2xm*vb2xm + vb2ym*vb2ym + vb2zm*vb2zm;
rg = sqrt(rgsq);
rginv = ra2inv = rb2inv = 0.0;
if (rg > 0) rginv = 1.0/rg;
if (rasq > 0) ra2inv = 1.0/rasq;
if (rbsq > 0) rb2inv = 1.0/rbsq;
rabinv = sqrt(ra2inv*rb2inv);
c = (ax*bx + ay*by + az*bz)*rabinv;
s = rg*rabinv*(ax*vb3x + ay*vb3y + az*vb3z);
// error check
if (c > 1.0 + TOLERANCE || c < (-1.0 - TOLERANCE)) {
int me;
MPI_Comm_rank(world,&me);
if (screen) {
char str[128];
sprintf(str,"Restrain problem: %d " BIGINT_FORMAT " %d %d %d %d",
me,update->ntimestep,
atom->tag[i1],atom->tag[i2],atom->tag[i3],atom->tag[i4]);
- error->warning(str);
+ error->warning(FLERR,str);
fprintf(screen," 1st atom: %d %g %g %g\n",
me,x[i1][0],x[i1][1],x[i1][2]);
fprintf(screen," 2nd atom: %d %g %g %g\n",
me,x[i2][0],x[i2][1],x[i2][2]);
fprintf(screen," 3rd atom: %d %g %g %g\n",
me,x[i3][0],x[i3][1],x[i3][2]);
fprintf(screen," 4th atom: %d %g %g %g\n",
me,x[i4][0],x[i4][1],x[i4][2]);
}
}
if (c > 1.0) c = 1.0;
if (c < -1.0) c = -1.0;
m = 1; //multiplicity
p = 1.0;
df1 = 0.0;
for (i = 0; i < m; i++) {
ddf1 = p*c - df1*s;
df1 = p*s + df1*c;
p = ddf1;
}
p = p*cos_shift[n] + df1*sin_shift[n];
df1 = df1*cos_shift[n] - ddf1*sin_shift[n];
df1 *= -m;
p += 1.0;
energy = k_step * p;
fg = vb1x*vb2xm + vb1y*vb2ym + vb1z*vb2zm;
hg = vb3x*vb2xm + vb3y*vb2ym + vb3z*vb2zm;
fga = fg*ra2inv*rginv;
hgb = hg*rb2inv*rginv;
gaa = -ra2inv*rg;
gbb = rb2inv*rg;
dtfx = gaa*ax;
dtfy = gaa*ay;
dtfz = gaa*az;
dtgx = fga*ax - hgb*bx;
dtgy = fga*ay - hgb*by;
dtgz = fga*az - hgb*bz;
dthx = gbb*bx;
dthy = gbb*by;
dthz = gbb*bz;
df = -k_step * df1;
sx2 = df*dtgx;
sy2 = df*dtgy;
sz2 = df*dtgz;
f1[0] = df*dtfx;
f1[1] = df*dtfy;
f1[2] = df*dtfz;
f2[0] = sx2 - f1[0];
f2[1] = sy2 - f1[1];
f2[2] = sz2 - f1[2];
f4[0] = df*dthx;
f4[1] = df*dthy;
f4[2] = df*dthz;
f3[0] = -sx2 - f4[0];
f3[1] = -sy2 - f4[1];
f3[2] = -sz2 - f4[2];
// apply force to each of 4 atoms
if (newton_bond || i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (newton_bond || i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (newton_bond || i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (newton_bond || i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
}
}
/* ----------------------------------------------------------------------
potential energy of added force
------------------------------------------------------------------------- */
double FixRestrain::compute_scalar()
{
MPI_Allreduce(&energy,&energy_all,1,MPI_DOUBLE,MPI_SUM,world);
return energy_all;
}
diff --git a/src/fix_rigid.cpp b/src/fix_rigid.cpp
index b2b79a5af..cf63dfa11 100644
--- a/src/fix_rigid.cpp
+++ b/src/fix_rigid.cpp
@@ -1,1985 +1,1982 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fix_rigid.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "domain.h"
#include "update.h"
#include "respa.h"
#include "modify.h"
#include "group.h"
#include "comm.h"
#include "random_mars.h"
#include "force.h"
#include "output.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define TOLERANCE 1.0e-6
#define EPSILON 1.0e-7
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixRigid::FixRigid(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
int i,ibody;
scalar_flag = 1;
extscalar = 0;
time_integrate = 1;
rigid_flag = 1;
virial_flag = 1;
create_attribute = 1;
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
// perform initial allocation of atom-based arrays
// register with Atom class
extended = dorientflag = qorientflag = 0;
body = NULL;
displace = NULL;
eflags = NULL;
dorient = NULL;
qorient = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
// parse args for rigid body specification
// set nbody and body[i] for each atom
- if (narg < 4) error->all("Illegal fix rigid command");
+ if (narg < 4) error->all(FLERR,"Illegal fix rigid command");
int iarg;
// single rigid body
// nbody = 1
// all atoms in fix group are part of body
if (strcmp(arg[3],"single") == 0) {
iarg = 4;
nbody = 1;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
body[i] = -1;
if (mask[i] & groupbit) body[i] = 0;
}
// each molecule in fix group is a rigid body
// maxmol = largest molecule #
// ncount = # of atoms in each molecule (have to sum across procs)
// nbody = # of non-zero ncount values
// use nall as incremented ptr to set body[] values for each atom
} else if (strcmp(arg[3],"molecule") == 0) {
iarg = 4;
if (atom->molecule_flag == 0)
- error->all("Fix rigid molecule requires atom attribute molecule");
+ error->all(FLERR,"Fix rigid molecule requires atom attribute molecule");
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int maxmol = -1;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) maxmol = MAX(maxmol,molecule[i]);
int itmp;
MPI_Allreduce(&maxmol,&itmp,1,MPI_INT,MPI_MAX,world);
maxmol = itmp + 1;
int *ncount = new int[maxmol];
for (i = 0; i < maxmol; i++) ncount[i] = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) ncount[molecule[i]]++;
int *nall = new int[maxmol];
MPI_Allreduce(ncount,nall,maxmol,MPI_INT,MPI_SUM,world);
nbody = 0;
for (i = 0; i < maxmol; i++)
if (nall[i]) nall[i] = nbody++;
else nall[i] = -1;
for (i = 0; i < nlocal; i++) {
body[i] = -1;
if (mask[i] & groupbit) body[i] = nall[molecule[i]];
}
delete [] ncount;
delete [] nall;
// each listed group is a rigid body
// check if all listed groups exist
// an atom must belong to fix group and listed group to be in rigid body
// error if atom belongs to more than 1 rigid body
} else if (strcmp(arg[3],"group") == 0) {
- if (narg < 5) error->all("Illegal fix rigid command");
+ if (narg < 5) error->all(FLERR,"Illegal fix rigid command");
nbody = atoi(arg[4]);
- if (nbody <= 0) error->all("Illegal fix rigid command");
- if (narg < 5+nbody) error->all("Illegal fix rigid command");
+ if (nbody <= 0) error->all(FLERR,"Illegal fix rigid command");
+ if (narg < 5+nbody) error->all(FLERR,"Illegal fix rigid command");
iarg = 5+nbody;
int *igroups = new int[nbody];
for (ibody = 0; ibody < nbody; ibody++) {
igroups[ibody] = group->find(arg[5+ibody]);
if (igroups[ibody] == -1)
- error->all("Could not find fix rigid group ID");
+ error->all(FLERR,"Could not find fix rigid group ID");
}
int *mask = atom->mask;
int nlocal = atom->nlocal;
int flag = 0;
for (i = 0; i < nlocal; i++) {
body[i] = -1;
if (mask[i] & groupbit)
for (ibody = 0; ibody < nbody; ibody++)
if (mask[i] & group->bitmask[igroups[ibody]]) {
if (body[i] >= 0) flag = 1;
body[i] = ibody;
}
}
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall)
- error->all("One or more atoms belong to multiple rigid bodies");
+ error->all(FLERR,"One or more atoms belong to multiple rigid bodies");
delete [] igroups;
- } else error->all("Illegal fix rigid command");
+ } else error->all(FLERR,"Illegal fix rigid command");
// error check on nbody
- if (nbody == 0) error->all("No rigid bodies defined");
+ if (nbody == 0) error->all(FLERR,"No rigid bodies defined");
// create all nbody-length arrays
memory->create(nrigid,nbody,"rigid:nrigid");
memory->create(masstotal,nbody,"rigid:masstotal");
memory->create(xcm,nbody,3,"rigid:xcm");
memory->create(vcm,nbody,3,"rigid:vcm");
memory->create(fcm,nbody,3,"rigid:fcm");
memory->create(inertia,nbody,3,"rigid:inertia");
memory->create(ex_space,nbody,3,"rigid:ex_space");
memory->create(ey_space,nbody,3,"rigid:ey_space");
memory->create(ez_space,nbody,3,"rigid:ez_space");
memory->create(angmom,nbody,3,"rigid:angmom");
memory->create(omega,nbody,3,"rigid:omega");
memory->create(torque,nbody,3,"rigid:torque");
memory->create(quat,nbody,4,"rigid:quat");
memory->create(imagebody,nbody,"rigid:imagebody");
memory->create(fflag,nbody,3,"rigid:fflag");
memory->create(tflag,nbody,3,"rigid:tflag");
memory->create(langextra,nbody,6,"rigid:langextra");
memory->create(sum,nbody,6,"rigid:sum");
memory->create(all,nbody,6,"rigid:all");
memory->create(remapflag,nbody,4,"rigid:remapflag");
// initialize force/torque flags to default = 1.0
// for 2d: fz, tx, ty = 0.0
array_flag = 1;
size_array_rows = nbody;
size_array_cols = 15;
global_freq = 1;
extarray = 0;
for (i = 0; i < nbody; i++) {
fflag[i][0] = fflag[i][1] = fflag[i][2] = 1.0;
tflag[i][0] = tflag[i][1] = tflag[i][2] = 1.0;
if (domain->dimension == 2) fflag[i][2] = tflag[i][0] = tflag[i][1] = 0.0;
}
// parse optional args
int seed;
langflag = 0;
tempflag = 0;
pressflag = 0;
t_chain = 10;
t_iter = 1;
t_order = 3;
p_chain = 10;
while (iarg < narg) {
if (strcmp(arg[iarg],"force") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix rigid command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix rigid command");
int mlo,mhi;
force->bounds(arg[iarg+1],nbody,mlo,mhi);
double xflag,yflag,zflag;
if (strcmp(arg[iarg+2],"off") == 0) xflag = 0.0;
else if (strcmp(arg[iarg+2],"on") == 0) xflag = 1.0;
- else error->all("Illegal fix rigid command");
+ else error->all(FLERR,"Illegal fix rigid command");
if (strcmp(arg[iarg+3],"off") == 0) yflag = 0.0;
else if (strcmp(arg[iarg+3],"on") == 0) yflag = 1.0;
- else error->all("Illegal fix rigid command");
+ else error->all(FLERR,"Illegal fix rigid command");
if (strcmp(arg[iarg+4],"off") == 0) zflag = 0.0;
else if (strcmp(arg[iarg+4],"on") == 0) zflag = 1.0;
- else error->all("Illegal fix rigid command");
+ else error->all(FLERR,"Illegal fix rigid command");
if (domain->dimension == 2 && zflag == 1.0)
- error->all("Fix rigid z force cannot be on for 2d simulation");
+ error->all(FLERR,"Fix rigid z force cannot be on for 2d simulation");
int count = 0;
for (int m = mlo; m <= mhi; m++) {
fflag[m-1][0] = xflag;
fflag[m-1][1] = yflag;
fflag[m-1][2] = zflag;
count++;
}
- if (count == 0) error->all("Illegal fix rigid command");
+ if (count == 0) error->all(FLERR,"Illegal fix rigid command");
iarg += 5;
} else if (strcmp(arg[iarg],"torque") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix rigid command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix rigid command");
int mlo,mhi;
force->bounds(arg[iarg+1],nbody,mlo,mhi);
double xflag,yflag,zflag;
if (strcmp(arg[iarg+2],"off") == 0) xflag = 0.0;
else if (strcmp(arg[iarg+2],"on") == 0) xflag = 1.0;
- else error->all("Illegal fix rigid command");
+ else error->all(FLERR,"Illegal fix rigid command");
if (strcmp(arg[iarg+3],"off") == 0) yflag = 0.0;
else if (strcmp(arg[iarg+3],"on") == 0) yflag = 1.0;
- else error->all("Illegal fix rigid command");
+ else error->all(FLERR,"Illegal fix rigid command");
if (strcmp(arg[iarg+4],"off") == 0) zflag = 0.0;
else if (strcmp(arg[iarg+4],"on") == 0) zflag = 1.0;
- else error->all("Illegal fix rigid command");
+ else error->all(FLERR,"Illegal fix rigid command");
if (domain->dimension == 2 && (xflag == 1.0 || yflag == 1.0))
- error->all("Fix rigid xy torque cannot be on for 2d simulation");
+ error->all(FLERR,"Fix rigid xy torque cannot be on for 2d simulation");
int count = 0;
for (int m = mlo; m <= mhi; m++) {
tflag[m-1][0] = xflag;
tflag[m-1][1] = yflag;
tflag[m-1][2] = zflag;
count++;
}
- if (count == 0) error->all("Illegal fix rigid command");
+ if (count == 0) error->all(FLERR,"Illegal fix rigid command");
iarg += 5;
} else if (strcmp(arg[iarg],"langevin") == 0) {
- if (iarg+5 > narg) error->all("Illegal fix rigid command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix rigid command");
if (strcmp(style,"rigid") != 0 && strcmp(style,"rigid/nve") != 0)
- error->all("Illegal fix rigid command");
+ error->all(FLERR,"Illegal fix rigid command");
langflag = 1;
t_start = atof(arg[iarg+1]);
t_stop = atof(arg[iarg+2]);
t_period = atof(arg[iarg+3]);
seed = atoi(arg[iarg+4]);
if (t_period <= 0.0)
- error->all("Fix rigid langevin period must be > 0.0");
- if (seed <= 0) error->all("Illegal fix rigid command");
+ error->all(FLERR,"Fix rigid langevin period must be > 0.0");
+ if (seed <= 0) error->all(FLERR,"Illegal fix rigid command");
iarg += 5;
} else if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix rigid command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix rigid command");
if (strcmp(style,"rigid/nvt") != 0 && strcmp(style,"rigid/npt") != 0)
- error->all("Illegal fix rigid command");
+ error->all(FLERR,"Illegal fix rigid command");
tempflag = 1;
t_start = atof(arg[iarg+1]);
t_stop = atof(arg[iarg+2]);
t_period = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"press") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix rigid command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix rigid command");
if (strcmp(style,"rigid/npt") != 0)
- error->all("Illegal fix rigid command");
+ error->all(FLERR,"Illegal fix rigid command");
pressflag = 1;
p_start = atof(arg[iarg+1]);
p_stop = atof(arg[iarg+2]);
p_period = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"tparam") == 0) {
- if (iarg+4 > narg) error->all("Illegal fix rigid command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal fix rigid command");
if (strcmp(style,"rigid/nvt") != 0)
- error->all("Illegal fix rigid command");
+ error->all(FLERR,"Illegal fix rigid command");
t_chain = atoi(arg[iarg+1]);
t_iter = atoi(arg[iarg+2]);
t_order = atoi(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"pparam") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix rigid command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix rigid command");
if (strcmp(style,"rigid/npt") != 0)
- error->all("Illegal fix rigid command");
+ error->all(FLERR,"Illegal fix rigid command");
p_chain = atoi(arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix rigid command");
+ } else error->all(FLERR,"Illegal fix rigid command");
}
// initialize Marsaglia RNG with processor-unique seed
if (langflag) random = new RanMars(lmp,seed + me);
else random = NULL;
// initialize vector output quantities in case accessed before run
for (i = 0; i < nbody; i++) {
xcm[i][0] = xcm[i][1] = xcm[i][2] = 0.0;
vcm[i][0] = vcm[i][1] = vcm[i][2] = 0.0;
fcm[i][0] = fcm[i][1] = fcm[i][2] = 0.0;
torque[i][0] = torque[i][1] = torque[i][2] = 0.0;
}
// nrigid[n] = # of atoms in Nth rigid body
// error if one or zero atoms
int *ncount = new int[nbody];
for (ibody = 0; ibody < nbody; ibody++) ncount[ibody] = 0;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (body[i] >= 0) ncount[body[i]]++;
MPI_Allreduce(ncount,nrigid,nbody,MPI_INT,MPI_SUM,world);
delete [] ncount;
for (ibody = 0; ibody < nbody; ibody++)
- if (nrigid[ibody] <= 1) error->all("One or zero atoms in rigid body");
+ if (nrigid[ibody] <= 1) error->all(FLERR,"One or zero atoms in rigid body");
// set image flags for each rigid body to default values
// will be reset during init() based on xcm and then by pre_neighbor()
// set here, so image value will persist from run to run
for (ibody = 0; ibody < nbody; ibody++)
imagebody[ibody] = (512 << 20) | (512 << 10) | 512;
// bitmasks for properties of extended particles
INERTIA_POINT = 1;
INERTIA_SPHERE = 2;
INERTIA_ELLIPSOID = 4;
ORIENT_DIPOLE = 8;
ORIENT_QUAT = 16;
OMEGA = 32;
ANGMOM = 64;
TORQUE = 128;
// atom style pointers to particles that store extra info
avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
// print statistics
int nsum = 0;
for (ibody = 0; ibody < nbody; ibody++) nsum += nrigid[ibody];
if (me == 0) {
if (screen) fprintf(screen,"%d rigid bodies with %d atoms\n",nbody,nsum);
if (logfile) fprintf(logfile,"%d rigid bodies with %d atoms\n",nbody,nsum);
}
}
/* ---------------------------------------------------------------------- */
FixRigid::~FixRigid()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
delete random;
// delete locally stored arrays
memory->destroy(body);
memory->destroy(displace);
memory->destroy(eflags);
memory->destroy(dorient);
memory->destroy(qorient);
// delete nbody-length arrays
memory->destroy(nrigid);
memory->destroy(masstotal);
memory->destroy(xcm);
memory->destroy(vcm);
memory->destroy(fcm);
memory->destroy(inertia);
memory->destroy(ex_space);
memory->destroy(ey_space);
memory->destroy(ez_space);
memory->destroy(angmom);
memory->destroy(omega);
memory->destroy(torque);
memory->destroy(quat);
memory->destroy(imagebody);
memory->destroy(fflag);
memory->destroy(tflag);
memory->destroy(langextra);
memory->destroy(sum);
memory->destroy(all);
memory->destroy(remapflag);
}
/* ---------------------------------------------------------------------- */
int FixRigid::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
if (langflag) mask |= POST_FORCE;
mask |= PRE_NEIGHBOR;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixRigid::init()
{
int i,ibody;
triclinic = domain->triclinic;
// warn if more than one rigid fix
int count = 0;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"rigid") == 0) count++;
- if (count > 1 && me == 0) error->warning("More than one fix rigid");
+ if (count > 1 && me == 0) error->warning(FLERR,"More than one fix rigid");
// error if npt,nph fix comes before rigid fix
for (i = 0; i < modify->nfix; i++) {
if (strcmp(modify->fix[i]->style,"npt") == 0) break;
if (strcmp(modify->fix[i]->style,"nph") == 0) break;
}
if (i < modify->nfix) {
for (int j = i; j < modify->nfix; j++)
if (strcmp(modify->fix[j]->style,"rigid") == 0)
- error->all("Rigid fix must come before NPT/NPH fix");
+ error->all(FLERR,"Rigid fix must come before NPT/NPH fix");
}
// timestep info
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dtq = 0.5 * update->dt;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
// extended = 1 if any particle in a rigid body is finite size
// or has a dipole moment
extended = dorientflag = qorientflag = 0;
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
double **mu = atom->mu;
double *radius = atom->radius;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *ellipsoid = atom->ellipsoid;
int *type = atom->type;
int nlocal = atom->nlocal;
if (atom->radius_flag || atom->ellipsoid_flag || atom->mu_flag) {
int flag = 0;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
if (radius && radius[i] > 0.0) flag = 1;
if (ellipsoid && ellipsoid[i] >= 0) flag = 1;
if (mu && mu[i][3] > 0.0) flag = 1;
}
MPI_Allreduce(&flag,&extended,1,MPI_INT,MPI_MAX,world);
}
// grow extended arrays and set extended flags for each particle
// qorientflag = 1 if any particle stores quat orientation
// dorientflag = 1 if any particle stores dipole orientation
if (extended) {
if (atom->mu_flag) dorientflag = 1;
if (atom->ellipsoid_flag) qorientflag = 1;
grow_arrays(atom->nmax);
for (i = 0; i < nlocal; i++) {
eflags[i] = 0;
if (body[i] < 0) continue;
// set INERTIA to POINT or SPHERE or ELLIPSOID
if (radius && radius[i] > 0.0) {
eflags[i] |= INERTIA_SPHERE;
eflags[i] |= OMEGA;
eflags[i] |= TORQUE;
} else if (ellipsoid && ellipsoid[i] >= 0) {
eflags[i] |= INERTIA_ELLIPSOID;
eflags[i] |= ORIENT_QUAT;
eflags[i] |= ANGMOM;
eflags[i] |= TORQUE;
} else eflags[i] |= INERTIA_POINT;
// set DIPOLE if atom->mu and mu[3] > 0.0
if (atom->mu_flag && mu[i][3] > 0.0)
eflags[i] |= ORIENT_DIPOLE;
}
}
// compute masstotal & center-of-mass of each rigid body
// error if image flag is not 0 in a non-periodic dim
double **x = atom->x;
int *image = atom->image;
int *periodicity = domain->periodicity;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double xy = domain->xy;
double xz = domain->xz;
double yz = domain->yz;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
int xbox,ybox,zbox;
double massone,xunwrap,yunwrap,zunwrap;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
if ((xbox && !periodicity[0]) || (ybox && !periodicity[1]) ||
(zbox && !periodicity[2]))
- error->one("Fix rigid atom has non-zero image flag "
+ error->one(FLERR,"Fix rigid atom has non-zero image flag "
"in a non-periodic dimension");
if (triclinic == 0) {
xunwrap = x[i][0] + xbox*xprd;
yunwrap = x[i][1] + ybox*yprd;
zunwrap = x[i][2] + zbox*zprd;
} else {
xunwrap = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
yunwrap = x[i][1] + ybox*yprd + zbox*yz;
zunwrap = x[i][2] + zbox*zprd;
}
sum[ibody][0] += xunwrap * massone;
sum[ibody][1] += yunwrap * massone;
sum[ibody][2] += zunwrap * massone;
sum[ibody][3] += massone;
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
for (ibody = 0; ibody < nbody; ibody++) {
masstotal[ibody] = all[ibody][3];
xcm[ibody][0] = all[ibody][0]/masstotal[ibody];
xcm[ibody][1] = all[ibody][1]/masstotal[ibody];
xcm[ibody][2] = all[ibody][2]/masstotal[ibody];
}
// remap the xcm of each body back into simulation box if needed
// only really necessary the 1st time a run is performed
pre_neighbor();
// compute 6 moments of inertia of each body
// dx,dy,dz = coords relative to center-of-mass
// symmetric 3x3 inertia tensor stored in Voigt notation as 6-vector
double dx,dy,dz;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (triclinic == 0) {
xunwrap = x[i][0] + xbox*xprd;
yunwrap = x[i][1] + ybox*yprd;
zunwrap = x[i][2] + zbox*zprd;
} else {
xunwrap = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
yunwrap = x[i][1] + ybox*yprd + zbox*yz;
zunwrap = x[i][2] + zbox*zprd;
}
dx = xunwrap - xcm[ibody][0];
dy = yunwrap - xcm[ibody][1];
dz = zunwrap - xcm[ibody][2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
sum[ibody][0] += massone * (dy*dy + dz*dz);
sum[ibody][1] += massone * (dx*dx + dz*dz);
sum[ibody][2] += massone * (dx*dx + dy*dy);
sum[ibody][3] -= massone * dy*dz;
sum[ibody][4] -= massone * dx*dz;
sum[ibody][5] -= massone * dx*dy;
}
// extended particles may contribute extra terms to moments of inertia
if (extended) {
double ivec[6];
double *shape,*quatatom;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
massone = rmass[i];
if (eflags[i] & INERTIA_SPHERE) {
sum[ibody][0] += 0.4 * massone * radius[i]*radius[i];
sum[ibody][1] += 0.4 * massone * radius[i]*radius[i];
sum[ibody][2] += 0.4 * massone * radius[i]*radius[i];
} else if (eflags[i] & INERTIA_ELLIPSOID) {
shape = ebonus[ellipsoid[i]].shape;
quatatom = ebonus[ellipsoid[i]].quat;
MathExtra::inertia_ellipsoid(shape,quatatom,massone,ivec);
sum[ibody][0] += ivec[0];
sum[ibody][1] += ivec[1];
sum[ibody][2] += ivec[2];
sum[ibody][3] += ivec[3];
sum[ibody][4] += ivec[4];
sum[ibody][5] += ivec[5];
}
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
// diagonalize inertia tensor for each body via Jacobi rotations
// inertia = 3 eigenvalues = principal moments of inertia
// evectors and exzy_space = 3 evectors = principal axes of rigid body
int ierror;
double cross[3];
double tensor[3][3],evectors[3][3];
for (ibody = 0; ibody < nbody; ibody++) {
tensor[0][0] = all[ibody][0];
tensor[1][1] = all[ibody][1];
tensor[2][2] = all[ibody][2];
tensor[1][2] = tensor[2][1] = all[ibody][3];
tensor[0][2] = tensor[2][0] = all[ibody][4];
tensor[0][1] = tensor[1][0] = all[ibody][5];
ierror = MathExtra::jacobi(tensor,inertia[ibody],evectors);
- if (ierror) error->all("Insufficient Jacobi rotations for rigid body");
+ if (ierror) error->all(FLERR,"Insufficient Jacobi rotations for rigid body");
ex_space[ibody][0] = evectors[0][0];
ex_space[ibody][1] = evectors[1][0];
ex_space[ibody][2] = evectors[2][0];
ey_space[ibody][0] = evectors[0][1];
ey_space[ibody][1] = evectors[1][1];
ey_space[ibody][2] = evectors[2][1];
ez_space[ibody][0] = evectors[0][2];
ez_space[ibody][1] = evectors[1][2];
ez_space[ibody][2] = evectors[2][2];
// if any principal moment < scaled EPSILON, set to 0.0
double max;
max = MAX(inertia[ibody][0],inertia[ibody][1]);
max = MAX(max,inertia[ibody][2]);
if (inertia[ibody][0] < EPSILON*max) inertia[ibody][0] = 0.0;
if (inertia[ibody][1] < EPSILON*max) inertia[ibody][1] = 0.0;
if (inertia[ibody][2] < EPSILON*max) inertia[ibody][2] = 0.0;
// enforce 3 evectors as a right-handed coordinate system
// flip 3rd vector if needed
MathExtra::cross3(ex_space[ibody],ey_space[ibody],cross);
if (MathExtra::dot3(cross,ez_space[ibody]) < 0.0)
MathExtra::negate3(ez_space[ibody]);
// create initial quaternion
MathExtra::exyz_to_q(ex_space[ibody],ey_space[ibody],ez_space[ibody],
quat[ibody]);
}
// displace = initial atom coords in basis of principal axes
// set displace = 0.0 for atoms not in any rigid body
// for extended particles, set their orientation wrt to rigid body
double qc[4],delta[3];
double *quatatom;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) {
displace[i][0] = displace[i][1] = displace[i][2] = 0.0;
continue;
}
ibody = body[i];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (triclinic == 0) {
xunwrap = x[i][0] + xbox*xprd;
yunwrap = x[i][1] + ybox*yprd;
zunwrap = x[i][2] + zbox*zprd;
} else {
xunwrap = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
yunwrap = x[i][1] + ybox*yprd + zbox*yz;
zunwrap = x[i][2] + zbox*zprd;
}
delta[0] = xunwrap - xcm[ibody][0];
delta[1] = yunwrap - xcm[ibody][1];
delta[2] = zunwrap - xcm[ibody][2];
MathExtra::transpose_matvec(ex_space[ibody],ey_space[ibody],
ez_space[ibody],delta,displace[i]);
if (extended) {
if (eflags[i] & ORIENT_DIPOLE) {
MathExtra::transpose_matvec(ex_space[ibody],ey_space[ibody],
ez_space[ibody],mu[i],dorient[i]);
MathExtra::snormalize3(mu[i][3],dorient[i],dorient[i]);
} else if (dorientflag)
dorient[i][0] = dorient[i][1] = dorient[i][2] = 0.0;
if (eflags[i] & ORIENT_QUAT) {
quatatom = ebonus[ellipsoid[i]].quat;
MathExtra::qconjugate(quat[ibody],qc);
MathExtra::quatquat(qc,quatatom,qorient[i]);
MathExtra::qnormalize(qorient[i]);
} else if (qorientflag)
qorient[i][0] = qorient[i][1] = qorient[i][2] = qorient[i][3] = 0.0;
}
}
// test for valid principal moments & axes
// recompute moments of inertia around new axes
// 3 diagonal moments should equal principal moments
// 3 off-diagonal moments should be 0.0
// extended particles may contribute extra terms to moments of inertia
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
sum[ibody][0] += massone *
(displace[i][1]*displace[i][1] + displace[i][2]*displace[i][2]);
sum[ibody][1] += massone *
(displace[i][0]*displace[i][0] + displace[i][2]*displace[i][2]);
sum[ibody][2] += massone *
(displace[i][0]*displace[i][0] + displace[i][1]*displace[i][1]);
sum[ibody][3] -= massone * displace[i][1]*displace[i][2];
sum[ibody][4] -= massone * displace[i][0]*displace[i][2];
sum[ibody][5] -= massone * displace[i][0]*displace[i][1];
}
if (extended) {
double ivec[6];
double *shape;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
massone = rmass[i];
if (eflags[i] & INERTIA_SPHERE) {
sum[ibody][0] += 0.4 * massone * radius[i]*radius[i];
sum[ibody][1] += 0.4 * massone * radius[i]*radius[i];
sum[ibody][2] += 0.4 * massone * radius[i]*radius[i];
} else if (eflags[i] & INERTIA_ELLIPSOID) {
shape = ebonus[ellipsoid[i]].shape;
MathExtra::inertia_ellipsoid(shape,qorient[i],massone,ivec);
sum[ibody][0] += ivec[0];
sum[ibody][1] += ivec[1];
sum[ibody][2] += ivec[2];
sum[ibody][3] += ivec[3];
sum[ibody][4] += ivec[4];
sum[ibody][5] += ivec[5];
}
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
double norm;
for (ibody = 0; ibody < nbody; ibody++) {
if (inertia[ibody][0] == 0.0) {
if (fabs(all[ibody][0]) > TOLERANCE)
- error->all("Fix rigid: Bad principal moments");
+ error->all(FLERR,"Fix rigid: Bad principal moments");
} else {
if (fabs((all[ibody][0]-inertia[ibody][0])/inertia[ibody][0]) >
- TOLERANCE) error->all("Fix rigid: Bad principal moments");
+ TOLERANCE) error->all(FLERR,"Fix rigid: Bad principal moments");
}
if (inertia[ibody][1] == 0.0) {
if (fabs(all[ibody][1]) > TOLERANCE)
- error->all("Fix rigid: Bad principal moments");
+ error->all(FLERR,"Fix rigid: Bad principal moments");
} else {
if (fabs((all[ibody][1]-inertia[ibody][1])/inertia[ibody][1]) >
- TOLERANCE) error->all("Fix rigid: Bad principal moments");
+ TOLERANCE) error->all(FLERR,"Fix rigid: Bad principal moments");
}
if (inertia[ibody][2] == 0.0) {
if (fabs(all[ibody][2]) > TOLERANCE)
- error->all("Fix rigid: Bad principal moments");
+ error->all(FLERR,"Fix rigid: Bad principal moments");
} else {
if (fabs((all[ibody][2]-inertia[ibody][2])/inertia[ibody][2]) >
- TOLERANCE) error->all("Fix rigid: Bad principal moments");
+ TOLERANCE) error->all(FLERR,"Fix rigid: Bad principal moments");
}
norm = (inertia[ibody][0] + inertia[ibody][1] + inertia[ibody][2]) / 3.0;
if (fabs(all[ibody][3]/norm) > TOLERANCE ||
fabs(all[ibody][4]/norm) > TOLERANCE ||
fabs(all[ibody][5]/norm) > TOLERANCE)
- error->all("Fix rigid: Bad principal moments");
+ error->all(FLERR,"Fix rigid: Bad principal moments");
}
// temperature scale factor
double ndof = 0.0;
for (ibody = 0; ibody < nbody; ibody++) {
ndof += fflag[ibody][0] + fflag[ibody][1] + fflag[ibody][2];
ndof += tflag[ibody][0] + tflag[ibody][1] + tflag[ibody][2];
}
tfactor = force->mvv2e / (ndof * force->boltz);
}
/* ---------------------------------------------------------------------- */
void FixRigid::setup(int vflag)
{
int i,n,ibody;
double massone,radone;
// vcm = velocity of center-of-mass of each rigid body
// fcm = force on center-of-mass of each rigid body
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int nlocal = atom->nlocal;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
sum[ibody][0] += v[i][0] * massone;
sum[ibody][1] += v[i][1] * massone;
sum[ibody][2] += v[i][2] * massone;
sum[ibody][3] += f[i][0];
sum[ibody][4] += f[i][1];
sum[ibody][5] += f[i][2];
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
for (ibody = 0; ibody < nbody; ibody++) {
vcm[ibody][0] = all[ibody][0]/masstotal[ibody];
vcm[ibody][1] = all[ibody][1]/masstotal[ibody];
vcm[ibody][2] = all[ibody][2]/masstotal[ibody];
fcm[ibody][0] = all[ibody][3];
fcm[ibody][1] = all[ibody][4];
fcm[ibody][2] = all[ibody][5];
}
// angmom = angular momentum of each rigid body
// torque = torque on each rigid body
int *image = atom->image;
double **x = atom->x;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double xy = domain->xy;
double xz = domain->xz;
double yz = domain->yz;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
int xbox,ybox,zbox;
double xunwrap,yunwrap,zunwrap,dx,dy,dz;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (triclinic == 0) {
xunwrap = x[i][0] + xbox*xprd;
yunwrap = x[i][1] + ybox*yprd;
zunwrap = x[i][2] + zbox*zprd;
} else {
xunwrap = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
yunwrap = x[i][1] + ybox*yprd + zbox*yz;
zunwrap = x[i][2] + zbox*zprd;
}
dx = xunwrap - xcm[ibody][0];
dy = yunwrap - xcm[ibody][1];
dz = zunwrap - xcm[ibody][2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
sum[ibody][0] += dy * massone*v[i][2] - dz * massone*v[i][1];
sum[ibody][1] += dz * massone*v[i][0] - dx * massone*v[i][2];
sum[ibody][2] += dx * massone*v[i][1] - dy * massone*v[i][0];
sum[ibody][3] += dy * f[i][2] - dz * f[i][1];
sum[ibody][4] += dz * f[i][0] - dx * f[i][2];
sum[ibody][5] += dx * f[i][1] - dy * f[i][0];
}
// extended particles add their rotation/torque to angmom/torque of body
if (extended) {
double **omega_one = atom->omega;
double **angmom_one = atom->angmom;
double **torque_one = atom->torque;
double *radius = atom->radius;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
if (eflags[i] & OMEGA) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
radone = radius[i];
sum[ibody][0] += 0.4 * massone * radone*radone * omega_one[i][0];
sum[ibody][1] += 0.4 * massone * radone*radone * omega_one[i][1];
sum[ibody][2] += 0.4 * massone * radone*radone * omega_one[i][2];
}
if (eflags[i] & ANGMOM) {
sum[ibody][0] += angmom_one[i][0];
sum[ibody][1] += angmom_one[i][1];
sum[ibody][2] += angmom_one[i][2];
}
if (eflags[i] & TORQUE) {
sum[ibody][3] += torque_one[i][0];
sum[ibody][4] += torque_one[i][1];
sum[ibody][5] += torque_one[i][2];
}
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
for (ibody = 0; ibody < nbody; ibody++) {
angmom[ibody][0] = all[ibody][0];
angmom[ibody][1] = all[ibody][1];
angmom[ibody][2] = all[ibody][2];
torque[ibody][0] = all[ibody][3];
torque[ibody][1] = all[ibody][4];
torque[ibody][2] = all[ibody][5];
}
// zero langextra in case Langevin thermostat not used
// no point to calling post_force() here since langextra
// is only added to fcm/torque in final_integrate()
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) langextra[ibody][i] = 0.0;
// virial setup before call to set_v
if (vflag) v_setup(vflag);
else evflag = 0;
// set velocities from angmom & omega
for (ibody = 0; ibody < nbody; ibody++)
MathExtra::angmom_to_omega(angmom[ibody],ex_space[ibody],ey_space[ibody],
ez_space[ibody],inertia[ibody],omega[ibody]);
set_v();
// guesstimate virial as 2x the set_v contribution
if (vflag_global)
for (n = 0; n < 6; n++) virial[n] *= 2.0;
if (vflag_atom) {
for (i = 0; i < nlocal; i++)
for (n = 0; n < 6; n++)
vatom[i][n] *= 2.0;
}
}
/* ---------------------------------------------------------------------- */
void FixRigid::initial_integrate(int vflag)
{
double dtfm;
for (int ibody = 0; ibody < nbody; ibody++) {
// update vcm by 1/2 step
dtfm = dtf / masstotal[ibody];
vcm[ibody][0] += dtfm * fcm[ibody][0] * fflag[ibody][0];
vcm[ibody][1] += dtfm * fcm[ibody][1] * fflag[ibody][1];
vcm[ibody][2] += dtfm * fcm[ibody][2] * fflag[ibody][2];
// update xcm by full step
xcm[ibody][0] += dtv * vcm[ibody][0];
xcm[ibody][1] += dtv * vcm[ibody][1];
xcm[ibody][2] += dtv * vcm[ibody][2];
// update angular momentum by 1/2 step
angmom[ibody][0] += dtf * torque[ibody][0] * tflag[ibody][0];
angmom[ibody][1] += dtf * torque[ibody][1] * tflag[ibody][1];
angmom[ibody][2] += dtf * torque[ibody][2] * tflag[ibody][2];
// compute omega at 1/2 step from angmom at 1/2 step and current q
// update quaternion a full step via Richardson iteration
// returns new normalized quaternion, also updated omega at 1/2 step
// update ex,ey,ez to reflect new quaternion
MathExtra::angmom_to_omega(angmom[ibody],ex_space[ibody],ey_space[ibody],
ez_space[ibody],inertia[ibody],omega[ibody]);
MathExtra::richardson(quat[ibody],angmom[ibody],omega[ibody],
inertia[ibody],dtq);
MathExtra::q_to_exyz(quat[ibody],
ex_space[ibody],ey_space[ibody],ez_space[ibody]);
}
// virial setup before call to set_xv
if (vflag) v_setup(vflag);
else evflag = 0;
// set coords/orient and velocity/rotation of atoms in rigid bodies
// from quarternion and omega
set_xv();
}
/* ----------------------------------------------------------------------
apply Langevin thermostat to all 6 DOF of rigid bodies
computed by proc 0, broadcast to other procs
unlike fix langevin, this stores extra force in extra arrays,
which are added in when final_integrate() calculates a new fcm/torque
------------------------------------------------------------------------- */
void FixRigid::post_force(int vflag)
{
if (me == 0) {
double gamma1,gamma2;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
double tsqrt = sqrt(t_target);
double boltz = force->boltz;
double dt = update->dt;
double mvv2e = force->mvv2e;
double ftm2v = force->ftm2v;
for (int i = 0; i < nbody; i++) {
gamma1 = -masstotal[i] / t_period / ftm2v;
gamma2 = sqrt(masstotal[i]) * tsqrt *
sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
langextra[i][0] = gamma1*vcm[i][0] + gamma2*(random->uniform()-0.5);
langextra[i][1] = gamma1*vcm[i][1] + gamma2*(random->uniform()-0.5);
langextra[i][2] = gamma1*vcm[i][2] + gamma2*(random->uniform()-0.5);
gamma1 = -1.0 / t_period / ftm2v;
gamma2 = tsqrt * sqrt(24.0*boltz/t_period/dt/mvv2e) / ftm2v;
langextra[i][3] = inertia[i][0]*gamma1*omega[i][0] +
sqrt(inertia[i][0])*gamma2*(random->uniform()-0.5);
langextra[i][4] = inertia[i][1]*gamma1*omega[i][1] +
sqrt(inertia[i][1])*gamma2*(random->uniform()-0.5);
langextra[i][5] = inertia[i][2]*gamma1*omega[i][2] +
sqrt(inertia[i][2])*gamma2*(random->uniform()-0.5);
}
}
MPI_Bcast(&langextra[0][0],6*nbody,MPI_DOUBLE,0,world);
}
/* ---------------------------------------------------------------------- */
void FixRigid::final_integrate()
{
int i,ibody;
double dtfm,xy,xz,yz;
// sum over atoms to get force and torque on rigid body
int *image = atom->image;
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
if (triclinic) {
xy = domain->xy;
xz = domain->xz;
yz = domain->yz;
}
int xbox,ybox,zbox;
double xunwrap,yunwrap,zunwrap,dx,dy,dz;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
sum[ibody][0] += f[i][0];
sum[ibody][1] += f[i][1];
sum[ibody][2] += f[i][2];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (triclinic == 0) {
xunwrap = x[i][0] + xbox*xprd;
yunwrap = x[i][1] + ybox*yprd;
zunwrap = x[i][2] + zbox*zprd;
} else {
xunwrap = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
yunwrap = x[i][1] + ybox*yprd + zbox*yz;
zunwrap = x[i][2] + zbox*zprd;
}
dx = xunwrap - xcm[ibody][0];
dy = yunwrap - xcm[ibody][1];
dz = zunwrap - xcm[ibody][2];
sum[ibody][3] += dy*f[i][2] - dz*f[i][1];
sum[ibody][4] += dz*f[i][0] - dx*f[i][2];
sum[ibody][5] += dx*f[i][1] - dy*f[i][0];
}
// extended particles add their torque to torque of body
if (extended) {
double **torque_one = atom->torque;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
if (eflags[i] & TORQUE) {
sum[ibody][3] += torque_one[i][0];
sum[ibody][4] += torque_one[i][1];
sum[ibody][5] += torque_one[i][2];
}
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
// update vcm and angmom
// include Langevin thermostat forces
// fflag,tflag = 0 for some dimensions in 2d
for (ibody = 0; ibody < nbody; ibody++) {
fcm[ibody][0] = all[ibody][0] + langextra[ibody][0];
fcm[ibody][1] = all[ibody][1] + langextra[ibody][1];
fcm[ibody][2] = all[ibody][2] + langextra[ibody][2];
torque[ibody][0] = all[ibody][3] + langextra[ibody][3];
torque[ibody][1] = all[ibody][4] + langextra[ibody][4];
torque[ibody][2] = all[ibody][5] + langextra[ibody][5];
// update vcm by 1/2 step
dtfm = dtf / masstotal[ibody];
vcm[ibody][0] += dtfm * fcm[ibody][0] * fflag[ibody][0];
vcm[ibody][1] += dtfm * fcm[ibody][1] * fflag[ibody][1];
vcm[ibody][2] += dtfm * fcm[ibody][2] * fflag[ibody][2];
// update angular momentum by 1/2 step
angmom[ibody][0] += dtf * torque[ibody][0] * tflag[ibody][0];
angmom[ibody][1] += dtf * torque[ibody][1] * tflag[ibody][1];
angmom[ibody][2] += dtf * torque[ibody][2] * tflag[ibody][2];
MathExtra::angmom_to_omega(angmom[ibody],ex_space[ibody],ey_space[ibody],
ez_space[ibody],inertia[ibody],omega[ibody]);
}
// set velocity/rotation of atoms in rigid bodies
// virial is already setup from initial_integrate
set_v();
}
/* ----------------------------------------------------------------------
apply evolution operators to quat, quat momentum
see Miller paper cited in fix rigid/nvt and fix rigid/npt
------------------------------------------------------------------------- */
void FixRigid::no_squish_rotate(int k, double *p, double *q,
double *inertia, double dt)
{
double phi,c_phi,s_phi,kp[4],kq[4];
// apply permuation operator on p and q, get kp and kq
if (k == 1) {
kq[0] = -q[1]; kp[0] = -p[1];
kq[1] = q[0]; kp[1] = p[0];
kq[2] = q[3]; kp[2] = p[3];
kq[3] = -q[2]; kp[3] = -p[2];
} else if (k == 2) {
kq[0] = -q[2]; kp[0] = -p[2];
kq[1] = -q[3]; kp[1] = -p[3];
kq[2] = q[0]; kp[2] = p[0];
kq[3] = q[1]; kp[3] = p[1];
} else if (k == 3) {
kq[0] = -q[3]; kp[0] = -p[3];
kq[1] = q[2]; kp[1] = p[2];
kq[2] = -q[1]; kp[2] = -p[1];
kq[3] = q[0]; kp[3] = p[0];
}
// obtain phi, cosines and sines
phi = p[0]*kq[0] + p[1]*kq[1] + p[2]*kq[2] + p[3]*kq[3];
if (fabs(inertia[k-1]) < 1e-6) phi *= 0.0;
else phi /= 4.0 * inertia[k-1];
c_phi = cos(dt * phi);
s_phi = sin(dt * phi);
// advance p and q
p[0] = c_phi*p[0] + s_phi*kp[0];
p[1] = c_phi*p[1] + s_phi*kp[1];
p[2] = c_phi*p[2] + s_phi*kp[2];
p[3] = c_phi*p[3] + s_phi*kp[3];
q[0] = c_phi*q[0] + s_phi*kq[0];
q[1] = c_phi*q[1] + s_phi*kq[1];
q[2] = c_phi*q[2] + s_phi*kq[2];
q[3] = c_phi*q[3] + s_phi*kq[3];
}
/* ---------------------------------------------------------------------- */
void FixRigid::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
dtv = step_respa[ilevel];
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
dtq = 0.5 * step_respa[ilevel];
if (ilevel == 0) initial_integrate(vflag);
else final_integrate();
}
/* ---------------------------------------------------------------------- */
void FixRigid::final_integrate_respa(int ilevel, int iloop)
{
dtf = 0.5 * step_respa[ilevel] * force->ftm2v;
final_integrate();
}
/* ----------------------------------------------------------------------
remap xcm of each rigid body back into periodic simulation box
done during pre_neighbor so will be after call to pbc()
and after fix_deform::pre_exchange() may have flipped box
use domain->remap() in case xcm is far away from box
due to 1st definition of rigid body or due to box flip
if don't do this, then atoms of a body which drifts far away
from a triclinic box will be remapped back into box
with huge displacements when the box tilt changes via set_x()
adjust image flag of body and image flags of all atoms in body
------------------------------------------------------------------------- */
void FixRigid::pre_neighbor()
{
int original,oldimage,newimage;
for (int ibody = 0; ibody < nbody; ibody++) {
original = imagebody[ibody];
domain->remap(xcm[ibody],imagebody[ibody]);
if (original == imagebody[ibody]) remapflag[ibody][3] = 0;
else {
oldimage = original & 1023;
newimage = imagebody[ibody] & 1023;
remapflag[ibody][0] = newimage - oldimage;
oldimage = (original >> 10) & 1023;
newimage = (imagebody[ibody] >> 10) & 1023;
remapflag[ibody][1] = newimage - oldimage;
oldimage = original >> 20;
newimage = imagebody[ibody] >> 20;
remapflag[ibody][2] = newimage - oldimage;
remapflag[ibody][3] = 1;
}
}
// adjust image flags of any atom in a rigid body whose xcm was remapped
int *image = atom->image;
int nlocal = atom->nlocal;
int ibody,idim,otherdims;
for (int i = 0; i < nlocal; i++) {
if (body[i] == -1) continue;
if (remapflag[body[i]][3] == 0) continue;
ibody = body[i];
if (remapflag[ibody][0]) {
idim = image[i] & 1023;
otherdims = image[i] ^ idim;
idim -= remapflag[ibody][0];
idim &= 1023;
image[i] = otherdims | idim;
}
if (remapflag[ibody][1]) {
idim = (image[i] >> 10) & 1023;
otherdims = image[i] ^ (idim << 10);
idim -= remapflag[ibody][1];
idim &= 1023;
image[i] = otherdims | (idim << 10);
}
if (remapflag[ibody][2]) {
idim = image[i] >> 20;
otherdims = image[i] ^ (idim << 20);
idim -= remapflag[ibody][2];
idim &= 1023;
image[i] = otherdims | (idim << 20);
}
}
}
/* ----------------------------------------------------------------------
count # of degrees-of-freedom removed by fix_rigid for atoms in igroup
------------------------------------------------------------------------- */
int FixRigid::dof(int igroup)
{
int groupbit = group->bitmask[igroup];
// nall = # of point particles in each rigid body
// mall = # of finite-size particles in each rigid body
// particles must also be in temperature group
int *mask = atom->mask;
int nlocal = atom->nlocal;
int *ncount = new int[nbody];
int *mcount = new int[nbody];
for (int ibody = 0; ibody < nbody; ibody++)
ncount[ibody] = mcount[ibody] = 0;
for (int i = 0; i < nlocal; i++)
if (body[i] >= 0 && mask[i] & groupbit) {
if (extended && eflags[i]) mcount[body[i]]++;
else ncount[body[i]]++;
}
int *nall = new int[nbody];
int *mall = new int[nbody];
MPI_Allreduce(ncount,nall,nbody,MPI_INT,MPI_SUM,world);
MPI_Allreduce(mcount,mall,nbody,MPI_INT,MPI_SUM,world);
// warn if nall+mall != nrigid for any body included in temperature group
int flag = 0;
for (int ibody = 0; ibody < nbody; ibody++) {
if (nall[ibody]+mall[ibody] > 0 &&
nall[ibody]+mall[ibody] != nrigid[ibody]) flag = 1;
}
if (flag && me == 0)
- error->warning("Computing temperature of portions of rigid bodies");
+ error->warning(FLERR,"Computing temperature of portions of rigid bodies");
// remove appropriate DOFs for each rigid body wholly in temperature group
// N = # of point particles in body
// M = # of finite-size particles in body
// 3d body has 3N + 6M dof to start with
// 2d body has 2N + 3M dof to start with
// 3d point-particle body with all non-zero I should have 6 dof, remove 3N-6
// 3d point-particle body (linear) with a 0 I should have 5 dof, remove 3N-5
// 2d point-particle body should have 3 dof, remove 2N-3
// 3d body with any finite-size M should have 6 dof, remove (3N+6M) - 6
// 2d body with any finite-size M should have 3 dof, remove (2N+3M) - 3
int n = 0;
if (domain->dimension == 3) {
for (int ibody = 0; ibody < nbody; ibody++)
if (nall[ibody]+mall[ibody] == nrigid[ibody]) {
n += 3*nall[ibody] + 6*mall[ibody] - 6;
if (inertia[ibody][0] == 0.0 || inertia[ibody][1] == 0.0 ||
inertia[ibody][2] == 0.0) n++;
}
} else if (domain->dimension == 2) {
for (int ibody = 0; ibody < nbody; ibody++)
if (nall[ibody]+mall[ibody] == nrigid[ibody])
n += 2*nall[ibody] + 3*mall[ibody] - 3;
}
delete [] ncount;
delete [] mcount;
delete [] nall;
delete [] mall;
return n;
}
/* ----------------------------------------------------------------------
adjust xcm of each rigid body due to box deformation
called by various fixes that change box size/shape
flag = 0/1 means map from box to lamda coords or vice versa
------------------------------------------------------------------------- */
void FixRigid::deform(int flag)
{
if (flag == 0)
for (int ibody = 0; ibody < nbody; ibody++)
domain->x2lamda(xcm[ibody],xcm[ibody]);
else
for (int ibody = 0; ibody < nbody; ibody++)
domain->lamda2x(xcm[ibody],xcm[ibody]);
}
/* ----------------------------------------------------------------------
set space-frame coords and velocity of each atom in each rigid body
set orientation and rotation of extended particles
x = Q displace + Xcm, mapped back to periodic box
v = Vcm + (W cross (x - Xcm))
------------------------------------------------------------------------- */
void FixRigid::set_xv()
{
int ibody;
int xbox,ybox,zbox;
double x0,x1,x2,v0,v1,v2,fc0,fc1,fc2,massone;
double xy,xz,yz;
double ione[3],exone[3],eyone[3],ezone[3],vr[6],p[3][3];
int *image = atom->image;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
if (triclinic) {
xy = domain->xy;
xz = domain->xz;
yz = domain->yz;
}
// set x and v of each atom
for (int i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
// save old positions and velocities for virial
if (evflag) {
if (triclinic == 0) {
x0 = x[i][0] + xbox*xprd;
x1 = x[i][1] + ybox*yprd;
x2 = x[i][2] + zbox*zprd;
} else {
x0 = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
x1 = x[i][1] + ybox*yprd + zbox*yz;
x2 = x[i][2] + zbox*zprd;
}
v0 = v[i][0];
v1 = v[i][1];
v2 = v[i][2];
}
// x = displacement from center-of-mass, based on body orientation
// v = vcm + omega around center-of-mass
MathExtra::matvec(ex_space[ibody],ey_space[ibody],
ez_space[ibody],displace[i],x[i]);
v[i][0] = omega[ibody][1]*x[i][2] - omega[ibody][2]*x[i][1] +
vcm[ibody][0];
v[i][1] = omega[ibody][2]*x[i][0] - omega[ibody][0]*x[i][2] +
vcm[ibody][1];
v[i][2] = omega[ibody][0]*x[i][1] - omega[ibody][1]*x[i][0] +
vcm[ibody][2];
// add center of mass to displacement
// map back into periodic box via xbox,ybox,zbox
// for triclinic, add in box tilt factors as well
if (triclinic == 0) {
x[i][0] += xcm[ibody][0] - xbox*xprd;
x[i][1] += xcm[ibody][1] - ybox*yprd;
x[i][2] += xcm[ibody][2] - zbox*zprd;
} else {
x[i][0] += xcm[ibody][0] - xbox*xprd - ybox*xy - zbox*xz;
x[i][1] += xcm[ibody][1] - ybox*yprd - zbox*yz;
x[i][2] += xcm[ibody][2] - zbox*zprd;
}
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c final_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if (evflag) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
fc0 = massone*(v[i][0] - v0)/dtf - f[i][0];
fc1 = massone*(v[i][1] - v1)/dtf - f[i][1];
fc2 = massone*(v[i][2] - v2)/dtf - f[i][2];
vr[0] = 0.5*x0*fc0;
vr[1] = 0.5*x1*fc1;
vr[2] = 0.5*x2*fc2;
vr[3] = 0.5*x0*fc1;
vr[4] = 0.5*x0*fc2;
vr[5] = 0.5*x1*fc2;
v_tally(1,&i,1.0,vr);
}
}
// set orientation, omega, angmom of each extended particle
if (extended) {
double *shape,*quatatom;
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
double **omega_one = atom->omega;
double **angmom_one = atom->angmom;
double **mu = atom->mu;
int *ellipsoid = atom->ellipsoid;
for (int i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
if (eflags[i] & ORIENT_DIPOLE) {
MathExtra::quat_to_mat(quat[ibody],p);
MathExtra::matvec(p,dorient[i],mu[i]);
MathExtra::snormalize3(mu[i][3],mu[i],mu[i]);
}
if (eflags[i] & ORIENT_QUAT) {
quatatom = ebonus[ellipsoid[i]].quat;
MathExtra::quatquat(quat[ibody],qorient[i],quatatom);
MathExtra::qnormalize(quatatom);
}
if (eflags[i] & OMEGA) {
omega_one[i][0] = omega[ibody][0];
omega_one[i][1] = omega[ibody][1];
omega_one[i][2] = omega[ibody][2];
}
if (eflags[i] & ANGMOM) {
shape = ebonus[ellipsoid[i]].shape;
quatatom = ebonus[ellipsoid[i]].quat;
ione[0] = 0.2*rmass[i] * (shape[1]*shape[1] + shape[2]*shape[2]);
ione[1] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[2]*shape[2]);
ione[2] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[1]*shape[1]);
MathExtra::q_to_exyz(quatatom,exone,eyone,ezone);
MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone,ione,
angmom_one[i]);
}
}
}
}
/* ----------------------------------------------------------------------
set space-frame velocity of each atom in a rigid body
set omega and angmom of extended particles
v = Vcm + (W cross (x - Xcm))
------------------------------------------------------------------------- */
void FixRigid::set_v()
{
int ibody;
int xbox,ybox,zbox;
double x0,x1,x2,v0,v1,v2,fc0,fc1,fc2,massone;
double xy,xz,yz;
double ione[3],exone[3],eyone[3],ezone[3],delta[3],vr[6];
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *image = atom->image;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
if (triclinic) {
xy = domain->xy;
xz = domain->xz;
yz = domain->yz;
}
// set v of each atom
for (int i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
MathExtra::matvec(ex_space[ibody],ey_space[ibody],
ez_space[ibody],displace[i],delta);
// save old velocities for virial
if (evflag) {
v0 = v[i][0];
v1 = v[i][1];
v2 = v[i][2];
}
v[i][0] = omega[ibody][1]*delta[2] - omega[ibody][2]*delta[1] +
vcm[ibody][0];
v[i][1] = omega[ibody][2]*delta[0] - omega[ibody][0]*delta[2] +
vcm[ibody][1];
v[i][2] = omega[ibody][0]*delta[1] - omega[ibody][1]*delta[0] +
vcm[ibody][2];
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c initial_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if (evflag) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
fc0 = massone*(v[i][0] - v0)/dtf - f[i][0];
fc1 = massone*(v[i][1] - v1)/dtf - f[i][1];
fc2 = massone*(v[i][2] - v2)/dtf - f[i][2];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (triclinic == 0) {
x0 = x[i][0] + xbox*xprd;
x1 = x[i][1] + ybox*yprd;
x2 = x[i][2] + zbox*zprd;
} else {
x0 = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
x1 = x[i][1] + ybox*yprd + zbox*yz;
x2 = x[i][2] + zbox*zprd;
}
vr[0] = 0.5*x0*fc0;
vr[1] = 0.5*x1*fc1;
vr[2] = 0.5*x2*fc2;
vr[3] = 0.5*x0*fc1;
vr[4] = 0.5*x0*fc2;
vr[5] = 0.5*x1*fc2;
v_tally(1,&i,1.0,vr);
}
}
// set omega, angmom of each extended particle
if (extended) {
double *shape,*quatatom;
AtomVecEllipsoid::Bonus *ebonus;
if (avec_ellipsoid) ebonus = avec_ellipsoid->bonus;
double **omega_one = atom->omega;
double **angmom_one = atom->angmom;
int *ellipsoid = atom->ellipsoid;
for (int i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
if (eflags[i] & OMEGA) {
omega_one[i][0] = omega[ibody][0];
omega_one[i][1] = omega[ibody][1];
omega_one[i][2] = omega[ibody][2];
}
if (eflags[i] & ANGMOM) {
shape = ebonus[ellipsoid[i]].shape;
quatatom = ebonus[ellipsoid[i]].quat;
ione[0] = 0.2*rmass[i] * (shape[1]*shape[1] + shape[2]*shape[2]);
ione[1] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[2]*shape[2]);
ione[2] = 0.2*rmass[i] * (shape[0]*shape[0] + shape[1]*shape[1]);
MathExtra::q_to_exyz(quatatom,exone,eyone,ezone);
MathExtra::omega_to_angmom(omega[ibody],exone,eyone,ezone,ione,
angmom_one[i]);
}
}
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixRigid::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int);
bytes += nmax*3 * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
if (extended) {
bytes += nmax * sizeof(int);
if (dorientflag) bytes = nmax*3 * sizeof(double);
if (qorientflag) bytes = nmax*4 * sizeof(double);
}
return bytes;
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixRigid::grow_arrays(int nmax)
{
memory->grow(body,nmax,"rigid:body");
memory->grow(displace,nmax,3,"rigid:displace");
if (extended) {
memory->grow(eflags,nmax,"rigid:eflags");
if (dorientflag) memory->grow(dorient,nmax,3,"rigid:dorient");
if (qorientflag) memory->grow(qorient,nmax,4,"rigid:qorient");
}
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixRigid::copy_arrays(int i, int j)
{
body[j] = body[i];
displace[j][0] = displace[i][0];
displace[j][1] = displace[i][1];
displace[j][2] = displace[i][2];
if (extended) {
eflags[j] = eflags[i];
if (dorientflag) {
dorient[j][0] = dorient[i][0];
dorient[j][1] = dorient[i][1];
dorient[j][2] = dorient[i][2];
}
if (qorientflag) {
qorient[j][0] = qorient[i][0];
qorient[j][1] = qorient[i][1];
qorient[j][2] = qorient[i][2];
qorient[j][3] = qorient[i][3];
}
}
}
/* ----------------------------------------------------------------------
initialize one atom's array values, called when atom is created
------------------------------------------------------------------------- */
void FixRigid::set_arrays(int i)
{
body[i] = -1;
displace[i][0] = 0.0;
displace[i][1] = 0.0;
displace[i][2] = 0.0;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixRigid::pack_exchange(int i, double *buf)
{
buf[0] = body[i];
buf[1] = displace[i][0];
buf[2] = displace[i][1];
buf[3] = displace[i][2];
if (!extended) return 4;
int m = 4;
buf[m++] = eflags[i];
if (dorientflag) {
buf[m++] = dorient[i][0];
buf[m++] = dorient[i][1];
buf[m++] = dorient[i][2];
}
if (qorientflag) {
buf[m++] = qorient[i][0];
buf[m++] = qorient[i][1];
buf[m++] = qorient[i][2];
buf[m++] = qorient[i][3];
}
return m;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixRigid::unpack_exchange(int nlocal, double *buf)
{
body[nlocal] = static_cast<int> (buf[0]);
displace[nlocal][0] = buf[1];
displace[nlocal][1] = buf[2];
displace[nlocal][2] = buf[3];
if (!extended) return 4;
int m = 4;
eflags[nlocal] = static_cast<int> (buf[m++]);
if (dorientflag) {
dorient[nlocal][0] = buf[m++];
dorient[nlocal][1] = buf[m++];
dorient[nlocal][2] = buf[m++];
}
if (qorientflag) {
qorient[nlocal][0] = buf[m++];
qorient[nlocal][1] = buf[m++];
qorient[nlocal][2] = buf[m++];
qorient[nlocal][3] = buf[m++];
}
return m;
}
/* ---------------------------------------------------------------------- */
void FixRigid::reset_dt()
{
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dtq = 0.5 * update->dt;
}
/* ----------------------------------------------------------------------
return temperature of collection of rigid bodies
non-active DOF are removed by fflag/tflag and in tfactor
------------------------------------------------------------------------- */
double FixRigid::compute_scalar()
{
double wbody[3],rot[3][3];
double t = 0.0;
for (int i = 0; i < nbody; i++) {
t += masstotal[i] * (fflag[i][0]*vcm[i][0]*vcm[i][0] +
fflag[i][1]*vcm[i][1]*vcm[i][1] + \
fflag[i][2]*vcm[i][2]*vcm[i][2]);
// wbody = angular velocity in body frame
MathExtra::quat_to_mat(quat[i],rot);
MathExtra::transpose_matvec(rot,angmom[i],wbody);
if (inertia[i][0] == 0.0) wbody[0] = 0.0;
else wbody[0] /= inertia[i][0];
if (inertia[i][1] == 0.0) wbody[1] = 0.0;
else wbody[1] /= inertia[i][1];
if (inertia[i][2] == 0.0) wbody[2] = 0.0;
else wbody[2] /= inertia[i][2];
t += tflag[i][0]*inertia[i][0]*wbody[0]*wbody[0] +
tflag[i][1]*inertia[i][1]*wbody[1]*wbody[1] +
tflag[i][2]*inertia[i][2]*wbody[2]*wbody[2];
}
t *= tfactor;
return t;
}
/* ----------------------------------------------------------------------
return attributes of a rigid body
15 values per body
xcm = 0,1,2; vcm = 3,4,5; fcm = 6,7,8; torque = 9,10,11; image = 12,13,14
------------------------------------------------------------------------- */
double FixRigid::compute_array(int i, int j)
{
if (j < 3) return xcm[i][j];
if (j < 6) return vcm[i][j-3];
if (j < 9) return fcm[i][j-6];
if (j < 12) return torque[i][j-9];
if (j == 12) return (imagebody[i] & 1023) - 512;
if (j == 13) return (imagebody[i] >> 10 & 1023) - 512;
return (imagebody[i] >> 20) - 512;
}
diff --git a/src/fix_rigid_nvt.cpp b/src/fix_rigid_nvt.cpp
index bad5e961d..824f8b4bb 100644
--- a/src/fix_rigid_nvt.cpp
+++ b/src/fix_rigid_nvt.cpp
@@ -1,715 +1,715 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Tony Sheh (U Michigan), Trung Dac Nguyen (U Michigan)
references: Kamberaj et al., J. Chem. Phys. 122, 224114 (2005)
Miller et al., J Chem Phys. 116, 8649-8659
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fix_rigid_nvt.h"
#include "math_extra.h"
#include "atom.h"
#include "domain.h"
#include "update.h"
#include "modify.h"
#include "group.h"
#include "comm.h"
#include "force.h"
#include "output.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixRigidNVT::FixRigidNVT(LAMMPS *lmp, int narg, char **arg) :
FixRigid(lmp, narg, arg)
{
// other settings are made by FixRigid parent
scalar_flag = 1;
restart_global = 1;
extscalar = 1;
// error checking
// convert input period to frequency
if (tempflag == 0)
- error->all("Did not set temp for fix rigid/nvt");
+ error->all(FLERR,"Did not set temp for fix rigid/nvt");
if (t_start < 0.0 || t_stop <= 0.0)
- error->all("Target temperature for fix rigid/nvt cannot be 0.0");
- if (t_period <= 0.0) error->all("Fix rigid/nvt period must be > 0.0");
+ error->all(FLERR,"Target temperature for fix rigid/nvt cannot be 0.0");
+ if (t_period <= 0.0) error->all(FLERR,"Fix rigid/nvt period must be > 0.0");
t_freq = 1.0 / t_period;
- if (t_chain < 1) error->all("Illegal fix_modify command");
- if (t_iter < 1) error->all("Illegal fix_modify command");
+ if (t_chain < 1) error->all(FLERR,"Illegal fix_modify command");
+ if (t_iter < 1) error->all(FLERR,"Illegal fix_modify command");
if (t_order != 3 && t_order != 5)
- error->all("Fix_modify order must be 3 or 5");
+ error->all(FLERR,"Fix_modify order must be 3 or 5");
allocate_chain();
allocate_order();
memory->create(conjqm,nbody,4,"nve_rigid:conjqm");
// one-time initialize of thermostat variables
eta_t[0] = eta_r[0] = 0.0;
eta_dot_t[0] = eta_dot_r[0] = 0.0;
f_eta_t[0] = f_eta_r[0] = 0.0;
for (int i = 1; i < t_chain; i++) {
eta_t[i] = eta_r[i] = 0.0;
eta_dot_t[i] = eta_dot_r[i] = 0.0;
}
}
/* ---------------------------------------------------------------------- */
FixRigidNVT::~FixRigidNVT()
{
deallocate_chain();
deallocate_order();
memory->destroy(conjqm);
}
/* ---------------------------------------------------------------------- */
int FixRigidNVT::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= PRE_NEIGHBOR;
mask |= THERMO_ENERGY;
mask |= INITIAL_INTEGRATE_RESPA;
mask |= FINAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::init()
{
FixRigid::init();
// initialize thermostats
// set timesteps, constants
// store Yoshida-Suzuki integrator parameters
dtv = update->dt;
dtf = 0.5 * update->dt * force->ftm2v;
dtq = 0.5 * update->dt;
boltz = force->boltz;
nf_t = nf_r = domain->dimension * nbody;
for (int ibody = 0; ibody < nbody; ibody++)
for (int k = 0; k < domain->dimension; k++)
if (fabs(inertia[ibody][k]) < 1e-6) nf_r--;
// see Table 1 in Kamberaj et al
if (t_order == 3) {
w[0] = 1.0 / (2.0 - pow(2.0, 1.0/3.0));
w[1] = 1.0 - 2.0*w[0];
w[2] = w[0];
} else if (t_order == 5) {
w[0] = 1.0 / (4.0 - pow(4.0, 1.0/3.0));
w[1] = w[0];
w[2] = 1.0 - 4.0 * w[0];
w[3] = w[0];
w[4] = w[0];
}
// initialize thermostat settings
t_target = t_start;
double kt = boltz * t_target;
double t_mass = kt / (t_freq*t_freq);
q_t[0] = nf_t * t_mass;
q_r[0] = nf_r * t_mass;
for (int i = 1; i < t_chain; i++)
q_t[i] = q_r[i] = t_mass;
// initialize thermostat chain positions, velocites, forces
for (int i = 1; i < t_chain; i++) {
f_eta_t[i] = q_t[i-1] * eta_dot_t[i-1] * eta_dot_t[i-1] - kt;
f_eta_r[i] = q_r[i-1] * eta_dot_r[i-1] * eta_dot_r[i-1] - kt;
}
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::setup(int vflag)
{
FixRigid::setup(vflag);
t_target = t_start;
double mbody[3];
for (int ibody = 0; ibody < nbody; ibody++) {
MathExtra::transpose_matvec(ex_space[ibody],ey_space[ibody],ez_space[ibody],
angmom[ibody],mbody);
MathExtra::quatvec(quat[ibody],mbody,conjqm[ibody]);
conjqm[ibody][0] *= 2.0;
conjqm[ibody][1] *= 2.0;
conjqm[ibody][2] *= 2.0;
conjqm[ibody][3] *= 2.0;
}
}
/* ----------------------------------------------------------------------
perform preforce velocity Verlet integration
see Kamberaj paper for step references
------------------------------------------------------------------------- */
void FixRigidNVT::initial_integrate(int vflag)
{
double tmp,akin_t,akin_r,scale_t,scale_r;
double dtfm,mbody[3],tbody[3],fquat[4];
double dtf2 = dtf * 2.0;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
t_target = t_start + delta * (t_stop - t_start);
// intialize velocity scale for translation and rotation
akin_t = akin_r = 0.0;
tmp = -1.0 * dtq * eta_dot_t[0];
scale_t = exp(tmp);
tmp = -1.0 * dtq * eta_dot_r[0];
scale_r = exp(tmp);
for (int ibody = 0; ibody < nbody; ibody++) {
// step 1.1 - update vcm by 1/2 step
dtfm = dtf / masstotal[ibody];
vcm[ibody][0] += dtfm * fcm[ibody][0] * fflag[ibody][0];
vcm[ibody][1] += dtfm * fcm[ibody][1] * fflag[ibody][1];
vcm[ibody][2] += dtfm * fcm[ibody][2] * fflag[ibody][2];
vcm[ibody][0] *= scale_t;
vcm[ibody][1] *= scale_t;
vcm[ibody][2] *= scale_t;
tmp = vcm[ibody][0]*vcm[ibody][0] + vcm[ibody][1]*vcm[ibody][1] +
vcm[ibody][2]*vcm[ibody][2];
akin_t += masstotal[ibody]*tmp;
// step 1.2 - update xcm by full step
xcm[ibody][0] += dtv * vcm[ibody][0];
xcm[ibody][1] += dtv * vcm[ibody][1];
xcm[ibody][2] += dtv * vcm[ibody][2];
torque[ibody][0] *= tflag[ibody][0];
torque[ibody][1] *= tflag[ibody][1];
torque[ibody][2] *= tflag[ibody][2];
// step 1.3 - apply torque (body coords) to quaternion momentum
MathExtra::transpose_matvec(ex_space[ibody],ey_space[ibody],ez_space[ibody],
torque[ibody],tbody);
MathExtra::quatvec(quat[ibody],tbody,fquat);
conjqm[ibody][0] += dtf2 * fquat[0];
conjqm[ibody][1] += dtf2 * fquat[1];
conjqm[ibody][2] += dtf2 * fquat[2];
conjqm[ibody][3] += dtf2 * fquat[3];
conjqm[ibody][0] *= scale_r;
conjqm[ibody][1] *= scale_r;
conjqm[ibody][2] *= scale_r;
conjqm[ibody][3] *= scale_r;
// step 1.4 to 1.8 - use no_squish rotate to update p (i.e. conjqm) and q
no_squish_rotate(3,conjqm[ibody],quat[ibody],inertia[ibody],dtq);
no_squish_rotate(2,conjqm[ibody],quat[ibody],inertia[ibody],dtq);
no_squish_rotate(1,conjqm[ibody],quat[ibody],inertia[ibody],dtv);
no_squish_rotate(2,conjqm[ibody],quat[ibody],inertia[ibody],dtq);
no_squish_rotate(3,conjqm[ibody],quat[ibody],inertia[ibody],dtq);
// update the exyz_space from new quaternion
// transform p back to angmom
// update angular velocity
MathExtra::q_to_exyz(quat[ibody],ex_space[ibody],ey_space[ibody],
ez_space[ibody]);
MathExtra::invquatvec(quat[ibody],conjqm[ibody],mbody);
MathExtra::matvec(ex_space[ibody],ey_space[ibody],ez_space[ibody],
mbody,angmom[ibody]);
angmom[ibody][0] *= 0.5;
angmom[ibody][1] *= 0.5;
angmom[ibody][2] *= 0.5;
MathExtra::angmom_to_omega(angmom[ibody],ex_space[ibody],ey_space[ibody],
ez_space[ibody],inertia[ibody],omega[ibody]);
akin_r += angmom[ibody][0]*omega[ibody][0] +
angmom[ibody][1]*omega[ibody][1] + angmom[ibody][2]*omega[ibody][2];
}
// update thermostat chains
update_nhcp(akin_t,akin_r);
// virial setup before call to set_xv
if (vflag) v_setup(vflag);
else evflag = 0;
// set coords/orient and velocity/rotation of atoms in rigid bodies
// from quarternion and omega
set_xv();
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::final_integrate()
{
int i,ibody;
double tmp,scale_t,scale_r;
double dtfm,xy,xz,yz;
// compute velocity scales for translation and rotation
tmp = -1.0 * dtq * eta_dot_t[0];
scale_t = exp(tmp);
tmp = -1.0 * dtq * eta_dot_r[0];
scale_r = exp(tmp);
// sum over atoms to get force and torque on rigid body
int *image = atom->image;
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
if (triclinic) {
xy = domain->xy;
xz = domain->xz;
yz = domain->yz;
}
int xbox,ybox,zbox;
double xunwrap,yunwrap,zunwrap,dx,dy,dz;
for (ibody = 0; ibody < nbody; ibody++)
for (i = 0; i < 6; i++) sum[ibody][i] = 0.0;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
sum[ibody][0] += f[i][0];
sum[ibody][1] += f[i][1];
sum[ibody][2] += f[i][2];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
if (triclinic == 0) {
xunwrap = x[i][0] + xbox*xprd;
yunwrap = x[i][1] + ybox*yprd;
zunwrap = x[i][2] + zbox*zprd;
} else {
xunwrap = x[i][0] + xbox*xprd + ybox*xy + zbox*xz;
yunwrap = x[i][1] + ybox*yprd + zbox*yz;
zunwrap = x[i][2] + zbox*zprd;
}
dx = xunwrap - xcm[ibody][0];
dy = yunwrap - xcm[ibody][1];
dz = zunwrap - xcm[ibody][2];
sum[ibody][3] += dy*f[i][2] - dz*f[i][1];
sum[ibody][4] += dz*f[i][0] - dx*f[i][2];
sum[ibody][5] += dx*f[i][1] - dy*f[i][0];
}
// extended particles add their torque to torque of body
if (extended) {
double **torque_one = atom->torque;
for (i = 0; i < nlocal; i++) {
if (body[i] < 0) continue;
ibody = body[i];
if (eflags[i] & TORQUE) {
sum[ibody][3] += torque_one[i][0];
sum[ibody][4] += torque_one[i][1];
sum[ibody][5] += torque_one[i][2];
}
}
}
MPI_Allreduce(sum[0],all[0],6*nbody,MPI_DOUBLE,MPI_SUM,world);
double mbody[3],tbody[3],fquat[4];
double dtf2 = dtf * 2.0;
for (ibody = 0; ibody < nbody; ibody++) {
fcm[ibody][0] = all[ibody][0];
fcm[ibody][1] = all[ibody][1];
fcm[ibody][2] = all[ibody][2];
torque[ibody][0] = all[ibody][3];
torque[ibody][1] = all[ibody][4];
torque[ibody][2] = all[ibody][5];
// 2.5-2.6 update vcm by 1/2 step
dtfm = dtf / masstotal[ibody];
vcm[ibody][0] *= scale_t;
vcm[ibody][1] *= scale_t;
vcm[ibody][2] *= scale_t;
vcm[ibody][0] += dtfm * fcm[ibody][0] * fflag[ibody][0];
vcm[ibody][1] += dtfm * fcm[ibody][1] * fflag[ibody][1];
vcm[ibody][2] += dtfm * fcm[ibody][2] * fflag[ibody][2];
// 2.1-2.4 update conjqm, angular momentum and angular velocity
// apply body torque flags
torque[ibody][0] *= tflag[ibody][0];
torque[ibody][1] *= tflag[ibody][1];
torque[ibody][2] *= tflag[ibody][2];
// convert torque to the body frame
MathExtra::transpose_matvec(ex_space[ibody],ey_space[ibody],ez_space[ibody],
torque[ibody],tbody);
// compute "force" for quaternion
MathExtra::quatvec(quat[ibody],tbody,fquat);
// update the conjugate quaternion momentum (conjqm)
conjqm[ibody][0] = scale_r * conjqm[ibody][0] + dtf2 * fquat[0];
conjqm[ibody][1] = scale_r * conjqm[ibody][1] + dtf2 * fquat[1];
conjqm[ibody][2] = scale_r * conjqm[ibody][2] + dtf2 * fquat[2];
conjqm[ibody][3] = scale_r * conjqm[ibody][3] + dtf2 * fquat[3];
// compute angular momentum in the body frame
// then convert to the space-fixed frame
MathExtra::invquatvec(quat[ibody],conjqm[ibody],mbody);
MathExtra::matvec(ex_space[ibody],ey_space[ibody],ez_space[ibody],
mbody,angmom[ibody]);
angmom[ibody][0] *= 0.5;
angmom[ibody][1] *= 0.5;
angmom[ibody][2] *= 0.5;
// compute new angular velocity
MathExtra::angmom_to_omega(angmom[ibody],ex_space[ibody],ey_space[ibody],
ez_space[ibody],inertia[ibody],omega[ibody]);
}
// set velocity/rotation of atoms in rigid bodies
// virial is already setup from initial_integrate
set_v();
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::update_nhcp(double akin_t, double akin_r)
{
int i,j,k;
double kt,gfkt_t,gfkt_r,tmp,ms,s,s2;
kt = boltz * t_target;
gfkt_t = nf_t * kt;
gfkt_r = nf_r * kt;
akin_t *= force->mvv2e;
akin_r *= force->mvv2e;
// update thermostat masses
double t_mass = boltz * t_target / (t_freq * t_freq);
q_t[0] = nf_t * t_mass;
q_r[0] = nf_r * t_mass;
for (i = 1; i < t_chain; i++)
q_t[i] = q_r[i] = t_mass;
// update order/timestep dependent coefficients
for (i = 0; i < t_order; i++) {
wdti1[i] = w[i] * dtv / t_iter;
wdti2[i] = wdti1[i] / 2.0;
wdti4[i] = wdti1[i] / 4.0;
}
// update force of thermostats coupled to particles
f_eta_t[0] = (akin_t - gfkt_t) / q_t[0];
f_eta_r[0] = (akin_r - gfkt_r) / q_r[0];
// multiple timestep iteration
for (i = 0; i < t_iter; i++) {
for (j = 0; j < t_order; j++) {
// update thermostat velocities half step
eta_dot_t[t_chain-1] += wdti2[j] * f_eta_t[t_chain-1];
eta_dot_r[t_chain-1] += wdti2[j] * f_eta_r[t_chain-1];
for (k = 1; k < t_chain; k++) {
tmp = wdti4[j] * eta_dot_t[t_chain-k];
ms = maclaurin_series(tmp);
s = exp(-1.0 * tmp);
s2 = s * s;
eta_dot_t[t_chain-k-1] = eta_dot_t[t_chain-k-1] * s2 +
wdti2[j] * f_eta_t[t_chain-k-1] * s * ms;
tmp = wdti4[j] * eta_dot_r[t_chain-k];
ms = maclaurin_series(tmp);
s = exp(-1.0 * tmp);
s2 = s * s;
eta_dot_r[t_chain-k-1] = eta_dot_r[t_chain-k-1] * s2 +
wdti2[j] * f_eta_r[t_chain-k-1] * s * ms;
}
// update thermostat positions a full step
for (k = 0; k < t_chain; k++) {
eta_t[k] += wdti1[j] * eta_dot_t[k];
eta_r[k] += wdti1[j] * eta_dot_r[k];
}
// update thermostat forces
for (k = 1; k < t_chain; k++) {
f_eta_t[k] = q_t[k-1] * eta_dot_t[k-1] * eta_dot_t[k-1] - kt;
f_eta_t[k] /= q_t[k];
f_eta_r[k] = q_r[k-1] * eta_dot_r[k-1] * eta_dot_r[k-1] - kt;
f_eta_r[k] /= q_r[k];
}
// update thermostat velocities a full step
for (k = 0; k < t_chain-1; k++) {
tmp = wdti4[j] * eta_dot_t[k+1];
ms = maclaurin_series(tmp);
s = exp(-1.0 * tmp);
s2 = s * s;
eta_dot_t[k] = eta_dot_t[k] * s2 + wdti2[j] * f_eta_t[k] * s * ms;
tmp = q_t[k] * eta_dot_t[k] * eta_dot_t[k] - kt;
f_eta_t[k+1] = tmp / q_t[k+1];
tmp = wdti4[j] * eta_dot_r[k+1];
ms = maclaurin_series(tmp);
s = exp(-1.0 * tmp);
s2 = s * s;
eta_dot_r[k] = eta_dot_r[k] * s2 + wdti2[j] * f_eta_r[k] * s * ms;
tmp = q_r[k] * eta_dot_r[k] * eta_dot_r[k] - kt;
f_eta_r[k+1] = tmp / q_r[k+1];
}
eta_dot_t[t_chain-1] += wdti2[j] * f_eta_t[t_chain-1];
eta_dot_r[t_chain-1] += wdti2[j] * f_eta_r[t_chain-1];
}
}
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixRigidNVT::write_restart(FILE *fp)
{
int n = 0;
double *list = new double[1+6*t_chain];
list[n++] = t_chain;
for (int i = 0; i < t_chain; i++) {
list[n++] = eta_t[i];
list[n++] = eta_r[i];
list[n++] = eta_dot_t[i];
list[n++] = eta_dot_r[i];
list[n++] = f_eta_t[i];
list[n++] = f_eta_r[i];
}
if (comm->me == 0) {
int size = (1 + 6*t_chain)*sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(list,sizeof(double),1+6*t_chain,fp);
}
delete list;
}
/* ----------------------------------------------------------------------
compute kinetic energy in the extended Hamiltonian
conserved quantity = sum of returned energy and potential energy
-----------------------------------------------------------------------*/
double FixRigidNVT::compute_scalar()
{
int i,k,ibody;
double kt = boltz * t_target;
double energy,ke_t,ke_q,tmp,Pkq[4];
// compute the kinetic parts of H_NVE in Kameraj et al (JCP 2005, pp 224114)
// translational kinetic energy
ke_t = 0.0;
for (ibody = 0; ibody < nbody; ibody++)
ke_t += 0.5 * masstotal[ibody] * (vcm[ibody][0]*vcm[ibody][0] +
vcm[ibody][1]*vcm[ibody][1] +
vcm[ibody][2]*vcm[ibody][2]);
// rotational kinetic energy
ke_q = 0.0;
for (ibody = 0; ibody < nbody; ibody++) {
for (k = 1; k < 4; k++) {
if (k == 1) {
Pkq[0] = -quat[ibody][1];
Pkq[1] = quat[ibody][0];
Pkq[2] = quat[ibody][3];
Pkq[3] = -quat[ibody][2];
} else if (k == 2) {
Pkq[0] = -quat[ibody][2];
Pkq[1] = -quat[ibody][3];
Pkq[2] = quat[ibody][0];
Pkq[3] = quat[ibody][1];
} else if (k == 3) {
Pkq[0] = -quat[ibody][3];
Pkq[1] = quat[ibody][2];
Pkq[2] = -quat[ibody][1];
Pkq[3] = quat[ibody][0];
}
tmp = conjqm[ibody][0]*Pkq[0] + conjqm[ibody][1]*Pkq[1] +
conjqm[ibody][2]*Pkq[2] + conjqm[ibody][3]*Pkq[3];
tmp *= tmp;
if (fabs(inertia[ibody][k-1]) < 1e-6) tmp = 0.0;
else tmp /= (8.0 * inertia[ibody][k-1]);
ke_q += tmp;
}
}
energy = ke_t + ke_q;
// thermostat chain energy: from equation 12 in Kameraj et al (JCP 2005)
energy += kt * (nf_t * eta_t[0] + nf_r * eta_r[0]);
for (i = 1; i < t_chain; i++)
energy += kt * (eta_t[i] + eta_r[i]);
for (i = 0; i < t_chain; i++) {
energy += 0.5 * q_t[i] * (eta_dot_t[i] * eta_dot_t[i]);
energy += 0.5 * q_r[i] * (eta_dot_r[i] * eta_dot_r[i]);
}
return energy;
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixRigidNVT::restart(char *buf)
{
int n = 0;
double *list = (double *) buf;
int t_chain_prev = static_cast<int> (list[n++]);
if (t_chain_prev != t_chain)
- error->all("Cannot restart fix rigid/nvt with different # of chains");
+ error->all(FLERR,"Cannot restart fix rigid/nvt with different # of chains");
for (int i = 0; i < t_chain; i++) {
eta_t[i] = list[n++];
eta_r[i] = list[n++];
eta_dot_t[i] = list[n++];
eta_dot_r[i] = list[n++];
f_eta_t[i] = list[n++];
f_eta_r[i] = list[n++];
}
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::allocate_chain()
{
q_t = new double[t_chain];
q_r = new double[t_chain];
eta_t = new double[t_chain];
eta_r = new double[t_chain];
eta_dot_t = new double[t_chain];
eta_dot_r = new double[t_chain];
f_eta_t = new double[t_chain];
f_eta_r = new double[t_chain];
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::allocate_order()
{
w = new double[t_order];
wdti1 = new double[t_order];
wdti2 = new double[t_order];
wdti4 = new double[t_order];
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::deallocate_chain()
{
delete [] q_t;
delete [] q_r;
delete [] eta_t;
delete [] eta_r;
delete [] eta_dot_t;
delete [] eta_dot_r;
delete [] f_eta_t;
delete [] f_eta_r;
}
/* ---------------------------------------------------------------------- */
void FixRigidNVT::deallocate_order()
{
delete [] w;
delete [] wdti1;
delete [] wdti2;
delete [] wdti4;
}
diff --git a/src/fix_setforce.cpp b/src/fix_setforce.cpp
index 897aad56a..c7dba74f5 100644
--- a/src/fix_setforce.cpp
+++ b/src/fix_setforce.cpp
@@ -1,330 +1,330 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "fix_setforce.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "region.h"
#include "respa.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NONE,CONSTANT,EQUAL,ATOM};
/* ---------------------------------------------------------------------- */
FixSetForce::FixSetForce(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix setforce command");
+ if (narg < 6) error->all(FLERR,"Illegal fix setforce command");
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extvector = 1;
xstr = ystr = zstr = NULL;
if (strstr(arg[3],"v_") == arg[3]) {
int n = strlen(&arg[3][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[3][2]);
} else if (strcmp(arg[3],"NULL") == 0) {
xstyle = NONE;
} else {
xvalue = atof(arg[3]);
xstyle = CONSTANT;
}
if (strstr(arg[4],"v_") == arg[4]) {
int n = strlen(&arg[4][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[4][2]);
} else if (strcmp(arg[4],"NULL") == 0) {
ystyle = NONE;
} else {
yvalue = atof(arg[4]);
ystyle = CONSTANT;
}
if (strstr(arg[5],"v_") == arg[5]) {
int n = strlen(&arg[5][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[5][2]);
} else if (strcmp(arg[5],"NULL") == 0) {
zstyle = NONE;
} else {
zvalue = atof(arg[5]);
zstyle = CONSTANT;
}
// optional args
iregion = -1;
idregion = NULL;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"region") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix setforce command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix setforce command");
iregion = domain->find_region(arg[iarg+1]);
if (iregion == -1)
- error->all("Region ID for fix setforce does not exist");
+ error->all(FLERR,"Region ID for fix setforce does not exist");
int n = strlen(arg[iarg+1]) + 1;
idregion = new char[n];
strcpy(idregion,arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal fix setforce command");
+ } else error->all(FLERR,"Illegal fix setforce command");
}
force_flag = 0;
foriginal[0] = foriginal[1] = foriginal[2] = 0.0;
maxatom = 0;
sforce = NULL;
}
/* ---------------------------------------------------------------------- */
FixSetForce::~FixSetForce()
{
delete [] xstr;
delete [] ystr;
delete [] zstr;
delete [] idregion;
memory->destroy(sforce);
}
/* ---------------------------------------------------------------------- */
int FixSetForce::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixSetForce::init()
{
// check variables
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for fix setforce does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for fix setforce does not exist");
if (input->variable->equalstyle(xvar)) xstyle = EQUAL;
else if (input->variable->atomstyle(xvar)) xstyle = ATOM;
- else error->all("Variable for fix setforce is invalid style");
+ else error->all(FLERR,"Variable for fix setforce is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for fix setforce does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for fix setforce does not exist");
if (input->variable->equalstyle(yvar)) ystyle = EQUAL;
else if (input->variable->atomstyle(yvar)) ystyle = ATOM;
- else error->all("Variable for fix setforce is invalid style");
+ else error->all(FLERR,"Variable for fix setforce is invalid style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for fix setforce does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for fix setforce does not exist");
if (input->variable->equalstyle(zvar)) zstyle = EQUAL;
else if (input->variable->atomstyle(zvar)) zstyle = ATOM;
- else error->all("Variable for fix setforce is invalid style");
+ else error->all(FLERR,"Variable for fix setforce is invalid style");
}
// set index and check validity of region
if (iregion >= 0) {
iregion = domain->find_region(idregion);
- if (iregion == -1) error->all("Region ID for fix setforce does not exist");
+ if (iregion == -1) error->all(FLERR,"Region ID for fix setforce does not exist");
}
if (xstyle == ATOM || ystyle == ATOM || zstyle == ATOM)
varflag = ATOM;
else if (xstyle == EQUAL || ystyle == EQUAL || zstyle == EQUAL)
varflag = EQUAL;
else varflag = CONSTANT;
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
// cannot use non-zero forces for a minimization since no energy is integrated
// use fix addforce instead
int flag = 0;
if (update->whichflag == 2) {
if (xstyle == EQUAL || xstyle == ATOM) flag = 1;
if (ystyle == EQUAL || ystyle == ATOM) flag = 1;
if (zstyle == EQUAL || zstyle == ATOM) flag = 1;
if (xstyle == CONSTANT && xvalue != 0.0) flag = 1;
if (ystyle == CONSTANT && yvalue != 0.0) flag = 1;
if (zstyle == CONSTANT && zvalue != 0.0) flag = 1;
}
if (flag)
- error->all("Cannot use non-zero forces in an energy minimization");
+ error->all(FLERR,"Cannot use non-zero forces in an energy minimization");
}
/* ---------------------------------------------------------------------- */
void FixSetForce::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else
for (int ilevel = 0; ilevel < nlevels_respa; ilevel++) {
((Respa *) update->integrate)->copy_flevel_f(ilevel);
post_force_respa(vflag,ilevel,0);
((Respa *) update->integrate)->copy_f_flevel(ilevel);
}
}
/* ---------------------------------------------------------------------- */
void FixSetForce::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixSetForce::post_force(int vflag)
{
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// reallocate sforce array if necessary
if (varflag == ATOM && nlocal > maxatom) {
maxatom = atom->nmax;
memory->destroy(sforce);
memory->create(sforce,maxatom,3,"setforce:sforce");
}
foriginal[0] = foriginal[1] = foriginal[2] = 0.0;
force_flag = 0;
if (varflag == CONSTANT) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
foriginal[0] += f[i][0];
foriginal[1] += f[i][1];
foriginal[2] += f[i][2];
if (xstyle) f[i][0] = xvalue;
if (ystyle) f[i][1] = yvalue;
if (zstyle) f[i][2] = zvalue;
}
// variable force, wrap with clear/add
} else {
modify->clearstep_compute();
if (xstyle == EQUAL) xvalue = input->variable->compute_equal(xvar);
else if (xstyle == ATOM && sforce)
input->variable->compute_atom(xvar,igroup,&sforce[0][0],3,0);
if (ystyle == EQUAL) yvalue = input->variable->compute_equal(yvar);
else if (ystyle == ATOM && sforce)
input->variable->compute_atom(yvar,igroup,&sforce[0][1],3,0);
if (zstyle == EQUAL) zvalue = input->variable->compute_equal(zvar);
else if (zstyle == ATOM && sforce)
input->variable->compute_atom(zvar,igroup,&sforce[0][2],3,0);
modify->addstep_compute(update->ntimestep + 1);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (iregion >= 0 &&
!domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
continue;
foriginal[0] += f[i][0];
foriginal[1] += f[i][1];
foriginal[2] += f[i][2];
if (xstyle == ATOM) f[i][0] = sforce[i][0];
else if (xstyle) f[i][0] = xvalue;
if (ystyle == ATOM) f[i][1] = sforce[i][1];
else if (ystyle) f[i][1] = yvalue;
if (zstyle == ATOM) f[i][2] = sforce[i][2];
else if (zstyle) f[i][2] = zvalue;
}
}
}
/* ---------------------------------------------------------------------- */
void FixSetForce::post_force_respa(int vflag, int ilevel, int iloop)
{
// set force to desired value on outermost level, 0.0 on other levels
if (ilevel == nlevels_respa-1) post_force(vflag);
else {
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (xstyle) f[i][0] = 0.0;
if (ystyle) f[i][1] = 0.0;
if (zstyle) f[i][2] = 0.0;
}
}
}
/* ---------------------------------------------------------------------- */
void FixSetForce::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
return components of total force on fix group before force was changed
------------------------------------------------------------------------- */
double FixSetForce::compute_vector(int n)
{
// only sum across procs one time
if (force_flag == 0) {
MPI_Allreduce(foriginal,foriginal_all,3,MPI_DOUBLE,MPI_SUM,world);
force_flag = 1;
}
return foriginal_all[n];
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixSetForce::memory_usage()
{
double bytes = 0.0;
if (varflag == ATOM) bytes = atom->nmax*3 * sizeof(double);
return bytes;
}
diff --git a/src/fix_shake.cpp b/src/fix_shake.cpp
index fca15216f..e00e84e42 100644
--- a/src/fix_shake.cpp
+++ b/src/fix_shake.cpp
@@ -1,2428 +1,2426 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "fix_shake.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "respa.h"
#include "modify.h"
#include "domain.h"
#include "force.h"
#include "bond.h"
#include "angle.h"
#include "comm.h"
#include "group.h"
#include "fix_respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
#define MASSDELTA 0.1
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
/* ---------------------------------------------------------------------- */
FixShake::FixShake(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
PI = 4.0*atan(1.0);
virial_flag = 1;
create_attribute = 1;
// error check
if (atom->molecular == 0)
- error->all("Cannot use fix shake with non-molecular system");
+ error->all(FLERR,"Cannot use fix shake with non-molecular system");
// perform initial allocation of atom-based arrays
// register with Atom class
shake_flag = NULL;
shake_atom = shake_type = NULL;
xshake = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
// set comm size needed by this fix
comm_forward = 3;
// parse SHAKE args
- if (narg < 8) error->all("Illegal fix shake command");
+ if (narg < 8) error->all(FLERR,"Illegal fix shake command");
tolerance = atof(arg[3]);
max_iter = atoi(arg[4]);
output_every = atoi(arg[5]);
// parse SHAKE args for bond and angle types
// will be used by find_clusters
// store args for "b" "a" "t" as flags in (1:n) list for fast access
// store args for "m" in list of length nmass for looping over
// for "m" verify that atom masses have been set
bond_flag = new int[atom->nbondtypes+1];
for (int i = 1; i <= atom->nbondtypes; i++) bond_flag[i] = 0;
angle_flag = new int[atom->nangletypes+1];
for (int i = 1; i <= atom->nangletypes; i++) angle_flag[i] = 0;
type_flag = new int[atom->ntypes+1];
for (int i = 1; i <= atom->ntypes; i++) type_flag[i] = 0;
mass_list = new double[atom->ntypes];
nmass = 0;
char mode = '\0';
int next = 6;
while (next < narg) {
if (strcmp(arg[next],"b") == 0) mode = 'b';
else if (strcmp(arg[next],"a") == 0) mode = 'a';
else if (strcmp(arg[next],"t") == 0) mode = 't';
else if (strcmp(arg[next],"m") == 0) {
mode = 'm';
atom->check_mass();
} else if (mode == 'b') {
int i = atoi(arg[next]);
if (i < 1 || i > atom->nbondtypes)
- error->all("Invalid bond type index for fix shake");
+ error->all(FLERR,"Invalid bond type index for fix shake");
bond_flag[i] = 1;
} else if (mode == 'a') {
int i = atoi(arg[next]);
if (i < 1 || i > atom->nangletypes)
- error->all("Invalid angle type index for fix shake");
+ error->all(FLERR,"Invalid angle type index for fix shake");
angle_flag[i] = 1;
} else if (mode == 't') {
int i = atoi(arg[next]);
if (i < 1 || i > atom->ntypes)
- error->all("Invalid atom type index for fix shake");
+ error->all(FLERR,"Invalid atom type index for fix shake");
type_flag[i] = 1;
} else if (mode == 'm') {
double massone = atof(arg[next]);
- if (massone == 0.0) error->all("Invalid atom mass for fix shake");
- if (nmass == atom->ntypes) error->all("Too many masses for fix shake");
+ if (massone == 0.0) error->all(FLERR,"Invalid atom mass for fix shake");
+ if (nmass == atom->ntypes) error->all(FLERR,"Too many masses for fix shake");
mass_list[nmass++] = massone;
- } else error->all("Illegal fix shake command");
+ } else error->all(FLERR,"Illegal fix shake command");
next++;
}
// allocate bond and angle distance arrays, indexed from 1 to n
bond_distance = new double[atom->nbondtypes+1];
angle_distance = new double[atom->nangletypes+1];
// allocate statistics arrays
if (output_every) {
int nb = atom->nbondtypes + 1;
b_count = new int[nb];
b_count_all = new int[nb];
b_ave = new double[nb];
b_ave_all = new double[nb];
b_max = new double[nb];
b_max_all = new double[nb];
b_min = new double[nb];
b_min_all = new double[nb];
int na = atom->nangletypes + 1;
a_count = new int[na];
a_count_all = new int[na];
a_ave = new double[na];
a_ave_all = new double[na];
a_max = new double[na];
a_max_all = new double[na];
a_min = new double[na];
a_min_all = new double[na];
}
// identify all SHAKE clusters
find_clusters();
// initialize list of SHAKE clusters to constrain
maxlist = 0;
list = NULL;
}
/* ---------------------------------------------------------------------- */
FixShake::~FixShake()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
// set bond_type and angle_type back to positive for SHAKE clusters
// must set for all SHAKE bonds and angles stored by each atom
int **bond_type = atom->bond_type;
int **angle_type = atom->angle_type;
int nlocal = atom->nlocal;
int n;
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
else if (shake_flag[i] == 1) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = anglefind(i,shake_atom[i][1],shake_atom[i][2]);
if (n >= 0) angle_type[i][n] = -angle_type[i][n];
} else if (shake_flag[i] == 2) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 3) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 4) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][3]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
}
}
// delete locally stored arrays
memory->destroy(shake_flag);
memory->destroy(shake_atom);
memory->destroy(shake_type);
memory->destroy(xshake);
delete [] bond_flag;
delete [] angle_flag;
delete [] type_flag;
delete [] mass_list;
delete [] bond_distance;
delete [] angle_distance;
if (output_every) {
delete [] b_count;
delete [] b_count_all;
delete [] b_ave;
delete [] b_ave_all;
delete [] b_max;
delete [] b_max_all;
delete [] b_min;
delete [] b_min_all;
delete [] a_count;
delete [] a_count_all;
delete [] a_ave;
delete [] a_ave_all;
delete [] a_max;
delete [] a_max_all;
delete [] a_min;
delete [] a_min_all;
}
memory->destroy(list);
}
/* ---------------------------------------------------------------------- */
int FixShake::setmask()
{
int mask = 0;
mask |= PRE_NEIGHBOR;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ----------------------------------------------------------------------
set bond and angle distances
this init must happen after force->bond and force->angle inits
------------------------------------------------------------------------- */
void FixShake::init()
{
int i,m,flag,flag_all,type1,type2,bond1_type,bond2_type;
double rsq,angle;
// error if more than one shake fix
int count = 0;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"shake") == 0) count++;
- if (count > 1) error->all("More than one fix shake");
+ if (count > 1) error->all(FLERR,"More than one fix shake");
// cannot use with minimization since SHAKE turns off bonds
// that should contribute to potential energy
if (update->whichflag == 2)
- error->all("Fix shake cannot be used with minimization");
+ error->all(FLERR,"Fix shake cannot be used with minimization");
// error if npt,nph fix comes before shake fix
for (i = 0; i < modify->nfix; i++) {
if (strcmp(modify->fix[i]->style,"npt") == 0) break;
if (strcmp(modify->fix[i]->style,"nph") == 0) break;
}
if (i < modify->nfix) {
for (int j = i; j < modify->nfix; j++)
if (strcmp(modify->fix[j]->style,"shake") == 0)
- error->all("Shake fix must come before NPT/NPH fix");
+ error->all(FLERR,"Shake fix must come before NPT/NPH fix");
}
// if rRESPA, find associated fix that must exist
// could have changed locations in fix list since created
// set ptrs to rRESPA variables
if (strstr(update->integrate_style,"respa")) {
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"RESPA") == 0) ifix_respa = i;
nlevels_respa = ((Respa *) update->integrate)->nlevels;
loop_respa = ((Respa *) update->integrate)->loop;
step_respa = ((Respa *) update->integrate)->step;
}
// set equilibrium bond distances
if (force->bond == NULL)
- error->all("Bond potential must be defined for SHAKE");
+ error->all(FLERR,"Bond potential must be defined for SHAKE");
for (i = 1; i <= atom->nbondtypes; i++)
bond_distance[i] = force->bond->equilibrium_distance(i);
// set equilibrium angle distances
int nlocal = atom->nlocal;
for (i = 1; i <= atom->nangletypes; i++) {
if (angle_flag[i] == 0) continue;
if (force->angle == NULL)
- error->all("Angle potential must be defined for SHAKE");
+ error->all(FLERR,"Angle potential must be defined for SHAKE");
// scan all atoms for a SHAKE angle cluster
// extract bond types for the 2 bonds in the cluster
// bond types must be same in all clusters of this angle type,
// else set error flag
flag = 0;
bond1_type = bond2_type = 0;
for (m = 0; m < nlocal; m++) {
if (shake_flag[m] != 1) continue;
if (shake_type[m][2] != i) continue;
type1 = MIN(shake_type[m][0],shake_type[m][1]);
type2 = MAX(shake_type[m][0],shake_type[m][1]);
if (bond1_type > 0) {
if (type1 != bond1_type || type2 != bond2_type) {
flag = 1;
break;
}
}
bond1_type = type1;
bond2_type = type2;
}
// error check for any bond types that are not the same
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_MAX,world);
- if (flag_all) error->all("Shake angles have different bond types");
+ if (flag_all) error->all(FLERR,"Shake angles have different bond types");
// insure all procs have bond types
MPI_Allreduce(&bond1_type,&flag_all,1,MPI_INT,MPI_MAX,world);
bond1_type = flag_all;
MPI_Allreduce(&bond2_type,&flag_all,1,MPI_INT,MPI_MAX,world);
bond2_type = flag_all;
// if bond types are 0, no SHAKE angles of this type exist
// just skip this angle
if (bond1_type == 0) {
angle_distance[i] = 0.0;
continue;
}
// compute the angle distance as a function of 2 bond distances
angle = force->angle->equilibrium_angle(i);
rsq = 2.0*bond_distance[bond1_type]*bond_distance[bond2_type] *
(1.0-cos(angle));
angle_distance[i] = sqrt(rsq);
}
}
/* ----------------------------------------------------------------------
SHAKE as pre-integrator constraint
------------------------------------------------------------------------- */
void FixShake::setup(int vflag)
{
pre_neighbor();
if (output_every) stats();
// setup SHAKE output
bigint ntimestep = update->ntimestep;
next_output = ntimestep + output_every;
if (output_every == 0) next_output = update->laststep + 1;
if (output_every && ntimestep % output_every != 0)
next_output = (ntimestep/output_every)*output_every + output_every;
// half timestep constraint on pre-step, full timestep thereafter
if (strstr(update->integrate_style,"verlet")) {
dtv = update->dt;
dtfsq = 0.5 * update->dt * update->dt * force->ftm2v;
post_force(vflag);
dtfsq = update->dt * update->dt * force->ftm2v;
} else {
dtv = step_respa[0];
dtf_innerhalf = 0.5 * step_respa[0] * force->ftm2v;
dtf_inner = dtf_innerhalf;
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
dtf_inner = step_respa[0] * force->ftm2v;
}
}
/* ----------------------------------------------------------------------
build list of SHAKE clusters to constrain
if one or more atoms in cluster are on this proc,
this proc lists the cluster exactly once
------------------------------------------------------------------------- */
void FixShake::pre_neighbor()
{
int atom1,atom2,atom3,atom4;
// local copies of atom quantities
// used by SHAKE until next re-neighboring
x = atom->x;
v = atom->v;
f = atom->f;
mass = atom->mass;
rmass = atom->rmass;
type = atom->type;
nlocal = atom->nlocal;
// extend size of SHAKE list if necessary
if (nlocal > maxlist) {
maxlist = nlocal;
memory->destroy(list);
memory->create(list,maxlist,"shake:list");
}
// build list of SHAKE clusters I compute
nlist = 0;
for (int i = 0; i < nlocal; i++)
if (shake_flag[i]) {
if (shake_flag[i] == 2) {
atom1 = atom->map(shake_atom[i][0]);
atom2 = atom->map(shake_atom[i][1]);
if (atom1 == -1 || atom2 == -1) {
char str[128];
sprintf(str,
"Shake atoms %d %d missing on proc %d at step " BIGINT_FORMAT,
shake_atom[i][0],shake_atom[i][1],me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (i <= atom1 && i <= atom2) list[nlist++] = i;
} else if (shake_flag[i] % 2 == 1) {
atom1 = atom->map(shake_atom[i][0]);
atom2 = atom->map(shake_atom[i][1]);
atom3 = atom->map(shake_atom[i][2]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1) {
char str[128];
sprintf(str,
"Shake atoms %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
shake_atom[i][0],shake_atom[i][1],shake_atom[i][2],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (i <= atom1 && i <= atom2 && i <= atom3) list[nlist++] = i;
} else {
atom1 = atom->map(shake_atom[i][0]);
atom2 = atom->map(shake_atom[i][1]);
atom3 = atom->map(shake_atom[i][2]);
atom4 = atom->map(shake_atom[i][3]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) {
char str[128];
sprintf(str,
"Shake atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
shake_atom[i][0],shake_atom[i][1],
shake_atom[i][2],shake_atom[i][3],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (i <= atom1 && i <= atom2 && i <= atom3 && i <= atom4)
list[nlist++] = i;
}
}
}
/* ----------------------------------------------------------------------
compute the force adjustment for SHAKE constraint
------------------------------------------------------------------------- */
void FixShake::post_force(int vflag)
{
if (update->ntimestep == next_output) stats();
// xshake = unconstrained move with current v,f
// communicate results if necessary
unconstrained_update();
if (nprocs > 1) comm->forward_comm_fix(this);
// virial setup
if (vflag) v_setup(vflag);
else evflag = 0;
// loop over clusters to add constraint forces
int m;
for (int i = 0; i < nlist; i++) {
m = list[i];
if (shake_flag[m] == 2) shake2(m);
else if (shake_flag[m] == 3) shake3(m);
else if (shake_flag[m] == 4) shake4(m);
else shake3angle(m);
}
}
/* ----------------------------------------------------------------------
enforce SHAKE constraints from rRESPA
xshake prediction portion is different than Verlet
------------------------------------------------------------------------- */
void FixShake::post_force_respa(int vflag, int ilevel, int iloop)
{
// call stats only on outermost level
if (ilevel == nlevels_respa-1 && update->ntimestep == next_output) stats();
// enforce SHAKE constraints on every loop iteration of every rRESPA level
// except last loop iteration of inner levels
if (ilevel < nlevels_respa-1 && iloop == loop_respa[ilevel]-1) return;
// xshake = unconstrained move with current v,f as function of level
// communicate results if necessary
unconstrained_update_respa(ilevel);
if (nprocs > 1) comm->forward_comm_fix(this);
// virial setup, only need to compute on outermost level
if (ilevel == nlevels_respa-1 && vflag) v_setup(vflag);
else evflag = 0;
// loop over clusters to add constraint forces
int m;
for (int i = 0; i < nlist; i++) {
m = list[i];
if (shake_flag[m] == 2) shake2(m);
else if (shake_flag[m] == 3) shake3(m);
else if (shake_flag[m] == 4) shake4(m);
else shake3angle(m);
}
}
/* ----------------------------------------------------------------------
count # of degrees-of-freedom removed by SHAKE for atoms in igroup
------------------------------------------------------------------------- */
int FixShake::dof(int igroup)
{
int groupbit = group->bitmask[igroup];
int *mask = atom->mask;
int *tag = atom->tag;
int nlocal = atom->nlocal;
// count dof in a cluster if and only if
// the central atom is in group and atom i is the central atom
int n = 0;
for (int i = 0; i < nlocal; i++) {
if (!(mask[i] & groupbit)) continue;
if (shake_flag[i] == 0) continue;
if (shake_atom[i][0] != tag[i]) continue;
if (shake_flag[i] == 1) n += 3;
else if (shake_flag[i] == 2) n += 1;
else if (shake_flag[i] == 3) n += 2;
else if (shake_flag[i] == 4) n += 3;
}
int nall;
MPI_Allreduce(&n,&nall,1,MPI_INT,MPI_SUM,world);
return nall;
}
/* ----------------------------------------------------------------------
identify whether each atom is in a SHAKE cluster
only include atoms in fix group and those bonds/angles specified in input
test whether all clusters are valid
set shake_flag, shake_atom, shake_type values
set bond,angle types negative so will be ignored in neighbor lists
------------------------------------------------------------------------- */
void FixShake::find_clusters()
{
int i,j,m,n;
int flag,flag_all,messtag,loop,nbuf,nbufmax,size;
double massone;
int *buf,*bufcopy;
MPI_Request request;
MPI_Status status;
if (me == 0 && screen) fprintf(screen,"Finding SHAKE clusters ...\n");
// local copies of atom ptrs
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
double *mass = atom->mass;
double *rmass = atom->rmass;
int **bond_type = atom->bond_type;
int **angle_type = atom->angle_type;
int **nspecial = atom->nspecial;
int **special = atom->special;
int nlocal = atom->nlocal;
int angles_allow = atom->avec->angles_allow;
// setup ring of procs
int next = me + 1;
int prev = me -1;
if (next == nprocs) next = 0;
if (prev < 0) prev = nprocs - 1;
// -----------------------------------------------------
// allocate arrays for self (1d) and bond partners (2d)
// max = max # of bond partners for owned atoms = 2nd dim of partner arrays
// npartner[i] = # of bonds attached to atom i
// nshake[i] = # of SHAKE bonds attached to atom i
// partner_tag[i][] = global IDs of each partner
// partner_mask[i][] = mask of each partner
// partner_type[i][] = type of each partner
// partner_massflag[i][] = 1 if partner meets mass criterion, 0 if not
// partner_bondtype[i][] = type of bond attached to each partner
// partner_shake[i][] = 1 if SHAKE bonded to partner, 0 if not
// partner_nshake[i][] = nshake value for each partner
// -----------------------------------------------------
int max = 0;
for (i = 0; i < nlocal; i++) max = MAX(max,nspecial[i][0]);
int *npartner,*nshake;
memory->create(npartner,nlocal,"shake:npartner");
memory->create(nshake,nlocal,"shake:nshake");
int **partner_tag,**partner_mask,**partner_type,**partner_massflag;
int ** partner_bondtype,**partner_shake,**partner_nshake;
memory->create(partner_tag,nlocal,max,"shake:partner_tag");
memory->create(partner_mask,nlocal,max,"shake:partner_mask");
memory->create(partner_type,nlocal,max,"shake:partner_type");
memory->create(partner_massflag,nlocal,max,"shake:partner_massflag");
memory->create(partner_bondtype,nlocal,max,"shake:partner_bondtype");
memory->create(partner_shake,nlocal,max,"shake:partner_shake");
memory->create(partner_nshake,nlocal,max,"shake:partner_nshake");
// -----------------------------------------------------
// set npartner and partner_tag from special arrays
// -----------------------------------------------------
for (i = 0; i < nlocal; i++) {
npartner[i] = nspecial[i][0];
for (j = 0; j < npartner[i]; j++) partner_tag[i][j] = special[i][j];
}
// -----------------------------------------------------
// set partner_mask, partner_type, partner_massflag, partner_bondtype
// for bonded partners
// requires communication for off-proc partners
// -----------------------------------------------------
// fill in mask, type, massflag, bondtype if own bond partner
// info to store in buf for each off-proc bond = nper = 6
// 2 atoms IDs in bond, space for mask, type, massflag, bondtype
// nbufmax = largest buffer needed to hold info from any proc
int nper = 6;
nbuf = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
partner_mask[i][j] = 0;
partner_type[i][j] = 0;
partner_massflag[i][j] = 0;
partner_bondtype[i][j] = 0;
m = atom->map(partner_tag[i][j]);
if (m >= 0 && m < nlocal) {
partner_mask[i][j] = mask[m];
partner_type[i][j] = type[m];
if (nmass) {
if (rmass) massone = rmass[m];
else massone = mass[type[m]];
partner_massflag[i][j] = masscheck(massone);
}
n = bondfind(i,tag[i],partner_tag[i][j]);
if (n >= 0) partner_bondtype[i][j] = bond_type[i][n];
else {
n = bondfind(m,tag[i],partner_tag[i][j]);
if (n >= 0) partner_bondtype[i][j] = bond_type[m][n];
}
} else nbuf += nper;
}
}
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with info
size = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
m = atom->map(partner_tag[i][j]);
if (m < 0 || m >= nlocal) {
buf[size] = tag[i];
buf[size+1] = partner_tag[i][j];
buf[size+2] = 0;
buf[size+3] = 0;
buf[size+4] = 0;
n = bondfind(i,tag[i],partner_tag[i][j]);
if (n >= 0) buf[size+5] = bond_type[i][n];
else buf[size+5] = 0;
size += nper;
}
}
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan bond partner IDs for atoms I own
// if I own partner:
// fill in mask and type and massflag
// search for bond with 1st atom and fill in bondtype
messtag = 1;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
m = atom->map(buf[i+1]);
if (m >= 0 && m < nlocal) {
buf[i+2] = mask[m];
buf[i+3] = type[m];
if (nmass) {
if (rmass) massone = rmass[m];
else massone = mass[type[m]];
buf[i+4] = masscheck(massone);
}
if (buf[i+5] == 0) {
n = bondfind(m,buf[i],buf[i+1]);
if (n >= 0) buf[i+5] = bond_type[m][n];
}
}
i += nper;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// store partner info returned to me
m = 0;
while (m < size) {
i = atom->map(buf[m]);
for (j = 0; j < npartner[i]; j++)
if (buf[m+1] == partner_tag[i][j]) break;
partner_mask[i][j] = buf[m+2];
partner_type[i][j] = buf[m+3];
partner_massflag[i][j] = buf[m+4];
partner_bondtype[i][j] = buf[m+5];
m += nper;
}
delete [] buf;
delete [] bufcopy;
// error check for unfilled partner info
// if partner_type not set, is an error
// partner_bondtype may not be set if special list is not consistent
// with bondatom (e.g. due to delete_bonds command)
// this is OK if one or both atoms are not in fix group, since
// bond won't be SHAKEn anyway
// else it's an error
flag = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < npartner[i]; j++) {
if (partner_type[i][j] == 0) flag = 1;
if (!(mask[i] & groupbit)) continue;
if (!(partner_mask[i][j] & groupbit)) continue;
if (partner_bondtype[i][j] == 0) flag = 1;
}
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Did not find fix shake partner info");
+ if (flag_all) error->all(FLERR,"Did not find fix shake partner info");
// -----------------------------------------------------
// identify SHAKEable bonds
// set nshake[i] = # of SHAKE bonds attached to atom i
// set partner_shake[i][] = 1 if SHAKE bonded to partner, 0 if not
// both atoms must be in group, bondtype must be > 0
// check if bondtype is in input bond_flag
// check if type of either atom is in input type_flag
// check if mass of either atom is in input mass_list
// -----------------------------------------------------
int np;
for (i = 0; i < nlocal; i++) {
nshake[i] = 0;
np = npartner[i];
for (j = 0; j < np; j++) {
partner_shake[i][j] = 0;
if (!(mask[i] & groupbit)) continue;
if (!(partner_mask[i][j] & groupbit)) continue;
if (partner_bondtype[i][j] <= 0) continue;
if (bond_flag[partner_bondtype[i][j]]) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
}
if (type_flag[type[i]] || type_flag[partner_type[i][j]]) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
}
if (nmass) {
if (partner_massflag[i][j]) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
} else {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
if (masscheck(massone)) {
partner_shake[i][j] = 1;
nshake[i]++;
continue;
}
}
}
}
}
// -----------------------------------------------------
// set partner_nshake for bonded partners
// requires communication for off-proc partners
// -----------------------------------------------------
// fill in partner_nshake if own bond partner
// info to store in buf for each off-proc bond =
// 2 atoms IDs in bond, space for nshake value
// nbufmax = largest buffer needed to hold info from any proc
nbuf = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
m = atom->map(partner_tag[i][j]);
if (m >= 0 && m < nlocal) partner_nshake[i][j] = nshake[m];
else nbuf += 3;
}
}
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with info
size = 0;
for (i = 0; i < nlocal; i++) {
for (j = 0; j < npartner[i]; j++) {
m = atom->map(partner_tag[i][j]);
if (m < 0 || m >= nlocal) {
buf[size] = tag[i];
buf[size+1] = partner_tag[i][j];
size += 3;
}
}
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan bond partner IDs for atoms I own
// if I own partner, fill in nshake value
messtag = 2;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
m = atom->map(buf[i+1]);
if (m >= 0 && m < nlocal) buf[i+2] = nshake[m];
i += 3;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// store partner info returned to me
m = 0;
while (m < size) {
i = atom->map(buf[m]);
for (j = 0; j < npartner[i]; j++)
if (buf[m+1] == partner_tag[i][j]) break;
partner_nshake[i][j] = buf[m+2];
m += 3;
}
delete [] buf;
delete [] bufcopy;
// -----------------------------------------------------
// error checks
// no atom with nshake > 3
// no connected atoms which both have nshake > 1
// -----------------------------------------------------
flag = 0;
for (i = 0; i < nlocal; i++) if (nshake[i] > 3) flag = 1;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Shake cluster of more than 4 atoms");
+ if (flag_all) error->all(FLERR,"Shake cluster of more than 4 atoms");
flag = 0;
for (i = 0; i < nlocal; i++) {
if (nshake[i] <= 1) continue;
for (j = 0; j < npartner[i]; j++)
if (partner_shake[i][j] && partner_nshake[i][j] > 1) flag = 1;
}
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Shake clusters are connected");
+ if (flag_all) error->all(FLERR,"Shake clusters are connected");
// -----------------------------------------------------
// set SHAKE arrays that are stored with atoms & add angle constraints
// zero shake arrays for all owned atoms
// if I am central atom set shake_flag & shake_atom & shake_type
// for 2-atom clusters, I am central atom if my atom ID < partner ID
// for 3-atom clusters, test for angle constraint
// angle will be stored by this atom if it exists
// if angle type matches angle_flag, then it is angle-constrained
// shake_flag[] = 0 if atom not in SHAKE cluster
// 2,3,4 = size of bond-only cluster
// 1 = 3-atom angle cluster
// shake_atom[][] = global IDs of 2,3,4 atoms in cluster
// central atom is 1st
// for 2-atom cluster, lowest ID is 1st
// shake_type[][] = bondtype of each bond in cluster
// for 3-atom angle cluster, 3rd value is angletype
// -----------------------------------------------------
for (i = 0; i < nlocal; i++) {
shake_flag[i] = 0;
shake_atom[i][0] = 0;
shake_atom[i][1] = 0;
shake_atom[i][2] = 0;
shake_atom[i][3] = 0;
shake_type[i][0] = 0;
shake_type[i][1] = 0;
shake_type[i][2] = 0;
if (nshake[i] == 1) {
for (j = 0; j < npartner[i]; j++)
if (partner_shake[i][j]) break;
if (partner_nshake[i][j] == 1 && tag[i] < partner_tag[i][j]) {
shake_flag[i] = 2;
shake_atom[i][0] = tag[i];
shake_atom[i][1] = partner_tag[i][j];
shake_type[i][0] = partner_bondtype[i][j];
}
}
if (nshake[i] > 1) {
shake_flag[i] = 1;
shake_atom[i][0] = tag[i];
for (j = 0; j < npartner[i]; j++)
if (partner_shake[i][j]) {
m = shake_flag[i];
shake_atom[i][m] = partner_tag[i][j];
shake_type[i][m-1] = partner_bondtype[i][j];
shake_flag[i]++;
}
}
if (nshake[i] == 2 && angles_allow) {
n = anglefind(i,shake_atom[i][1],shake_atom[i][2]);
if (n < 0) continue;
if (angle_type[i][n] < 0) continue;
if (angle_flag[angle_type[i][n]]) {
shake_flag[i] = 1;
shake_type[i][2] = angle_type[i][n];
}
}
}
// -----------------------------------------------------
// set shake_flag,shake_atom,shake_type for non-central atoms
// requires communication for off-proc atoms
// -----------------------------------------------------
// fill in shake arrays for each bond partner I own
// info to store in buf for each off-proc bond =
// all values from shake_flag, shake_atom, shake_type
// nbufmax = largest buffer needed to hold info from any proc
nbuf = 0;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
for (j = 0; j < npartner[i]; j++) {
if (partner_shake[i][j] == 0) continue;
m = atom->map(partner_tag[i][j]);
if (m >= 0 && m < nlocal) {
shake_flag[m] = shake_flag[i];
shake_atom[m][0] = shake_atom[i][0];
shake_atom[m][1] = shake_atom[i][1];
shake_atom[m][2] = shake_atom[i][2];
shake_atom[m][3] = shake_atom[i][3];
shake_type[m][0] = shake_type[i][0];
shake_type[m][1] = shake_type[i][1];
shake_type[m][2] = shake_type[i][2];
} else nbuf += 9;
}
}
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with info
size = 0;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
for (j = 0; j < npartner[i]; j++) {
if (partner_shake[i][j] == 0) continue;
m = atom->map(partner_tag[i][j]);
if (m < 0 || m >= nlocal) {
buf[size] = partner_tag[i][j];
buf[size+1] = shake_flag[i];
buf[size+2] = shake_atom[i][0];
buf[size+3] = shake_atom[i][1];
buf[size+4] = shake_atom[i][2];
buf[size+5] = shake_atom[i][3];
buf[size+6] = shake_type[i][0];
buf[size+7] = shake_type[i][1];
buf[size+8] = shake_type[i][2];
size += 9;
}
}
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan for ID that I own
// if I own ID, fill in shake array values
messtag = 3;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
m = atom->map(buf[i]);
if (m >= 0 && m < nlocal) {
shake_flag[m] = buf[i+1];
shake_atom[m][0] = buf[i+2];
shake_atom[m][1] = buf[i+3];
shake_atom[m][2] = buf[i+4];
shake_atom[m][3] = buf[i+5];
shake_type[m][0] = buf[i+6];
shake_type[m][1] = buf[i+7];
shake_type[m][2] = buf[i+8];
}
i += 9;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
delete [] buf;
delete [] bufcopy;
// -----------------------------------------------------
// free local memory
// -----------------------------------------------------
memory->destroy(npartner);
memory->destroy(nshake);
memory->destroy(partner_tag);
memory->destroy(partner_mask);
memory->destroy(partner_type);
memory->destroy(partner_massflag);
memory->destroy(partner_bondtype);
memory->destroy(partner_shake);
memory->destroy(partner_nshake);
// -----------------------------------------------------
// set bond_type and angle_type negative for SHAKE clusters
// must set for all SHAKE bonds and angles stored by each atom
// -----------------------------------------------------
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
else if (shake_flag[i] == 1) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = anglefind(i,shake_atom[i][1],shake_atom[i][2]);
if (n >= 0) angle_type[i][n] = -angle_type[i][n];
} else if (shake_flag[i] == 2) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 3) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
} else if (shake_flag[i] == 4) {
n = bondfind(i,shake_atom[i][0],shake_atom[i][1]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][2]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
n = bondfind(i,shake_atom[i][0],shake_atom[i][3]);
if (n >= 0) bond_type[i][n] = -bond_type[i][n];
}
}
// -----------------------------------------------------
// print info on SHAKE clusters
// -----------------------------------------------------
int count1,count2,count3,count4;
count1 = count2 = count3 = count4 = 0;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 1) count1++;
else if (shake_flag[i] == 2) count2++;
else if (shake_flag[i] == 3) count3++;
else if (shake_flag[i] == 4) count4++;
}
int tmp;
tmp = count1;
MPI_Allreduce(&tmp,&count1,1,MPI_INT,MPI_SUM,world);
tmp = count2;
MPI_Allreduce(&tmp,&count2,1,MPI_INT,MPI_SUM,world);
tmp = count3;
MPI_Allreduce(&tmp,&count3,1,MPI_INT,MPI_SUM,world);
tmp = count4;
MPI_Allreduce(&tmp,&count4,1,MPI_INT,MPI_SUM,world);
if (me == 0) {
if (screen) {
fprintf(screen," %d = # of size 2 clusters\n",count2/2);
fprintf(screen," %d = # of size 3 clusters\n",count3/3);
fprintf(screen," %d = # of size 4 clusters\n",count4/4);
fprintf(screen," %d = # of frozen angles\n",count1/3);
}
if (logfile) {
fprintf(logfile," %d = # of size 2 clusters\n",count2/2);
fprintf(logfile," %d = # of size 3 clusters\n",count3/3);
fprintf(logfile," %d = # of size 4 clusters\n",count4/4);
fprintf(logfile," %d = # of frozen angles\n",count1/3);
}
}
}
/* ----------------------------------------------------------------------
check if massone is within MASSDELTA of any mass in mass_list
return 1 if yes, 0 if not
------------------------------------------------------------------------- */
int FixShake::masscheck(double massone)
{
for (int i = 0; i < nmass; i++)
if (fabs(mass_list[i]-massone) <= MASSDELTA) return 1;
return 0;
}
/* ----------------------------------------------------------------------
update the unconstrained position of each atom
only for SHAKE clusters, else set to 0.0
assumes NVE update, seems to be accurate enough for NVT,NPT,NPH as well
------------------------------------------------------------------------- */
void FixShake::unconstrained_update()
{
double dtfmsq;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
dtfmsq = dtfsq / rmass[i];
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
} else {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
dtfmsq = dtfsq / mass[type[i]];
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
update the unconstrained position of each atom in a rRESPA step
only for SHAKE clusters, else set to 0.0
assumes NVE update, seems to be accurate enough for NVT,NPT,NPH as well
------------------------------------------------------------------------- */
void FixShake::unconstrained_update_respa(int ilevel)
{
// xshake = atom coords after next x update in innermost loop
// depends on rRESPA level
// for levels > 0 this includes more than one velocity update
// xshake = predicted position from call to this routine at level N =
// x + dt0 (v + dtN/m fN + 1/2 dt(N-1)/m f(N-1) + ... + 1/2 dt0/m f0)
// also set dtfsq = dt0*dtN so that shake2,shake3,etc can use it
double ***f_level = ((FixRespa *) modify->fix[ifix_respa])->f_level;
dtfsq = dtf_inner * step_respa[ilevel];
double invmass,dtfmsq;
int jlevel;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
invmass = 1.0 / rmass[i];
dtfmsq = dtfsq * invmass;
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
for (jlevel = 0; jlevel < ilevel; jlevel++) {
dtfmsq = dtf_innerhalf * step_respa[jlevel] * invmass;
xshake[i][0] += dtfmsq*f_level[i][jlevel][0];
xshake[i][1] += dtfmsq*f_level[i][jlevel][1];
xshake[i][2] += dtfmsq*f_level[i][jlevel][2];
}
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
} else {
for (int i = 0; i < nlocal; i++) {
if (shake_flag[i]) {
invmass = 1.0 / mass[type[i]];
dtfmsq = dtfsq * invmass;
xshake[i][0] = x[i][0] + dtv*v[i][0] + dtfmsq*f[i][0];
xshake[i][1] = x[i][1] + dtv*v[i][1] + dtfmsq*f[i][1];
xshake[i][2] = x[i][2] + dtv*v[i][2] + dtfmsq*f[i][2];
for (jlevel = 0; jlevel < ilevel; jlevel++) {
dtfmsq = dtf_innerhalf * step_respa[jlevel] * invmass;
xshake[i][0] += dtfmsq*f_level[i][jlevel][0];
xshake[i][1] += dtfmsq*f_level[i][jlevel][1];
xshake[i][2] += dtfmsq*f_level[i][jlevel][2];
}
} else xshake[i][2] = xshake[i][1] = xshake[i][0] = 0.0;
}
}
}
/* ---------------------------------------------------------------------- */
void FixShake::shake2(int m)
{
int nlist,list[2];
double v[6];
double invmass0,invmass1;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
double bond1 = bond_distance[shake_type[m][0]];
// r01 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
// s01 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
// a,b,c = coeffs in quadratic equation for lamda
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
}
double a = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double b = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double c = s01sq - bond1*bond1;
// error check
double determ = b*b - 4.0*a*c;
if (determ < 0.0) {
- error->warning("Shake determinant < 0.0",0);
+ error->warning(FLERR,"Shake determinant < 0.0",0);
determ = 0.0;
}
// exact quadratic solution for lamda
double lamda,lamda1,lamda2;
lamda1 = (-b+sqrt(determ)) / (2.0*a);
lamda2 = (-b-sqrt(determ)) / (2.0*a);
if (fabs(lamda1) <= fabs(lamda2)) lamda = lamda1;
else lamda = lamda2;
// update forces if atom is owned by this processor
lamda /= dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda*r01[0];
f[i0][1] += lamda*r01[1];
f[i0][2] += lamda*r01[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda*r01[0];
f[i1][1] -= lamda*r01[1];
f[i1][2] -= lamda*r01[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
v[0] = lamda*r01[0]*r01[0];
v[1] = lamda*r01[1]*r01[1];
v[2] = lamda*r01[2]*r01[2];
v[3] = lamda*r01[0]*r01[1];
v[4] = lamda*r01[0]*r01[2];
v[5] = lamda*r01[1]*r01[2];
v_tally(nlist,list,2.0,v);
}
}
/* ---------------------------------------------------------------------- */
void FixShake::shake3(int m)
{
int nlist,list[3];
double v[6];
double invmass0,invmass1,invmass2;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
int i2 = atom->map(shake_atom[m][2]);
double bond1 = bond_distance[shake_type[m][0]];
double bond2 = bond_distance[shake_type[m][1]];
// r01,r02 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
double r02[3];
r02[0] = x[i0][0] - x[i2][0];
r02[1] = x[i0][1] - x[i2][1];
r02[2] = x[i0][2] - x[i2][2];
domain->minimum_image(r02);
// s01,s02 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
double s02[3];
s02[0] = xshake[i0][0] - xshake[i2][0];
s02[1] = xshake[i0][1] - xshake[i2][1];
s02[2] = xshake[i0][2] - xshake[i2][2];
domain->minimum_image(s02);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double r02sq = r02[0]*r02[0] + r02[1]*r02[1] + r02[2]*r02[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
double s02sq = s02[0]*s02[0] + s02[1]*s02[1] + s02[2]*s02[2];
// matrix coeffs and rhs for lamda equations
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
invmass2 = 1.0/rmass[i2];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
invmass2 = 1.0/mass[type[i2]];
}
double a11 = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double a12 = 2.0 * invmass0 *
(s01[0]*r02[0] + s01[1]*r02[1] + s01[2]*r02[2]);
double a21 = 2.0 * invmass0 *
(s02[0]*r01[0] + s02[1]*r01[1] + s02[2]*r01[2]);
double a22 = 2.0 * (invmass0+invmass2) *
(s02[0]*r02[0] + s02[1]*r02[1] + s02[2]*r02[2]);
// inverse of matrix
double determ = a11*a22 - a12*a21;
- if (determ == 0.0) error->one("Shake determinant = 0.0");
+ if (determ == 0.0) error->one(FLERR,"Shake determinant = 0.0");
double determinv = 1.0/determ;
double a11inv = a22*determinv;
double a12inv = -a12*determinv;
double a21inv = -a21*determinv;
double a22inv = a11*determinv;
// quadratic correction coeffs
double r0102 = (r01[0]*r02[0] + r01[1]*r02[1] + r01[2]*r02[2]);
double quad1_0101 = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double quad1_0202 = invmass0*invmass0 * r02sq;
double quad1_0102 = 2.0 * (invmass0+invmass1)*invmass0 * r0102;
double quad2_0202 = (invmass0+invmass2)*(invmass0+invmass2) * r02sq;
double quad2_0101 = invmass0*invmass0 * r01sq;
double quad2_0102 = 2.0 * (invmass0+invmass2)*invmass0 * r0102;
// iterate until converged
double lamda01 = 0.0;
double lamda02 = 0.0;
int niter = 0;
int done = 0;
double quad1,quad2,b1,b2,lamda01_new,lamda02_new;
while (!done && niter < max_iter) {
quad1 = quad1_0101 * lamda01*lamda01 + quad1_0202 * lamda02*lamda02 +
quad1_0102 * lamda01*lamda02;
quad2 = quad2_0101 * lamda01*lamda01 + quad2_0202 * lamda02*lamda02 +
quad2_0102 * lamda01*lamda02;
b1 = bond1*bond1 - s01sq - quad1;
b2 = bond2*bond2 - s02sq - quad2;
lamda01_new = a11inv*b1 + a12inv*b2;
lamda02_new = a21inv*b1 + a22inv*b2;
done = 1;
if (fabs(lamda01_new-lamda01) > tolerance) done = 0;
if (fabs(lamda02_new-lamda02) > tolerance) done = 0;
lamda01 = lamda01_new;
lamda02 = lamda02_new;
niter++;
}
// update forces if atom is owned by this processor
lamda01 = lamda01/dtfsq;
lamda02 = lamda02/dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda01*r01[0] + lamda02*r02[0];
f[i0][1] += lamda01*r01[1] + lamda02*r02[1];
f[i0][2] += lamda01*r01[2] + lamda02*r02[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda01*r01[0];
f[i1][1] -= lamda01*r01[1];
f[i1][2] -= lamda01*r01[2];
}
if (i2 < nlocal) {
f[i2][0] -= lamda02*r02[0];
f[i2][1] -= lamda02*r02[1];
f[i2][2] -= lamda02*r02[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
if (i2 < nlocal) list[nlist++] = i2;
v[0] = lamda01*r01[0]*r01[0] + lamda02*r02[0]*r02[0];
v[1] = lamda01*r01[1]*r01[1] + lamda02*r02[1]*r02[1];
v[2] = lamda01*r01[2]*r01[2] + lamda02*r02[2]*r02[2];
v[3] = lamda01*r01[0]*r01[1] + lamda02*r02[0]*r02[1];
v[4] = lamda01*r01[0]*r01[2] + lamda02*r02[0]*r02[2];
v[5] = lamda01*r01[1]*r01[2] + lamda02*r02[1]*r02[2];
v_tally(nlist,list,3.0,v);
}
}
/* ---------------------------------------------------------------------- */
void FixShake::shake4(int m)
{
int nlist,list[4];
double v[6];
double invmass0,invmass1,invmass2,invmass3;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
int i2 = atom->map(shake_atom[m][2]);
int i3 = atom->map(shake_atom[m][3]);
double bond1 = bond_distance[shake_type[m][0]];
double bond2 = bond_distance[shake_type[m][1]];
double bond3 = bond_distance[shake_type[m][2]];
// r01,r02,r03 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
double r02[3];
r02[0] = x[i0][0] - x[i2][0];
r02[1] = x[i0][1] - x[i2][1];
r02[2] = x[i0][2] - x[i2][2];
domain->minimum_image(r02);
double r03[3];
r03[0] = x[i0][0] - x[i3][0];
r03[1] = x[i0][1] - x[i3][1];
r03[2] = x[i0][2] - x[i3][2];
domain->minimum_image(r03);
// s01,s02,s03 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
double s02[3];
s02[0] = xshake[i0][0] - xshake[i2][0];
s02[1] = xshake[i0][1] - xshake[i2][1];
s02[2] = xshake[i0][2] - xshake[i2][2];
domain->minimum_image(s02);
double s03[3];
s03[0] = xshake[i0][0] - xshake[i3][0];
s03[1] = xshake[i0][1] - xshake[i3][1];
s03[2] = xshake[i0][2] - xshake[i3][2];
domain->minimum_image(s03);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double r02sq = r02[0]*r02[0] + r02[1]*r02[1] + r02[2]*r02[2];
double r03sq = r03[0]*r03[0] + r03[1]*r03[1] + r03[2]*r03[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
double s02sq = s02[0]*s02[0] + s02[1]*s02[1] + s02[2]*s02[2];
double s03sq = s03[0]*s03[0] + s03[1]*s03[1] + s03[2]*s03[2];
// matrix coeffs and rhs for lamda equations
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
invmass2 = 1.0/rmass[i2];
invmass3 = 1.0/rmass[i3];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
invmass2 = 1.0/mass[type[i2]];
invmass3 = 1.0/mass[type[i3]];
}
double a11 = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double a12 = 2.0 * invmass0 *
(s01[0]*r02[0] + s01[1]*r02[1] + s01[2]*r02[2]);
double a13 = 2.0 * invmass0 *
(s01[0]*r03[0] + s01[1]*r03[1] + s01[2]*r03[2]);
double a21 = 2.0 * invmass0 *
(s02[0]*r01[0] + s02[1]*r01[1] + s02[2]*r01[2]);
double a22 = 2.0 * (invmass0+invmass2) *
(s02[0]*r02[0] + s02[1]*r02[1] + s02[2]*r02[2]);
double a23 = 2.0 * invmass0 *
(s02[0]*r03[0] + s02[1]*r03[1] + s02[2]*r03[2]);
double a31 = 2.0 * invmass0 *
(s03[0]*r01[0] + s03[1]*r01[1] + s03[2]*r01[2]);
double a32 = 2.0 * invmass0 *
(s03[0]*r02[0] + s03[1]*r02[1] + s03[2]*r02[2]);
double a33 = 2.0 * (invmass0+invmass3) *
(s03[0]*r03[0] + s03[1]*r03[1] + s03[2]*r03[2]);
// inverse of matrix;
double determ = a11*a22*a33 + a12*a23*a31 + a13*a21*a32 -
a11*a23*a32 - a12*a21*a33 - a13*a22*a31;
- if (determ == 0.0) error->one("Shake determinant = 0.0");
+ if (determ == 0.0) error->one(FLERR,"Shake determinant = 0.0");
double determinv = 1.0/determ;
double a11inv = determinv * (a22*a33 - a23*a32);
double a12inv = -determinv * (a12*a33 - a13*a32);
double a13inv = determinv * (a12*a23 - a13*a22);
double a21inv = -determinv * (a21*a33 - a23*a31);
double a22inv = determinv * (a11*a33 - a13*a31);
double a23inv = -determinv * (a11*a23 - a13*a21);
double a31inv = determinv * (a21*a32 - a22*a31);
double a32inv = -determinv * (a11*a32 - a12*a31);
double a33inv = determinv * (a11*a22 - a12*a21);
// quadratic correction coeffs
double r0102 = (r01[0]*r02[0] + r01[1]*r02[1] + r01[2]*r02[2]);
double r0103 = (r01[0]*r03[0] + r01[1]*r03[1] + r01[2]*r03[2]);
double r0203 = (r02[0]*r03[0] + r02[1]*r03[1] + r02[2]*r03[2]);
double quad1_0101 = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double quad1_0202 = invmass0*invmass0 * r02sq;
double quad1_0303 = invmass0*invmass0 * r03sq;
double quad1_0102 = 2.0 * (invmass0+invmass1)*invmass0 * r0102;
double quad1_0103 = 2.0 * (invmass0+invmass1)*invmass0 * r0103;
double quad1_0203 = 2.0 * invmass0*invmass0 * r0203;
double quad2_0101 = invmass0*invmass0 * r01sq;
double quad2_0202 = (invmass0+invmass2)*(invmass0+invmass2) * r02sq;
double quad2_0303 = invmass0*invmass0 * r03sq;
double quad2_0102 = 2.0 * (invmass0+invmass2)*invmass0 * r0102;
double quad2_0103 = 2.0 * invmass0*invmass0 * r0103;
double quad2_0203 = 2.0 * (invmass0+invmass2)*invmass0 * r0203;
double quad3_0101 = invmass0*invmass0 * r01sq;
double quad3_0202 = invmass0*invmass0 * r02sq;
double quad3_0303 = (invmass0+invmass3)*(invmass0+invmass3) * r03sq;
double quad3_0102 = 2.0 * invmass0*invmass0 * r0102;
double quad3_0103 = 2.0 * (invmass0+invmass3)*invmass0 * r0103;
double quad3_0203 = 2.0 * (invmass0+invmass3)*invmass0 * r0203;
// iterate until converged
double lamda01 = 0.0;
double lamda02 = 0.0;
double lamda03 = 0.0;
int niter = 0;
int done = 0;
double quad1,quad2,quad3,b1,b2,b3,lamda01_new,lamda02_new,lamda03_new;
while (!done && niter < max_iter) {
quad1 = quad1_0101 * lamda01*lamda01 +
quad1_0202 * lamda02*lamda02 +
quad1_0303 * lamda03*lamda03 +
quad1_0102 * lamda01*lamda02 +
quad1_0103 * lamda01*lamda03 +
quad1_0203 * lamda02*lamda03;
quad2 = quad2_0101 * lamda01*lamda01 +
quad2_0202 * lamda02*lamda02 +
quad2_0303 * lamda03*lamda03 +
quad2_0102 * lamda01*lamda02 +
quad2_0103 * lamda01*lamda03 +
quad2_0203 * lamda02*lamda03;
quad3 = quad3_0101 * lamda01*lamda01 +
quad3_0202 * lamda02*lamda02 +
quad3_0303 * lamda03*lamda03 +
quad3_0102 * lamda01*lamda02 +
quad3_0103 * lamda01*lamda03 +
quad3_0203 * lamda02*lamda03;
b1 = bond1*bond1 - s01sq - quad1;
b2 = bond2*bond2 - s02sq - quad2;
b3 = bond3*bond3 - s03sq - quad3;
lamda01_new = a11inv*b1 + a12inv*b2 + a13inv*b3;
lamda02_new = a21inv*b1 + a22inv*b2 + a23inv*b3;
lamda03_new = a31inv*b1 + a32inv*b2 + a33inv*b3;
done = 1;
if (fabs(lamda01_new-lamda01) > tolerance) done = 0;
if (fabs(lamda02_new-lamda02) > tolerance) done = 0;
if (fabs(lamda03_new-lamda03) > tolerance) done = 0;
lamda01 = lamda01_new;
lamda02 = lamda02_new;
lamda03 = lamda03_new;
niter++;
}
// update forces if atom is owned by this processor
lamda01 = lamda01/dtfsq;
lamda02 = lamda02/dtfsq;
lamda03 = lamda03/dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda01*r01[0] + lamda02*r02[0] + lamda03*r03[0];
f[i0][1] += lamda01*r01[1] + lamda02*r02[1] + lamda03*r03[1];
f[i0][2] += lamda01*r01[2] + lamda02*r02[2] + lamda03*r03[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda01*r01[0];
f[i1][1] -= lamda01*r01[1];
f[i1][2] -= lamda01*r01[2];
}
if (i2 < nlocal) {
f[i2][0] -= lamda02*r02[0];
f[i2][1] -= lamda02*r02[1];
f[i2][2] -= lamda02*r02[2];
}
if (i3 < nlocal) {
f[i3][0] -= lamda03*r03[0];
f[i3][1] -= lamda03*r03[1];
f[i3][2] -= lamda03*r03[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
if (i2 < nlocal) list[nlist++] = i2;
if (i3 < nlocal) list[nlist++] = i3;
v[0] = lamda01*r01[0]*r01[0]+lamda02*r02[0]*r02[0]+lamda03*r03[0]*r03[0];
v[1] = lamda01*r01[1]*r01[1]+lamda02*r02[1]*r02[1]+lamda03*r03[1]*r03[1];
v[2] = lamda01*r01[2]*r01[2]+lamda02*r02[2]*r02[2]+lamda03*r03[2]*r03[2];
v[3] = lamda01*r01[0]*r01[1]+lamda02*r02[0]*r02[1]+lamda03*r03[0]*r03[1];
v[4] = lamda01*r01[0]*r01[2]+lamda02*r02[0]*r02[2]+lamda03*r03[0]*r03[2];
v[5] = lamda01*r01[1]*r01[2]+lamda02*r02[1]*r02[2]+lamda03*r03[1]*r03[2];
v_tally(nlist,list,4.0,v);
}
}
/* ---------------------------------------------------------------------- */
void FixShake::shake3angle(int m)
{
int nlist,list[3];
double v[6];
double invmass0,invmass1,invmass2;
// local atom IDs and constraint distances
int i0 = atom->map(shake_atom[m][0]);
int i1 = atom->map(shake_atom[m][1]);
int i2 = atom->map(shake_atom[m][2]);
double bond1 = bond_distance[shake_type[m][0]];
double bond2 = bond_distance[shake_type[m][1]];
double bond12 = angle_distance[shake_type[m][2]];
// r01,r02,r12 = distance vec between atoms, with PBC
double r01[3];
r01[0] = x[i0][0] - x[i1][0];
r01[1] = x[i0][1] - x[i1][1];
r01[2] = x[i0][2] - x[i1][2];
domain->minimum_image(r01);
double r02[3];
r02[0] = x[i0][0] - x[i2][0];
r02[1] = x[i0][1] - x[i2][1];
r02[2] = x[i0][2] - x[i2][2];
domain->minimum_image(r02);
double r12[3];
r12[0] = x[i1][0] - x[i2][0];
r12[1] = x[i1][1] - x[i2][1];
r12[2] = x[i1][2] - x[i2][2];
domain->minimum_image(r12);
// s01,s02,s12 = distance vec after unconstrained update, with PBC
double s01[3];
s01[0] = xshake[i0][0] - xshake[i1][0];
s01[1] = xshake[i0][1] - xshake[i1][1];
s01[2] = xshake[i0][2] - xshake[i1][2];
domain->minimum_image(s01);
double s02[3];
s02[0] = xshake[i0][0] - xshake[i2][0];
s02[1] = xshake[i0][1] - xshake[i2][1];
s02[2] = xshake[i0][2] - xshake[i2][2];
domain->minimum_image(s02);
double s12[3];
s12[0] = xshake[i1][0] - xshake[i2][0];
s12[1] = xshake[i1][1] - xshake[i2][1];
s12[2] = xshake[i1][2] - xshake[i2][2];
domain->minimum_image(s12);
// scalar distances between atoms
double r01sq = r01[0]*r01[0] + r01[1]*r01[1] + r01[2]*r01[2];
double r02sq = r02[0]*r02[0] + r02[1]*r02[1] + r02[2]*r02[2];
double r12sq = r12[0]*r12[0] + r12[1]*r12[1] + r12[2]*r12[2];
double s01sq = s01[0]*s01[0] + s01[1]*s01[1] + s01[2]*s01[2];
double s02sq = s02[0]*s02[0] + s02[1]*s02[1] + s02[2]*s02[2];
double s12sq = s12[0]*s12[0] + s12[1]*s12[1] + s12[2]*s12[2];
// matrix coeffs and rhs for lamda equations
if (rmass) {
invmass0 = 1.0/rmass[i0];
invmass1 = 1.0/rmass[i1];
invmass2 = 1.0/rmass[i2];
} else {
invmass0 = 1.0/mass[type[i0]];
invmass1 = 1.0/mass[type[i1]];
invmass2 = 1.0/mass[type[i2]];
}
double a11 = 2.0 * (invmass0+invmass1) *
(s01[0]*r01[0] + s01[1]*r01[1] + s01[2]*r01[2]);
double a12 = 2.0 * invmass0 *
(s01[0]*r02[0] + s01[1]*r02[1] + s01[2]*r02[2]);
double a13 = - 2.0 * invmass1 *
(s01[0]*r12[0] + s01[1]*r12[1] + s01[2]*r12[2]);
double a21 = 2.0 * invmass0 *
(s02[0]*r01[0] + s02[1]*r01[1] + s02[2]*r01[2]);
double a22 = 2.0 * (invmass0+invmass2) *
(s02[0]*r02[0] + s02[1]*r02[1] + s02[2]*r02[2]);
double a23 = 2.0 * invmass2 *
(s02[0]*r12[0] + s02[1]*r12[1] + s02[2]*r12[2]);
double a31 = - 2.0 * invmass1 *
(s12[0]*r01[0] + s12[1]*r01[1] + s12[2]*r01[2]);
double a32 = 2.0 * invmass2 *
(s12[0]*r02[0] + s12[1]*r02[1] + s12[2]*r02[2]);
double a33 = 2.0 * (invmass1+invmass2) *
(s12[0]*r12[0] + s12[1]*r12[1] + s12[2]*r12[2]);
// inverse of matrix
double determ = a11*a22*a33 + a12*a23*a31 + a13*a21*a32 -
a11*a23*a32 - a12*a21*a33 - a13*a22*a31;
- if (determ == 0.0) error->one("Shake determinant = 0.0");
+ if (determ == 0.0) error->one(FLERR,"Shake determinant = 0.0");
double determinv = 1.0/determ;
double a11inv = determinv * (a22*a33 - a23*a32);
double a12inv = -determinv * (a12*a33 - a13*a32);
double a13inv = determinv * (a12*a23 - a13*a22);
double a21inv = -determinv * (a21*a33 - a23*a31);
double a22inv = determinv * (a11*a33 - a13*a31);
double a23inv = -determinv * (a11*a23 - a13*a21);
double a31inv = determinv * (a21*a32 - a22*a31);
double a32inv = -determinv * (a11*a32 - a12*a31);
double a33inv = determinv * (a11*a22 - a12*a21);
// quadratic correction coeffs
double r0102 = (r01[0]*r02[0] + r01[1]*r02[1] + r01[2]*r02[2]);
double r0112 = (r01[0]*r12[0] + r01[1]*r12[1] + r01[2]*r12[2]);
double r0212 = (r02[0]*r12[0] + r02[1]*r12[1] + r02[2]*r12[2]);
double quad1_0101 = (invmass0+invmass1)*(invmass0+invmass1) * r01sq;
double quad1_0202 = invmass0*invmass0 * r02sq;
double quad1_1212 = invmass1*invmass1 * r12sq;
double quad1_0102 = 2.0 * (invmass0+invmass1)*invmass0 * r0102;
double quad1_0112 = - 2.0 * (invmass0+invmass1)*invmass1 * r0112;
double quad1_0212 = - 2.0 * invmass0*invmass1 * r0212;
double quad2_0101 = invmass0*invmass0 * r01sq;
double quad2_0202 = (invmass0+invmass2)*(invmass0+invmass2) * r02sq;
double quad2_1212 = invmass2*invmass2 * r12sq;
double quad2_0102 = 2.0 * (invmass0+invmass2)*invmass0 * r0102;
double quad2_0112 = 2.0 * invmass0*invmass2 * r0112;
double quad2_0212 = 2.0 * (invmass0+invmass2)*invmass2 * r0212;
double quad3_0101 = invmass1*invmass1 * r01sq;
double quad3_0202 = invmass2*invmass2 * r02sq;
double quad3_1212 = (invmass1+invmass2)*(invmass1+invmass2) * r12sq;
double quad3_0102 = - 2.0 * invmass1*invmass2 * r0102;
double quad3_0112 = - 2.0 * (invmass1+invmass2)*invmass1 * r0112;
double quad3_0212 = 2.0 * (invmass1+invmass2)*invmass2 * r0212;
// iterate until converged
double lamda01 = 0.0;
double lamda02 = 0.0;
double lamda12 = 0.0;
int niter = 0;
int done = 0;
double quad1,quad2,quad3,b1,b2,b3,lamda01_new,lamda02_new,lamda12_new;
while (!done && niter < max_iter) {
quad1 = quad1_0101 * lamda01*lamda01 +
quad1_0202 * lamda02*lamda02 +
quad1_1212 * lamda12*lamda12 +
quad1_0102 * lamda01*lamda02 +
quad1_0112 * lamda01*lamda12 +
quad1_0212 * lamda02*lamda12;
quad2 = quad2_0101 * lamda01*lamda01 +
quad2_0202 * lamda02*lamda02 +
quad2_1212 * lamda12*lamda12 +
quad2_0102 * lamda01*lamda02 +
quad2_0112 * lamda01*lamda12 +
quad2_0212 * lamda02*lamda12;
quad3 = quad3_0101 * lamda01*lamda01 +
quad3_0202 * lamda02*lamda02 +
quad3_1212 * lamda12*lamda12 +
quad3_0102 * lamda01*lamda02 +
quad3_0112 * lamda01*lamda12 +
quad3_0212 * lamda02*lamda12;
b1 = bond1*bond1 - s01sq - quad1;
b2 = bond2*bond2 - s02sq - quad2;
b3 = bond12*bond12 - s12sq - quad3;
lamda01_new = a11inv*b1 + a12inv*b2 + a13inv*b3;
lamda02_new = a21inv*b1 + a22inv*b2 + a23inv*b3;
lamda12_new = a31inv*b1 + a32inv*b2 + a33inv*b3;
done = 1;
if (fabs(lamda01_new-lamda01) > tolerance) done = 0;
if (fabs(lamda02_new-lamda02) > tolerance) done = 0;
if (fabs(lamda12_new-lamda12) > tolerance) done = 0;
lamda01 = lamda01_new;
lamda02 = lamda02_new;
lamda12 = lamda12_new;
niter++;
}
// update forces if atom is owned by this processor
lamda01 = lamda01/dtfsq;
lamda02 = lamda02/dtfsq;
lamda12 = lamda12/dtfsq;
if (i0 < nlocal) {
f[i0][0] += lamda01*r01[0] + lamda02*r02[0];
f[i0][1] += lamda01*r01[1] + lamda02*r02[1];
f[i0][2] += lamda01*r01[2] + lamda02*r02[2];
}
if (i1 < nlocal) {
f[i1][0] -= lamda01*r01[0] - lamda12*r12[0];
f[i1][1] -= lamda01*r01[1] - lamda12*r12[1];
f[i1][2] -= lamda01*r01[2] - lamda12*r12[2];
}
if (i2 < nlocal) {
f[i2][0] -= lamda02*r02[0] + lamda12*r12[0];
f[i2][1] -= lamda02*r02[1] + lamda12*r12[1];
f[i2][2] -= lamda02*r02[2] + lamda12*r12[2];
}
if (evflag) {
nlist = 0;
if (i0 < nlocal) list[nlist++] = i0;
if (i1 < nlocal) list[nlist++] = i1;
if (i2 < nlocal) list[nlist++] = i2;
v[0] = lamda01*r01[0]*r01[0]+lamda02*r02[0]*r02[0]+lamda12*r12[0]*r12[0];
v[1] = lamda01*r01[1]*r01[1]+lamda02*r02[1]*r02[1]+lamda12*r12[1]*r12[1];
v[2] = lamda01*r01[2]*r01[2]+lamda02*r02[2]*r02[2]+lamda12*r12[2]*r12[2];
v[3] = lamda01*r01[0]*r01[1]+lamda02*r02[0]*r02[1]+lamda12*r12[0]*r12[1];
v[4] = lamda01*r01[0]*r01[2]+lamda02*r02[0]*r02[2]+lamda12*r12[0]*r12[2];
v[5] = lamda01*r01[1]*r01[2]+lamda02*r02[1]*r02[2]+lamda12*r12[1]*r12[2];
v_tally(nlist,list,3.0,v);
}
}
/* ----------------------------------------------------------------------
print-out bond & angle statistics
------------------------------------------------------------------------- */
void FixShake::stats()
{
int i,j,m,n,iatom,jatom,katom;
double delx,dely,delz;
double r,r1,r2,r3,angle;
// zero out accumulators
int nb = atom->nbondtypes + 1;
int na = atom->nangletypes + 1;
for (i = 0; i < nb; i++) {
b_count[i] = 0;
b_ave[i] = b_max[i] = 0.0;
b_min[i] = BIG;
}
for (i = 0; i < na; i++) {
a_count[i] = 0;
a_ave[i] = a_max[i] = 0.0;
a_min[i] = BIG;
}
// log stats for each bond & angle
// OK to double count since are just averaging
double **x = atom->x;
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) {
if (shake_flag[i] == 0) continue;
// bond stats
n = shake_flag[i];
if (n == 1) n = 3;
iatom = atom->map(shake_atom[i][0]);
for (j = 1; j < n; j++) {
jatom = atom->map(shake_atom[i][j]);
delx = x[iatom][0] - x[jatom][0];
dely = x[iatom][1] - x[jatom][1];
delz = x[iatom][2] - x[jatom][2];
domain->minimum_image(delx,dely,delz);
r = sqrt(delx*delx + dely*dely + delz*delz);
m = shake_type[i][j-1];
b_count[m]++;
b_ave[m] += r;
b_max[m] = MAX(b_max[m],r);
b_min[m] = MIN(b_min[m],r);
}
// angle stats
if (shake_flag[i] == 1) {
iatom = atom->map(shake_atom[i][0]);
jatom = atom->map(shake_atom[i][1]);
katom = atom->map(shake_atom[i][2]);
delx = x[iatom][0] - x[jatom][0];
dely = x[iatom][1] - x[jatom][1];
delz = x[iatom][2] - x[jatom][2];
domain->minimum_image(delx,dely,delz);
r1 = sqrt(delx*delx + dely*dely + delz*delz);
delx = x[iatom][0] - x[katom][0];
dely = x[iatom][1] - x[katom][1];
delz = x[iatom][2] - x[katom][2];
domain->minimum_image(delx,dely,delz);
r2 = sqrt(delx*delx + dely*dely + delz*delz);
delx = x[jatom][0] - x[katom][0];
dely = x[jatom][1] - x[katom][1];
delz = x[jatom][2] - x[katom][2];
domain->minimum_image(delx,dely,delz);
r3 = sqrt(delx*delx + dely*dely + delz*delz);
angle = acos((r1*r1 + r2*r2 - r3*r3) / (2.0*r1*r2));
angle *= 180.0/PI;
m = shake_type[i][2];
a_count[m]++;
a_ave[m] += angle;
a_max[m] = MAX(a_max[m],angle);
a_min[m] = MIN(a_min[m],angle);
}
}
// sum across all procs
MPI_Allreduce(b_count,b_count_all,nb,MPI_INT,MPI_SUM,world);
MPI_Allreduce(b_ave,b_ave_all,nb,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(b_max,b_max_all,nb,MPI_DOUBLE,MPI_MAX,world);
MPI_Allreduce(b_min,b_min_all,nb,MPI_DOUBLE,MPI_MIN,world);
MPI_Allreduce(a_count,a_count_all,na,MPI_INT,MPI_SUM,world);
MPI_Allreduce(a_ave,a_ave_all,na,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(a_max,a_max_all,na,MPI_DOUBLE,MPI_MAX,world);
MPI_Allreduce(a_min,a_min_all,na,MPI_DOUBLE,MPI_MIN,world);
// print stats only for non-zero counts
if (me == 0) {
if (screen) {
fprintf(screen,
"SHAKE stats (type/ave/delta) on step " BIGINT_FORMAT "\n",
update->ntimestep);
for (i = 1; i < nb; i++)
if (b_count_all[i])
fprintf(screen," %d %g %g\n",i,
b_ave_all[i]/b_count_all[i],b_max_all[i]-b_min_all[i]);
for (i = 1; i < na; i++)
if (a_count_all[i])
fprintf(screen," %d %g %g\n",i,
a_ave_all[i]/a_count_all[i],a_max_all[i]-a_min_all[i]);
}
if (logfile) {
fprintf(logfile,
"SHAKE stats (type/ave/delta) on step " BIGINT_FORMAT "\n",
update->ntimestep);
for (i = 0; i < nb; i++)
if (b_count_all[i])
fprintf(logfile," %d %g %g\n",i,
b_ave_all[i]/b_count_all[i],b_max_all[i]-b_min_all[i]);
for (i = 0; i < na; i++)
if (a_count_all[i])
fprintf(logfile," %d %g %g\n",i,
a_ave_all[i]/a_count_all[i],a_max_all[i]-a_min_all[i]);
}
}
// next timestep for stats
next_output += output_every;
}
/* ----------------------------------------------------------------------
find a bond between global tags n1 and n2 stored with local atom i
return -1 if don't find it
return bond index if do find it
------------------------------------------------------------------------- */
int FixShake::bondfind(int i, int n1, int n2)
{
int *tag = atom->tag;
int **bond_atom = atom->bond_atom;
int nbonds = atom->num_bond[i];
int m;
for (m = 0; m < nbonds; m++) {
if (n1 == tag[i] && n2 == bond_atom[i][m]) break;
if (n1 == bond_atom[i][m] && n2 == tag[i]) break;
}
if (m < nbonds) return m;
return -1;
}
/* ----------------------------------------------------------------------
find an angle with global end atoms n1 and n2 stored with local atom i
return -1 if don't find it
return angle index if do find it
------------------------------------------------------------------------- */
int FixShake::anglefind(int i, int n1, int n2)
{
int **angle_atom1 = atom->angle_atom1;
int **angle_atom3 = atom->angle_atom3;
int nangles = atom->num_angle[i];
int m;
for (m = 0; m < nangles; m++) {
if (n1 == angle_atom1[i][m] && n2 == angle_atom3[i][m]) break;
if (n1 == angle_atom3[i][m] && n2 == angle_atom1[i][m]) break;
}
if (m < nangles) return m;
return -1;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixShake::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int);
bytes += nmax*4 * sizeof(int);
bytes += nmax*3 * sizeof(int);
bytes += nmax*3 * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixShake::grow_arrays(int nmax)
{
memory->grow(shake_flag,nmax,"shake:shake_flag");
memory->grow(shake_atom,nmax,4,"shake:shake_atom");
memory->grow(shake_type,nmax,3,"shake:shake_type");
memory->destroy(xshake);
memory->create(xshake,nmax,3,"shake:xshake");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixShake::copy_arrays(int i, int j)
{
int flag = shake_flag[j] = shake_flag[i];
if (flag == 1) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_atom[j][2] = shake_atom[i][2];
shake_type[j][0] = shake_type[i][0];
shake_type[j][1] = shake_type[i][1];
shake_type[j][2] = shake_type[i][2];
} else if (flag == 2) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_type[j][0] = shake_type[i][0];
} else if (flag == 3) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_atom[j][2] = shake_atom[i][2];
shake_type[j][0] = shake_type[i][0];
shake_type[j][1] = shake_type[i][1];
} else if (flag == 4) {
shake_atom[j][0] = shake_atom[i][0];
shake_atom[j][1] = shake_atom[i][1];
shake_atom[j][2] = shake_atom[i][2];
shake_atom[j][3] = shake_atom[i][3];
shake_type[j][0] = shake_type[i][0];
shake_type[j][1] = shake_type[i][1];
shake_type[j][2] = shake_type[i][2];
}
}
/* ----------------------------------------------------------------------
initialize one atom's array values, called when atom is created
------------------------------------------------------------------------- */
void FixShake::set_arrays(int i)
{
shake_flag[i] = 0;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixShake::pack_exchange(int i, double *buf)
{
int m = 0;
buf[m++] = shake_flag[i];
int flag = shake_flag[i];
if (flag == 1) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_atom[i][2];
buf[m++] = shake_type[i][0];
buf[m++] = shake_type[i][1];
buf[m++] = shake_type[i][2];
} else if (flag == 2) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_type[i][0];
} else if (flag == 3) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_atom[i][2];
buf[m++] = shake_type[i][0];
buf[m++] = shake_type[i][1];
} else if (flag == 4) {
buf[m++] = shake_atom[i][0];
buf[m++] = shake_atom[i][1];
buf[m++] = shake_atom[i][2];
buf[m++] = shake_atom[i][3];
buf[m++] = shake_type[i][0];
buf[m++] = shake_type[i][1];
buf[m++] = shake_type[i][2];
}
return m;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixShake::unpack_exchange(int nlocal, double *buf)
{
int m = 0;
int flag = shake_flag[nlocal] = static_cast<int> (buf[m++]);
if (flag == 1) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_atom[nlocal][2] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
shake_type[nlocal][1] = static_cast<int> (buf[m++]);
shake_type[nlocal][2] = static_cast<int> (buf[m++]);
} else if (flag == 2) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
} else if (flag == 3) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_atom[nlocal][2] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
shake_type[nlocal][1] = static_cast<int> (buf[m++]);
} else if (flag == 4) {
shake_atom[nlocal][0] = static_cast<int> (buf[m++]);
shake_atom[nlocal][1] = static_cast<int> (buf[m++]);
shake_atom[nlocal][2] = static_cast<int> (buf[m++]);
shake_atom[nlocal][3] = static_cast<int> (buf[m++]);
shake_type[nlocal][0] = static_cast<int> (buf[m++]);
shake_type[nlocal][1] = static_cast<int> (buf[m++]);
shake_type[nlocal][2] = static_cast<int> (buf[m++]);
}
return m;
}
/* ---------------------------------------------------------------------- */
int FixShake::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int i,j,m;
double dx,dy,dz;
m = 0;
if (pbc_flag == 0) {
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = xshake[j][0];
buf[m++] = xshake[j][1];
buf[m++] = xshake[j][2];
}
} else {
if (domain->triclinic == 0) {
dx = pbc[0]*domain->xprd;
dy = pbc[1]*domain->yprd;
dz = pbc[2]*domain->zprd;
} else {
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
dz = pbc[2]*domain->zprd;
}
for (i = 0; i < n; i++) {
j = list[i];
buf[m++] = xshake[j][0] + dx;
buf[m++] = xshake[j][1] + dy;
buf[m++] = xshake[j][2] + dz;
}
}
return 3;
}
/* ---------------------------------------------------------------------- */
void FixShake::unpack_comm(int n, int first, double *buf)
{
int i,m,last;
m = 0;
last = first + n;
for (i = first; i < last; i++) {
xshake[i][0] = buf[m++];
xshake[i][1] = buf[m++];
xshake[i][2] = buf[m++];
}
}
/* ---------------------------------------------------------------------- */
void FixShake::reset_dt()
{
if (strstr(update->integrate_style,"verlet")) {
dtv = update->dt;
dtfsq = update->dt * update->dt * force->ftm2v;
} else {
dtv = step_respa[0];
dtf_innerhalf = 0.5 * step_respa[0] * force->ftm2v;
dtf_inner = step_respa[0] * force->ftm2v;
}
}
diff --git a/src/fix_shear_history.cpp b/src/fix_shear_history.cpp
index 0740a2f25..4e284c7f6 100644
--- a/src/fix_shear_history.cpp
+++ b/src/fix_shear_history.cpp
@@ -1,311 +1,311 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdio.h"
#include "fix_shear_history.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "force.h"
#include "pair.h"
#include "update.h"
#include "modify.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAXTOUCH 15
/* ---------------------------------------------------------------------- */
FixShearHistory::FixShearHistory(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
// set time_depend so that history will be preserved correctly
// across multiple runs via laststep setting in granular pair styles
restart_peratom = 1;
create_attribute = 1;
time_depend = 1;
// perform initial allocation of atom-based arrays
// register with atom class
npartner = NULL;
partner = NULL;
shearpartner = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
atom->add_callback(1);
// initialize npartner to 0 so neighbor list creation is OK the 1st time
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) npartner[i] = 0;
}
/* ---------------------------------------------------------------------- */
FixShearHistory::~FixShearHistory()
{
// unregister this fix so atom class doesn't invoke it any more
atom->delete_callback(id,0);
atom->delete_callback(id,1);
// delete locally stored arrays
memory->destroy(npartner);
memory->destroy(partner);
memory->destroy(shearpartner);
}
/* ---------------------------------------------------------------------- */
int FixShearHistory::setmask()
{
int mask = 0;
mask |= PRE_EXCHANGE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixShearHistory::init()
{
if (atom->tag_enable == 0)
- error->all("Pair style granular with history requires atoms have IDs");
+ error->all(FLERR,"Pair style granular with history requires atoms have IDs");
}
/* ---------------------------------------------------------------------- */
void FixShearHistory::setup_pre_exchange()
{
pre_exchange();
}
/* ----------------------------------------------------------------------
copy shear partner info from neighbor lists to atom arrays
so can be exchanged with atoms
------------------------------------------------------------------------- */
void FixShearHistory::pre_exchange()
{
int i,j,ii,jj,m,inum,jnum;
int *ilist,*jlist,*numneigh,**firstneigh;
int *touch,**firsttouch;
double *shear,*allshear,**firstshear;
// zero npartners for all current atoms
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++) npartner[i] = 0;
// copy shear info from neighbor list atoms to atom arrays
int *tag = atom->tag;
NeighList *list = pair->list;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
firsttouch = list->listgranhistory->firstneigh;
firstshear = list->listgranhistory->firstdouble;
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
jlist = firstneigh[i];
allshear = firstshear[i];
jnum = numneigh[i];
touch = firsttouch[i];
for (jj = 0; jj < jnum; jj++) {
if (touch[jj]) {
shear = &allshear[3*jj];
j = jlist[jj];
j &= NEIGHMASK;
if (npartner[i] < MAXTOUCH) {
m = npartner[i];
partner[i][m] = tag[j];
shearpartner[i][m][0] = shear[0];
shearpartner[i][m][1] = shear[1];
shearpartner[i][m][2] = shear[2];
}
npartner[i]++;
if (j < nlocal) {
if (npartner[j] < MAXTOUCH) {
m = npartner[j];
partner[j][m] = tag[i];
shearpartner[j][m][0] = -shear[0];
shearpartner[j][m][1] = -shear[1];
shearpartner[j][m][2] = -shear[2];
}
npartner[j]++;
}
}
}
}
// test for too many touching neighbors
int flag = 0;
for (i = 0; i < nlocal; i++)
if (npartner[i] >= MAXTOUCH) flag = 1;
int flag_all;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
- if (flag_all) error->all("Too many touching neighbors - boost MAXTOUCH");
+ if (flag_all) error->all(FLERR,"Too many touching neighbors - boost MAXTOUCH");
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixShearHistory::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int);
bytes += nmax*MAXTOUCH * sizeof(int);
bytes += nmax*MAXTOUCH*3 * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate local atom-based arrays
------------------------------------------------------------------------- */
void FixShearHistory::grow_arrays(int nmax)
{
memory->grow(npartner,nmax,"shear_history:npartner");
memory->grow(partner,nmax,MAXTOUCH,"shear_history:partner");
memory->grow(shearpartner,nmax,MAXTOUCH,3,"shear_history:shearpartner");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixShearHistory::copy_arrays(int i, int j)
{
npartner[j] = npartner[i];
for (int m = 0; m < npartner[j]; m++) {
partner[j][m] = partner[i][m];
shearpartner[j][m][0] = shearpartner[i][m][0];
shearpartner[j][m][1] = shearpartner[i][m][1];
shearpartner[j][m][2] = shearpartner[i][m][2];
}
}
/* ----------------------------------------------------------------------
initialize one atom's array values, called when atom is created
------------------------------------------------------------------------- */
void FixShearHistory::set_arrays(int i)
{
npartner[i] = 0;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixShearHistory::pack_exchange(int i, double *buf)
{
int m = 0;
buf[m++] = npartner[i];
for (int n = 0; n < npartner[i]; n++) {
buf[m++] = partner[i][n];
buf[m++] = shearpartner[i][n][0];
buf[m++] = shearpartner[i][n][1];
buf[m++] = shearpartner[i][n][2];
}
return m;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixShearHistory::unpack_exchange(int nlocal, double *buf)
{
int m = 0;
npartner[nlocal] = static_cast<int> (buf[m++]);
for (int n = 0; n < npartner[nlocal]; n++) {
partner[nlocal][n] = static_cast<int> (buf[m++]);
shearpartner[nlocal][n][0] = buf[m++];
shearpartner[nlocal][n][1] = buf[m++];
shearpartner[nlocal][n][2] = buf[m++];
}
return m;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixShearHistory::pack_restart(int i, double *buf)
{
int m = 0;
buf[m++] = 4*npartner[i] + 2;
buf[m++] = npartner[i];
for (int n = 0; n < npartner[i]; n++) {
buf[m++] = partner[i][n];
buf[m++] = shearpartner[i][n][0];
buf[m++] = shearpartner[i][n][1];
buf[m++] = shearpartner[i][n][2];
}
return m;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixShearHistory::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
npartner[nlocal] = static_cast<int> (extra[nlocal][m++]);
for (int n = 0; n < npartner[nlocal]; n++) {
partner[nlocal][n] = static_cast<int> (extra[nlocal][m++]);
shearpartner[nlocal][n][0] = extra[nlocal][m++];
shearpartner[nlocal][n][1] = extra[nlocal][m++];
shearpartner[nlocal][n][2] = extra[nlocal][m++];
}
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixShearHistory::maxsize_restart()
{
return 4*MAXTOUCH + 2;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixShearHistory::size_restart(int nlocal)
{
return 4*npartner[nlocal] + 2;
}
diff --git a/src/fix_spring.cpp b/src/fix_spring.cpp
index d6666f2b4..f3ac3e378 100644
--- a/src/fix_spring.cpp
+++ b/src/fix_spring.cpp
@@ -1,345 +1,342 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_spring.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "domain.h"
#include "error.h"
#include "group.h"
using namespace LAMMPS_NS;
#define SMALL 1.0e-10
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
enum{TETHER,COUPLE};
/* ---------------------------------------------------------------------- */
FixSpring::FixSpring(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 9) error->all("Illegal fix spring command");
+ if (narg < 9) error->all(FLERR,"Illegal fix spring command");
scalar_flag = 1;
vector_flag = 1;
size_vector = 4;
global_freq = 1;
extscalar = 1;
extvector = 1;
group2 = NULL;
if (strcmp(arg[3],"tether") == 0) {
- if (narg != 9) error->all("Illegal fix spring command");
+ if (narg != 9) error->all(FLERR,"Illegal fix spring command");
styleflag = TETHER;
k_spring = atof(arg[4]);
xflag = yflag = zflag = 1;
if (strcmp(arg[5],"NULL") == 0) xflag = 0;
else xc = atof(arg[5]);
if (strcmp(arg[6],"NULL") == 0) yflag = 0;
else yc = atof(arg[6]);
if (strcmp(arg[7],"NULL") == 0) zflag = 0;
else zc = atof(arg[7]);
r0 = atof(arg[8]);
- if (r0 < 0) error->all("R0 < 0 for fix spring command");
+ if (r0 < 0) error->all(FLERR,"R0 < 0 for fix spring command");
} else if (strcmp(arg[3],"couple") == 0) {
- if (narg != 10) error->all("Illegal fix spring command");
+ if (narg != 10) error->all(FLERR,"Illegal fix spring command");
styleflag = COUPLE;
int n = strlen(arg[4]) + 1;
group2 = new char[n];
strcpy(group2,arg[4]);
igroup2 = group->find(arg[4]);
if (igroup2 == -1)
- error->all("Fix spring couple group ID does not exist");
+ error->all(FLERR,"Fix spring couple group ID does not exist");
if (igroup2 == igroup)
- error->all("Two groups cannot be the same in fix spring couple");
+ error->all(FLERR,"Two groups cannot be the same in fix spring couple");
group2bit = group->bitmask[igroup2];
k_spring = atof(arg[5]);
xflag = yflag = zflag = 1;
if (strcmp(arg[6],"NULL") == 0) xflag = 0;
else xc = atof(arg[6]);
if (strcmp(arg[7],"NULL") == 0) yflag = 0;
else yc = atof(arg[7]);
if (strcmp(arg[8],"NULL") == 0) zflag = 0;
else zc = atof(arg[8]);
r0 = atof(arg[9]);
- if (r0 < 0) error->all("R0 < 0 for fix spring command");
+ if (r0 < 0) error->all(FLERR,"R0 < 0 for fix spring command");
- } else error->all("Illegal fix spring command");
+ } else error->all(FLERR,"Illegal fix spring command");
ftotal[0] = ftotal[1] = ftotal[2] = ftotal[3] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixSpring::~FixSpring()
{
delete [] group2;
}
/* ---------------------------------------------------------------------- */
int FixSpring::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixSpring::init()
{
// recheck that group 2 has not been deleted
if (group2) {
igroup2 = group->find(group2);
if (igroup2 == -1)
- error->all("Fix spring couple group ID does not exist");
+ error->all(FLERR,"Fix spring couple group ID does not exist");
group2bit = group->bitmask[igroup2];
}
masstotal = group->mass(igroup);
if (styleflag == COUPLE) masstotal2 = group->mass(igroup2);
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixSpring::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixSpring::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixSpring::post_force(int vflag)
{
if (styleflag == TETHER) spring_tether();
else spring_couple();
}
/* ---------------------------------------------------------------------- */
void FixSpring::spring_tether()
{
double xcm[3];
group->xcm(igroup,masstotal,xcm);
// fx,fy,fz = components of k * (r-r0) / masstotal
double dx,dy,dz,fx,fy,fz,r,dr;
dx = xcm[0] - xc;
dy = xcm[1] - yc;
dz = xcm[2] - zc;
if (!xflag) dx = 0.0;
if (!yflag) dy = 0.0;
if (!zflag) dz = 0.0;
r = sqrt(dx*dx + dy*dy + dz*dz);
r = MAX(r,SMALL);
dr = r - r0;
fx = k_spring*dx*dr/r;
fy = k_spring*dy*dr/r;
fz = k_spring*dz*dr/r;
ftotal[0] = -fx;
ftotal[1] = -fy;
ftotal[2] = -fz;
ftotal[3] = sqrt(fx*fx + fy*fy + fz*fz);
if (dr < 0.0) ftotal[3] = -ftotal[3];
espring = 0.5*k_spring * dr*dr;
fx /= masstotal;
fy /= masstotal;
fz /= masstotal;
// apply restoring force to atoms in group
double **f = atom->f;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double massone;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = rmass[i];
f[i][0] -= fx*massone;
f[i][1] -= fy*massone;
f[i][2] -= fz*massone;
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = mass[type[i]];
f[i][0] -= fx*massone;
f[i][1] -= fy*massone;
f[i][2] -= fz*massone;
}
}
}
/* ---------------------------------------------------------------------- */
void FixSpring::spring_couple()
{
double xcm[3],xcm2[3];
group->xcm(igroup,masstotal,xcm);
group->xcm(igroup2,masstotal2,xcm2);
// fx,fy,fz = components of k * (r-r0) / masstotal
// fx2,fy2,fz2 = components of k * (r-r0) / masstotal2
double dx,dy,dz,fx,fy,fz,fx2,fy2,fz2,r,dr;
dx = xcm2[0] - xcm[0] - xc;
dy = xcm2[1] - xcm[1] - yc;
dz = xcm2[2] - xcm[2] - zc;
if (!xflag) dx = 0.0;
if (!yflag) dy = 0.0;
if (!zflag) dz = 0.0;
r = sqrt(dx*dx + dy*dy + dz*dz);
r = MAX(r,SMALL);
dr = r - r0;
fx = k_spring*dx*dr/r;
fy = k_spring*dy*dr/r;
fz = k_spring*dz*dr/r;
ftotal[0] = fx;
ftotal[1] = fy;
ftotal[2] = fz;
ftotal[3] = sqrt(fx*fx + fy*fy + fz*fz);
if (dr < 0.0) ftotal[3] = -ftotal[3];
espring = 0.5*k_spring * dr*dr;
fx2 = fx/masstotal2;
fy2 = fy/masstotal2;
fz2 = fz/masstotal2;
fx /= masstotal;
fy /= masstotal;
fz /= masstotal;
// apply restoring force to atoms in group
// f = -k*(r-r0)*mass/masstotal
double **f = atom->f;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double massone;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
massone = rmass[i];
f[i][0] += fx*massone;
f[i][1] += fy*massone;
f[i][2] += fz*massone;
}
if (mask[i] & group2bit) {
massone = rmass[i];
f[i][0] -= fx2*massone;
f[i][1] -= fy2*massone;
f[i][2] -= fz2*massone;
}
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
massone = mass[type[i]];
f[i][0] += fx*massone;
f[i][1] += fy*massone;
f[i][2] += fz*massone;
}
if (mask[i] & group2bit) {
massone = mass[type[i]];
f[i][0] -= fx2*massone;
f[i][1] -= fy2*massone;
f[i][2] -= fz2*massone;
}
}
}
}
/* ---------------------------------------------------------------------- */
void FixSpring::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixSpring::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
energy of stretched spring
------------------------------------------------------------------------- */
double FixSpring::compute_scalar()
{
return espring;
}
/* ----------------------------------------------------------------------
return components of total spring force on fix group
------------------------------------------------------------------------- */
double FixSpring::compute_vector(int n)
{
return ftotal[n];
}
diff --git a/src/fix_spring_rg.cpp b/src/fix_spring_rg.cpp
index e4d55eba2..4723c8fdb 100644
--- a/src/fix_spring_rg.cpp
+++ b/src/fix_spring_rg.cpp
@@ -1,138 +1,138 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Naveen Michaud-Agrawal (Johns Hopkins U)
Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_spring_rg.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "respa.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixSpringRG::FixSpringRG(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 5) error->all("Illegal fix spring/rg command");
+ if (narg != 5) error->all(FLERR,"Illegal fix spring/rg command");
k = atof(arg[3]);
rg0_flag = 0;
if (strcmp(arg[4],"NULL") == 0) rg0_flag = 1;
else rg0 = atof(arg[4]);
}
/* ---------------------------------------------------------------------- */
int FixSpringRG::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixSpringRG::init()
{
masstotal = group->mass(igroup);
// if rg0 was specified as NULL, compute current Rg
// only occurs on 1st run
if (rg0_flag) {
double xcm[3];
group->xcm(igroup,masstotal,xcm);
rg0 = group->gyration(igroup,masstotal,xcm);
rg0_flag = 0;
}
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixSpringRG::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixSpringRG::post_force(int vflag)
{
// compute current Rg and center-of-mass
double xcm[3];
group->xcm(igroup,masstotal,xcm);
double rg = group->gyration(igroup,masstotal,xcm);
// apply restoring force to atoms in group
// f = -k*(r-r0)*mass/masstotal
double dx,dy,dz,term1;
double **f = atom->f;
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
int nlocal = atom->nlocal;
double massfrac;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
term1 = 2.0 * k * (1.0 - rg0/rg);
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - xcm[0];
dy = (x[i][1] + ybox*yprd) - xcm[1];
dz = (x[i][2] + zbox*zprd) - xcm[2];
massfrac = mass[type[i]]/masstotal;
f[i][0] -= term1*dx*massfrac;
f[i][1] -= term1*dy*massfrac;
f[i][2] -= term1*dz*massfrac;
}
}
/* ---------------------------------------------------------------------- */
void FixSpringRG::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
diff --git a/src/fix_spring_self.cpp b/src/fix_spring_self.cpp
index 849d7c478..6fb3472fb 100644
--- a/src/fix_spring_self.cpp
+++ b/src/fix_spring_self.cpp
@@ -1,294 +1,294 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Naveen Michaud-Agrawal (Johns Hopkins University)
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_spring_self.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixSpringSelf::FixSpringSelf(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 4) error->all("Illegal fix spring/self command");
+ if (narg != 4) error->all(FLERR,"Illegal fix spring/self command");
restart_peratom = 1;
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
k = atof(arg[3]);
- if (k <= 0.0) error->all("Illegal fix spring/self command");
+ if (k <= 0.0) error->all(FLERR,"Illegal fix spring/self command");
// perform initial allocation of atom-based array
// register with Atom class
xoriginal = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
atom->add_callback(1);
// xoriginal = initial unwrapped positions of atoms
double **x = atom->x;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
xoriginal[i][0] = x[i][0] + xbox*xprd;
xoriginal[i][1] = x[i][1] + ybox*yprd;
xoriginal[i][2] = x[i][2] + zbox*zprd;
} else xoriginal[i][0] = xoriginal[i][1] = xoriginal[i][2] = 0.0;
}
espring = 0.0;
}
/* ---------------------------------------------------------------------- */
FixSpringSelf::~FixSpringSelf()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
atom->delete_callback(id,1);
// delete locally stored array
memory->destroy(xoriginal);
}
/* ---------------------------------------------------------------------- */
int FixSpringSelf::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixSpringSelf::init()
{
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixSpringSelf::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixSpringSelf::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixSpringSelf::post_force(int vflag)
{
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
double dx,dy,dz;
espring = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xoriginal[i][0];
dy = x[i][1] + ybox*yprd - xoriginal[i][1];
dz = x[i][2] + zbox*zprd - xoriginal[i][2];
f[i][0] -= k*dx;
f[i][1] -= k*dy;
f[i][2] -= k*dz;
espring += k * (dx*dx + dy*dy + dz*dz);
}
espring *= 0.5;
}
/* ---------------------------------------------------------------------- */
void FixSpringSelf::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixSpringSelf::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
energy of stretched springs
------------------------------------------------------------------------- */
double FixSpringSelf::compute_scalar()
{
double all;
MPI_Allreduce(&espring,&all,1,MPI_DOUBLE,MPI_SUM,world);
return all;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixSpringSelf::memory_usage()
{
double bytes = atom->nmax*3 * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate atom-based array
------------------------------------------------------------------------- */
void FixSpringSelf::grow_arrays(int nmax)
{
memory->grow(xoriginal,nmax,3,"fix_spring/self:xoriginal");
}
/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */
void FixSpringSelf::copy_arrays(int i, int j)
{
xoriginal[j][0] = xoriginal[i][0];
xoriginal[j][1] = xoriginal[i][1];
xoriginal[j][2] = xoriginal[i][2];
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixSpringSelf::pack_exchange(int i, double *buf)
{
buf[0] = xoriginal[i][0];
buf[1] = xoriginal[i][1];
buf[2] = xoriginal[i][2];
return 3;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixSpringSelf::unpack_exchange(int nlocal, double *buf)
{
xoriginal[nlocal][0] = buf[0];
xoriginal[nlocal][1] = buf[1];
xoriginal[nlocal][2] = buf[2];
return 3;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixSpringSelf::pack_restart(int i, double *buf)
{
buf[0] = 4;
buf[1] = xoriginal[i][0];
buf[2] = xoriginal[i][1];
buf[3] = xoriginal[i][2];
return 4;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixSpringSelf::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
xoriginal[nlocal][0] = extra[nlocal][m++];
xoriginal[nlocal][1] = extra[nlocal][m++];
xoriginal[nlocal][2] = extra[nlocal][m++];
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixSpringSelf::maxsize_restart()
{
return 4;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixSpringSelf::size_restart(int nlocal)
{
return 4;
}
diff --git a/src/fix_store_force.cpp b/src/fix_store_force.cpp
index 5d1e52b64..98c5f918f 100644
--- a/src/fix_store_force.cpp
+++ b/src/fix_store_force.cpp
@@ -1,139 +1,139 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "fix_store_force.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixStoreForce::FixStoreForce(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 3) error->all("Illegal fix store/coord command");
+ if (narg < 3) error->all(FLERR,"Illegal fix store/coord command");
peratom_flag = 1;
size_peratom_cols = 3;
peratom_freq = 1;
nmax = atom->nmax;
memory->create(foriginal,nmax,3,"store/force:foriginal");
array_atom = foriginal;
// zero the array since dump may access it on timestep 0
// zero the array since a variable may access it before first run
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
foriginal[i][0] = foriginal[i][1] = foriginal[i][2] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixStoreForce::~FixStoreForce()
{
memory->destroy(foriginal);
}
/* ---------------------------------------------------------------------- */
int FixStoreForce::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixStoreForce::init()
{
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixStoreForce::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixStoreForce::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixStoreForce::post_force(int vflag)
{
if (atom->nlocal > nmax) {
nmax = atom->nmax;
memory->destroy(foriginal);
memory->create(foriginal,nmax,3,"store/force:foriginal");
array_atom = foriginal;
}
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
foriginal[i][0] = f[i][0];
foriginal[i][1] = f[i][1];
foriginal[i][2] = f[i][2];
} else foriginal[i][0] = foriginal[i][1] = foriginal[i][2] = 0.0;
}
/* ---------------------------------------------------------------------- */
void FixStoreForce::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixStoreForce::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixStoreForce::memory_usage()
{
double bytes = atom->nmax*3 * sizeof(double);
return bytes;
}
diff --git a/src/fix_store_state.cpp b/src/fix_store_state.cpp
index 7f49140d5..8a90365e0 100644
--- a/src/fix_store_state.cpp
+++ b/src/fix_store_state.cpp
@@ -1,1258 +1,1258 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_store_state.h"
#include "atom.h"
#include "domain.h"
#include "update.h"
#include "group.h"
#include "modify.h"
#include "compute.h"
#include "fix.h"
#include "input.h"
#include "variable.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{KEYWORD,COMPUTE,FIX,VARIABLE};
#define INVOKED_PERATOM 8
/* ---------------------------------------------------------------------- */
FixStoreState::FixStoreState(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal fix store/state command");
+ if (narg < 5) error->all(FLERR,"Illegal fix store/state command");
restart_peratom = 1;
peratom_freq = 1;
nevery = atoi(arg[3]);
- if (nevery < 0) error->all("Illegal fix store/state command");
+ if (nevery < 0) error->all(FLERR,"Illegal fix store/state command");
// parse values until one isn't recognized
// customize a new keyword by adding to if statement
pack_choice = new FnPtrPack[narg-4];
which = new int[narg-4];
argindex = new int[narg-4];
ids = new char*[narg-4];
value2index = new int[narg-4];
nvalues = 0;
cfv_any = 0;
int iarg = 4;
while (iarg < narg) {
which[nvalues] = KEYWORD;
ids[nvalues] = NULL;
if (strcmp(arg[iarg],"id") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_id;
} else if (strcmp(arg[iarg],"mol") == 0) {
if (!atom->molecule_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_molecule;
} else if (strcmp(arg[iarg],"type") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_type;
} else if (strcmp(arg[iarg],"mass") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_mass;
} else if (strcmp(arg[iarg],"x") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_x;
} else if (strcmp(arg[iarg],"y") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_y;
} else if (strcmp(arg[iarg],"z") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_z;
} else if (strcmp(arg[iarg],"xs") == 0) {
if (domain->triclinic)
pack_choice[nvalues++] = &FixStoreState::pack_xs_triclinic;
else pack_choice[nvalues++] = &FixStoreState::pack_xs;
} else if (strcmp(arg[iarg],"ys") == 0) {
if (domain->triclinic)
pack_choice[nvalues++] = &FixStoreState::pack_ys_triclinic;
else pack_choice[nvalues++] = &FixStoreState::pack_ys;
} else if (strcmp(arg[iarg],"zs") == 0) {
if (domain->triclinic)
pack_choice[nvalues++] = &FixStoreState::pack_zs_triclinic;
else pack_choice[nvalues++] = &FixStoreState::pack_zs;
} else if (strcmp(arg[iarg],"xu") == 0) {
if (domain->triclinic)
pack_choice[nvalues++] = &FixStoreState::pack_xu_triclinic;
else pack_choice[nvalues++] = &FixStoreState::pack_xu;
} else if (strcmp(arg[iarg],"yu") == 0) {
if (domain->triclinic)
pack_choice[nvalues++] = &FixStoreState::pack_yu_triclinic;
else pack_choice[nvalues++] = &FixStoreState::pack_yu;
} else if (strcmp(arg[iarg],"zu") == 0) {
if (domain->triclinic)
pack_choice[nvalues++] = &FixStoreState::pack_zu_triclinic;
else pack_choice[nvalues++] = &FixStoreState::pack_zu;
} else if (strcmp(arg[iarg],"ix") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_ix;
} else if (strcmp(arg[iarg],"iy") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_iy;
} else if (strcmp(arg[iarg],"iz") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_iz;
} else if (strcmp(arg[iarg],"vx") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_vx;
} else if (strcmp(arg[iarg],"vy") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_vy;
} else if (strcmp(arg[iarg],"vz") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_vz;
} else if (strcmp(arg[iarg],"fx") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_fx;
} else if (strcmp(arg[iarg],"fy") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_fy;
} else if (strcmp(arg[iarg],"fz") == 0) {
pack_choice[nvalues++] = &FixStoreState::pack_fz;
} else if (strcmp(arg[iarg],"q") == 0) {
if (!atom->q_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_q;
} else if (strcmp(arg[iarg],"mux") == 0) {
if (!atom->mu_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_mux;
} else if (strcmp(arg[iarg],"muy") == 0) {
if (!atom->mu_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_muy;
} else if (strcmp(arg[iarg],"muz") == 0) {
if (!atom->mu_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_muz;
} else if (strcmp(arg[iarg],"radius") == 0) {
if (!atom->radius_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_radius;
} else if (strcmp(arg[iarg],"omegax") == 0) {
if (!atom->omega_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_omegax;
} else if (strcmp(arg[iarg],"omegay") == 0) {
if (!atom->omega_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_omegay;
} else if (strcmp(arg[iarg],"omegaz") == 0) {
if (!atom->omega_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_omegaz;
} else if (strcmp(arg[iarg],"angmomx") == 0) {
if (!atom->angmom_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_angmomx;
} else if (strcmp(arg[iarg],"angmomy") == 0) {
if (!atom->angmom_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_angmomy;
} else if (strcmp(arg[iarg],"angmomz") == 0) {
if (!atom->angmom_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_angmomz;
} else if (strcmp(arg[iarg],"tqx") == 0) {
if (!atom->torque_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_tqx;
} else if (strcmp(arg[iarg],"tqy") == 0) {
if (!atom->torque_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_tqy;
} else if (strcmp(arg[iarg],"tqz") == 0) {
if (!atom->torque_flag)
- error->all("Fix store/state for atom property that isn't allocated");
+ error->all(FLERR,"Fix store/state for atom property that isn't allocated");
pack_choice[nvalues++] = &FixStoreState::pack_tqz;
} else if (strncmp(arg[iarg],"c_",2) == 0 ||
strncmp(arg[iarg],"f_",2) == 0 ||
strncmp(arg[iarg],"v_",2) == 0) {
cfv_any = 1;
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
int n = strlen(arg[iarg]);
char *suffix = new char[n];
strcpy(suffix,&arg[iarg][2]);
char *ptr = strchr(suffix,'[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
- error->all("Illegal fix store/state command");
+ error->all(FLERR,"Illegal fix store/state command");
argindex[nvalues] = atoi(ptr+1);
*ptr = '\0';
} else argindex[nvalues] = 0;
n = strlen(suffix) + 1;
ids[nvalues] = new char[n];
strcpy(ids[nvalues],suffix);
nvalues++;
delete [] suffix;
} else break;
iarg++;
}
// optional args
comflag = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"com") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix store/state command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix store/state command");
if (strcmp(arg[iarg+1],"no") == 0) comflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) comflag = 1;
- else error->all("Illegal fix store/state command");
+ else error->all(FLERR,"Illegal fix store/state command");
iarg += 2;
- } else error->all("Illegal fix store/state command");
+ } else error->all(FLERR,"Illegal fix store/state command");
}
// error check
for (int i = 0; i < nvalues; i++) {
if (which[i] == COMPUTE) {
int icompute = modify->find_compute(ids[i]);
if (icompute < 0)
- error->all("Compute ID for fix store/state does not exist");
+ error->all(FLERR,"Compute ID for fix store/state does not exist");
if (modify->compute[icompute]->peratom_flag == 0)
- error->all("Fix store/state compute "
+ error->all(FLERR,"Fix store/state compute "
"does not calculate per-atom values");
if (argindex[i] == 0 &&
modify->compute[icompute]->size_peratom_cols != 0)
- error->all("Fix store/state compute does not "
+ error->all(FLERR,"Fix store/state compute does not "
"calculate a per-atom vector");
if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0)
- error->all("Fix store/state compute does not "
+ error->all(FLERR,"Fix store/state compute does not "
"calculate a per-atom array");
if (argindex[i] &&
argindex[i] > modify->compute[icompute]->size_peratom_cols)
- error->all("Fix store/state compute array is accessed out-of-range");
+ error->all(FLERR,"Fix store/state compute array is accessed out-of-range");
} else if (which[i] == FIX) {
int ifix = modify->find_fix(ids[i]);
if (ifix < 0)
- error->all("Fix ID for fix store/state does not exist");
+ error->all(FLERR,"Fix ID for fix store/state does not exist");
if (modify->fix[ifix]->peratom_flag == 0)
- error->all("Fix store/state fix does not calculate per-atom values");
+ error->all(FLERR,"Fix store/state fix does not calculate per-atom values");
if (argindex[i] == 0 && modify->fix[ifix]->size_peratom_cols != 0)
- error->all("Fix store/state fix does not calculate a per-atom vector");
+ error->all(FLERR,"Fix store/state fix does not calculate a per-atom vector");
if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0)
- error->all("Fix store/state fix does not calculate a per-atom array");
+ error->all(FLERR,"Fix store/state fix does not calculate a per-atom array");
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_peratom_cols)
- error->all("Fix store/state fix array is accessed out-of-range");
+ error->all(FLERR,"Fix store/state fix array is accessed out-of-range");
if (nevery % modify->fix[ifix]->peratom_freq)
- error->all("Fix for fix store/state not computed at compatible time");
+ error->all(FLERR,"Fix for fix store/state not computed at compatible time");
} else if (which[i] == VARIABLE) {
int ivariable = input->variable->find(ids[i]);
if (ivariable < 0)
- error->all("Variable name for fix store/state does not exist");
+ error->all(FLERR,"Variable name for fix store/state does not exist");
if (input->variable->atomstyle(ivariable) == 0)
- error->all("Fix store/state variable is not atom-style variable");
+ error->all(FLERR,"Fix store/state variable is not atom-style variable");
}
}
// this fix produces either a per-atom vector or array
peratom_flag = 1;
if (nvalues == 1) size_peratom_cols = 0;
else size_peratom_cols = nvalues;
// perform initial allocation of atom-based array
// register with Atom class
values = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
atom->add_callback(1);
// zero the array since dump may access it on timestep 0
// zero the array since a variable may access it before first run
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
for (int m = 0; m < nvalues; m++)
values[i][m] = 0.0;
// store current values for keywords but not for compute, fix, variable
kflag = 1;
cfv_flag = 0;
end_of_step();
firstflag = 1;
}
/* ---------------------------------------------------------------------- */
FixStoreState::~FixStoreState()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
atom->delete_callback(id,1);
delete [] which;
delete [] argindex;
for (int m = 0; m < nvalues; m++) delete [] ids[m];
delete [] ids;
delete [] value2index;
delete [] pack_choice;
memory->destroy(values);
}
/* ---------------------------------------------------------------------- */
int FixStoreState::setmask()
{
int mask = 0;
if (nevery) mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixStoreState::init()
{
// set indices and check validity of all computes,fixes,variables
for (int m = 0; m < nvalues; m++) {
if (which[m] == COMPUTE) {
int icompute = modify->find_compute(ids[m]);
if (icompute < 0)
- error->all("Compute ID for fix store/state does not exist");
+ error->all(FLERR,"Compute ID for fix store/state does not exist");
value2index[m] = icompute;
} else if (which[m] == FIX) {
int ifix = modify->find_fix(ids[m]);
if (ifix < 0)
- error->all("Fix ID for fix store/state does not exist");
+ error->all(FLERR,"Fix ID for fix store/state does not exist");
value2index[m] = ifix;
} else if (which[m] == VARIABLE) {
int ivariable = input->variable->find(ids[m]);
if (ivariable < 0)
- error->all("Variable name for fix store/state does not exist");
+ error->all(FLERR,"Variable name for fix store/state does not exist");
value2index[m] = ivariable;
}
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::setup(int vflag)
{
// if first invocation, store current values for compute, fix, variable
if (firstflag) {
kflag = 0;
cfv_flag = 1;
end_of_step();
firstflag = 0;
kflag = cfv_flag = 1;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::end_of_step()
{
int i,j,n;
// compute com if comflag set
if (comflag) {
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,cm);
}
// if any compute/fix/variable and nevery, wrap with clear/add
if (cfv_any && nevery) modify->clearstep_compute();
// fill vector or array with per-atom values
if (values) vbuf = &values[0][0];
else vbuf = NULL;
for (int m = 0; m < nvalues; m++) {
if (which[m] == KEYWORD && kflag) (this->*pack_choice[m])(m);
else if (cfv_flag) {
n = value2index[m];
j = argindex[m];
int *mask = atom->mask;
int nlocal = atom->nlocal;
// invoke compute if not previously invoked
if (which[m] == COMPUTE) {
Compute *compute = modify->compute[n];
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
if (j == 0) {
double *compute_vector = compute->vector_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) values[i][m] += compute_vector[i];
} else {
int jm1 = j - 1;
double **compute_array = compute->array_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) values[i][m] += compute_array[i][jm1];
}
// access fix fields, guaranteed to be ready
} else if (which[m] == FIX) {
if (j == 0) {
double *fix_vector = modify->fix[n]->vector_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) values[i][m] += fix_vector[i];
} else {
int jm1 = j - 1;
double **fix_array = modify->fix[n]->array_atom;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) values[i][m] += fix_array[i][jm1];
}
// evaluate atom-style variable
} else if (which[m] == VARIABLE)
input->variable->compute_atom(n,igroup,&values[0][m],nvalues,0);
}
}
// if any compute/fix/variable and nevery, wrap with clear/add
if (cfv_any && nevery) {
int nextstep = (update->ntimestep/nevery)*nevery + nevery;
modify->addstep_compute(nextstep);
}
}
/* ----------------------------------------------------------------------
memory usage of local atom-based array
------------------------------------------------------------------------- */
double FixStoreState::memory_usage()
{
double bytes = atom->nmax*nvalues * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate atom-based array
------------------------------------------------------------------------- */
void FixStoreState::grow_arrays(int nmax)
{
memory->grow(values,nmax,nvalues,"store/state:values");
if (nvalues == 1) {
if (nmax) vector_atom = &values[0][0];
else vector_atom = NULL;
} else array_atom = values;
}
/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */
void FixStoreState::copy_arrays(int i, int j)
{
for (int m = 0; m < nvalues; m++) values[j][m] = values[i][m];
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixStoreState::pack_exchange(int i, double *buf)
{
for (int m = 0; m < nvalues; m++) buf[m] = values[i][m];
return nvalues;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixStoreState::unpack_exchange(int nlocal, double *buf)
{
for (int m = 0; m < nvalues; m++) values[nlocal][m] = buf[m];
return nvalues;
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixStoreState::pack_restart(int i, double *buf)
{
buf[0] = nvalues+1;
for (int m = 0; m < nvalues; m++) buf[m+1] = values[i][m];
return nvalues+1;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixStoreState::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
for (int i = 0; i < nvalues; i++) values[nlocal][i] = extra[nlocal][m++];
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixStoreState::maxsize_restart()
{
return nvalues+1;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixStoreState::size_restart(int nlocal)
{
return nvalues+1;
}
/* ----------------------------------------------------------------------
one method for every keyword fix store/state can archive
the atom property is packed into buf starting at n with stride nvalues
customize a new keyword by adding a method
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_id(int n)
{
int *tag = atom->tag;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = tag[i];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_molecule(int n)
{
int *molecule = atom->molecule;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = molecule[i];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_type(int n)
{
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = type[i];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_mass(int n)
{
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = rmass[i];
else vbuf[n] = 0.0;
n += nvalues;
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = mass[type[i]];
else vbuf[n] = 0.0;
n += nvalues;
}
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_x(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = x[i][0];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_y(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = x[i][1];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_z(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = x[i][2];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_xs(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double boxxlo = domain->boxlo[0];
double invxprd = 1.0/domain->xprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = (x[i][0] - boxxlo) * invxprd;
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_ys(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double boxylo = domain->boxlo[1];
double invyprd = 1.0/domain->yprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = (x[i][1] - boxylo) * invyprd;
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_zs(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double boxzlo = domain->boxlo[2];
double invzprd = 1.0/domain->zprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = (x[i][2] - boxzlo) * invzprd;
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_xs_triclinic(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
vbuf[n] = h_inv[0]*(x[i][0]-boxlo[0]) +
h_inv[5]*(x[i][1]-boxlo[1]) + h_inv[4]*(x[i][2]-boxlo[2]);
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_ys_triclinic(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
vbuf[n] = h_inv[1]*(x[i][1]-boxlo[1]) + h_inv[3]*(x[i][2]-boxlo[2]);
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_zs_triclinic(int n)
{
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *boxlo = domain->boxlo;
double *h_inv = domain->h_inv;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit)
vbuf[n] = h_inv[2]*(x[i][2]-boxlo[2]);
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_xu(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
vbuf[n] = x[i][0] + ((image[i] & 1023) - 512) * xprd;
if (comflag) vbuf[n] -= cm[0];
} else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_yu(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double yprd = domain->yprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
vbuf[n] = x[i][1] + ((image[i] >> 10 & 1023) - 512) * yprd;
if (comflag) vbuf[n] -= cm[1];
} else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_zu(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double zprd = domain->zprd;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
vbuf[n] = x[i][2] + ((image[i] >> 20) - 512) * zprd;
if (comflag) vbuf[n] -= cm[2];
} else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_xu_triclinic(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
int xbox,ybox,zbox;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
vbuf[n] = x[i][0] + h[0]*xbox + h[5]*ybox + h[4]*zbox;
if (comflag) vbuf[n] -= cm[0];
} else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_yu_triclinic(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
int ybox,zbox;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
vbuf[n] = x[i][1] + h[1]*ybox + h[3]*zbox;
if (comflag) vbuf[n] -= cm[1];
} else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_zu_triclinic(int n)
{
double **x = atom->x;
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double *h = domain->h;
int zbox;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
zbox = (image[i] >> 20) - 512;
vbuf[n] = x[i][2] + h[2]*zbox;
if (comflag) vbuf[n] -= cm[2];
} else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_ix(int n)
{
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = (image[i] & 1023) - 512;
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_iy(int n)
{
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = (image[i] >> 10 & 1023) - 512;
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_iz(int n)
{
int *image = atom->image;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = (image[i] >> 20) - 512;
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_vx(int n)
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = v[i][0];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_vy(int n)
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = v[i][1];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_vz(int n)
{
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = v[i][2];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_fx(int n)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = f[i][0];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_fy(int n)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = f[i][1];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_fz(int n)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = f[i][2];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_q(int n)
{
double *q = atom->q;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = q[i];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_mux(int n)
{
double **mu = atom->mu;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = mu[i][0];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_muy(int n)
{
double **mu = atom->mu;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = mu[i][1];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_muz(int n)
{
double **mu = atom->mu;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = mu[i][2];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_radius(int n)
{
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = radius[i];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_omegax(int n)
{
double **omega = atom->omega;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = omega[i][0];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_omegay(int n)
{
double **omega = atom->omega;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = omega[i][1];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_omegaz(int n)
{
double **omega = atom->omega;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = omega[i][2];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_angmomx(int n)
{
double **angmom = atom->angmom;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = angmom[i][0];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_angmomy(int n)
{
double **angmom = atom->angmom;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = angmom[i][1];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_angmomz(int n)
{
double **angmom = atom->angmom;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = angmom[i][2];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_tqx(int n)
{
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = torque[i][0];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_tqy(int n)
{
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = torque[i][1];
else vbuf[n] = 0.0;
n += nvalues;
}
}
/* ---------------------------------------------------------------------- */
void FixStoreState::pack_tqz(int n)
{
double **torque = atom->torque;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) vbuf[n] = torque[i][2];
else vbuf[n] = 0.0;
n += nvalues;
}
}
diff --git a/src/fix_temp_berendsen.cpp b/src/fix_temp_berendsen.cpp
index a74de7d36..bed8d8bb6 100644
--- a/src/fix_temp_berendsen.cpp
+++ b/src/fix_temp_berendsen.cpp
@@ -1,191 +1,191 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_temp_berendsen.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "group.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NOBIAS,BIAS};
/* ---------------------------------------------------------------------- */
FixTempBerendsen::FixTempBerendsen(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 6) error->all("Illegal fix temp/berendsen command");
+ if (narg != 6) error->all(FLERR,"Illegal fix temp/berendsen command");
// Berendsen thermostat should be applied every step
nevery = 1;
scalar_flag = 1;
global_freq = nevery;
extscalar = 1;
t_start = atof(arg[3]);
t_stop = atof(arg[4]);
t_period = atof(arg[5]);
// error checks
- if (t_period <= 0.0) error->all("Fix temp/berendsen period must be > 0.0");
+ if (t_period <= 0.0) error->all(FLERR,"Fix temp/berendsen period must be > 0.0");
// create a new compute temp style
// id = fix-ID + temp, compute group = fix group
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[3];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
energy = 0;
}
/* ---------------------------------------------------------------------- */
FixTempBerendsen::~FixTempBerendsen()
{
// delete temperature if fix created it
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
}
/* ---------------------------------------------------------------------- */
int FixTempBerendsen::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
mask |= THERMO_ENERGY;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTempBerendsen::init()
{
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix temp/berendsen does not exist");
+ error->all(FLERR,"Temperature ID for fix temp/berendsen does not exist");
temperature = modify->compute[icompute];
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
}
/* ---------------------------------------------------------------------- */
void FixTempBerendsen::end_of_step()
{
double t_current = temperature->compute_scalar();
if (t_current == 0.0)
- error->all("Computed temperature for fix temp/berendsen cannot be 0.0");
+ error->all(FLERR,"Computed temperature for fix temp/berendsen cannot be 0.0");
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
// rescale velocities by lamda
// for BIAS:
// temperature is current, so do not need to re-compute
// OK to not test returned v = 0, since lamda is multiplied by v
double lamda = sqrt(1.0 + update->dt/t_period*(t_target/t_current - 1.0));
double efactor = 0.5 * force->boltz * temperature->dof;
energy += t_current * (1.0-lamda*lamda) * efactor;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] *= lamda;
v[i][1] *= lamda;
v[i][2] *= lamda;
}
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= lamda;
v[i][1] *= lamda;
v[i][2] *= lamda;
temperature->restore_bias(i,v[i]);
}
}
}
}
/* ---------------------------------------------------------------------- */
int FixTempBerendsen::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void FixTempBerendsen::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
double FixTempBerendsen::compute_scalar()
{
return energy;
}
diff --git a/src/fix_temp_rescale.cpp b/src/fix_temp_rescale.cpp
index 1b4c8f3f0..d0d67368b 100644
--- a/src/fix_temp_rescale.cpp
+++ b/src/fix_temp_rescale.cpp
@@ -1,195 +1,195 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "fix_temp_rescale.h"
#include "atom.h"
#include "force.h"
#include "group.h"
#include "update.h"
#include "domain.h"
#include "region.h"
#include "comm.h"
#include "modify.h"
#include "compute.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{NOBIAS,BIAS};
/* ---------------------------------------------------------------------- */
FixTempRescale::FixTempRescale(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 8) error->all("Illegal fix temp/rescale command");
+ if (narg < 8) error->all(FLERR,"Illegal fix temp/rescale command");
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix temp/rescale command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix temp/rescale command");
scalar_flag = 1;
global_freq = nevery;
extscalar = 1;
t_start = atof(arg[4]);
t_stop = atof(arg[5]);
t_window = atof(arg[6]);
fraction = atof(arg[7]);
// create a new compute temp
// id = fix-ID + temp, compute group = fix group
int n = strlen(id) + 6;
id_temp = new char[n];
strcpy(id_temp,id);
strcat(id_temp,"_temp");
char **newarg = new char*[6];
newarg[0] = id_temp;
newarg[1] = group->names[igroup];
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg);
delete [] newarg;
tflag = 1;
energy = 0.0;
}
/* ---------------------------------------------------------------------- */
FixTempRescale::~FixTempRescale()
{
// delete temperature if fix created it
if (tflag) modify->delete_compute(id_temp);
delete [] id_temp;
}
/* ---------------------------------------------------------------------- */
int FixTempRescale::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
mask |= THERMO_ENERGY;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTempRescale::init()
{
int icompute = modify->find_compute(id_temp);
if (icompute < 0)
- error->all("Temperature ID for fix temp/rescale does not exist");
+ error->all(FLERR,"Temperature ID for fix temp/rescale does not exist");
temperature = modify->compute[icompute];
if (temperature->tempbias) which = BIAS;
else which = NOBIAS;
}
/* ---------------------------------------------------------------------- */
void FixTempRescale::end_of_step()
{
double t_current = temperature->compute_scalar();
if (t_current == 0.0)
- error->all("Computed temperature for fix temp/rescale cannot be 0.0");
+ error->all(FLERR,"Computed temperature for fix temp/rescale cannot be 0.0");
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double t_target = t_start + delta * (t_stop-t_start);
// rescale velocity of appropriate atoms if outside window
// for BIAS:
// temperature is current, so do not need to re-compute
// OK to not test returned v = 0, since factor is multiplied by v
if (fabs(t_current-t_target) > t_window) {
t_target = t_current - fraction*(t_current-t_target);
double factor = sqrt(t_target/t_current);
double efactor = 0.5 * force->boltz * temperature->dof;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
energy += (t_current-t_target) * efactor;
if (which == NOBIAS) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] *= factor;
v[i][1] *= factor;
v[i][2] *= factor;
}
}
} else {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
temperature->remove_bias(i,v[i]);
v[i][0] *= factor;
v[i][1] *= factor;
v[i][2] *= factor;
temperature->restore_bias(i,v[i]);
}
}
}
}
}
/* ---------------------------------------------------------------------- */
int FixTempRescale::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"temp") == 0) {
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
if (tflag) {
modify->delete_compute(id_temp);
tflag = 0;
}
delete [] id_temp;
int n = strlen(arg[1]) + 1;
id_temp = new char[n];
strcpy(id_temp,arg[1]);
int icompute = modify->find_compute(id_temp);
- if (icompute < 0) error->all("Could not find fix_modify temperature ID");
+ if (icompute < 0) error->all(FLERR,"Could not find fix_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Fix_modify temperature ID does not compute temperature");
+ error->all(FLERR,"Fix_modify temperature ID does not compute temperature");
if (temperature->igroup != igroup && comm->me == 0)
- error->warning("Group for fix_modify temp != fix group");
+ error->warning(FLERR,"Group for fix_modify temp != fix group");
return 2;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void FixTempRescale::reset_target(double t_new)
{
t_start = t_stop = t_new;
}
/* ---------------------------------------------------------------------- */
double FixTempRescale::compute_scalar()
{
return energy;
}
diff --git a/src/fix_thermal_conductivity.cpp b/src/fix_thermal_conductivity.cpp
index b53c3626a..b339bbd82 100644
--- a/src/fix_thermal_conductivity.cpp
+++ b/src/fix_thermal_conductivity.cpp
@@ -1,329 +1,326 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Craig Tenney (UND) added support
for swapping atoms of different masses
------------------------------------------------------------------------- */
#include "math.h"
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "fix_thermal_conductivity.h"
#include "atom.h"
#include "force.h"
#include "domain.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e10
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixThermalConductivity::FixThermalConductivity(LAMMPS *lmp,
int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix thermal/conductivity command");
+ if (narg < 6) error->all(FLERR,"Illegal fix thermal/conductivity command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix thermal/conductivity command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix thermal/conductivity command");
scalar_flag = 1;
global_freq = nevery;
extscalar = 0;
if (strcmp(arg[4],"x") == 0) edim = 0;
else if (strcmp(arg[4],"y") == 0) edim = 1;
else if (strcmp(arg[4],"z") == 0) edim = 2;
- else error->all("Illegal fix thermal/conductivity command");
+ else error->all(FLERR,"Illegal fix thermal/conductivity command");
nbin = atoi(arg[5]);
if (nbin % 2 || nbin <= 2)
- error->all("Illegal fix thermal/conductivity command");
+ error->all(FLERR,"Illegal fix thermal/conductivity command");
// optional keywords
nswap = 1;
int iarg = 6;
while (iarg < narg) {
if (strcmp(arg[iarg],"swap") == 0) {
if (iarg+2 > narg)
- error->all("Illegal fix thermal/conductivity command");
+ error->all(FLERR,"Illegal fix thermal/conductivity command");
nswap = atoi(arg[iarg+1]);
if (nswap <= 0)
- error->all("Fix thermal/conductivity swap value must be positive");
+ error->all(FLERR,"Fix thermal/conductivity swap value must be positive");
iarg += 2;
- } else error->all("Illegal fix thermal/conductivity command");
+ } else error->all(FLERR,"Illegal fix thermal/conductivity command");
}
// initialize array sizes to nswap+1 so have space to shift values down
index_lo = new int[nswap+1];
index_hi = new int[nswap+1];
ke_lo = new double[nswap+1];
ke_hi = new double[nswap+1];
e_exchange = 0.0;
}
/* ---------------------------------------------------------------------- */
FixThermalConductivity::~FixThermalConductivity()
{
delete [] index_lo;
delete [] index_hi;
delete [] ke_lo;
delete [] ke_hi;
}
/* ---------------------------------------------------------------------- */
int FixThermalConductivity::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixThermalConductivity::init()
{
// warn if any fix ave/spatial comes after this fix
// can cause glitch in averaging since ave will happen after swap
int foundme = 0;
for (int i = 0; i < modify->nfix; i++) {
if (modify->fix[i] == this) foundme = 1;
if (foundme && strcmp(modify->fix[i]->style,"ave/spatial") == 0 && me == 0)
- error->warning("Fix thermal/conductivity comes before fix ave/spatial");
+ error->warning(FLERR,"Fix thermal/conductivity comes before fix ave/spatial");
}
// set bounds of 2 slabs in edim
// only necessary for static box, else re-computed in end_of_step()
// lo bin is always bottom bin
// hi bin is just above half height
if (domain->box_change == 0) {
prd = domain->prd[edim];
boxlo = domain->boxlo[edim];
boxhi = domain->boxhi[edim];
double binsize = (boxhi-boxlo) / nbin;
slablo_lo = boxlo;
slablo_hi = boxlo + binsize;
slabhi_lo = boxlo + (nbin/2)*binsize;
slabhi_hi = boxlo + (nbin/2+1)*binsize;
}
periodicity = domain->periodicity[edim];
}
/* ---------------------------------------------------------------------- */
void FixThermalConductivity::end_of_step()
{
int i,j,m,insert;
double coord,ke;
MPI_Status status;
struct {
double value;
int proc;
} mine[2],all[2];
// if box changes, recompute bounds of 2 slabs in edim
if (domain->box_change) {
prd = domain->prd[edim];
boxlo = domain->boxlo[edim];
boxhi = domain->boxhi[edim];
double binsize = (boxhi-boxlo) / nbin;
slablo_lo = boxlo;
slablo_hi = boxlo + binsize;
slabhi_lo = boxlo + (nbin/2)*binsize;
slabhi_hi = boxlo + (nbin/2+1)*binsize;
}
// make 2 lists of up to nswap atoms
// hottest atoms in lo slab, coldest atoms in hi slab (really mid slab)
// lo slab list is sorted by hottest, hi slab is sorted by coldest
// map atoms back into periodic box if necessary
// insert = location in list to insert new atom
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
nhi = nlo = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
coord = x[i][edim];
if (coord < boxlo && periodicity) coord += prd;
else if (coord >= boxhi && periodicity) coord -= prd;
if (coord >= slablo_lo && coord < slablo_hi) {
ke = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (rmass) ke *= 0.5*rmass[i];
else ke *= 0.5*mass[type[i]];
if (nlo < nswap || ke > ke_lo[nswap-1]) {
for (insert = nlo-1; insert >= 0; insert--)
if (ke < ke_lo[insert]) break;
insert++;
for (m = nlo-1; m >= insert; m--) {
ke_lo[m+1] = ke_lo[m];
index_lo[m+1] = index_lo[m];
}
ke_lo[insert] = ke;
index_lo[insert] = i;
if (nlo < nswap) nlo++;
}
}
if (coord >= slabhi_lo && coord < slabhi_hi) {
ke = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (rmass) ke *= 0.5*rmass[i];
else ke *= 0.5*mass[type[i]];
if (nhi < nswap || ke < ke_hi[nswap-1]) {
for (insert = nhi-1; insert >= 0; insert--)
if (ke > ke_hi[insert]) break;
insert++;
for (m = nhi-1; m >= insert; m--) {
ke_hi[m+1] = ke_hi[m];
index_hi[m+1] = index_hi[m];
}
ke_hi[insert] = ke;
index_hi[insert] = i;
if (nhi < nswap) nhi++;
}
}
}
// loop over nswap pairs
// pair 2 global atoms at beginning of sorted lo/hi slab lists via Allreduce
// BIG values are for procs with no atom to contribute
// use negative of hottest KE since is doing a MINLOC
// MINLOC also communicates which procs own them
// exchange kinetic energy between the 2 particles
// if I own both particles just swap, else point2point comm of velocities
double sbuf[4],rbuf[4],vcm[3];
double eswap = 0.0;
mine[0].proc = mine[1].proc = me;
int ilo = 0;
int ihi = 0;
for (m = 0; m < nswap; m++) {
if (ilo < nlo) mine[0].value = -ke_lo[ilo];
else mine[0].value = BIG;
if (ihi < nhi) mine[1].value = ke_hi[ihi];
else mine[1].value = BIG;
MPI_Allreduce(mine,all,2,MPI_DOUBLE_INT,MPI_MINLOC,world);
if (all[0].value == BIG || all[1].value == BIG) continue;
if (me == all[0].proc && me == all[1].proc) {
i = index_lo[ilo++];
j = index_hi[ihi++];
sbuf[0] = v[j][0];
sbuf[1] = v[j][1];
sbuf[2] = v[j][2];
if (rmass) sbuf[3] = rmass[j];
else sbuf[3] = mass[type[j]];
rbuf[0] = v[i][0];
rbuf[1] = v[i][1];
rbuf[2] = v[i][2];
if (rmass) rbuf[3] = rmass[i];
else rbuf[3] = mass[type[i]];
vcm[0] = (sbuf[3]*sbuf[0] + rbuf[3]*rbuf[0]) / (sbuf[3] + rbuf[3]);
vcm[1] = (sbuf[3]*sbuf[1] + rbuf[3]*rbuf[1]) / (sbuf[3] + rbuf[3]);
vcm[2] = (sbuf[3]*sbuf[2] + rbuf[3]*rbuf[2]) / (sbuf[3] + rbuf[3]);
v[j][0] = 2.0 * vcm[0] - sbuf[0];
v[j][1] = 2.0 * vcm[1] - sbuf[1];
v[j][2] = 2.0 * vcm[2] - sbuf[2];
eswap += sbuf[3] * (vcm[0] * (vcm[0] - sbuf[0]) +
vcm[1] * (vcm[1] - sbuf[1]) +
vcm[2] * (vcm[2] - sbuf[2]));
v[i][0] = 2.0 * vcm[0] - rbuf[0];
v[i][1] = 2.0 * vcm[1] - rbuf[1];
v[i][2] = 2.0 * vcm[2] - rbuf[2];
eswap -= rbuf[3] * (vcm[0] * (vcm[0] - rbuf[0]) +
vcm[1] * (vcm[1] - rbuf[1]) +
vcm[2] * (vcm[2] - rbuf[2]));
} else if (me == all[0].proc) {
j = index_lo[ilo++];
sbuf[0] = v[j][0];
sbuf[1] = v[j][1];
sbuf[2] = v[j][2];
if (rmass) sbuf[3] = rmass[j];
else sbuf[3] = mass[type[j]];
MPI_Sendrecv(sbuf,4,MPI_DOUBLE,all[1].proc,0,
rbuf,4,MPI_DOUBLE,all[1].proc,0,world,&status);
vcm[0] = (sbuf[3]*sbuf[0] + rbuf[3]*rbuf[0]) / (sbuf[3] + rbuf[3]);
vcm[1] = (sbuf[3]*sbuf[1] + rbuf[3]*rbuf[1]) / (sbuf[3] + rbuf[3]);
vcm[2] = (sbuf[3]*sbuf[2] + rbuf[3]*rbuf[2]) / (sbuf[3] + rbuf[3]);
v[j][0] = 2.0 * vcm[0] - sbuf[0];
v[j][1] = 2.0 * vcm[1] - sbuf[1];
v[j][2] = 2.0 * vcm[2] - sbuf[2];
eswap -= sbuf[3] * (vcm[0] * (vcm[0] - sbuf[0]) +
vcm[1] * (vcm[1] - sbuf[1]) +
vcm[2] * (vcm[2] - sbuf[2]));
} else if (me == all[1].proc) {
j = index_hi[ihi++];
sbuf[0] = v[j][0];
sbuf[1] = v[j][1];
sbuf[2] = v[j][2];
if (rmass) sbuf[3] = rmass[j];
else sbuf[3] = mass[type[j]];
MPI_Sendrecv(sbuf,4,MPI_DOUBLE,all[0].proc,0,
rbuf,4,MPI_DOUBLE,all[0].proc,0,world,&status);
vcm[0] = (sbuf[3]*sbuf[0] + rbuf[3]*rbuf[0]) / (sbuf[3] + rbuf[3]);
vcm[1] = (sbuf[3]*sbuf[1] + rbuf[3]*rbuf[1]) / (sbuf[3] + rbuf[3]);
vcm[2] = (sbuf[3]*sbuf[2] + rbuf[3]*rbuf[2]) / (sbuf[3] + rbuf[3]);
v[j][0] = 2.0 * vcm[0] - sbuf[0];
v[j][1] = 2.0 * vcm[1] - sbuf[1];
v[j][2] = 2.0 * vcm[2] - sbuf[2];
eswap += sbuf[3] * (vcm[0] * (vcm[0] - sbuf[0]) +
vcm[1] * (vcm[1] - sbuf[1]) +
vcm[2] * (vcm[2] - sbuf[2]));
}
}
// tally energy exchange from all swaps
double eswap_all;
MPI_Allreduce(&eswap,&eswap_all,1,MPI_DOUBLE,MPI_SUM,world);
e_exchange += force->mvv2e * eswap_all;
}
/* ---------------------------------------------------------------------- */
double FixThermalConductivity::compute_scalar()
{
return e_exchange;
}
diff --git a/src/fix_tmd.cpp b/src/fix_tmd.cpp
index 50865b200..b73b04c5b 100644
--- a/src/fix_tmd.cpp
+++ b/src/fix_tmd.cpp
@@ -1,561 +1,561 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Paul Crozier (SNL)
Christian Burisch (Bochum Univeristy, Germany)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_tmd.h"
#include "atom.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "group.h"
#include "respa.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define CHUNK 1000
#define MAXLINE 256
/* ---------------------------------------------------------------------- */
FixTMD::FixTMD(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 6) error->all("Illegal fix tmd command");
+ if (narg < 6) error->all(FLERR,"Illegal fix tmd command");
rho_stop = atof(arg[3]);
nfileevery = atoi(arg[5]);
- if (rho_stop < 0 || nfileevery < 0) error->all("Illegal fix tmd command");
- if (nfileevery && narg != 7) error->all("Illegal fix tmd command");
+ if (rho_stop < 0 || nfileevery < 0) error->all(FLERR,"Illegal fix tmd command");
+ if (nfileevery && narg != 7) error->all(FLERR,"Illegal fix tmd command");
MPI_Comm_rank(world,&me);
// perform initial allocation of atom-based arrays
// register with Atom class
xf = NULL;
xold = NULL;
grow_arrays(atom->nmax);
atom->add_callback(0);
// make sure an atom map exists before reading in target coordinates
if (atom->map_style == 0)
- error->all("Cannot use fix TMD unless atom map exists");
+ error->all(FLERR,"Cannot use fix TMD unless atom map exists");
// read from arg[4] and store coordinates of final target in xf
readfile(arg[4]);
// open arg[6] statistics file and write header
if (nfileevery) {
- if (narg != 7) error->all("Illegal fix tmd command");
+ if (narg != 7) error->all(FLERR,"Illegal fix tmd command");
if (me == 0) {
fp = fopen(arg[6],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix tmd file %s",arg[6]);
- error->one(str);
+ error->one(FLERR,str);
}
fprintf(fp,"%s %s\n","# Step rho_target rho_old gamma_back",
"gamma_forward lambda work_lambda work_analytical");
}
}
masstotal = group->mass(igroup);
// rho_start = initial rho
// xold = initial x or 0.0 if not in group
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double **x = atom->x;
double *mass = atom->mass;
int nlocal = atom->nlocal;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double dx,dy,dz;
int xbox,ybox,zbox;
rho_start = 0.0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xf[i][0];
dy = x[i][1] + ybox*yprd - xf[i][1];
dz = x[i][2] + zbox*zprd - xf[i][2];
rho_start += mass[type[i]]*(dx*dx + dy*dy + dz*dz);
xold[i][0] = x[i][0] + xbox*xprd;
xold[i][1] = x[i][1] + ybox*yprd;
xold[i][2] = x[i][2] + zbox*zprd;
} else xold[i][0] = xold[i][1] = xold[i][2] = 0.0;
}
double rho_start_total;
MPI_Allreduce(&rho_start,&rho_start_total,1,MPI_DOUBLE,MPI_SUM,world);
rho_start = sqrt(rho_start_total/masstotal);
rho_old = rho_start;
work_lambda = 0.0;
work_analytical = 0.0;
previous_stat = 0;
}
/* ---------------------------------------------------------------------- */
FixTMD::~FixTMD()
{
if (nfileevery && me == 0) fclose(fp);
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
// delete locally stored arrays
memory->destroy(xf);
memory->destroy(xold);
}
/* ---------------------------------------------------------------------- */
int FixTMD::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= INITIAL_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTMD::init()
{
// check that no integrator fix comes after a TMD fix
int flag = 0;
for (int i = 0; i < modify->nfix; i++) {
if (strcmp(modify->fix[i]->style,"tmd") == 0) flag = 1;
if (flag && strcmp(modify->fix[i]->style,"nve") == 0) flag = 2;
if (flag && strcmp(modify->fix[i]->style,"nvt") == 0) flag = 2;
if (flag && strcmp(modify->fix[i]->style,"npt") == 0) flag = 2;
if (flag && strcmp(modify->fix[i]->style,"nph") == 0) flag = 2;
}
- if (flag == 2) error->all("Fix tmd must come after integration fixes");
+ if (flag == 2) error->all(FLERR,"Fix tmd must come after integration fixes");
// timesteps
dtv = update->dt;
dtf = update->dt * force->ftm2v;
if (strstr(update->integrate_style,"respa"))
step_respa = ((Respa *) update->integrate)->step;
}
/* ---------------------------------------------------------------------- */
void FixTMD::initial_integrate(int vflag)
{
double a,b,c,d,e;
double dx,dy,dz,dxkt,dykt,dzkt;
double dxold,dyold,dzold,xback,yback,zback;
double gamma_forward,gamma_back,gamma_max,lambda;
double kt,fr,kttotal,frtotal,dtfm;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
double *mass = atom->mass;
int *image = atom->image;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double rho_target = rho_start + delta * (rho_stop - rho_start);
// compute the Lagrange multiplier
a = b = e = 0.0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dxold = xold[i][0] - xf[i][0];
dyold = xold[i][1] - xf[i][1];
dzold = xold[i][2] - xf[i][2];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = x[i][0] + xbox*xprd - xf[i][0];
dy = x[i][1] + ybox*yprd - xf[i][1];
dz = x[i][2] + zbox*zprd - xf[i][2];
a += mass[type[i]]*(dxold*dxold + dyold*dyold + dzold*dzold);
b += mass[type[i]]*(dx *dxold + dy *dyold + dz *dzold);
e += mass[type[i]]*(dx *dx + dy *dy + dz *dz);
}
}
double abe[3],abetotal[3];
abe[0] = a; abe[1] = b; abe[2] = e;
MPI_Allreduce(abe,abetotal,3,MPI_DOUBLE,MPI_SUM,world);
a = abetotal[0]/masstotal;
b = 2.0*abetotal[1]/masstotal;
e = abetotal[2]/masstotal;
c = e - rho_old*rho_old;
d = b*b - 4*a*c;
if (d < 0) d = 0;
if (b >= 0) gamma_max = (-b - sqrt(d))/(2*a);
else gamma_max = (-b + sqrt(d))/(2*a);
gamma_back = c/(a*gamma_max);
if (a == 0.0) gamma_back = 0;
c = e - rho_target*rho_target;
d = b*b - 4*a*c;
if (d < 0) d = 0;
if (b >= 0) gamma_max = (-b - sqrt(d))/(2*a);
else gamma_max = (-b + sqrt(d))/(2*a);
gamma_forward = c/(a*gamma_max);
if (a == 0.0) gamma_forward = 0;
fr = kt = 0.0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dxold = xold[i][0] - xf[i][0];
dyold = xold[i][1] - xf[i][1];
dzold = xold[i][2] - xf[i][2];
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
xback = x[i][0] + xbox*xprd + gamma_back*dxold;
yback = x[i][1] + ybox*yprd + gamma_back*dyold;
zback = x[i][2] + zbox*zprd + gamma_back*dzold;
dxkt = xback - xold[i][0];
dykt = yback - xold[i][1];
dzkt = zback - xold[i][2];
kt += mass[type[i]]*(dxkt*dxkt + dykt*dykt + dzkt*dzkt);
fr += f[i][0]*dxold + f[i][1]*dyold + f[i][2]*dzold;
}
}
double r[2],rtotal[2];
r[0] = fr; r[1] = kt;
MPI_Allreduce(r,rtotal,2,MPI_DOUBLE,MPI_SUM,world);
frtotal = rtotal[0];
kttotal = rtotal[1];
// stat write of mean constraint force based on previous time step constraint
if (nfileevery && me == 0) {
work_analytical +=
(-frtotal - kttotal/dtv/dtf)*(rho_target - rho_old)/rho_old;
lambda = gamma_back*rho_old*masstotal/dtv/dtf;
work_lambda += lambda*(rho_target - rho_old);
if (!(update->ntimestep % nfileevery) &&
(previous_stat != update->ntimestep)) {
fprintf(fp,
BIGINT_FORMAT " %g %g %g %g %g %g %g\n",
update->ntimestep,rho_target,rho_old,
gamma_back,gamma_forward,lambda,work_lambda,work_analytical);
fflush(fp);
previous_stat = update->ntimestep;
}
}
rho_old = rho_target;
// apply the constraint and save constrained positions for next step
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
dtfm = dtf / mass[type[i]];
dxold = xold[i][0] - xf[i][0];
x[i][0] += gamma_forward*dxold;
v[i][0] += gamma_forward*dxold/dtv;
f[i][0] += gamma_forward*dxold/dtv/dtfm;
dyold = xold[i][1] - xf[i][1];
x[i][1] += gamma_forward*dyold;
v[i][1] += gamma_forward*dyold/dtv;
f[i][1] += gamma_forward*dyold/dtv/dtfm;
dzold = xold[i][2] - xf[i][2];
x[i][2] += gamma_forward*dzold;
v[i][2] += gamma_forward*dzold/dtv;
f[i][2] += gamma_forward*dzold/dtv/dtfm;
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
xold[i][0] = x[i][0] + xbox*xprd;
xold[i][1] = x[i][1] + ybox*yprd;
xold[i][2] = x[i][2] + zbox*zprd;
}
}
}
/* ---------------------------------------------------------------------- */
void FixTMD::initial_integrate_respa(int vflag, int ilevel, int flag)
{
if (flag) return; // only used by NPT,NPH
dtv = step_respa[ilevel];
dtf = step_respa[ilevel] * force->ftm2v;
if (ilevel == 0) initial_integrate(vflag);
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixTMD::memory_usage()
{
double bytes = 2*atom->nmax*3 * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
allocate atom-based arrays
------------------------------------------------------------------------- */
void FixTMD::grow_arrays(int nmax)
{
memory->grow(xf,nmax,3,"fix_tmd:xf");
memory->grow(xold,nmax,3,"fix_tmd:xold");
}
/* ----------------------------------------------------------------------
copy values within local atom-based arrays
------------------------------------------------------------------------- */
void FixTMD::copy_arrays(int i, int j)
{
xf[j][0] = xf[i][0];
xf[j][1] = xf[i][1];
xf[j][2] = xf[i][2];
xold[j][0] = xold[i][0];
xold[j][1] = xold[i][1];
xold[j][2] = xold[i][2];
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for exchange with another proc
------------------------------------------------------------------------- */
int FixTMD::pack_exchange(int i, double *buf)
{
buf[0] = xf[i][0];
buf[1] = xf[i][1];
buf[2] = xf[i][2];
buf[3] = xold[i][0];
buf[4] = xold[i][1];
buf[5] = xold[i][2];
return 6;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based arrays from exchange with another proc
------------------------------------------------------------------------- */
int FixTMD::unpack_exchange(int nlocal, double *buf)
{
xf[nlocal][0] = buf[0];
xf[nlocal][1] = buf[1];
xf[nlocal][2] = buf[2];
xold[nlocal][0] = buf[3];
xold[nlocal][1] = buf[4];
xold[nlocal][2] = buf[5];
return 6;
}
/* ----------------------------------------------------------------------
read target coordinates from file, store with appropriate atom
------------------------------------------------------------------------- */
void FixTMD::readfile(char *file)
{
if (me == 0) {
if (screen) fprintf(screen,"Reading TMD target file %s ...\n",file);
open(file);
}
int *mask = atom->mask;
int nlocal = atom->nlocal;
char *buffer = new char[CHUNK*MAXLINE];
char *ptr,*next,*bufptr;
int i,m,nlines,tag,imageflag,ix,iy,iz;
double x,y,z,xprd,yprd,zprd;
int firstline = 1;
int ncount = 0;
int eof = 0;
xprd = yprd = zprd = -1.0;
while (!eof) {
if (me == 0) {
m = 0;
for (nlines = 0; nlines < CHUNK; nlines++) {
ptr = fgets(&buffer[m],MAXLINE,fp);
if (ptr == NULL) break;
m += strlen(&buffer[m]);
}
if (ptr == NULL) eof = 1;
buffer[m++] = '\n';
}
MPI_Bcast(&eof,1,MPI_INT,0,world);
MPI_Bcast(&nlines,1,MPI_INT,0,world);
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
bufptr = buffer;
for (i = 0; i < nlines; i++) {
next = strchr(bufptr,'\n');
*next = '\0';
if (firstline) {
if (strstr(bufptr,"xlo xhi")) {
double lo,hi;
sscanf(bufptr,"%lg %lg",&lo,&hi);
xprd = hi - lo;
bufptr = next + 1;
continue;
} else if (strstr(bufptr,"ylo yhi")) {
double lo,hi;
sscanf(bufptr,"%lg %lg",&lo,&hi);
yprd = hi - lo;
bufptr = next + 1;
continue;
} else if (strstr(bufptr,"zlo zhi")) {
double lo,hi;
sscanf(bufptr,"%lg %lg",&lo,&hi);
zprd = hi - lo;
bufptr = next + 1;
continue;
} else if (atom->count_words(bufptr) == 4) {
if (xprd >= 0.0 || yprd >= 0.0 || zprd >= 0.0)
- error->all("Incorrect format in TMD target file");
+ error->all(FLERR,"Incorrect format in TMD target file");
imageflag = 0;
firstline = 0;
} else if (atom->count_words(bufptr) == 7) {
if (xprd < 0.0 || yprd < 0.0 || zprd < 0.0)
- error->all("Incorrect format in TMD target file");
+ error->all(FLERR,"Incorrect format in TMD target file");
imageflag = 1;
firstline = 0;
- } else error->all("Incorrect format in TMD target file");
+ } else error->all(FLERR,"Incorrect format in TMD target file");
}
if (imageflag)
sscanf(bufptr,"%d %lg %lg %lg %d %d %d",&tag,&x,&y,&z,&ix,&iy,&iz);
else
sscanf(bufptr,"%d %lg %lg %lg",&tag,&x,&y,&z);
m = atom->map(tag);
if (m >= 0 && m < nlocal && mask[m] & groupbit) {
if (imageflag) {
xf[m][0] = x + ix*xprd;
xf[m][1] = y + iy*yprd;
xf[m][2] = z + iz*zprd;
} else {
xf[m][0] = x;
xf[m][1] = y;
xf[m][2] = z;
}
ncount++;
}
bufptr = next + 1;
}
}
// clean up
delete [] buffer;
if (me == 0) {
if (compressed) pclose(fp);
else fclose(fp);
}
// check that all atoms in group were listed in target file
// set xf = 0.0 for atoms not in group
int gcount = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) gcount++;
else xf[i][0] = xf[i][1] = xf[i][2] = 0.0;
int flag = 0;
if (gcount != ncount) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
- if (flagall) error->all("TMD target file did not list all group atoms");
+ if (flagall) error->all(FLERR,"TMD target file did not list all group atoms");
}
/* ----------------------------------------------------------------------
proc 0 opens TMD data file
test if gzipped
------------------------------------------------------------------------- */
void FixTMD::open(char *file)
{
compressed = 0;
char *suffix = file + strlen(file) - 3;
if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1;
if (!compressed) fp = fopen(file,"r");
else {
#ifdef LAMMPS_GZIP
char gunzip[128];
sprintf(gunzip,"gunzip -c %s",file);
fp = popen(gunzip,"r");
#else
- error->one("Cannot open gzipped file");
+ error->one(FLERR,"Cannot open gzipped file");
#endif
}
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
/* ---------------------------------------------------------------------- */
void FixTMD::reset_dt()
{
dtv = update->dt;
dtf = update->dt * force->ftm2v;
}
diff --git a/src/fix_ttm.cpp b/src/fix_ttm.cpp
index ff037a780..4bc35c509 100644
--- a/src/fix_ttm.cpp
+++ b/src/fix_ttm.cpp
@@ -1,687 +1,684 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Paul Crozier (SNL)
Carolyn Phillips (University of Michigan)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "fix_ttm.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "domain.h"
#include "region.h"
#include "respa.h"
#include "comm.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
FixTTM::FixTTM(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 15) error->all("Illegal fix ttm command");
+ if (narg < 15) error->all(FLERR,"Illegal fix ttm command");
vector_flag = 1;
size_vector = 2;
global_freq = 1;
extvector = 1;
nevery = 1;
restart_peratom = 1;
restart_global = 1;
seed = atoi(arg[3]);
electronic_specific_heat = atof(arg[4]);
electronic_density = atof(arg[5]);
electronic_thermal_conductivity = atof(arg[6]);
gamma_p = atof(arg[7]);
gamma_s = atof(arg[8]);
v_0 = atof(arg[9]);
nxnodes = atoi(arg[10]);
nynodes = atoi(arg[11]);
nznodes = atoi(arg[12]);
fpr = fopen(arg[13],"r");
if (fpr == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",arg[13]);
- error->one(str);
+ error->one(FLERR,str);
}
nfileevery = atoi(arg[14]);
if (nfileevery) {
- if (narg != 16) error->all("Illegal fix ttm command");
+ if (narg != 16) error->all(FLERR,"Illegal fix ttm command");
MPI_Comm_rank(world,&me);
if (me == 0) {
fp = fopen(arg[15],"w");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix ttm file %s",arg[15]);
- error->one(str);
+ error->one(FLERR,str);
}
}
}
// error check
- if (seed <= 0) error->all("Invalid random number seed in fix ttm command");
+ if (seed <= 0) error->all(FLERR,"Invalid random number seed in fix ttm command");
if (electronic_specific_heat <= 0.0)
- error->all("Fix ttm electronic_specific_heat must be > 0.0");
+ error->all(FLERR,"Fix ttm electronic_specific_heat must be > 0.0");
if (electronic_density <= 0.0)
- error->all("Fix ttm electronic_density must be > 0.0");
+ error->all(FLERR,"Fix ttm electronic_density must be > 0.0");
if (electronic_thermal_conductivity < 0.0)
- error->all("Fix ttm electronic_thermal_conductivity must be >= 0.0");
- if (gamma_p <= 0.0) error->all("Fix ttm gamma_p must be > 0.0");
- if (gamma_s < 0.0) error->all("Fix ttm gamma_s must be >= 0.0");
- if (v_0 < 0.0) error->all("Fix ttm v_0 must be >= 0.0");
+ error->all(FLERR,"Fix ttm electronic_thermal_conductivity must be >= 0.0");
+ if (gamma_p <= 0.0) error->all(FLERR,"Fix ttm gamma_p must be > 0.0");
+ if (gamma_s < 0.0) error->all(FLERR,"Fix ttm gamma_s must be >= 0.0");
+ if (v_0 < 0.0) error->all(FLERR,"Fix ttm v_0 must be >= 0.0");
if (nxnodes <= 0 || nynodes <= 0 || nznodes <= 0)
- error->all("Fix ttm number of nodes must be > 0");
+ error->all(FLERR,"Fix ttm number of nodes must be > 0");
v_0_sq = v_0*v_0;
// initialize Marsaglia RNG with processor-unique seed
random = new RanMars(lmp,seed + comm->me);
// allocate per-type arrays for force prefactors
gfactor1 = new double[atom->ntypes+1];
gfactor2 = new double[atom->ntypes+1];
// allocate 3d grid variables
total_nnodes = nxnodes*nynodes*nznodes;
memory->create(nsum,nxnodes,nynodes,nznodes,"ttm:nsum");
memory->create(nsum_all,nxnodes,nynodes,nznodes,"ttm:nsum_all");
memory->create(T_initial_set,nxnodes,nynodes,nznodes,"ttm:T_initial_set");
memory->create(sum_vsq,nxnodes,nynodes,nznodes,"ttm:sum_vsq");
memory->create(sum_mass_vsq,nxnodes,nynodes,nznodes,"ttm:sum_mass_vsq");
memory->create(sum_vsq_all,nxnodes,nynodes,nznodes,"ttm:sum_vsq_all");
memory->create(sum_mass_vsq_all,nxnodes,nynodes,nznodes,
"ttm:sum_mass_vsq_all");
memory->create(T_electron_old,nxnodes,nynodes,nznodes,"ttm:T_electron_old");
memory->create(T_electron,nxnodes,nynodes,nznodes,"ttm:T_electron");
memory->create(net_energy_transfer,nxnodes,nynodes,nznodes,
"TTM:net_energy_transfer");
memory->create(net_energy_transfer_all,nxnodes,nynodes,nznodes,
"TTM:net_energy_transfer_all");
flangevin = NULL;
grow_arrays(atom->nmax);
// zero out the flangevin array
for (int i = 0; i < atom->nmax; i++) {
flangevin[i][0] = 0;
flangevin[i][1] = 0;
flangevin[i][2] = 0;
}
atom->add_callback(0);
atom->add_callback(1);
// set initial electron temperatures from user input file
if (me == 0) read_initial_electron_temperatures();
MPI_Bcast(&T_electron[0][0][0],total_nnodes,MPI_DOUBLE,0,world);
}
/* ---------------------------------------------------------------------- */
FixTTM::~FixTTM()
{
if (nfileevery && me == 0) fclose(fp);
delete random;
delete [] gfactor1;
delete [] gfactor2;
memory->destroy(nsum);
memory->destroy(nsum_all);
memory->destroy(T_initial_set);
memory->destroy(sum_vsq);
memory->destroy(sum_mass_vsq);
memory->destroy(sum_vsq_all);
memory->destroy(sum_mass_vsq_all);
memory->destroy(T_electron_old);
memory->destroy(T_electron);
memory->destroy(flangevin);
memory->destroy(net_energy_transfer);
memory->destroy(net_energy_transfer_all);
}
/* ---------------------------------------------------------------------- */
int FixTTM::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixTTM::init()
{
if (domain->dimension == 2)
- error->all("Cannot use fix ttm with 2d simulation");
+ error->all(FLERR,"Cannot use fix ttm with 2d simulation");
if (domain->nonperiodic != 0)
- error->all("Cannot use nonperiodic boundares with fix ttm");
+ error->all(FLERR,"Cannot use nonperiodic boundares with fix ttm");
if (domain->triclinic)
- error->all("Cannot use fix ttm with triclinic box");
+ error->all(FLERR,"Cannot use fix ttm with triclinic box");
// set force prefactors
for (int i = 1; i <= atom->ntypes; i++) {
gfactor1[i] = - gamma_p / force->ftm2v;
gfactor2[i] =
sqrt(24.0*force->boltz*gamma_p/update->dt/force->mvv2e) / force->ftm2v;
}
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
net_energy_transfer_all[ixnode][iynode][iznode] = 0;
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixTTM::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force_setup(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa_setup(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixTTM::post_force(int vflag)
{
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double gamma1,gamma2;
// apply damping and thermostat to all atoms in fix group
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
double xscale = (x[i][0] - domain->boxlo[0])/domain->xprd;
double yscale = (x[i][1] - domain->boxlo[1])/domain->yprd;
double zscale = (x[i][2] - domain->boxlo[2])/domain->zprd;
int ixnode = static_cast<int>(xscale*nxnodes);
int iynode = static_cast<int>(yscale*nynodes);
int iznode = static_cast<int>(zscale*nznodes);
while (ixnode > nxnodes-1) ixnode -= nxnodes;
while (iynode > nynodes-1) iynode -= nynodes;
while (iznode > nznodes-1) iznode -= nznodes;
while (ixnode < 0) ixnode += nxnodes;
while (iynode < 0) iynode += nynodes;
while (iznode < 0) iznode += nznodes;
if (T_electron[ixnode][iynode][iznode] < 0)
- error->all("Electronic temperature dropped below zero");
+ error->all(FLERR,"Electronic temperature dropped below zero");
double tsqrt = sqrt(T_electron[ixnode][iynode][iznode]);
gamma1 = gfactor1[type[i]];
double vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
if (vsq > v_0_sq) gamma1 *= (gamma_p + gamma_s)/gamma_p;
gamma2 = gfactor2[type[i]] * tsqrt;
flangevin[i][0] = gamma1*v[i][0] + gamma2*(random->uniform()-0.5);
flangevin[i][1] = gamma1*v[i][1] + gamma2*(random->uniform()-0.5);
flangevin[i][2] = gamma1*v[i][2] + gamma2*(random->uniform()-0.5);
f[i][0] += flangevin[i][0];
f[i][1] += flangevin[i][1];
f[i][2] += flangevin[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixTTM::post_force_setup(int vflag)
{
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
// apply langevin forces that have been stored from previous run
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
f[i][0] += flangevin[i][0];
f[i][1] += flangevin[i][1];
f[i][2] += flangevin[i][2];
}
}
}
/* ---------------------------------------------------------------------- */
void FixTTM::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixTTM::post_force_respa_setup(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force_setup(vflag);
}
/* ---------------------------------------------------------------------- */
void FixTTM::reset_dt()
{
for (int i = 1; i <= atom->ntypes; i++)
gfactor2[i] =
sqrt(24.0*force->boltz*gamma_p/update->dt/force->mvv2e) / force->ftm2v;
}
/* ----------------------------------------------------------------------
read in initial electron temperatures from a user-specified file
only called by proc 0
------------------------------------------------------------------------- */
void FixTTM::read_initial_electron_temperatures()
{
char line[MAXLINE];
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
T_initial_set[ixnode][iynode][iznode] = 0;
// read initial electron temperature values from file
int ixnode,iynode,iznode;
double T_tmp;
while (1) {
if (fgets(line,MAXLINE,fpr) == NULL) break;
sscanf(line,"%d %d %d %lg",&ixnode,&iynode,&iznode,&T_tmp);
- if (T_tmp < 0.0) error->one("Fix ttm electron temperatures must be > 0.0");
+ if (T_tmp < 0.0) error->one(FLERR,"Fix ttm electron temperatures must be > 0.0");
T_electron[ixnode][iynode][iznode] = T_tmp;
T_initial_set[ixnode][iynode][iznode] = 1;
}
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
if (T_initial_set[ixnode][iynode][iznode] == 0)
- error->one("Initial temperatures not all set in fix ttm");
+ error->one(FLERR,"Initial temperatures not all set in fix ttm");
// close file
fclose(fpr);
}
/* ---------------------------------------------------------------------- */
void FixTTM::end_of_step()
{
double **x = atom->x;
double **v = atom->v;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
net_energy_transfer[ixnode][iynode][iznode] = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
double xscale = (x[i][0] - domain->boxlo[0])/domain->xprd;
double yscale = (x[i][1] - domain->boxlo[1])/domain->yprd;
double zscale = (x[i][2] - domain->boxlo[2])/domain->zprd;
int ixnode = static_cast<int>(xscale*nxnodes);
int iynode = static_cast<int>(yscale*nynodes);
int iznode = static_cast<int>(zscale*nznodes);
while (ixnode > nxnodes-1) ixnode -= nxnodes;
while (iynode > nynodes-1) iynode -= nynodes;
while (iznode > nznodes-1) iznode -= nznodes;
while (ixnode < 0) ixnode += nxnodes;
while (iynode < 0) iynode += nynodes;
while (iznode < 0) iznode += nznodes;
net_energy_transfer[ixnode][iynode][iznode] +=
(flangevin[i][0]*v[i][0] + flangevin[i][1]*v[i][1] +
flangevin[i][2]*v[i][2]);
}
MPI_Allreduce(&net_energy_transfer[0][0][0],
&net_energy_transfer_all[0][0][0],
total_nnodes,MPI_DOUBLE,MPI_SUM,world);
double dx = domain->xprd/nxnodes;
double dy = domain->yprd/nynodes;
double dz = domain->zprd/nznodes;
double del_vol = dx*dy*dz;
// num_inner_timesteps = # of inner steps (thermal solves)
// required this MD step to maintain a stable explicit solve
int num_inner_timesteps = 1;
double inner_dt = update->dt;
double stability_criterion = 1.0 -
2.0*inner_dt/(electronic_specific_heat*electronic_density) *
(electronic_thermal_conductivity*(1.0/dx/dx + 1.0/dy/dy + 1.0/dz/dz));
if (stability_criterion < 0.0) {
inner_dt = 0.5*(electronic_specific_heat*electronic_density) /
(electronic_thermal_conductivity*(1.0/dx/dx + 1.0/dy/dy + 1.0/dz/dz));
num_inner_timesteps = static_cast<int>(update->dt/inner_dt) + 1;
inner_dt = update->dt/double(num_inner_timesteps);
if (num_inner_timesteps > 1000000)
- error->warning("Too many inner timesteps in fix ttm",0);
+ error->warning(FLERR,"Too many inner timesteps in fix ttm",0);
}
for (int ith_inner_timestep = 0; ith_inner_timestep < num_inner_timesteps;
ith_inner_timestep++) {
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
T_electron_old[ixnode][iynode][iznode] =
T_electron[ixnode][iynode][iznode];
// compute new electron T profile
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++) {
int right_xnode = ixnode + 1;
int right_ynode = iynode + 1;
int right_znode = iznode + 1;
if (right_xnode == nxnodes) right_xnode = 0;
if (right_ynode == nynodes) right_ynode = 0;
if (right_znode == nznodes) right_znode = 0;
int left_xnode = ixnode - 1;
int left_ynode = iynode - 1;
int left_znode = iznode - 1;
if (left_xnode == -1) left_xnode = nxnodes - 1;
if (left_ynode == -1) left_ynode = nynodes - 1;
if (left_znode == -1) left_znode = nznodes - 1;
T_electron[ixnode][iynode][iznode] =
T_electron_old[ixnode][iynode][iznode] +
inner_dt/(electronic_specific_heat*electronic_density) *
(electronic_thermal_conductivity *
((T_electron_old[right_xnode][iynode][iznode] +
T_electron_old[left_xnode][iynode][iznode] -
2*T_electron_old[ixnode][iynode][iznode])/dx/dx +
(T_electron_old[ixnode][right_ynode][iznode] +
T_electron_old[ixnode][left_ynode][iznode] -
2*T_electron_old[ixnode][iynode][iznode])/dy/dy +
(T_electron_old[ixnode][iynode][right_znode] +
T_electron_old[ixnode][iynode][left_znode] -
2*T_electron_old[ixnode][iynode][iznode])/dz/dz) -
(net_energy_transfer_all[ixnode][iynode][iznode])/del_vol);
}
}
// output nodal temperatures for current timestep
if ((nfileevery) && !(update->ntimestep % nfileevery)) {
// compute atomic Ta for each grid point
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++) {
nsum[ixnode][iynode][iznode] = 0;
nsum_all[ixnode][iynode][iznode] = 0;
sum_vsq[ixnode][iynode][iznode] = 0.0;
sum_mass_vsq[ixnode][iynode][iznode] = 0.0;
sum_vsq_all[ixnode][iynode][iznode] = 0.0;
sum_mass_vsq_all[ixnode][iynode][iznode] = 0.0;
}
double massone;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
double xscale = (x[i][0] - domain->boxlo[0])/domain->xprd;
double yscale = (x[i][1] - domain->boxlo[1])/domain->yprd;
double zscale = (x[i][2] - domain->boxlo[2])/domain->zprd;
int ixnode = static_cast<int>(xscale*nxnodes);
int iynode = static_cast<int>(yscale*nynodes);
int iznode = static_cast<int>(zscale*nznodes);
while (ixnode > nxnodes-1) ixnode -= nxnodes;
while (iynode > nynodes-1) iynode -= nynodes;
while (iznode > nznodes-1) iznode -= nznodes;
while (ixnode < 0) ixnode += nxnodes;
while (iynode < 0) iynode += nynodes;
while (iznode < 0) iznode += nznodes;
double vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
nsum[ixnode][iynode][iznode] += 1;
sum_vsq[ixnode][iynode][iznode] += vsq;
sum_mass_vsq[ixnode][iynode][iznode] += massone*vsq;
}
MPI_Allreduce(&nsum[0][0][0],&nsum_all[0][0][0],total_nnodes,
MPI_INT,MPI_SUM,world);
MPI_Allreduce(&sum_vsq[0][0][0],&sum_vsq_all[0][0][0],total_nnodes,
MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(&sum_mass_vsq[0][0][0],&sum_mass_vsq_all[0][0][0],
total_nnodes,MPI_DOUBLE,MPI_SUM,world);
if (me == 0) {
fprintf(fp,BIGINT_FORMAT,update->ntimestep);
double T_a;
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++) {
T_a = 0;
if (nsum_all[ixnode][iynode][iznode] > 0)
T_a = sum_mass_vsq_all[ixnode][iynode][iznode]/
(3.0*force->boltz*nsum_all[ixnode][iynode][iznode]/force->mvv2e);
fprintf(fp," %f",T_a);
}
fprintf(fp,"\t");
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
fprintf(fp,"%f ",T_electron[ixnode][iynode][iznode]);
fprintf(fp,"\n");
}
}
}
/* ----------------------------------------------------------------------
memory usage of 3d grid
------------------------------------------------------------------------- */
double FixTTM::memory_usage()
{
double bytes = 0.0;
bytes += 5*total_nnodes * sizeof(int);
bytes += 14*total_nnodes * sizeof(double);
return bytes;
}
/* ---------------------------------------------------------------------- */
void FixTTM::grow_arrays(int ngrow)
{
memory->grow(flangevin,ngrow,3,"TTM:flangevin");
}
/* ----------------------------------------------------------------------
return the energy of the electronic subsystem or the net_energy transfer
between the subsystems
------------------------------------------------------------------------- */
double FixTTM::compute_vector(int n)
{
double e_energy = 0.0;
double transfer_energy = 0.0;
double dx = domain->xprd/nxnodes;
double dy = domain->yprd/nynodes;
double dz = domain->zprd/nznodes;
double del_vol = dx*dy*dz;
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++) {
e_energy +=
T_electron[ixnode][iynode][iznode]*electronic_specific_heat*
electronic_density*del_vol;
transfer_energy +=
net_energy_transfer_all[ixnode][iynode][iznode]*update->dt;
}
if (n == 0) return e_energy;
if (n == 1) return transfer_energy;
return 0.0;
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixTTM::write_restart(FILE *fp)
{
double *rlist;
memory->create(rlist,nxnodes*nynodes*nznodes+1,"TTM:rlist");
int n = 0;
rlist[n++] = seed;
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
rlist[n++] = T_electron[ixnode][iynode][iznode];
if (comm->me == 0) {
int size = n * sizeof(double);
fwrite(&size,sizeof(int),1,fp);
fwrite(rlist,sizeof(double),n,fp);
}
memory->destroy(rlist);
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixTTM::restart(char *buf)
{
int n = 0;
double *rlist = (double *) buf;
// the seed must be changed from the initial seed
seed = static_cast<int> (0.5*rlist[n++]);
for (int ixnode = 0; ixnode < nxnodes; ixnode++)
for (int iynode = 0; iynode < nynodes; iynode++)
for (int iznode = 0; iznode < nznodes; iznode++)
T_electron[ixnode][iynode][iznode] = rlist[n++];
delete random;
random = new RanMars(lmp,seed+comm->me);
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixTTM::pack_restart(int i, double *buf)
{
buf[0] = 4;
buf[1] = flangevin[i][0];
buf[2] = flangevin[i][1];
buf[3] = flangevin[i][2];
return 4;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixTTM::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int m = 0;
for (int i = 0; i < nth; i++) m += static_cast<int> (extra[nlocal][m]);
m++;
flangevin[nlocal][0] = extra[nlocal][m++];
flangevin[nlocal][1] = extra[nlocal][m++];
flangevin[nlocal][2] = extra[nlocal][m++];
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixTTM::maxsize_restart()
{
return 4;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixTTM::size_restart(int nlocal)
{
return 4;
}
diff --git a/src/fix_viscosity.cpp b/src/fix_viscosity.cpp
index 8191e6d97..04bcd3394 100644
--- a/src/fix_viscosity.cpp
+++ b/src/fix_viscosity.cpp
@@ -1,309 +1,306 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Craig Tenney (UND) added support
for swapping atoms of different masses
------------------------------------------------------------------------- */
#include "math.h"
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "fix_viscosity.h"
#include "atom.h"
#include "domain.h"
#include "modify.h"
#include "error.h"
using namespace LAMMPS_NS;
// needs to be big, but not so big that lose precision when subtract velocity
#define BIG 1.0e10
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
FixViscosity::FixViscosity(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 7) error->all("Illegal fix viscosity command");
+ if (narg < 7) error->all(FLERR,"Illegal fix viscosity command");
MPI_Comm_rank(world,&me);
nevery = atoi(arg[3]);
- if (nevery <= 0) error->all("Illegal fix viscosity command");
+ if (nevery <= 0) error->all(FLERR,"Illegal fix viscosity command");
scalar_flag = 1;
global_freq = nevery;
extscalar = 0;
if (strcmp(arg[4],"x") == 0) vdim = 0;
else if (strcmp(arg[4],"y") == 0) vdim = 1;
else if (strcmp(arg[4],"z") == 0) vdim = 2;
- else error->all("Illegal fix viscosity command");
+ else error->all(FLERR,"Illegal fix viscosity command");
if (strcmp(arg[5],"x") == 0) pdim = 0;
else if (strcmp(arg[5],"y") == 0) pdim = 1;
else if (strcmp(arg[5],"z") == 0) pdim = 2;
- else error->all("Illegal fix viscosity command");
+ else error->all(FLERR,"Illegal fix viscosity command");
nbin = atoi(arg[6]);
- if (nbin % 2 || nbin <= 2) error->all("Illegal fix viscosity command");
+ if (nbin % 2 || nbin <= 2) error->all(FLERR,"Illegal fix viscosity command");
// optional keywords
nswap = 1;
vtarget = BIG;
int iarg = 7;
while (iarg < narg) {
if (strcmp(arg[iarg],"swap") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix viscosity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix viscosity command");
nswap = atoi(arg[iarg+1]);
- if (nswap <= 0) error->all("Fix viscosity swap value must be positive");
+ if (nswap <= 0) error->all(FLERR,"Fix viscosity swap value must be positive");
iarg += 2;
} else if (strcmp(arg[iarg],"vtarget") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix viscosity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix viscosity command");
if (strcmp(arg[iarg+1],"INF") == 0) vtarget = BIG;
else vtarget = atof(arg[iarg+1]);
if (vtarget <= 0.0)
- error->all("Fix viscosity vtarget value must be positive");
+ error->all(FLERR,"Fix viscosity vtarget value must be positive");
iarg += 2;
- } else error->all("Illegal fix viscosity command");
+ } else error->all(FLERR,"Illegal fix viscosity command");
}
// initialize array sizes to nswap+1 so have space to shift values down
pos_index = new int[nswap+1];
neg_index = new int[nswap+1];
pos_delta = new double[nswap+1];
neg_delta = new double[nswap+1];
p_exchange = 0.0;
}
/* ---------------------------------------------------------------------- */
FixViscosity::~FixViscosity()
{
delete [] pos_index;
delete [] neg_index;
delete [] pos_delta;
delete [] neg_delta;
}
/* ---------------------------------------------------------------------- */
int FixViscosity::setmask()
{
int mask = 0;
mask |= END_OF_STEP;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixViscosity::init()
{
// warn if any fix ave/spatial comes after this fix
// can cause glitch in averaging since ave will happen after swap
int foundme = 0;
for (int i = 0; i < modify->nfix; i++) {
if (modify->fix[i] == this) foundme = 1;
if (foundme && strcmp(modify->fix[i]->style,"ave/spatial") == 0 && me == 0)
- error->warning("Fix viscosity comes before fix ave/spatial");
+ error->warning(FLERR,"Fix viscosity comes before fix ave/spatial");
}
// set bounds of 2 slabs in pdim
// only necessary for static box, else re-computed in end_of_step()
// lo bin is always bottom bin
// hi bin is just above half height
if (domain->box_change == 0) {
prd = domain->prd[pdim];
boxlo = domain->boxlo[pdim];
boxhi = domain->boxhi[pdim];
double binsize = (boxhi-boxlo) / nbin;
slablo_lo = boxlo;
slablo_hi = boxlo + binsize;
slabhi_lo = boxlo + (nbin/2)*binsize;
slabhi_hi = boxlo + (nbin/2+1)*binsize;
}
periodicity = domain->periodicity[pdim];
}
/* ---------------------------------------------------------------------- */
void FixViscosity::end_of_step()
{
int i,m,insert;
double coord,delta;
MPI_Status status;
struct {
double value;
int proc;
} mine[2],all[2];
// if box changes, recompute bounds of 2 slabs in pdim
if (domain->box_change) {
prd = domain->prd[pdim];
boxlo = domain->boxlo[pdim];
boxhi = domain->boxhi[pdim];
double binsize = (boxhi-boxlo) / nbin;
slablo_lo = boxlo;
slablo_hi = boxlo + binsize;
slabhi_lo = boxlo + (nbin/2)*binsize;
slabhi_hi = boxlo + (nbin/2+1)*binsize;
}
// make 2 lists of up to nswap atoms with velocity closest to +/- vtarget
// lists are sorted by closeness to vtarget
// only consider atoms in the bottom/middle slabs
// map atoms back into periodic box if necessary
// insert = location in list to insert new atom
double **x = atom->x;
double **v = atom->v;
int *type = atom->type;
int *mask = atom->mask;
int nlocal = atom->nlocal;
npositive = nnegative = 0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
coord = x[i][pdim];
if (coord < boxlo && periodicity) coord += prd;
else if (coord >= boxhi && periodicity) coord -= prd;
if (coord >= slablo_lo && coord < slablo_hi) {
if (v[i][vdim] < 0.0) continue;
delta = fabs(v[i][vdim] - vtarget);
if (npositive < nswap || delta < pos_delta[nswap-1]) {
for (insert = npositive-1; insert >= 0; insert--)
if (delta > pos_delta[insert]) break;
insert++;
for (m = npositive-1; m >= insert; m--) {
pos_delta[m+1] = pos_delta[m];
pos_index[m+1] = pos_index[m];
}
pos_delta[insert] = delta;
pos_index[insert] = i;
if (npositive < nswap) npositive++;
}
}
if (coord >= slabhi_lo && coord < slabhi_hi) {
if (v[i][vdim] > 0.0) continue;
delta = fabs(v[i][vdim] + vtarget);
if (nnegative < nswap || delta < neg_delta[nswap-1]) {
for (insert = nnegative-1; insert >= 0; insert--)
if (delta > neg_delta[insert]) break;
insert++;
for (m = nnegative-1; m >= insert; m--) {
neg_delta[m+1] = neg_delta[m];
neg_index[m+1] = neg_index[m];
}
neg_delta[insert] = delta;
neg_index[insert] = i;
if (nnegative < nswap) nnegative++;
}
}
}
// loop over nswap pairs
// find 2 global atoms with smallest delta in bottom/top slabs
// BIG values are for procs with no atom to contribute
// MINLOC also communicates which procs own them
// exchange momenta between the 2 particles
// if I own both particles just swap, else point2point comm of vel,mass
double *mass = atom->mass;
double *rmass = atom->rmass;
int ipos,ineg;
double sbuf[2],rbuf[2],vcm;
double pswap = 0.0;
mine[0].proc = mine[1].proc = me;
int ipositive = 0;
int inegative = 0;
for (m = 0; m < nswap; m++) {
if (ipositive < npositive) mine[0].value = pos_delta[ipositive];
else mine[0].value = BIG;
if (inegative < nnegative) mine[1].value = neg_delta[inegative];
else mine[1].value = BIG;
MPI_Allreduce(mine,all,2,MPI_DOUBLE_INT,MPI_MINLOC,world);
if (all[0].value == BIG || all[1].value == BIG) continue;
if (me == all[0].proc && me == all[1].proc) {
ipos = pos_index[ipositive++];
ineg = neg_index[inegative++];
rbuf[0] = v[ipos][vdim];
if (rmass) rbuf[1] = rmass[ipos];
else rbuf[1] = mass[type[ipos]];
sbuf[0] = v[ineg][vdim];
if (rmass) sbuf[1] = rmass[ineg];
else sbuf[1] = mass[type[ineg]];
vcm = (sbuf[1]*sbuf[0] + rbuf[1]*rbuf[0]) / (sbuf[1] + rbuf[1]);
v[ineg][vdim] = 2.0 * vcm - sbuf[0];
v[ipos][vdim] = 2.0 * vcm - rbuf[0];
pswap += rbuf[1] * (vcm - rbuf[0]) - sbuf[1] * (vcm - sbuf[0]);
} else if (me == all[0].proc) {
ipos = pos_index[ipositive++];
sbuf[0] = v[ipos][vdim];
if (rmass) sbuf[1] = rmass[ipos];
else sbuf[1] = mass[type[ipos]];
MPI_Sendrecv(sbuf,2,MPI_DOUBLE,all[1].proc,0,
rbuf,2,MPI_DOUBLE,all[1].proc,0,world,&status);
vcm = (sbuf[1]*sbuf[0] + rbuf[1]*rbuf[0]) / (sbuf[1] + rbuf[1]);
v[ipos][vdim] = 2.0 * vcm - sbuf[0];
pswap += sbuf[1] * (vcm - sbuf[0]);
} else if (me == all[1].proc) {
ineg = neg_index[inegative++];
sbuf[0] = v[ineg][vdim];
if (rmass) sbuf[1] = rmass[ineg];
else sbuf[1] = mass[type[ineg]];
MPI_Sendrecv(sbuf,2,MPI_DOUBLE,all[0].proc,0,
rbuf,2,MPI_DOUBLE,all[0].proc,0,world,&status);
vcm = (sbuf[1]*sbuf[0] + rbuf[1]*rbuf[0]) / (sbuf[1] + rbuf[1]);
v[ineg][vdim] = 2.0 * vcm - sbuf[0];
pswap -= sbuf[1] * (vcm - sbuf[0]);
}
}
// tally momentum exchange from all swaps
double pswap_all;
MPI_Allreduce(&pswap,&pswap_all,1,MPI_DOUBLE,MPI_SUM,world);
p_exchange += pswap_all;
}
/* ---------------------------------------------------------------------- */
double FixViscosity::compute_scalar()
{
return p_exchange;
}
diff --git a/src/fix_viscous.cpp b/src/fix_viscous.cpp
index 770eee559..5345268bb 100644
--- a/src/fix_viscous.cpp
+++ b/src/fix_viscous.cpp
@@ -1,136 +1,136 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_viscous.h"
#include "atom.h"
#include "update.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixViscous::FixViscous(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix viscous command");
+ if (narg < 4) error->all(FLERR,"Illegal fix viscous command");
double gamma_one = atof(arg[3]);
gamma = new double[atom->ntypes+1];
for (int i = 1; i <= atom->ntypes; i++) gamma[i] = gamma_one;
// optional args
int iarg = 4;
while (iarg < narg) {
if (strcmp(arg[iarg],"scale") == 0) {
- if (iarg+3 > narg) error->all("Illegal fix viscous command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal fix viscous command");
int itype = atoi(arg[iarg+1]);
double scale = atof(arg[iarg+2]);
if (itype <= 0 || itype > atom->ntypes)
- error->all("Illegal fix viscous command");
+ error->all(FLERR,"Illegal fix viscous command");
gamma[itype] = gamma_one * scale;
iarg += 3;
- } else error->all("Illegal fix viscous command");
+ } else error->all(FLERR,"Illegal fix viscous command");
}
}
/* ---------------------------------------------------------------------- */
FixViscous::~FixViscous()
{
delete [] gamma;
}
/* ---------------------------------------------------------------------- */
int FixViscous::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixViscous::init()
{
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixViscous::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixViscous::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixViscous::post_force(int vflag)
{
// apply drag force to atoms in group
// direction is opposed to velocity vector
// magnitude depends on atom type
double **v = atom->v;
double **f = atom->f;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double drag;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
drag = gamma[type[i]];
f[i][0] -= drag*v[i][0];
f[i][1] -= drag*v[i][1];
f[i][2] -= drag*v[i][2];
}
}
/* ---------------------------------------------------------------------- */
void FixViscous::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixViscous::min_post_force(int vflag)
{
post_force(vflag);
}
diff --git a/src/fix_wall.cpp b/src/fix_wall.cpp
index fdff4a11f..3cc68017c 100644
--- a/src/fix_wall.cpp
+++ b/src/fix_wall.cpp
@@ -1,288 +1,288 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_wall.h"
#include "atom.h"
#include "input.h"
#include "variable.h"
#include "domain.h"
#include "lattice.h"
#include "update.h"
#include "modify.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{XLO,XHI,YLO,YHI,ZLO,ZHI};
enum{NONE,EDGE,CONSTANT,VARIABLE};
/* ---------------------------------------------------------------------- */
FixWall::FixWall(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
scalar_flag = 1;
vector_flag = 1;
global_freq = 1;
extscalar = 1;
extvector = 1;
// parse args
nwall = 0;
int scaleflag = 1;
int iarg = 3;
while (iarg < narg) {
if ((strcmp(arg[iarg],"xlo") == 0) || (strcmp(arg[iarg],"xhi") == 0) ||
(strcmp(arg[iarg],"ylo") == 0) || (strcmp(arg[iarg],"yhi") == 0) ||
(strcmp(arg[iarg],"zlo") == 0) || (strcmp(arg[iarg],"zhi") == 0)) {
- if (iarg+5 > narg) error->all("Illegal fix wall command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal fix wall command");
int newwall;
if (strcmp(arg[iarg],"xlo") == 0) newwall = XLO;
else if (strcmp(arg[iarg],"xhi") == 0) newwall = XHI;
else if (strcmp(arg[iarg],"ylo") == 0) newwall = YLO;
else if (strcmp(arg[iarg],"yhi") == 0) newwall = YHI;
else if (strcmp(arg[iarg],"zlo") == 0) newwall = ZLO;
else if (strcmp(arg[iarg],"zhi") == 0) newwall = ZHI;
for (int m = 0; m < nwall; m++)
if (newwall == wallwhich[m])
- error->all("Wall defined twice in fix wall command");
+ error->all(FLERR,"Wall defined twice in fix wall command");
wallwhich[nwall] = newwall;
if (strcmp(arg[iarg+1],"EDGE") == 0) {
wallstyle[nwall] = EDGE;
int dim = wallwhich[nwall] / 2;
int side = wallwhich[nwall] % 2;
if (side == 0) coord0[nwall] = domain->boxlo[dim];
else coord0[nwall] = domain->boxhi[dim];
} else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
wallstyle[nwall] = VARIABLE;
int n = strlen(&arg[iarg+1][2]) + 1;
varstr[nwall] = new char[n];
strcpy(varstr[nwall],&arg[iarg+1][2]);
} else {
wallstyle[nwall] = CONSTANT;
coord0[nwall] = atof(arg[iarg+1]);
}
epsilon[nwall] = atof(arg[iarg+2]);
sigma[nwall] = atof(arg[iarg+3]);
cutoff[nwall] = atof(arg[iarg+4]);
nwall++;
iarg += 5;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal fix wall command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix wall command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix wall command");
+ else error->all(FLERR,"Illegal fix wall command");
iarg += 2;
- } else error->all("Illegal fix wall command");
+ } else error->all(FLERR,"Illegal fix wall command");
}
size_vector = nwall;
// error check
- if (nwall == 0) error->all("Illegal fix wall command");
+ if (nwall == 0) error->all(FLERR,"Illegal fix wall command");
for (int m = 0; m < nwall; m++)
if (cutoff[m] <= 0.0)
- error->all("Fix wall cutoff <= 0.0");
+ error->all(FLERR,"Fix wall cutoff <= 0.0");
for (int m = 0; m < nwall; m++) {
if ((wallwhich[m] == XLO || wallwhich[m] == XHI) && domain->xperiodic)
- error->all("Cannot use fix wall in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall in periodic dimension");
if ((wallwhich[m] == YLO || wallwhich[m] == YHI) && domain->yperiodic)
- error->all("Cannot use fix wall in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall in periodic dimension");
if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->zperiodic)
- error->all("Cannot use fix wall in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall in periodic dimension");
}
for (int m = 0; m < nwall; m++)
if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->dimension == 2)
- error->all("Cannot use fix wall zlo/zhi for a 2d simulation");
+ error->all(FLERR,"Cannot use fix wall zlo/zhi for a 2d simulation");
// scale coord for CONSTANT walls
int flag = 0;
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == CONSTANT) flag = 1;
if (flag) {
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix wall with undefined lattice");
+ error->all(FLERR,"Use of fix wall with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
double scale;
for (int m = 0; m < nwall; m++) {
if (wallwhich[m] < YLO) scale = xscale;
else if (wallwhich[m] < ZLO) scale = yscale;
else scale = zscale;
if (wallstyle[m] == CONSTANT) coord0[m] *= scale;
}
}
// set time_depend and varflag if any wall positions are variable
varflag = 0;
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == VARIABLE) time_depend = varflag = 1;
eflag = 0;
for (int m = 0; m <= nwall; m++) ewall[m] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixWall::~FixWall()
{
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == VARIABLE) delete [] varstr[m];
}
/* ---------------------------------------------------------------------- */
int FixWall::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixWall::init()
{
dt = update->dt;
for (int m = 0; m < nwall; m++) {
if (wallstyle[m] != VARIABLE) continue;
varindex[m] = input->variable->find(varstr[m]);
if (varindex[m] < 0)
- error->all("Variable name for fix wall does not exist");
+ error->all(FLERR,"Variable name for fix wall does not exist");
if (!input->variable->equalstyle(varindex[m]))
- error->all("Variable for fix wall is invalid style");
+ error->all(FLERR,"Variable for fix wall is invalid style");
}
// setup coefficients
for (int m = 0; m < nwall; m++) precompute(m);
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixWall::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixWall::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixWall::post_force(int vflag)
{
eflag = 0;
for (int m = 0; m <= nwall; m++) ewall[m] = 0.0;
// coord = current position of wall
// evaluate variable if necessary, wrap with clear/add
if (varflag) modify->clearstep_compute();
double coord;
for (int m = 0; m < nwall; m++) {
if (wallstyle[m] == VARIABLE)
coord = input->variable->compute_equal(varindex[m]);
else coord = coord0[m];
wall_particle(m,wallwhich[m],coord);
}
if (varflag) modify->addstep_compute(update->ntimestep + 1);
}
/* ---------------------------------------------------------------------- */
void FixWall::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixWall::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
energy of wall interaction
------------------------------------------------------------------------- */
double FixWall::compute_scalar()
{
// only sum across procs one time
if (eflag == 0) {
MPI_Allreduce(ewall,ewall_all,nwall+1,MPI_DOUBLE,MPI_SUM,world);
eflag = 1;
}
return ewall_all[0];
}
/* ----------------------------------------------------------------------
components of force on wall
------------------------------------------------------------------------- */
double FixWall::compute_vector(int n)
{
// only sum across procs one time
if (eflag == 0) {
MPI_Allreduce(ewall,ewall_all,nwall+1,MPI_DOUBLE,MPI_SUM,world);
eflag = 1;
}
return ewall_all[n+1];
}
diff --git a/src/fix_wall_harmonic.cpp b/src/fix_wall_harmonic.cpp
index 4d0660a0f..e7eb85b54 100644
--- a/src/fix_wall_harmonic.cpp
+++ b/src/fix_wall_harmonic.cpp
@@ -1,65 +1,65 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "fix_wall_harmonic.h"
#include "atom.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixWallHarmonic::FixWallHarmonic(LAMMPS *lmp, int narg, char **arg) :
FixWall(lmp, narg, arg) {}
/* ----------------------------------------------------------------------
interaction of all particles in group with a wall
m = index of wall coeffs
which = xlo,xhi,ylo,yhi,zlo,zhi
error if any particle is on or behind wall
------------------------------------------------------------------------- */
void FixWallHarmonic::wall_particle(int m, int which, double coord)
{
double delta,dr,fwall;
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int dim = which / 2;
int side = which % 2;
if (side == 0) side = -1;
int onflag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (side < 0) delta = x[i][dim] - coord;
else delta = coord - x[i][dim];
if (delta >= cutoff[m]) continue;
if (delta <= 0.0) {
onflag = 1;
continue;
}
dr = cutoff[m]-delta;
fwall = side * 2.0*epsilon[m]*dr;
f[i][dim] -= fwall;
ewall[0] += epsilon[m]*dr*dr;
ewall[m+1] += fwall;
}
- if (onflag) error->one("Particle on or inside fix wall surface");
+ if (onflag) error->one(FLERR,"Particle on or inside fix wall surface");
}
diff --git a/src/fix_wall_lj126.cpp b/src/fix_wall_lj126.cpp
index 132cea9c0..47b0eba6f 100644
--- a/src/fix_wall_lj126.cpp
+++ b/src/fix_wall_lj126.cpp
@@ -1,81 +1,81 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "fix_wall_lj126.h"
#include "atom.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixWallLJ126::FixWallLJ126(LAMMPS *lmp, int narg, char **arg) :
FixWall(lmp, narg, arg) {}
/* ---------------------------------------------------------------------- */
void FixWallLJ126::precompute(int m)
{
coeff1[m] = 48.0 * epsilon[m] * pow(sigma[m],12.0);
coeff2[m] = 24.0 * epsilon[m] * pow(sigma[m],6.0);
coeff3[m] = 4.0 * epsilon[m] * pow(sigma[m],12.0);
coeff4[m] = 4.0 * epsilon[m] * pow(sigma[m],6.0);
double r2inv = 1.0/(cutoff[m]*cutoff[m]);
double r6inv = r2inv*r2inv*r2inv;
offset[m] = r6inv*(coeff3[m]*r6inv - coeff4[m]);
}
/* ----------------------------------------------------------------------
interaction of all particles in group with a wall
m = index of wall coeffs
which = xlo,xhi,ylo,yhi,zlo,zhi
error if any particle is on or behind wall
------------------------------------------------------------------------- */
void FixWallLJ126::wall_particle(int m, int which, double coord)
{
double delta,rinv,r2inv,r6inv,fwall;
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int dim = which / 2;
int side = which % 2;
if (side == 0) side = -1;
int onflag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (side < 0) delta = x[i][dim] - coord;
else delta = coord - x[i][dim];
if (delta >= cutoff[m]) continue;
if (delta <= 0.0) {
onflag = 1;
continue;
}
rinv = 1.0/delta;
r2inv = rinv*rinv;
r6inv = r2inv*r2inv*r2inv;
fwall = side * r6inv*(coeff1[m]*r6inv - coeff2[m]) * rinv;
f[i][dim] -= fwall;
ewall[0] += r6inv*(coeff3[m]*r6inv - coeff4[m]) - offset[m];
ewall[m+1] += fwall;
}
- if (onflag) error->one("Particle on or inside fix wall surface");
+ if (onflag) error->one(FLERR,"Particle on or inside fix wall surface");
}
diff --git a/src/fix_wall_lj93.cpp b/src/fix_wall_lj93.cpp
index e106ec5e6..0f8f9dff1 100644
--- a/src/fix_wall_lj93.cpp
+++ b/src/fix_wall_lj93.cpp
@@ -1,84 +1,84 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "fix_wall_lj93.h"
#include "atom.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
FixWallLJ93::FixWallLJ93(LAMMPS *lmp, int narg, char **arg) :
FixWall(lmp, narg, arg) {}
/* ---------------------------------------------------------------------- */
void FixWallLJ93::precompute(int m)
{
coeff1[m] = 6.0/5.0 * epsilon[m] * pow(sigma[m],9.0);
coeff2[m] = 3.0 * epsilon[m] * pow(sigma[m],3.0);
coeff3[m] = 2.0/15.0 * epsilon[m] * pow(sigma[m],9.0);
coeff4[m] = epsilon[m] * pow(sigma[m],3.0);
double rinv = 1.0/cutoff[m];
double r2inv = rinv*rinv;
double r4inv = r2inv*r2inv;
offset[m] = coeff3[m]*r4inv*r4inv*rinv - coeff4[m]*r2inv*rinv;
}
/* ----------------------------------------------------------------------
interaction of all particles in group with a wall
m = index of wall coeffs
which = xlo,xhi,ylo,yhi,zlo,zhi
error if any particle is on or behind wall
------------------------------------------------------------------------- */
void FixWallLJ93::wall_particle(int m, int which, double coord)
{
double delta,rinv,r2inv,r4inv,r10inv,fwall;
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int dim = which / 2;
int side = which % 2;
if (side == 0) side = -1;
int onflag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (side < 0) delta = x[i][dim] - coord;
else delta = coord - x[i][dim];
if (delta >= cutoff[m]) continue;
if (delta <= 0.0) {
onflag = 1;
continue;
}
rinv = 1.0/delta;
r2inv = rinv*rinv;
r4inv = r2inv*r2inv;
r10inv = r4inv*r4inv*r2inv;
fwall = side * (coeff1[m]*r10inv - coeff2[m]*r4inv);
f[i][dim] -= fwall;
ewall[0] += coeff3[m]*r4inv*r4inv*rinv -
coeff4[m]*r2inv*rinv - offset[m];
ewall[m+1] += fwall;
}
- if (onflag) error->one("Particle on or inside fix wall surface");
+ if (onflag) error->one(FLERR,"Particle on or inside fix wall surface");
}
diff --git a/src/fix_wall_reflect.cpp b/src/fix_wall_reflect.cpp
index fa74faf48..2251fd266 100644
--- a/src/fix_wall_reflect.cpp
+++ b/src/fix_wall_reflect.cpp
@@ -1,225 +1,225 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "fix_wall_reflect.h"
#include "atom.h"
#include "comm.h"
#include "update.h"
#include "modify.h"
#include "domain.h"
#include "lattice.h"
#include "input.h"
#include "variable.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{XLO,XHI,YLO,YHI,ZLO,ZHI};
enum{NONE,EDGE,CONSTANT,VARIABLE};
/* ---------------------------------------------------------------------- */
FixWallReflect::FixWallReflect(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg < 4) error->all("Illegal fix wall/reflect command");
+ if (narg < 4) error->all(FLERR,"Illegal fix wall/reflect command");
// parse args
nwall = 0;
int scaleflag = 1;
int iarg = 3;
while (iarg < narg) {
if ((strcmp(arg[iarg],"xlo") == 0) || (strcmp(arg[iarg],"xhi") == 0) ||
(strcmp(arg[iarg],"ylo") == 0) || (strcmp(arg[iarg],"yhi") == 0) ||
(strcmp(arg[iarg],"zlo") == 0) || (strcmp(arg[iarg],"zhi") == 0)) {
- if (iarg+2 > narg) error->all("Illegal fix wall/reflect command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal fix wall/reflect command");
int newwall;
if (strcmp(arg[iarg],"xlo") == 0) newwall = XLO;
else if (strcmp(arg[iarg],"xhi") == 0) newwall = XHI;
else if (strcmp(arg[iarg],"ylo") == 0) newwall = YLO;
else if (strcmp(arg[iarg],"yhi") == 0) newwall = YHI;
else if (strcmp(arg[iarg],"zlo") == 0) newwall = ZLO;
else if (strcmp(arg[iarg],"zhi") == 0) newwall = ZHI;
for (int m = 0; m < nwall; m++)
if (newwall == wallwhich[m])
- error->all("Wall defined twice in fix wall/reflect command");
+ error->all(FLERR,"Wall defined twice in fix wall/reflect command");
wallwhich[nwall] = newwall;
if (strcmp(arg[iarg+1],"EDGE") == 0) {
wallstyle[nwall] = EDGE;
int dim = wallwhich[nwall] / 2;
int side = wallwhich[nwall] % 2;
if (side == 0) coord0[nwall] = domain->boxlo[dim];
else coord0[nwall] = domain->boxhi[dim];
} else if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
wallstyle[nwall] = VARIABLE;
int n = strlen(&arg[iarg+1][2]) + 1;
varstr[nwall] = new char[n];
strcpy(varstr[nwall],&arg[iarg+1][2]);
} else {
wallstyle[nwall] = CONSTANT;
coord0[nwall] = atof(arg[iarg+1]);
}
nwall++;
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal wall/reflect command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal wall/reflect command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal fix wall/reflect command");
+ else error->all(FLERR,"Illegal fix wall/reflect command");
iarg += 2;
- } else error->all("Illegal fix wall/reflect command");
+ } else error->all(FLERR,"Illegal fix wall/reflect command");
}
// error check
- if (nwall == 0) error->all("Illegal fix wall command");
+ if (nwall == 0) error->all(FLERR,"Illegal fix wall command");
for (int m = 0; m < nwall; m++) {
if ((wallwhich[m] == XLO || wallwhich[m] == XHI) && domain->xperiodic)
- error->all("Cannot use fix wall/reflect in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall/reflect in periodic dimension");
if ((wallwhich[m] == YLO || wallwhich[m] == YHI) && domain->yperiodic)
- error->all("Cannot use fix wall/reflect in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall/reflect in periodic dimension");
if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->zperiodic)
- error->all("Cannot use fix wall/reflect in periodic dimension");
+ error->all(FLERR,"Cannot use fix wall/reflect in periodic dimension");
}
for (int m = 0; m < nwall; m++)
if ((wallwhich[m] == ZLO || wallwhich[m] == ZHI) && domain->dimension == 2)
- error->all("Cannot use fix wall/reflect zlo/zhi for a 2d simulation");
+ error->all(FLERR,"Cannot use fix wall/reflect zlo/zhi for a 2d simulation");
// scale coord for CONSTANT walls
int flag = 0;
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == CONSTANT) flag = 1;
if (flag) {
if (scaleflag && domain->lattice == NULL)
- error->all("Use of fix wall with undefined lattice");
+ error->all(FLERR,"Use of fix wall with undefined lattice");
double xscale,yscale,zscale;
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
double scale;
for (int m = 0; m < nwall; m++) {
if (wallwhich[m] < YLO) scale = xscale;
else if (wallwhich[m] < ZLO) scale = yscale;
else scale = zscale;
if (wallstyle[m] == CONSTANT) coord0[m] *= scale;
}
}
// set time_depend and varflag if any wall positions are variable
varflag = 0;
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == VARIABLE) time_depend = varflag = 1;
}
/* ---------------------------------------------------------------------- */
FixWallReflect::~FixWallReflect()
{
for (int m = 0; m < nwall; m++)
if (wallstyle[m] == VARIABLE) delete [] varstr[m];
}
/* ---------------------------------------------------------------------- */
int FixWallReflect::setmask()
{
int mask = 0;
mask |= POST_INTEGRATE;
mask |= POST_INTEGRATE_RESPA;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixWallReflect::init()
{
for (int m = 0; m < nwall; m++) {
if (wallstyle[m] != VARIABLE) continue;
varindex[m] = input->variable->find(varstr[m]);
if (varindex[m] < 0)
- error->all("Variable name for fix wall/reflect does not exist");
+ error->all(FLERR,"Variable name for fix wall/reflect does not exist");
if (!input->variable->equalstyle(varindex[m]))
- error->all("Variable for fix wall/reflect is invalid style");
+ error->all(FLERR,"Variable for fix wall/reflect is invalid style");
}
int nrigid = 0;
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->rigid_flag) nrigid++;
if (nrigid && comm->me == 0)
- error->warning("Should not allow rigid bodies to bounce off "
+ error->warning(FLERR,"Should not allow rigid bodies to bounce off "
"relecting walls");
}
/* ---------------------------------------------------------------------- */
void FixWallReflect::post_integrate()
{
int i,dim,side;
double coord;
// coord = current position of wall
// evaluate variable if necessary, wrap with clear/add
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (varflag) modify->clearstep_compute();
for (int m = 0; m < nwall; m++) {
if (wallstyle[m] == VARIABLE)
coord = input->variable->compute_equal(varindex[m]);
else coord = coord0[m];
dim = wallwhich[m] / 2;
side = wallwhich[m] % 2;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (side == 0) {
if (x[i][dim] < coord) {
x[i][dim] = coord + (coord - x[i][dim]);
v[i][dim] = -v[i][dim];
}
} else {
if (x[i][dim] > coord) {
x[i][dim] = coord - (x[i][dim] - coord);
v[i][dim] = -v[i][dim];
}
}
}
}
if (varflag) modify->addstep_compute(update->ntimestep + 1);
}
diff --git a/src/fix_wall_region.cpp b/src/fix_wall_region.cpp
index c3e77cb5f..151e20259 100644
--- a/src/fix_wall_region.cpp
+++ b/src/fix_wall_region.cpp
@@ -1,357 +1,357 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "fix_wall_region.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "region.h"
#include "lattice.h"
#include "update.h"
#include "output.h"
#include "respa.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{LJ93,LJ126,COLLOID,HARMONIC};
/* ---------------------------------------------------------------------- */
FixWallRegion::FixWallRegion(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
- if (narg != 8) error->all("Illegal fix wall/region command");
+ if (narg != 8) error->all(FLERR,"Illegal fix wall/region command");
scalar_flag = 1;
vector_flag = 1;
size_vector = 3;
global_freq = 1;
extscalar = 1;
extvector = 1;
// parse args
iregion = domain->find_region(arg[3]);
if (iregion == -1)
- error->all("Region ID for fix wall/region does not exist");
+ error->all(FLERR,"Region ID for fix wall/region does not exist");
int n = strlen(arg[3]) + 1;
idregion = new char[n];
strcpy(idregion,arg[3]);
if (strcmp(arg[4],"lj93") == 0) style = LJ93;
else if (strcmp(arg[4],"lj126") == 0) style = LJ126;
else if (strcmp(arg[4],"colloid") == 0) style = COLLOID;
else if (strcmp(arg[4],"harmonic") == 0) style = HARMONIC;
- else error->all("Illegal fix wall/region command");
+ else error->all(FLERR,"Illegal fix wall/region command");
epsilon = atof(arg[5]);
sigma = atof(arg[6]);
cutoff = atof(arg[7]);
- if (cutoff <= 0.0) error->all("Fix wall/region cutoff <= 0.0");
+ if (cutoff <= 0.0) error->all(FLERR,"Fix wall/region cutoff <= 0.0");
eflag = 0;
ewall[0] = ewall[1] = ewall[2] = ewall[3] = 0.0;
}
/* ---------------------------------------------------------------------- */
FixWallRegion::~FixWallRegion()
{
delete [] idregion;
}
/* ---------------------------------------------------------------------- */
int FixWallRegion::setmask()
{
int mask = 0;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixWallRegion::init()
{
// set index and check validity of region
iregion = domain->find_region(idregion);
if (iregion == -1)
- error->all("Region ID for fix wall/region does not exist");
+ error->all(FLERR,"Region ID for fix wall/region does not exist");
// error checks for style COLLOID
// insure all particles in group are extended particles
if (style == COLLOID) {
if (!atom->sphere_flag)
- error->all("Fix wall/region colloid requires atom style sphere");
+ error->all(FLERR,"Fix wall/region colloid requires atom style sphere");
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int flag = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
if (radius[i] == 0.0) flag = 1;
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
if (flagall)
- error->all("Fix wall/region colloid requires extended particles");
+ error->all(FLERR,"Fix wall/region colloid requires extended particles");
}
// setup coefficients for each style
if (style == LJ93) {
coeff1 = 6.0/5.0 * epsilon * pow(sigma,9.0);
coeff2 = 3.0 * epsilon * pow(sigma,3.0);
coeff3 = 2.0/15.0 * epsilon * pow(sigma,9.0);
coeff4 = epsilon * pow(sigma,3.0);
double rinv = 1.0/cutoff;
double r2inv = rinv*rinv;
double r4inv = r2inv*r2inv;
offset = coeff3*r4inv*r4inv*rinv - coeff4*r2inv*rinv;
} else if (style == LJ126) {
coeff1 = 48.0 * epsilon * pow(sigma,12.0);
coeff2 = 24.0 * epsilon * pow(sigma,6.0);
coeff3 = 4.0 * epsilon * pow(sigma,12.0);
coeff4 = 4.0 * epsilon * pow(sigma,6.0);
double r2inv = 1.0/(cutoff*cutoff);
double r6inv = r2inv*r2inv*r2inv;
offset = r6inv*(coeff3*r6inv - coeff4);
} else if (style == COLLOID) {
coeff1 = -4.0/315.0 * epsilon * pow(sigma,6.0);
coeff2 = -2.0/3.0 * epsilon;
coeff3 = epsilon * pow(sigma,6.0)/7560.0;
coeff4 = epsilon/6.0;
double rinv = 1.0/cutoff;
double r2inv = rinv*rinv;
double r4inv = r2inv*r2inv;
offset = coeff3*r4inv*r4inv*rinv - coeff4*r2inv*rinv;
}
if (strstr(update->integrate_style,"respa"))
nlevels_respa = ((Respa *) update->integrate)->nlevels;
}
/* ---------------------------------------------------------------------- */
void FixWallRegion::setup(int vflag)
{
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* ---------------------------------------------------------------------- */
void FixWallRegion::min_setup(int vflag)
{
post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixWallRegion::post_force(int vflag)
{
int i,m,n;
double rinv,fx,fy,fz,tooclose;
eflag = 0;
ewall[0] = ewall[1] = ewall[2] = ewall[3] = 0.0;
double **x = atom->x;
double **f = atom->f;
double *radius = atom->radius;
int *mask = atom->mask;
int nlocal = atom->nlocal;
Region *region = domain->regions[iregion];
int onflag = 0;
// region->match() insures particle is in region or on surface, else error
// if returned contact dist r = 0, is on surface, also an error
// in COLLOID case, r <= radius is an error
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (!region->match(x[i][0],x[i][1],x[i][2])) {
onflag = 1;
continue;
}
if (style == COLLOID) tooclose = radius[i];
else tooclose = 0.0;
n = region->surface(x[i][0],x[i][1],x[i][2],cutoff);
for (m = 0; m < n; m++) {
if (region->contact[m].r <= tooclose) {
onflag = 1;
continue;
} else rinv = 1.0/region->contact[m].r;
if (style == LJ93) lj93(region->contact[m].r);
else if (style == LJ126) lj126(region->contact[m].r);
else if (style == COLLOID) colloid(region->contact[m].r,radius[i]);
else harmonic(region->contact[m].r);
ewall[0] += eng;
fx = fwall * region->contact[m].delx * rinv;
fy = fwall * region->contact[m].dely * rinv;
fz = fwall * region->contact[m].delz * rinv;
f[i][0] += fx;
f[i][1] += fy;
f[i][2] += fz;
ewall[1] -= fx;
ewall[2] -= fy;
ewall[3] -= fz;
}
}
- if (onflag) error->one("Particle on or inside surface of region "
+ if (onflag) error->one(FLERR,"Particle on or inside surface of region "
"used in fix wall/region");
}
/* ---------------------------------------------------------------------- */
void FixWallRegion::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixWallRegion::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
energy of wall interaction
------------------------------------------------------------------------- */
double FixWallRegion::compute_scalar()
{
// only sum across procs one time
if (eflag == 0) {
MPI_Allreduce(ewall,ewall_all,4,MPI_DOUBLE,MPI_SUM,world);
eflag = 1;
}
return ewall_all[0];
}
/* ----------------------------------------------------------------------
components of force on wall
------------------------------------------------------------------------- */
double FixWallRegion::compute_vector(int n)
{
// only sum across procs one time
if (eflag == 0) {
MPI_Allreduce(ewall,ewall_all,4,MPI_DOUBLE,MPI_SUM,world);
eflag = 1;
}
return ewall_all[n+1];
}
/* ----------------------------------------------------------------------
LJ 9/3 interaction for particle with wall
compute eng and fwall = magnitude of wall force
------------------------------------------------------------------------- */
void FixWallRegion::lj93(double r)
{
double rinv = 1.0/r;
double r2inv = rinv*rinv;
double r4inv = r2inv*r2inv;
double r10inv = r4inv*r4inv*r2inv;
fwall = coeff1*r10inv - coeff2*r4inv;
eng = coeff3*r4inv*r4inv*rinv - coeff4*r2inv*rinv - offset;
}
/* ----------------------------------------------------------------------
LJ 12/6 interaction for particle with wall
compute eng and fwall = magnitude of wall force
------------------------------------------------------------------------- */
void FixWallRegion::lj126(double r)
{
double rinv = 1.0/r;
double r2inv = rinv*rinv;
double r6inv = r2inv*r2inv*r2inv;
fwall = r6inv*(coeff1*r6inv - coeff2) * rinv;
eng = r6inv*(coeff3*r6inv - coeff4) - offset;
}
/* ----------------------------------------------------------------------
colloid interaction for finite-size particle of rad with wall
compute eng and fwall = magnitude of wall force
------------------------------------------------------------------------- */
void FixWallRegion::colloid(double r, double rad)
{
double new_coeff2 = coeff2*rad*rad*rad;
double diam = 2.0*rad;
double rad2 = rad*rad;
double rad4 = rad2*rad2;
double rad8 = rad4*rad4;
double delta2 = rad2 - r*r;
double rinv = 1.0/delta2;
double r2inv = rinv*rinv;
double r4inv = r2inv*r2inv;
double r8inv = r4inv*r4inv;
fwall = coeff1*(rad8*rad + 27.0*rad4*rad2*rad*pow(r,2.0)
+ 63.0*rad4*rad*pow(r,4.0)
+ 21.0*rad2*rad*pow(r,6.0))*r8inv - new_coeff2*r2inv;
double r2 = 0.5*diam - r;
double rinv2 = 1.0/r2;
double r2inv2 = rinv2*rinv2;
double r4inv2 = r2inv2*r2inv2;
double r3 = r + 0.5*diam;
double rinv3 = 1.0/r3;
double r2inv3 = rinv3*rinv3;
double r4inv3 = r2inv3*r2inv3;
eng = coeff3*((-3.5*diam+r)*r4inv2*r2inv2*rinv2
+ (3.5*diam+r)*r4inv3*r2inv3*rinv3) -
coeff4*((-diam*r+r2*r3*(log(-r2)-log(r3)))*
(-rinv2)*rinv3) - offset;
}
/* ----------------------------------------------------------------------
harmonic interaction for particle with wall
compute eng and fwall = magnitude of wall force
------------------------------------------------------------------------- */
void FixWallRegion::harmonic(double r)
{
double dr = cutoff - r;
fwall = 2.0*epsilon*dr;
eng = epsilon*dr*dr;
}
diff --git a/src/force.cpp b/src/force.cpp
index 2282b9a67..71511fc78 100644
--- a/src/force.cpp
+++ b/src/force.cpp
@@ -1,565 +1,562 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "force.h"
#include "style_bond.h"
#include "style_angle.h"
#include "style_dihedral.h"
#include "style_improper.h"
#include "style_pair.h"
#include "style_kspace.h"
#include "atom.h"
#include "comm.h"
#include "pair.h"
#include "pair_hybrid.h"
#include "bond.h"
#include "bond_hybrid.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "group.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
Force::Force(LAMMPS *lmp) : Pointers(lmp)
{
newton = newton_pair = newton_bond = 1;
special_lj[0] = special_coul[0] = 1.0;
special_lj[1] = special_lj[2] = special_lj[3] = 0.0;
special_coul[1] = special_coul[2] = special_coul[3] = 0.0;
special_angle = special_dihedral = 0;
special_extra = 0;
dielectric = 1.0;
pair = NULL;
bond = NULL;
angle = NULL;
dihedral = NULL;
improper = NULL;
kspace = NULL;
char *str = (char *) "none";
int n = strlen(str) + 1;
pair_style = new char[n];
strcpy(pair_style,str);
bond_style = new char[n];
strcpy(bond_style,str);
angle_style = new char[n];
strcpy(angle_style,str);
dihedral_style = new char[n];
strcpy(dihedral_style,str);
improper_style = new char[n];
strcpy(improper_style,str);
kspace_style = new char[n];
strcpy(kspace_style,str);
}
/* ---------------------------------------------------------------------- */
Force::~Force()
{
delete [] pair_style;
delete [] bond_style;
delete [] angle_style;
delete [] dihedral_style;
delete [] improper_style;
delete [] kspace_style;
if (pair) delete pair;
if (bond) delete bond;
if (angle) delete angle;
if (dihedral) delete dihedral;
if (improper) delete improper;
if (kspace) delete kspace;
}
/* ---------------------------------------------------------------------- */
void Force::init()
{
qqrd2e = qqr2e/dielectric;
if (kspace) kspace->init(); // kspace must come before pair
if (pair) pair->init(); // so g_ewald is defined
if (bond) bond->init();
if (angle) angle->init();
if (dihedral) dihedral->init();
if (improper) improper->init();
}
/* ----------------------------------------------------------------------
create a pair style, called from input script or restart file
------------------------------------------------------------------------- */
void Force::create_pair(const char *style, char *suffix)
{
delete [] pair_style;
if (pair) delete pair;
int sflag;
pair = new_pair(style,suffix,sflag);
if (sflag) {
char estyle[256];
sprintf(estyle,"%s/%s",style,suffix);
int n = strlen(estyle) + 1;
pair_style = new char[n];
strcpy(pair_style,estyle);
} else {
int n = strlen(style) + 1;
pair_style = new char[n];
strcpy(pair_style,style);
}
}
/* ----------------------------------------------------------------------
generate a pair class, first with suffix appended
------------------------------------------------------------------------- */
Pair *Force::new_pair(const char *style, char *suffix, int &sflag)
{
if (suffix && lmp->suffix_enable) {
sflag = 1;
char estyle[256];
sprintf(estyle,"%s/%s",style,suffix);
if (0) return NULL;
#define PAIR_CLASS
#define PairStyle(key,Class) \
else if (strcmp(estyle,#key) == 0) return new Class(lmp);
#include "style_pair.h"
#undef PairStyle
#undef PAIR_CLASS
}
sflag = 0;
if (strcmp(style,"none") == 0) return NULL;
#define PAIR_CLASS
#define PairStyle(key,Class) \
else if (strcmp(style,#key) == 0) return new Class(lmp);
#include "style_pair.h"
#undef PAIR_CLASS
- else error->all("Invalid pair style");
+ else error->all(FLERR,"Invalid pair style");
return NULL;
}
/* ----------------------------------------------------------------------
return ptr to Pair class if matches word or to matching hybrid sub-class
if exact, then style name must be exact match to word
if not exact, style name must contain word
return NULL if no match
return NULL if not exact and multiple hybrid sub-styles match
------------------------------------------------------------------------- */
Pair *Force::pair_match(const char *word, int exact)
{
int iwhich,count;
if (exact && strcmp(pair_style,word) == 0) return pair;
else if (!exact && strstr(pair_style,word)) return pair;
else if (strcmp(pair_style,"hybrid") == 0) {
PairHybrid *hybrid = (PairHybrid *) pair;
count = 0;
for (int i = 0; i < hybrid->nstyles; i++) {
if (exact && strcmp(hybrid->keywords[i],word) == 0)
return hybrid->styles[i];
if (!exact && strstr(hybrid->keywords[i],word)) {
iwhich = i;
count++;
}
}
if (!exact && count == 1) return hybrid->styles[iwhich];
} else if (strcmp(pair_style,"hybrid/overlay") == 0) {
PairHybridOverlay *hybrid = (PairHybridOverlay *) pair;
count = 0;
for (int i = 0; i < hybrid->nstyles; i++) {
if (exact && strcmp(hybrid->keywords[i],word) == 0)
return hybrid->styles[i];
else if (!exact && strstr(hybrid->keywords[i],word)) {
iwhich = i;
count++;
}
}
if (!exact && count == 1) return hybrid->styles[iwhich];
}
return NULL;
}
/* ----------------------------------------------------------------------
create a bond style, called from input script or restart file
------------------------------------------------------------------------- */
void Force::create_bond(const char *style)
{
delete [] bond_style;
if (bond) delete bond;
bond = new_bond(style);
int n = strlen(style) + 1;
bond_style = new char[n];
strcpy(bond_style,style);
}
/* ----------------------------------------------------------------------
generate a bond class
------------------------------------------------------------------------- */
Bond *Force::new_bond(const char *style)
{
if (strcmp(style,"none") == 0) return NULL;
#define BOND_CLASS
#define BondStyle(key,Class) \
else if (strcmp(style,#key) == 0) return new Class(lmp);
#include "style_bond.h"
#undef BOND_CLASS
- else error->all("Invalid bond style");
+ else error->all(FLERR,"Invalid bond style");
return NULL;
}
/* ----------------------------------------------------------------------
return ptr to current bond class or hybrid sub-class if matches style
------------------------------------------------------------------------- */
Bond *Force::bond_match(const char *style)
{
if (strcmp(bond_style,style) == 0) return bond;
else if (strcmp(bond_style,"hybrid") == 0) {
BondHybrid *hybrid = (BondHybrid *) bond;
for (int i = 0; i < hybrid->nstyles; i++)
if (strcmp(hybrid->keywords[i],style) == 0) return hybrid->styles[i];
}
return NULL;
}
/* ----------------------------------------------------------------------
create an angle style, called from input script or restart file
------------------------------------------------------------------------- */
void Force::create_angle(const char *style)
{
delete [] angle_style;
if (angle) delete angle;
angle = new_angle(style);
int n = strlen(style) + 1;
angle_style = new char[n];
strcpy(angle_style,style);
}
/* ----------------------------------------------------------------------
generate an angle class
------------------------------------------------------------------------- */
Angle *Force::new_angle(const char *style)
{
if (strcmp(style,"none") == 0) return NULL;
#define ANGLE_CLASS
#define AngleStyle(key,Class) \
else if (strcmp(style,#key) == 0) return new Class(lmp);
#include "style_angle.h"
#undef ANGLE_CLASS
- else error->all("Invalid angle style");
+ else error->all(FLERR,"Invalid angle style");
return NULL;
}
/* ----------------------------------------------------------------------
create a dihedral style, called from input script or restart file
------------------------------------------------------------------------- */
void Force::create_dihedral(const char *style)
{
delete [] dihedral_style;
if (dihedral) delete dihedral;
dihedral = new_dihedral(style);
int n = strlen(style) + 1;
dihedral_style = new char[n];
strcpy(dihedral_style,style);
}
/* ----------------------------------------------------------------------
generate a dihedral class
------------------------------------------------------------------------- */
Dihedral *Force::new_dihedral(const char *style)
{
if (strcmp(style,"none") == 0) return NULL;
#define DIHEDRAL_CLASS
#define DihedralStyle(key,Class) \
else if (strcmp(style,#key) == 0) return new Class(lmp);
#include "style_dihedral.h"
#undef DIHEDRAL_CLASS
- else error->all("Invalid dihedral style");
+ else error->all(FLERR,"Invalid dihedral style");
return NULL;
}
/* ----------------------------------------------------------------------
create an improper style, called from input script or restart file
------------------------------------------------------------------------- */
void Force::create_improper(const char *style)
{
delete [] improper_style;
if (improper) delete improper;
improper = new_improper(style);
int n = strlen(style) + 1;
improper_style = new char[n];
strcpy(improper_style,style);
}
/* ----------------------------------------------------------------------
generate a improper class
------------------------------------------------------------------------- */
Improper *Force::new_improper(const char *style)
{
if (strcmp(style,"none") == 0) return NULL;
#define IMPROPER_CLASS
#define ImproperStyle(key,Class) \
else if (strcmp(style,#key) == 0) return new Class(lmp);
#include "style_improper.h"
#undef IMPROPER_CLASS
- else error->all("Invalid improper style");
+ else error->all(FLERR,"Invalid improper style");
return NULL;
}
/* ----------------------------------------------------------------------
new kspace style
------------------------------------------------------------------------- */
void Force::create_kspace(int narg, char **arg)
{
delete [] kspace_style;
if (kspace) delete kspace;
if (strcmp(arg[0],"none") == 0) kspace = NULL;
#define KSPACE_CLASS
#define KSpaceStyle(key,Class) \
else if (strcmp(arg[0],#key) == 0) kspace = new Class(lmp,narg-1,&arg[1]);
#include "style_kspace.h"
#undef KSPACE_CLASS
- else error->all("Invalid kspace style");
+ else error->all(FLERR,"Invalid kspace style");
int n = strlen(arg[0]) + 1;
kspace_style = new char[n];
strcpy(kspace_style,arg[0]);
}
/* ----------------------------------------------------------------------
set special bond values
------------------------------------------------------------------------- */
void Force::set_special(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal special_bonds command");
+ if (narg == 0) error->all(FLERR,"Illegal special_bonds command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"amber") == 0) {
- if (iarg+1 > narg) error->all("Illegal special_bonds command");
+ if (iarg+1 > narg) error->all(FLERR,"Illegal special_bonds command");
special_lj[1] = 0.0;
special_lj[2] = 0.0;
special_lj[3] = 0.5;
special_coul[1] = 0.0;
special_coul[2] = 0.0;
special_coul[3] = 5.0/6.0;
iarg += 1;
} else if (strcmp(arg[iarg],"charmm") == 0) {
- if (iarg+1 > narg) error->all("Illegal special_bonds command");
+ if (iarg+1 > narg) error->all(FLERR,"Illegal special_bonds command");
special_lj[1] = 0.0;
special_lj[2] = 0.0;
special_lj[3] = 0.0;
special_coul[1] = 0.0;
special_coul[2] = 0.0;
special_coul[3] = 0.0;
iarg += 1;
} else if (strcmp(arg[iarg],"dreiding") == 0) {
- if (iarg+1 > narg) error->all("Illegal special_bonds command");
+ if (iarg+1 > narg) error->all(FLERR,"Illegal special_bonds command");
special_lj[1] = 0.0;
special_lj[2] = 0.0;
special_lj[3] = 1.0;
special_coul[1] = 0.0;
special_coul[2] = 0.0;
special_coul[3] = 1.0;
iarg += 1;
} else if (strcmp(arg[iarg],"fene") == 0) {
- if (iarg+1 > narg) error->all("Illegal special_bonds command");
+ if (iarg+1 > narg) error->all(FLERR,"Illegal special_bonds command");
special_lj[1] = 0.0;
special_lj[2] = 1.0;
special_lj[3] = 1.0;
special_coul[1] = 0.0;
special_coul[2] = 1.0;
special_coul[3] = 1.0;
iarg += 1;
} else if (strcmp(arg[iarg],"lj/coul") == 0) {
- if (iarg+4 > narg) error->all("Illegal special_bonds command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal special_bonds command");
special_lj[1] = special_coul[1] = atof(arg[iarg+1]);
special_lj[2] = special_coul[2] = atof(arg[iarg+2]);
special_lj[3] = special_coul[3] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"lj") == 0) {
- if (iarg+4 > narg) error->all("Illegal special_bonds command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal special_bonds command");
special_lj[1] = atof(arg[iarg+1]);
special_lj[2] = atof(arg[iarg+2]);
special_lj[3] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"coul") == 0) {
- if (iarg+4 > narg) error->all("Illegal special_bonds command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal special_bonds command");
special_coul[1] = atof(arg[iarg+1]);
special_coul[2] = atof(arg[iarg+2]);
special_coul[3] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"angle") == 0) {
- if (iarg+2 > narg) error->all("Illegal special_bonds command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal special_bonds command");
if (strcmp(arg[iarg+1],"no") == 0) special_angle = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) special_angle = 1;
- else error->all("Illegal special_bonds command");
+ else error->all(FLERR,"Illegal special_bonds command");
iarg += 2;
} else if (strcmp(arg[iarg],"dihedral") == 0) {
- if (iarg+2 > narg) error->all("Illegal special_bonds command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal special_bonds command");
if (strcmp(arg[iarg+1],"no") == 0) special_dihedral = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) special_dihedral = 1;
- else error->all("Illegal special_bonds command");
+ else error->all(FLERR,"Illegal special_bonds command");
iarg += 2;
} else if (strcmp(arg[iarg],"extra") == 0) {
- if (iarg+2 > narg) error->all("Illegal special_bonds command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal special_bonds command");
special_extra = atoi(arg[iarg+1]);
iarg += 2;
- } else error->all("Illegal special_bonds command");
+ } else error->all(FLERR,"Illegal special_bonds command");
}
for (int i = 1; i <= 3; i++)
if (special_lj[i] < 0.0 || special_lj[i] > 1.0 ||
special_coul[i] < 0.0 || special_coul[i] > 1.0)
- error->all("Illegal special_bonds command");
+ error->all(FLERR,"Illegal special_bonds command");
- if (special_extra < 0) error->all("Illegal special_bonds command");
+ if (special_extra < 0) error->all(FLERR,"Illegal special_bonds command");
}
/* ----------------------------------------------------------------------
compute bounds implied by numeric str with a possible wildcard asterik
nmax = upper bound
5 possibilities:
(1) i = i to i, (2) * = 1 to nmax,
(3) i* = i to nmax, (4) *j = 1 to j, (5) i*j = i to j
return nlo,nhi
------------------------------------------------------------------------- */
void Force::bounds(char *str, int nmax, int &nlo, int &nhi)
{
char *ptr = strchr(str,'*');
if (ptr == NULL) {
nlo = MAX(atoi(str),1);
nhi = MIN(atoi(str),nmax);
} else if (strlen(str) == 1) {
nlo = 1;
nhi = nmax;
} else if (ptr == str) {
nlo = 1;
nhi = MIN(atoi(ptr+1),nmax);
} else if (strlen(ptr+1) == 0) {
nlo = MAX(atoi(str),1);
nhi = nmax;
} else {
nlo = MAX(atoi(str),1);
nhi = MIN(atoi(ptr+1),nmax);
}
}
/* ----------------------------------------------------------------------
read a floating point value from a string
generate an error if not a legitimate floating point value
called by force fields to check validity of their arguments
------------------------------------------------------------------------- */
double Force::numeric(char *str)
{
int n = strlen(str);
for (int i = 0; i < n; i++) {
if (isdigit(str[i])) continue;
if (str[i] == '-' || str[i] == '+' || str[i] == '.') continue;
if (str[i] == 'e' || str[i] == 'E') continue;
- error->all("Expected floating point parameter in "
+ error->all(FLERR,"Expected floating point parameter in "
"input script or data file");
}
return atof(str);
}
/* ----------------------------------------------------------------------
read an integer value from a string
generate an error if not a legitimate integer value
called by force fields to check validity of their arguments
------------------------------------------------------------------------- */
int Force::inumeric(char *str)
{
int n = strlen(str);
for (int i = 0; i < n; i++) {
if (isdigit(str[i]) || str[i] == '-' || str[i] == '+') continue;
- error->all("Expected integer parameter in input script or data file");
+ error->all(FLERR,"Expected integer parameter in input script or data file");
}
return atoi(str);
}
/* ----------------------------------------------------------------------
memory usage of force classes
------------------------------------------------------------------------- */
bigint Force::memory_usage()
{
bigint bytes = 0;
if (pair) bytes += static_cast<bigint> (pair->memory_usage());
if (bond) bytes += static_cast<bigint> (bond->memory_usage());
if (angle) bytes += static_cast<bigint> (angle->memory_usage());
if (dihedral) bytes += static_cast<bigint> (dihedral->memory_usage());
if (improper) bytes += static_cast<bigint> (improper->memory_usage());
if (kspace) bytes += static_cast<bigint> (kspace->memory_usage());
return bytes;
}
diff --git a/src/group.cpp b/src/group.cpp
index 7ab12b35f..5d6073bae 100644
--- a/src/group.cpp
+++ b/src/group.cpp
@@ -1,1471 +1,1468 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "mpi.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "group.h"
#include "domain.h"
#include "atom.h"
#include "force.h"
#include "region.h"
#include "modify.h"
#include "fix.h"
#include "compute.h"
#include "output.h"
#include "dump.h"
#include "error.h"
using namespace LAMMPS_NS;
#define MAX_GROUP 32
enum{TYPE,MOLECULE,ID};
enum{LT,LE,GT,GE,EQ,NEQ,BETWEEN};
#define BIG 1.0e20
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ----------------------------------------------------------------------
initialize group memory
------------------------------------------------------------------------- */
Group::Group(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
names = new char*[MAX_GROUP];
bitmask = new int[MAX_GROUP];
inversemask = new int[MAX_GROUP];
for (int i = 0; i < MAX_GROUP; i++) names[i] = NULL;
for (int i = 0; i < MAX_GROUP; i++) bitmask[i] = 1 << i;
for (int i = 0; i < MAX_GROUP; i++) inversemask[i] = bitmask[i] ^ ~0;
// create "all" group
char *str = (char *) "all";
int n = strlen(str) + 1;
names[0] = new char[n];
strcpy(names[0],str);
ngroup = 1;
}
/* ----------------------------------------------------------------------
free all memory
------------------------------------------------------------------------- */
Group::~Group()
{
for (int i = 0; i < MAX_GROUP; i++) delete [] names[i];
delete [] names;
delete [] bitmask;
delete [] inversemask;
}
/* ----------------------------------------------------------------------
assign atoms to a new or existing group
------------------------------------------------------------------------- */
void Group::assign(int narg, char **arg)
{
int i;
if (domain->box_exist == 0)
- error->all("Group command before simulation box is defined");
- if (narg < 2) error->all("Illegal group command");
+ error->all(FLERR,"Group command before simulation box is defined");
+ if (narg < 2) error->all(FLERR,"Illegal group command");
// delete the group if not being used elsewhere
// clear mask of each atom assigned to this group
if (strcmp(arg[1],"delete") == 0) {
int igroup = find(arg[0]);
- if (igroup == -1) error->all("Could not find group delete group ID");
- if (igroup == 0) error->all("Cannot delete group all");
+ if (igroup == -1) error->all(FLERR,"Could not find group delete group ID");
+ if (igroup == 0) error->all(FLERR,"Cannot delete group all");
for (i = 0; i < modify->nfix; i++)
if (modify->fix[i]->igroup == igroup)
- error->all("Cannot delete group currently used by a fix");
+ error->all(FLERR,"Cannot delete group currently used by a fix");
for (i = 0; i < modify->ncompute; i++)
if (modify->compute[i]->igroup == igroup)
- error->all("Cannot delete group currently used by a compute");
+ error->all(FLERR,"Cannot delete group currently used by a compute");
for (i = 0; i < output->ndump; i++)
if (output->dump[i]->igroup == igroup)
- error->all("Cannot delete group currently used by a dump");
+ error->all(FLERR,"Cannot delete group currently used by a dump");
if (atom->firstgroupname && strcmp(arg[0],atom->firstgroupname) == 0)
- error->all("Cannot delete group currently used by atom_modify first");
+ error->all(FLERR,"Cannot delete group currently used by atom_modify first");
int *mask = atom->mask;
int nlocal = atom->nlocal;
int bits = inversemask[igroup];
for (i = 0; i < nlocal; i++) mask[i] &= bits;
delete [] names[igroup];
names[igroup] = NULL;
ngroup--;
return;
}
// find group in existing list
// add a new group if igroup = -1
int igroup = find(arg[0]);
if (igroup == -1) {
- if (ngroup == MAX_GROUP) error->all("Too many groups");
+ if (ngroup == MAX_GROUP) error->all(FLERR,"Too many groups");
igroup = find_unused();
int n = strlen(arg[0]) + 1;
names[igroup] = new char[n];
strcpy(names[igroup],arg[0]);
ngroup++;
}
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int bit = bitmask[igroup];
// style = region
// add to group if atom is in region
// init all regions via domain->init() to insure region can perform match()
if (strcmp(arg[1],"region") == 0) {
- if (narg != 3) error->all("Illegal group command");
+ if (narg != 3) error->all(FLERR,"Illegal group command");
int iregion = domain->find_region(arg[2]);
- if (iregion == -1) error->all("Group region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Group region ID does not exist");
domain->init();
for (i = 0; i < nlocal; i++)
if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
mask[i] |= bit;
// style = logical condition
} else if (narg >= 3 &&
(strcmp(arg[2],"<") == 0 || strcmp(arg[2],">") == 0 ||
strcmp(arg[2],"<=") == 0 || strcmp(arg[2],">=") == 0 ||
strcmp(arg[2],"<>") == 0)) {
- if (narg < 4 || narg > 5) error->all("Illegal group command");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Illegal group command");
int category,condition,bound1,bound2;
if (strcmp(arg[1],"type") == 0) category = TYPE;
else if (strcmp(arg[1],"molecule") == 0) category = MOLECULE;
else if (strcmp(arg[1],"id") == 0) category = ID;
- else error->all("Illegal group command");
+ else error->all(FLERR,"Illegal group command");
if (strcmp(arg[2],"<") == 0) condition = LT;
else if (strcmp(arg[2],"<=") == 0) condition = LE;
else if (strcmp(arg[2],">") == 0) condition = GT;
else if (strcmp(arg[2],">=") == 0) condition = GE;
else if (strcmp(arg[2],"==") == 0) condition = EQ;
else if (strcmp(arg[2],"!=") == 0) condition = NEQ;
else if (strcmp(arg[2],"<>") == 0) condition = BETWEEN;
- else error->all("Illegal group command");
+ else error->all(FLERR,"Illegal group command");
bound1 = atoi(arg[3]);
bound2 = -1;
if (condition == BETWEEN) {
- if (narg != 5) error->all("Illegal group command");
+ if (narg != 5) error->all(FLERR,"Illegal group command");
bound2 = atoi(arg[4]);
}
int *attribute;
if (category == TYPE) attribute = atom->type;
else if (category == MOLECULE) attribute = atom->molecule;
else if (category == ID) attribute = atom->tag;
// add to group if meets condition
if (condition == LT) {
for (i = 0; i < nlocal; i++) if (attribute[i] < bound1) mask[i] |= bit;
} else if (condition == LE) {
for (i = 0; i < nlocal; i++) if (attribute[i] <= bound1) mask[i] |= bit;
} else if (condition == GT) {
for (i = 0; i < nlocal; i++) if (attribute[i] > bound1) mask[i] |= bit;
} else if (condition == GE) {
for (i = 0; i < nlocal; i++) if (attribute[i] >= bound1) mask[i] |= bit;
} else if (condition == EQ) {
for (i = 0; i < nlocal; i++) if (attribute[i] == bound1) mask[i] |= bit;
} else if (condition == NEQ) {
for (i = 0; i < nlocal; i++) if (attribute[i] != bound1) mask[i] |= bit;
} else if (condition == BETWEEN) {
for (i = 0; i < nlocal; i++)
if (attribute[i] >= bound1 && attribute[i] <= bound2) mask[i] |= bit;
}
// style = list of values
} else if (strcmp(arg[1],"type") == 0 || strcmp(arg[1],"molecule") == 0 ||
strcmp(arg[1],"id") == 0) {
- if (narg < 3) error->all("Illegal group command");
+ if (narg < 3) error->all(FLERR,"Illegal group command");
int length = narg-2;
int *list = new int[length];
int category;
if (strcmp(arg[1],"type") == 0) category = TYPE;
else if (strcmp(arg[1],"molecule") == 0) category = MOLECULE;
else if (strcmp(arg[1],"id") == 0) category = ID;
- else error->all("Illegal group command");
+ else error->all(FLERR,"Illegal group command");
length = narg - 2;
for (int iarg = 2; iarg < narg; iarg++) list[iarg-2] = atoi(arg[iarg]);
int *attribute;
if (category == TYPE) attribute = atom->type;
else if (category == MOLECULE) attribute = atom->molecule;
else if (category == ID) attribute = atom->tag;
// add to group if attribute is any in list
for (int ilist = 0; ilist < length; ilist++)
for (i = 0; i < nlocal; i++)
if (attribute[i] == list[ilist]) mask[i] |= bit;
delete [] list;
// style = subtract
} else if (strcmp(arg[1],"subtract") == 0) {
- if (narg < 4) error->all("Illegal group command");
+ if (narg < 4) error->all(FLERR,"Illegal group command");
int length = narg-2;
int *list = new int[length];
int jgroup;
for (int iarg = 2; iarg < narg; iarg++) {
jgroup = find(arg[iarg]);
- if (jgroup == -1) error->all("Group ID does not exist");
+ if (jgroup == -1) error->all(FLERR,"Group ID does not exist");
list[iarg-2] = jgroup;
}
// add to group if in 1st group in list
int otherbit = bitmask[list[0]];
for (i = 0; i < nlocal; i++)
if (mask[i] & otherbit) mask[i] |= bit;
// remove atoms if they are in any of the other groups
// AND with inverse mask removes the atom from group
int inverse = inversemask[igroup];
for (int ilist = 1; ilist < length; ilist++) {
otherbit = bitmask[list[ilist]];
for (i = 0; i < nlocal; i++)
if (mask[i] & otherbit) mask[i] &= inverse;
}
delete [] list;
// style = union
} else if (strcmp(arg[1],"union") == 0) {
- if (narg < 3) error->all("Illegal group command");
+ if (narg < 3) error->all(FLERR,"Illegal group command");
int length = narg-2;
int *list = new int[length];
int jgroup;
for (int iarg = 2; iarg < narg; iarg++) {
jgroup = find(arg[iarg]);
- if (jgroup == -1) error->all("Group ID does not exist");
+ if (jgroup == -1) error->all(FLERR,"Group ID does not exist");
list[iarg-2] = jgroup;
}
// add to group if in any other group in list
int otherbit;
for (int ilist = 0; ilist < length; ilist++) {
otherbit = bitmask[list[ilist]];
for (i = 0; i < nlocal; i++)
if (mask[i] & otherbit) mask[i] |= bit;
}
delete [] list;
// style = intersect
} else if (strcmp(arg[1],"intersect") == 0) {
- if (narg < 4) error->all("Illegal group command");
+ if (narg < 4) error->all(FLERR,"Illegal group command");
int length = narg-2;
int *list = new int[length];
int jgroup;
for (int iarg = 2; iarg < narg; iarg++) {
jgroup = find(arg[iarg]);
- if (jgroup == -1) error->all("Group ID does not exist");
+ if (jgroup == -1) error->all(FLERR,"Group ID does not exist");
list[iarg-2] = jgroup;
}
// add to group if in all groups in list
int otherbit,ok,ilist;
for (i = 0; i < nlocal; i++) {
ok = 1;
for (ilist = 0; ilist < length; ilist++) {
otherbit = bitmask[list[ilist]];
if ((mask[i] & otherbit) == 0) ok = 0;
}
if (ok) mask[i] |= bit;
}
delete [] list;
// not a valid group style
- } else error->all("Illegal group command");
+ } else error->all(FLERR,"Illegal group command");
// print stats for changed group
int n;
n = 0;
for (i = 0; i < nlocal; i++) if (mask[i] & bit) n++;
double rlocal = n;
double all;
MPI_Allreduce(&rlocal,&all,1,MPI_DOUBLE,MPI_SUM,world);
if (me == 0) {
if (screen) fprintf(screen,"%.15g atoms in group %s\n",all,names[igroup]);
if (logfile)
fprintf(logfile,"%.15g atoms in group %s\n",all,names[igroup]);
}
}
/* ----------------------------------------------------------------------
add flagged atoms to a new or existing group
------------------------------------------------------------------------- */
void Group::create(char *name, int *flag)
{
int i;
// find group in existing list
// add a new group if igroup = -1
int igroup = find(name);
if (igroup == -1) {
- if (ngroup == MAX_GROUP) error->all("Too many groups");
+ if (ngroup == MAX_GROUP) error->all(FLERR,"Too many groups");
igroup = find_unused();
int n = strlen(name) + 1;
names[igroup] = new char[n];
strcpy(names[igroup],name);
ngroup++;
}
// add atoms to group whose flags are set
int *mask = atom->mask;
int nlocal = atom->nlocal;
int bit = bitmask[igroup];
for (i = 0; i < nlocal; i++)
if (flag[i]) mask[i] |= bit;
}
/* ----------------------------------------------------------------------
return group index if name matches existing group, -1 if no such group
------------------------------------------------------------------------- */
int Group::find(const char *name)
{
for (int igroup = 0; igroup < MAX_GROUP; igroup++)
if (names[igroup] && strcmp(name,names[igroup]) == 0) return igroup;
return -1;
}
/* ----------------------------------------------------------------------
return index of first available group
should never be called when group limit has been reached
------------------------------------------------------------------------- */
int Group::find_unused()
{
for (int igroup = 0; igroup < MAX_GROUP; igroup++)
if (names[igroup] == NULL) return igroup;
return -1;
}
/* ----------------------------------------------------------------------
write group info to a restart file
only called by proc 0
------------------------------------------------------------------------- */
void Group::write_restart(FILE *fp)
{
fwrite(&ngroup,sizeof(int),1,fp);
// use count to not change restart format with deleted groups
// remove this on next major release
int n;
int count = 0;
for (int i = 0; i < MAX_GROUP; i++) {
if (names[i]) n = strlen(names[i]) + 1;
else n = 0;
fwrite(&n,sizeof(int),1,fp);
if (n) {
fwrite(names[i],sizeof(char),n,fp);
count++;
}
if (count == ngroup) break;
}
}
/* ----------------------------------------------------------------------
read group info from a restart file
proc 0 reads, bcast to all procs
------------------------------------------------------------------------- */
void Group::read_restart(FILE *fp)
{
int i,n;
// delete existing group names
// atom masks will be overwritten by reading of restart file
for (i = 0; i < MAX_GROUP; i++) delete [] names[i];
if (me == 0) fread(&ngroup,sizeof(int),1,fp);
MPI_Bcast(&ngroup,1,MPI_INT,0,world);
// use count to not change restart format with deleted groups
// remove this on next major release
int count = 0;
for (i = 0; i < MAX_GROUP; i++) {
if (count == ngroup) {
names[i] = NULL;
continue;
}
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
if (n) {
names[i] = new char[n];
if (me == 0) fread(names[i],sizeof(char),n,fp);
MPI_Bcast(names[i],n,MPI_CHAR,0,world);
count++;
} else names[i] = NULL;
}
}
// ----------------------------------------------------------------------
// computations on a group of atoms
// ----------------------------------------------------------------------
/* ----------------------------------------------------------------------
count atoms in group
------------------------------------------------------------------------- */
bigint Group::count(int igroup)
{
int groupbit = bitmask[igroup];
int *mask = atom->mask;
int nlocal = atom->nlocal;
int n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) n++;
bigint nsingle = n;
bigint nall;
MPI_Allreduce(&nsingle,&nall,1,MPI_LMP_BIGINT,MPI_SUM,world);
return nall;
}
/* ----------------------------------------------------------------------
count atoms in group and region
------------------------------------------------------------------------- */
bigint Group::count(int igroup, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int n = 0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) n++;
bigint nsingle = n;
bigint nall;
MPI_Allreduce(&nsingle,&nall,1,MPI_LMP_BIGINT,MPI_SUM,world);
return nall;
}
/* ----------------------------------------------------------------------
compute the total mass of group of atoms
use either per-type mass or per-atom rmass
------------------------------------------------------------------------- */
double Group::mass(int igroup)
{
int groupbit = bitmask[igroup];
double *mass = atom->mass;
double *rmass = atom->rmass;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double one = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) one += rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) one += mass[type[i]];
}
double all;
MPI_Allreduce(&one,&all,1,MPI_DOUBLE,MPI_SUM,world);
return all;
}
/* ----------------------------------------------------------------------
compute the total mass of group of atoms in region
use either per-type mass or per-atom rmass
------------------------------------------------------------------------- */
double Group::mass(int igroup, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
double *mass = atom->mass;
double *rmass = atom->rmass;
int *mask = atom->mask;
int *type = atom->type;
int nlocal = atom->nlocal;
double one = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
one += rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
one += mass[type[i]];
}
double all;
MPI_Allreduce(&one,&all,1,MPI_DOUBLE,MPI_SUM,world);
return all;
}
/* ----------------------------------------------------------------------
compute the total charge of group of atoms
------------------------------------------------------------------------- */
double Group::charge(int igroup)
{
int groupbit = bitmask[igroup];
double *q = atom->q;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double qone = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) qone += q[i];
double qall;
MPI_Allreduce(&qone,&qall,1,MPI_DOUBLE,MPI_SUM,world);
return qall;
}
/* ----------------------------------------------------------------------
compute the total charge of group of atoms in region
------------------------------------------------------------------------- */
double Group::charge(int igroup, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
double *q = atom->q;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double qone = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
qone += q[i];
double qall;
MPI_Allreduce(&qone,&qall,1,MPI_DOUBLE,MPI_SUM,world);
return qall;
}
/* ----------------------------------------------------------------------
compute the coordinate bounds of the group of atoms
periodic images are not considered, so atoms are NOT unwrapped
------------------------------------------------------------------------- */
void Group::bounds(int igroup, double *minmax)
{
int groupbit = bitmask[igroup];
double extent[6];
extent[0] = extent[2] = extent[4] = BIG;
extent[1] = extent[3] = extent[5] = -BIG;
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
extent[0] = MIN(extent[0],x[i][0]);
extent[1] = MAX(extent[1],x[i][0]);
extent[2] = MIN(extent[2],x[i][1]);
extent[3] = MAX(extent[3],x[i][1]);
extent[4] = MIN(extent[4],x[i][2]);
extent[5] = MAX(extent[5],x[i][2]);
}
}
// compute extent across all procs
// flip sign of MIN to do it in one Allreduce MAX
// set box by extent in shrink-wrapped dims
extent[0] = -extent[0];
extent[2] = -extent[2];
extent[4] = -extent[4];
MPI_Allreduce(extent,minmax,6,MPI_DOUBLE,MPI_MAX,world);
minmax[0] = -minmax[0];
minmax[2] = -minmax[2];
minmax[4] = -minmax[4];
}
/* ----------------------------------------------------------------------
compute the coordinate bounds of the group of atoms in region
periodic images are not considered, so atoms are NOT unwrapped
------------------------------------------------------------------------- */
void Group::bounds(int igroup, double *minmax, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double extent[6];
extent[0] = extent[2] = extent[4] = BIG;
extent[1] = extent[3] = extent[5] = -BIG;
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
extent[0] = MIN(extent[0],x[i][0]);
extent[1] = MAX(extent[1],x[i][0]);
extent[2] = MIN(extent[2],x[i][1]);
extent[3] = MAX(extent[3],x[i][1]);
extent[4] = MIN(extent[4],x[i][2]);
extent[5] = MAX(extent[5],x[i][2]);
}
}
// compute extent across all procs
// flip sign of MIN to do it in one Allreduce MAX
// set box by extent in shrink-wrapped dims
extent[0] = -extent[0];
extent[2] = -extent[2];
extent[4] = -extent[4];
MPI_Allreduce(extent,minmax,6,MPI_DOUBLE,MPI_MAX,world);
minmax[0] = -minmax[0];
minmax[2] = -minmax[2];
minmax[4] = -minmax[4];
}
/* ----------------------------------------------------------------------
compute the center-of-mass coords of group of atoms
masstotal = total mass
return center-of-mass coords in cm[]
must unwrap atoms to compute center-of-mass correctly
------------------------------------------------------------------------- */
void Group::xcm(int igroup, double masstotal, double *cm)
{
int groupbit = bitmask[igroup];
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double cmone[3];
cmone[0] = cmone[1] = cmone[2] = 0.0;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
double massone;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
massone = rmass[i];
cmone[0] += (x[i][0] + xbox*xprd) * massone;
cmone[1] += (x[i][1] + ybox*yprd) * massone;
cmone[2] += (x[i][2] + zbox*zprd) * massone;
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
massone = mass[type[i]];
cmone[0] += (x[i][0] + xbox*xprd) * massone;
cmone[1] += (x[i][1] + ybox*yprd) * massone;
cmone[2] += (x[i][2] + zbox*zprd) * massone;
}
}
MPI_Allreduce(cmone,cm,3,MPI_DOUBLE,MPI_SUM,world);
if (masstotal > 0.0) {
cm[0] /= masstotal;
cm[1] /= masstotal;
cm[2] /= masstotal;
}
}
/* ----------------------------------------------------------------------
compute the center-of-mass coords of group of atoms in region
mastotal = total mass
return center-of-mass coords in cm[]
must unwrap atoms to compute center-of-mass correctly
------------------------------------------------------------------------- */
void Group::xcm(int igroup, double masstotal, double *cm, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double cmone[3];
cmone[0] = cmone[1] = cmone[2] = 0.0;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
int xbox,ybox,zbox;
double massone;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
massone = rmass[i];
cmone[0] += (x[i][0] + xbox*xprd) * massone;
cmone[1] += (x[i][1] + ybox*yprd) * massone;
cmone[2] += (x[i][2] + zbox*zprd) * massone;
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
massone = mass[type[i]];
cmone[0] += (x[i][0] + xbox*xprd) * massone;
cmone[1] += (x[i][1] + ybox*yprd) * massone;
cmone[2] += (x[i][2] + zbox*zprd) * massone;
}
}
MPI_Allreduce(cmone,cm,3,MPI_DOUBLE,MPI_SUM,world);
if (masstotal > 0.0) {
cm[0] /= masstotal;
cm[1] /= masstotal;
cm[2] /= masstotal;
}
}
/* ----------------------------------------------------------------------
compute the center-of-mass velocity of group of atoms
masstotal = total mass
return center-of-mass velocity in cm[]
------------------------------------------------------------------------- */
void Group::vcm(int igroup, double masstotal, double *cm)
{
int groupbit = bitmask[igroup];
double **v = atom->v;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double p[3],massone;
p[0] = p[1] = p[2] = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = rmass[i];
p[0] += v[i][0]*massone;
p[1] += v[i][1]*massone;
p[2] += v[i][2]*massone;
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
massone = mass[type[i]];
p[0] += v[i][0]*massone;
p[1] += v[i][1]*massone;
p[2] += v[i][2]*massone;
}
}
MPI_Allreduce(p,cm,3,MPI_DOUBLE,MPI_SUM,world);
if (masstotal > 0.0) {
cm[0] /= masstotal;
cm[1] /= masstotal;
cm[2] /= masstotal;
}
}
/* ----------------------------------------------------------------------
compute the center-of-mass velocity of group of atoms in region
masstotal = total mass
return center-of-mass velocity in cm[]
------------------------------------------------------------------------- */
void Group::vcm(int igroup, double masstotal, double *cm, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double p[3],massone;
p[0] = p[1] = p[2] = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
massone = rmass[i];
p[0] += v[i][0]*massone;
p[1] += v[i][1]*massone;
p[2] += v[i][2]*massone;
}
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
massone = mass[type[i]];
p[0] += v[i][0]*massone;
p[1] += v[i][1]*massone;
p[2] += v[i][2]*massone;
}
}
MPI_Allreduce(p,cm,3,MPI_DOUBLE,MPI_SUM,world);
if (masstotal > 0.0) {
cm[0] /= masstotal;
cm[1] /= masstotal;
cm[2] /= masstotal;
}
}
/* ----------------------------------------------------------------------
compute the total force on group of atoms
------------------------------------------------------------------------- */
void Group::fcm(int igroup, double *cm)
{
int groupbit = bitmask[igroup];
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double flocal[3];
flocal[0] = flocal[1] = flocal[2] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
flocal[0] += f[i][0];
flocal[1] += f[i][1];
flocal[2] += f[i][2];
}
MPI_Allreduce(flocal,cm,3,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute the total force on group of atoms in region
------------------------------------------------------------------------- */
void Group::fcm(int igroup, double *cm, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double flocal[3];
flocal[0] = flocal[1] = flocal[2] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
flocal[0] += f[i][0];
flocal[1] += f[i][1];
flocal[2] += f[i][2];
}
MPI_Allreduce(flocal,cm,3,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute the total kinetic energy of group of atoms and return it
------------------------------------------------------------------------- */
double Group::ke(int igroup)
{
int groupbit = bitmask[igroup];
double **v = atom->v;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double one = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
one += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit)
one += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
mass[type[i]];
}
double all;
MPI_Allreduce(&one,&all,1,MPI_DOUBLE,MPI_SUM,world);
all *= 0.5 * force->mvv2e;
return all;
}
/* ----------------------------------------------------------------------
compute the total kinetic energy of group of atoms in region and return it
------------------------------------------------------------------------- */
double Group::ke(int igroup, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int *type = atom->type;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
double one = 0.0;
if (rmass) {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
one += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
rmass[i];
} else {
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2]))
one += (v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2]) *
mass[type[i]];
}
double all;
MPI_Allreduce(&one,&all,1,MPI_DOUBLE,MPI_SUM,world);
all *= 0.5 * force->mvv2e;
return all;
}
/* ----------------------------------------------------------------------
compute the radius-of-gyration of group of atoms
around center-of-mass cm
must unwrap atoms to compute Rg correctly
------------------------------------------------------------------------- */
double Group::gyration(int igroup, double masstotal, double *cm)
{
int groupbit = bitmask[igroup];
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz,massone;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double rg = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
rg += (dx*dx + dy*dy + dz*dz) * massone;
}
double rg_all;
MPI_Allreduce(&rg,&rg_all,1,MPI_DOUBLE,MPI_SUM,world);
if (masstotal > 0.0) return sqrt(rg_all/masstotal);
return 0.0;
}
/* ----------------------------------------------------------------------
compute the radius-of-gyration of group of atoms in region
around center-of-mass cm
must unwrap atoms to compute Rg correctly
------------------------------------------------------------------------- */
double Group::gyration(int igroup, double masstotal, double *cm, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz,massone;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double rg = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
rg += (dx*dx + dy*dy + dz*dz) * massone;
}
double rg_all;
MPI_Allreduce(&rg,&rg_all,1,MPI_DOUBLE,MPI_SUM,world);
if (masstotal > 0.0) return sqrt(rg_all/masstotal);
return 0.0;
}
/* ----------------------------------------------------------------------
compute the angular momentum L (lmom) of group
around center-of-mass cm
must unwrap atoms to compute L correctly
------------------------------------------------------------------------- */
void Group::angmom(int igroup, double *cm, double *lmom)
{
int groupbit = bitmask[igroup];
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz,massone;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double p[3];
p[0] = p[1] = p[2] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
p[0] += massone * (dy*v[i][2] - dz*v[i][1]);
p[1] += massone * (dz*v[i][0] - dx*v[i][2]);
p[2] += massone * (dx*v[i][1] - dy*v[i][0]);
}
MPI_Allreduce(p,lmom,3,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute the angular momentum L (lmom) of group of atoms in region
around center-of-mass cm
must unwrap atoms to compute L correctly
------------------------------------------------------------------------- */
void Group::angmom(int igroup, double *cm, double *lmom, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz,massone;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double p[3];
p[0] = p[1] = p[2] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
p[0] += massone * (dy*v[i][2] - dz*v[i][1]);
p[1] += massone * (dz*v[i][0] - dx*v[i][2]);
p[2] += massone * (dx*v[i][1] - dy*v[i][0]);
}
MPI_Allreduce(p,lmom,3,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute the torque T (tq) on group
around center-of-mass cm
must unwrap atoms to compute T correctly
------------------------------------------------------------------------- */
void Group::torque(int igroup, double *cm, double *tq)
{
int groupbit = bitmask[igroup];
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double tlocal[3];
tlocal[0] = tlocal[1] = tlocal[2] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
tlocal[0] += dy*f[i][2] - dz*f[i][1];
tlocal[1] += dz*f[i][0] - dx*f[i][2];
tlocal[2] += dx*f[i][1] - dy*f[i][0];
}
MPI_Allreduce(tlocal,tq,3,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute the torque T (tq) on group of atoms in region
around center-of-mass cm
must unwrap atoms to compute T correctly
------------------------------------------------------------------------- */
void Group::torque(int igroup, double *cm, double *tq, int iregion)
{
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
double **f = atom->f;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double tlocal[3];
tlocal[0] = tlocal[1] = tlocal[2] = 0.0;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
tlocal[0] += dy*f[i][2] - dz*f[i][1];
tlocal[1] += dz*f[i][0] - dx*f[i][2];
tlocal[2] += dx*f[i][1] - dy*f[i][0];
}
MPI_Allreduce(tlocal,tq,3,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute moment of inertia tensor around center-of-mass cm of group
must unwrap atoms to compute itensor correctly
------------------------------------------------------------------------- */
void Group::inertia(int igroup, double *cm, double itensor[3][3])
{
int i,j;
int groupbit = bitmask[igroup];
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz,massone;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double ione[3][3];
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
ione[i][j] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
ione[0][0] += massone * (dy*dy + dz*dz);
ione[1][1] += massone * (dx*dx + dz*dz);
ione[2][2] += massone * (dx*dx + dy*dy);
ione[0][1] -= massone * dx*dy;
ione[1][2] -= massone * dy*dz;
ione[0][2] -= massone * dx*dz;
}
ione[1][0] = ione[0][1];
ione[2][1] = ione[1][2];
ione[2][0] = ione[0][2];
MPI_Allreduce(&ione[0][0],&itensor[0][0],9,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute moment of inertia tensor around cm of group of atoms in region
must unwrap atoms to compute itensor correctly
------------------------------------------------------------------------- */
void Group::inertia(int igroup, double *cm, double itensor[3][3], int iregion)
{
int i,j;
int groupbit = bitmask[igroup];
Region *region = domain->regions[iregion];
double **x = atom->x;
int *mask = atom->mask;
int *type = atom->type;
int *image = atom->image;
double *mass = atom->mass;
double *rmass = atom->rmass;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz,massone;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
double ione[3][3];
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
ione[i][j] = 0.0;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit && region->match(x[i][0],x[i][1],x[i][2])) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - cm[0];
dy = (x[i][1] + ybox*yprd) - cm[1];
dz = (x[i][2] + zbox*zprd) - cm[2];
if (rmass) massone = rmass[i];
else massone = mass[type[i]];
ione[0][0] += massone * (dy*dy + dz*dz);
ione[1][1] += massone * (dx*dx + dz*dz);
ione[2][2] += massone * (dx*dx + dy*dy);
ione[0][1] -= massone * dx*dy;
ione[1][2] -= massone * dy*dz;
ione[0][2] -= massone * dx*dz;
}
ione[1][0] = ione[0][1];
ione[2][1] = ione[1][2];
ione[2][0] = ione[0][2];
MPI_Allreduce(&ione[0][0],&itensor[0][0],9,MPI_DOUBLE,MPI_SUM,world);
}
/* ----------------------------------------------------------------------
compute angular velocity omega from L = Iw, inverting I to solve for w
really not a group operation, but L and I were computed for a group
------------------------------------------------------------------------- */
void Group::omega(double *angmom, double inertia[3][3], double *w)
{
double inverse[3][3];
inverse[0][0] = inertia[1][1]*inertia[2][2] - inertia[1][2]*inertia[2][1];
inverse[0][1] = -(inertia[0][1]*inertia[2][2] - inertia[0][2]*inertia[2][1]);
inverse[0][2] = inertia[0][1]*inertia[1][2] - inertia[0][2]*inertia[1][1];
inverse[1][0] = -(inertia[1][0]*inertia[2][2] - inertia[1][2]*inertia[2][0]);
inverse[1][1] = inertia[0][0]*inertia[2][2] - inertia[0][2]*inertia[2][0];
inverse[1][2] = -(inertia[0][0]*inertia[1][2] - inertia[0][2]*inertia[1][0]);
inverse[2][0] = inertia[1][0]*inertia[2][1] - inertia[1][1]*inertia[2][0];
inverse[2][1] = -(inertia[0][0]*inertia[2][1] - inertia[0][1]*inertia[2][0]);
inverse[2][2] = inertia[0][0]*inertia[1][1] - inertia[0][1]*inertia[1][0];
double determinant = inertia[0][0]*inertia[1][1]*inertia[2][2] +
inertia[0][1]*inertia[1][2]*inertia[2][0] +
inertia[0][2]*inertia[1][0]*inertia[2][1] -
inertia[0][0]*inertia[1][2]*inertia[2][1] -
inertia[0][1]*inertia[1][0]*inertia[2][2] -
inertia[2][0]*inertia[1][1]*inertia[0][2];
if (determinant > 0.0)
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
inverse[i][j] /= determinant;
w[0] = inverse[0][0]*angmom[0] + inverse[0][1]*angmom[1] +
inverse[0][2]*angmom[2];
w[1] = inverse[1][0]*angmom[0] + inverse[1][1]*angmom[1] +
inverse[1][2]*angmom[2];
w[2] = inverse[2][0]*angmom[0] + inverse[2][1]*angmom[1] +
inverse[2][2]*angmom[2];
}
diff --git a/src/improper.cpp b/src/improper.cpp
index 7b82590d0..3c65e8c89 100644
--- a/src/improper.cpp
+++ b/src/improper.cpp
@@ -1,243 +1,243 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "improper.h"
#include "atom.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Improper::Improper(LAMMPS *lmp) : Pointers(lmp)
{
energy = 0.0;
allocated = 0;
PI = 4.0*atan(1.0);
maxeatom = maxvatom = 0;
eatom = NULL;
vatom = NULL;
}
/* ---------------------------------------------------------------------- */
Improper::~Improper()
{
memory->destroy(eatom);
memory->destroy(vatom);
}
/* ----------------------------------------------------------------------
check if all coeffs are set
------------------------------------------------------------------------- */
void Improper::init()
{
- if (!allocated) error->all("Improper coeffs are not set");
+ if (!allocated) error->all(FLERR,"Improper coeffs are not set");
for (int i = 1; i <= atom->nimpropertypes; i++)
- if (setflag[i] == 0) error->all("All improper coeffs are not set");
+ if (setflag[i] == 0) error->all(FLERR,"All improper coeffs are not set");
}
/* ----------------------------------------------------------------------
setup for energy, virial computation
see integrate::ev_set() for values of eflag (0-3) and vflag (0-6)
------------------------------------------------------------------------- */
void Improper::ev_setup(int eflag, int vflag)
{
int i,n;
evflag = 1;
eflag_either = eflag;
eflag_global = eflag % 2;
eflag_atom = eflag / 2;
vflag_either = vflag;
vflag_global = vflag % 4;
vflag_atom = vflag / 4;
// reallocate per-atom arrays if necessary
if (eflag_atom && atom->nmax > maxeatom) {
maxeatom = atom->nmax;
memory->destroy(eatom);
memory->create(eatom,maxeatom,"bond:eatom");
}
if (vflag_atom && atom->nmax > maxvatom) {
maxvatom = atom->nmax;
memory->destroy(vatom);
memory->create(vatom,maxvatom,6,"bond:vatom");
}
// zero accumulators
if (eflag_global) energy = 0.0;
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) eatom[i] = 0.0;
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_bond) n += atom->nghost;
for (i = 0; i < n; i++) {
vatom[i][0] = 0.0;
vatom[i][1] = 0.0;
vatom[i][2] = 0.0;
vatom[i][3] = 0.0;
vatom[i][4] = 0.0;
vatom[i][5] = 0.0;
}
}
}
/* ----------------------------------------------------------------------
tally energy and virial into global and per-atom accumulators
virial = r1F1 + r2F2 + r3F3 + r4F4 = (r1-r2) F1 + (r3-r2) F3 + (r4-r2) F4
= (r1-r2) F1 + (r3-r2) F3 + (r4-r3 + r3-r2) F4
= vb1*f1 + vb2*f3 + (vb3+vb2)*f4
------------------------------------------------------------------------- */
void Improper::ev_tally(int i1, int i2, int i3, int i4,
int nlocal, int newton_bond,
double eimproper, double *f1, double *f3, double *f4,
double vb1x, double vb1y, double vb1z,
double vb2x, double vb2y, double vb2z,
double vb3x, double vb3y, double vb3z)
{
double eimproperquarter,v[6];
if (eflag_either) {
if (eflag_global) {
if (newton_bond) energy += eimproper;
else {
eimproperquarter = 0.25*eimproper;
if (i1 < nlocal) energy += eimproperquarter;
if (i2 < nlocal) energy += eimproperquarter;
if (i3 < nlocal) energy += eimproperquarter;
if (i4 < nlocal) energy += eimproperquarter;
}
}
if (eflag_atom) {
eimproperquarter = 0.25*eimproper;
if (newton_bond || i1 < nlocal) eatom[i1] += eimproperquarter;
if (newton_bond || i2 < nlocal) eatom[i2] += eimproperquarter;
if (newton_bond || i3 < nlocal) eatom[i3] += eimproperquarter;
if (newton_bond || i4 < nlocal) eatom[i4] += eimproperquarter;
}
}
if (vflag_either) {
v[0] = vb1x*f1[0] + vb2x*f3[0] + (vb3x+vb2x)*f4[0];
v[1] = vb1y*f1[1] + vb2y*f3[1] + (vb3y+vb2y)*f4[1];
v[2] = vb1z*f1[2] + vb2z*f3[2] + (vb3z+vb2z)*f4[2];
v[3] = vb1x*f1[1] + vb2x*f3[1] + (vb3x+vb2x)*f4[1];
v[4] = vb1x*f1[2] + vb2x*f3[2] + (vb3x+vb2x)*f4[2];
v[5] = vb1y*f1[2] + vb2y*f3[2] + (vb3y+vb2y)*f4[2];
if (vflag_global) {
if (newton_bond) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i1 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
if (i2 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
if (i3 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
if (i4 < nlocal) {
virial[0] += 0.25*v[0];
virial[1] += 0.25*v[1];
virial[2] += 0.25*v[2];
virial[3] += 0.25*v[3];
virial[4] += 0.25*v[4];
virial[5] += 0.25*v[5];
}
}
}
if (vflag_atom) {
if (newton_bond || i1 < nlocal) {
vatom[i1][0] += 0.25*v[0];
vatom[i1][1] += 0.25*v[1];
vatom[i1][2] += 0.25*v[2];
vatom[i1][3] += 0.25*v[3];
vatom[i1][4] += 0.25*v[4];
vatom[i1][5] += 0.25*v[5];
}
if (newton_bond || i2 < nlocal) {
vatom[i2][0] += 0.25*v[0];
vatom[i2][1] += 0.25*v[1];
vatom[i2][2] += 0.25*v[2];
vatom[i2][3] += 0.25*v[3];
vatom[i2][4] += 0.25*v[4];
vatom[i2][5] += 0.25*v[5];
}
if (newton_bond || i3 < nlocal) {
vatom[i3][0] += 0.25*v[0];
vatom[i3][1] += 0.25*v[1];
vatom[i3][2] += 0.25*v[2];
vatom[i3][3] += 0.25*v[3];
vatom[i3][4] += 0.25*v[4];
vatom[i3][5] += 0.25*v[5];
}
if (newton_bond || i4 < nlocal) {
vatom[i4][0] += 0.25*v[0];
vatom[i4][1] += 0.25*v[1];
vatom[i4][2] += 0.25*v[2];
vatom[i4][3] += 0.25*v[3];
vatom[i4][4] += 0.25*v[4];
vatom[i4][5] += 0.25*v[5];
}
}
}
}
/* ---------------------------------------------------------------------- */
double Improper::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
return bytes;
}
diff --git a/src/input.cpp b/src/input.cpp
index 05cb1f441..bcabc0230 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -1,1369 +1,1369 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "unistd.h"
#include "sys/stat.h"
#include "input.h"
#include "style_command.h"
#include "universe.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "group.h"
#include "domain.h"
#include "output.h"
#include "thermo.h"
#include "force.h"
#include "pair.h"
#include "min.h"
#include "modify.h"
#include "compute.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "update.h"
#include "neighbor.h"
#include "special.h"
#include "variable.h"
#include "accelerator_cuda.h"
#include "error.h"
#include "memory.h"
#ifdef _OPENMP
#include "omp.h"
#endif
using namespace LAMMPS_NS;
#define MAXLINE 2048
#define DELTA 4
/* ---------------------------------------------------------------------- */
Input::Input(LAMMPS *lmp, int argc, char **argv) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
line = new char[MAXLINE];
copy = new char[MAXLINE];
work = new char[MAXLINE];
narg = maxarg = 0;
arg = NULL;
echo_screen = 0;
echo_log = 1;
label_active = 0;
labelstr = NULL;
jump_skip = 0;
if (me == 0) {
nfile = maxfile = 1;
infiles = (FILE **) memory->smalloc(sizeof(FILE *),"input:infiles");
infiles[0] = infile;
} else infiles = NULL;
variable = new Variable(lmp);
// process command-line args
// check for args "-var" and "-echo"
// caller has already checked that sufficient arguments exist
int iarg = 0;
while (iarg < argc) {
if (strcmp(argv[iarg],"-var") == 0 || strcmp(argv[iarg],"-v") == 0) {
int jarg = iarg+2;
while (jarg < argc && argv[jarg][0] != '-') jarg++;
variable->set(argv[iarg+1],jarg-iarg-2,&argv[iarg+2]);
iarg = jarg;
} else if (strcmp(argv[iarg],"-echo") == 0 ||
strcmp(argv[iarg],"-e") == 0) {
narg = 1;
char **tmp = arg; // trick echo() into using argv instead of arg
arg = &argv[iarg+1];
echo();
arg = tmp;
iarg += 2;
} else iarg++;
}
}
/* ---------------------------------------------------------------------- */
Input::~Input()
{
// don't free command and arg strings
// they just point to other allocated memory
delete variable;
delete [] line;
delete [] copy;
delete [] work;
if (labelstr) delete [] labelstr;
memory->sfree(arg);
memory->sfree(infiles);
}
/* ----------------------------------------------------------------------
process all input from infile
infile = stdin or file if command-line arg "-in" was used
------------------------------------------------------------------------- */
void Input::file()
{
int m,n;
while (1) {
// read a line from input script
// if line ends in continuation char '&', concatenate next line(s)
// n = length of line including str terminator, 0 if end of file
// m = position of last printable char in line or -1 if blank line
if (me == 0) {
m = 0;
while (1) {
if (fgets(&line[m],MAXLINE-m,infile) == NULL) n = 0;
else n = strlen(line) + 1;
if (n == 0) break;
m = n-2;
while (m >= 0 && isspace(line[m])) m--;
if (m < 0 || line[m] != '&') break;
}
}
// bcast the line
// if n = 0, end-of-file
// error if label_active is set, since label wasn't encountered
// if original input file, code is done
// else go back to previous input file
MPI_Bcast(&n,1,MPI_INT,0,world);
if (n == 0) {
- if (label_active) error->all("Label wasn't found in input script");
+ if (label_active) error->all(FLERR,"Label wasn't found in input script");
if (me == 0) {
if (infile != stdin) fclose(infile);
nfile--;
}
MPI_Bcast(&nfile,1,MPI_INT,0,world);
if (nfile == 0) break;
if (me == 0) infile = infiles[nfile-1];
continue;
}
MPI_Bcast(line,n,MPI_CHAR,0,world);
// if n = MAXLINE, line is too long
if (n == MAXLINE) {
char str[MAXLINE+32];
sprintf(str,"Input line too long: %s",line);
- error->all(str);
+ error->all(FLERR,str);
}
// echo the command unless scanning for label
if (me == 0 && label_active == 0) {
if (echo_screen && screen) fprintf(screen,"%s",line);
if (echo_log && logfile) fprintf(logfile,"%s",line);
}
// parse the line
// if no command, skip to next line in input script
parse();
if (command == NULL) continue;
// if scanning for label, skip command unless it's a label command
if (label_active && strcmp(command,"label") != 0) continue;
// execute the command
if (execute_command()) {
char str[MAXLINE];
sprintf(str,"Unknown command: %s",line);
- error->all(str);
+ error->all(FLERR,str);
}
}
}
/* ----------------------------------------------------------------------
process all input from filename
------------------------------------------------------------------------- */
void Input::file(const char *filename)
{
// error if another nested file still open
// if single open file is not stdin, close it
// open new filename and set infile, infiles[0]
if (me == 0) {
if (nfile > 1)
- error->one("Another input script is already being processed");
+ error->one(FLERR,"Another input script is already being processed");
if (infile != stdin) fclose(infile);
infile = fopen(filename,"r");
if (infile == NULL) {
char str[128];
sprintf(str,"Cannot open input script %s",filename);
- error->one(str);
+ error->one(FLERR,str);
}
infiles[0] = infile;
} else infile = NULL;
file();
}
/* ----------------------------------------------------------------------
parse the command in single and execute it
return command name to caller
------------------------------------------------------------------------- */
char *Input::one(const char *single)
{
strcpy(line,single);
// echo the command unless scanning for label
if (me == 0 && label_active == 0) {
if (echo_screen && screen) fprintf(screen,"%s\n",line);
if (echo_log && logfile) fprintf(logfile,"%s\n",line);
}
// parse the line
// if no command, just return NULL
parse();
if (command == NULL) return NULL;
// if scanning for label, skip command unless it's a label command
if (label_active && strcmp(command,"label") != 0) return NULL;
// execute the command and return its name
if (execute_command()) {
char str[MAXLINE];
sprintf(str,"Unknown command: %s",line);
- error->all(str);
+ error->all(FLERR,str);
}
return command;
}
/* ----------------------------------------------------------------------
parse copy of command line
strip comment = all chars from # on
replace all $ via variable substitution
command = first word
narg = # of args
arg[] = individual args
treat text between single/double quotes as one arg
------------------------------------------------------------------------- */
void Input::parse()
{
// make a copy to work on
strcpy(copy,line);
// strip any # comment by resetting string terminator
// do not strip # inside single/double quotes
char quote = '\0';
char *ptr = copy;
while (*ptr) {
if (*ptr == '#' && !quote) {
*ptr = '\0';
break;
}
if (*ptr == quote) quote = '\0';
else if (*ptr == '"' || *ptr == '\'') quote = *ptr;
ptr++;
}
// perform $ variable substitution (print changes)
// except if searching for a label since earlier variable may not be defined
if (!label_active) substitute(copy,1);
// command = 1st arg
command = strtok(copy," \t\n\r\f");
if (command == NULL) return;
// point arg[] at each subsequent arg
// treat text between single/double quotes as one arg
// insert string terminators in copy to delimit args
quote = '\0';
int iarg,argstart;
narg = 0;
while (1) {
if (narg == maxarg) {
maxarg += DELTA;
arg = (char **) memory->srealloc(arg,maxarg*sizeof(char *),"input:arg");
}
arg[narg] = strtok(NULL," \t\n\r\f");
if (!arg[narg]) break;
if (!quote && (arg[narg][0] == '"' || arg[narg][0] == '\'')) {
quote = arg[narg][0];
argstart = narg;
arg[narg] = &arg[narg][1];
}
if (quote && arg[narg][strlen(arg[narg])-1] == quote) {
for (iarg = argstart; iarg < narg; iarg++)
arg[iarg][strlen(arg[iarg])] = ' ';
arg[narg][strlen(arg[narg])-1] = '\0';
narg = argstart;
quote = '\0';
}
narg++;
}
- if (quote) error->all("Unbalanced quotes in input line");
+ if (quote) error->all(FLERR,"Unbalanced quotes in input line");
}
/* ----------------------------------------------------------------------
substitute for $ variables in str and return it
str assumed to be long enough to hold expanded version
print updated string if flag is set and not searching for label
------------------------------------------------------------------------- */
void Input::substitute(char *str, int flag)
{
// use work[] as scratch space to expand str, then copy back to str
// do not replace $ inside single/double quotes
// var = pts at variable name, ended by NULL
// if $ is followed by '{', trailing '}' becomes NULL
// else $x becomes x followed by NULL
// beyond = pts at text following variable
char *var,*value,*beyond;
char quote = '\0';
char *ptr = str;
while (*ptr) {
if (*ptr == '$' && !quote) {
if (*(ptr+1) == '{') {
var = ptr+2;
int i = 0;
while (var[i] != '\0' && var[i] != '}') i++;
- if (var[i] == '\0') error->one("Invalid variable name");
+ if (var[i] == '\0') error->one(FLERR,"Invalid variable name");
var[i] = '\0';
beyond = ptr + strlen(var) + 3;
} else {
var = ptr;
var[0] = var[1];
var[1] = '\0';
beyond = ptr + strlen(var) + 1;
}
value = variable->retrieve(var);
- if (value == NULL) error->one("Substitution for illegal variable");
+ if (value == NULL) error->one(FLERR,"Substitution for illegal variable");
*ptr = '\0';
strcpy(work,str);
if (strlen(work)+strlen(value) >= MAXLINE)
- error->one("Input line too long after variable substitution");
+ error->one(FLERR,"Input line too long after variable substitution");
strcat(work,value);
if (strlen(work)+strlen(beyond) >= MAXLINE)
- error->one("Input line too long after variable substitution");
+ error->one(FLERR,"Input line too long after variable substitution");
strcat(work,beyond);
strcpy(str,work);
ptr += strlen(value);
if (flag && me == 0 && label_active == 0) {
if (echo_screen && screen) fprintf(screen,"%s",str);
if (echo_log && logfile) fprintf(logfile,"%s",str);
}
continue;
}
if (*ptr == quote) quote = '\0';
else if (*ptr == '"' || *ptr == '\'') quote = *ptr;
ptr++;
}
}
/* ----------------------------------------------------------------------
process a single parsed command
return 0 if successful, -1 if did not recognize command
------------------------------------------------------------------------- */
int Input::execute_command()
{
int flag = 1;
if (!strcmp(command,"clear")) clear();
else if (!strcmp(command,"echo")) echo();
else if (!strcmp(command,"if")) ifthenelse();
else if (!strcmp(command,"include")) include();
else if (!strcmp(command,"jump")) jump();
else if (!strcmp(command,"label")) label();
else if (!strcmp(command,"log")) log();
else if (!strcmp(command,"next")) next_command();
else if (!strcmp(command,"print")) print();
else if (!strcmp(command,"shell")) shell();
else if (!strcmp(command,"variable")) variable_command();
else if (!strcmp(command,"angle_coeff")) angle_coeff();
else if (!strcmp(command,"angle_style")) angle_style();
else if (!strcmp(command,"atom_modify")) atom_modify();
else if (!strcmp(command,"atom_style")) atom_style();
else if (!strcmp(command,"bond_coeff")) bond_coeff();
else if (!strcmp(command,"bond_style")) bond_style();
else if (!strcmp(command,"boundary")) boundary();
else if (!strcmp(command,"communicate")) communicate();
else if (!strcmp(command,"compute")) compute();
else if (!strcmp(command,"compute_modify")) compute_modify();
else if (!strcmp(command,"dielectric")) dielectric();
else if (!strcmp(command,"dihedral_coeff")) dihedral_coeff();
else if (!strcmp(command,"dihedral_style")) dihedral_style();
else if (!strcmp(command,"dimension")) dimension();
else if (!strcmp(command,"dump")) dump();
else if (!strcmp(command,"dump_modify")) dump_modify();
else if (!strcmp(command,"fix")) fix();
else if (!strcmp(command,"fix_modify")) fix_modify();
else if (!strcmp(command,"group")) group_command();
else if (!strcmp(command,"improper_coeff")) improper_coeff();
else if (!strcmp(command,"improper_style")) improper_style();
else if (!strcmp(command,"kspace_modify")) kspace_modify();
else if (!strcmp(command,"kspace_style")) kspace_style();
else if (!strcmp(command,"lattice")) lattice();
else if (!strcmp(command,"mass")) mass();
else if (!strcmp(command,"min_modify")) min_modify();
else if (!strcmp(command,"min_style")) min_style();
else if (!strcmp(command,"neigh_modify")) neigh_modify();
else if (!strcmp(command,"neighbor")) neighbor_command();
else if (!strcmp(command,"newton")) newton();
else if (!strcmp(command,"package")) package();
else if (!strcmp(command,"pair_coeff")) pair_coeff();
else if (!strcmp(command,"pair_modify")) pair_modify();
else if (!strcmp(command,"pair_style")) pair_style();
else if (!strcmp(command,"pair_write")) pair_write();
else if (!strcmp(command,"processors")) processors();
else if (!strcmp(command,"region")) region();
else if (!strcmp(command,"reset_timestep")) reset_timestep();
else if (!strcmp(command,"restart")) restart();
else if (!strcmp(command,"run_style")) run_style();
else if (!strcmp(command,"special_bonds")) special_bonds();
else if (!strcmp(command,"suffix")) suffix();
else if (!strcmp(command,"thermo")) thermo();
else if (!strcmp(command,"thermo_modify")) thermo_modify();
else if (!strcmp(command,"thermo_style")) thermo_style();
else if (!strcmp(command,"timestep")) timestep();
else if (!strcmp(command,"uncompute")) uncompute();
else if (!strcmp(command,"undump")) undump();
else if (!strcmp(command,"unfix")) unfix();
else if (!strcmp(command,"units")) units();
else flag = 0;
// return if command was listed above
if (flag) return 0;
// check if command is added via style.h
if (0) return 0; // dummy line to enable else-if macro expansion
#define COMMAND_CLASS
#define CommandStyle(key,Class) \
else if (strcmp(command,#key) == 0) { \
Class key(lmp); \
key.command(narg,arg); \
return 0; \
}
#include "style_command.h"
#undef COMMAND_CLASS
// unrecognized command
return -1;
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void Input::clear()
{
- if (narg > 0) error->all("Illegal clear command");
+ if (narg > 0) error->all(FLERR,"Illegal clear command");
lmp->destroy();
lmp->create();
}
/* ---------------------------------------------------------------------- */
void Input::echo()
{
- if (narg != 1) error->all("Illegal echo command");
+ if (narg != 1) error->all(FLERR,"Illegal echo command");
if (strcmp(arg[0],"none") == 0) {
echo_screen = 0;
echo_log = 0;
} else if (strcmp(arg[0],"screen") == 0) {
echo_screen = 1;
echo_log = 0;
} else if (strcmp(arg[0],"log") == 0) {
echo_screen = 0;
echo_log = 1;
} else if (strcmp(arg[0],"both") == 0) {
echo_screen = 1;
echo_log = 1;
- } else error->all("Illegal echo command");
+ } else error->all(FLERR,"Illegal echo command");
}
/* ---------------------------------------------------------------------- */
void Input::ifthenelse()
{
- if (narg < 3) error->all("Illegal if command");
+ if (narg < 3) error->all(FLERR,"Illegal if command");
// substitute for variables in Boolean expression for "if"
// in case expression was enclosed in quotes
// must substitute on copy of arg else will step on subsequent args
char *scopy = new char[MAXLINE];
strcpy(scopy,arg[0]);
substitute(scopy,0);
// evaluate Boolean expression for "if"
double btest = variable->evaluate_boolean(scopy);
// bound "then" commands
- if (strcmp(arg[1],"then") != 0) error->all("Illegal if command");
+ if (strcmp(arg[1],"then") != 0) error->all(FLERR,"Illegal if command");
int first = 2;
int iarg = first;
while (iarg < narg &&
(strcmp(arg[iarg],"elif") != 0 && strcmp(arg[iarg],"else") != 0))
iarg++;
int last = iarg-1;
// execute "then" commands
// make copies of all arg string commands
// required because re-parsing a command via one() will wipe out args
if (btest != 0.0) {
int ncommands = last-first + 1;
- if (ncommands <= 0) error->all("Illegal if command");
+ if (ncommands <= 0) error->all(FLERR,"Illegal if command");
char **commands = new char*[ncommands];
ncommands = 0;
for (int i = first; i <= last; i++) {
int n = strlen(arg[i]) + 1;
- if (n == 1) error->all("Illegal if command");
+ if (n == 1) error->all(FLERR,"Illegal if command");
commands[ncommands] = new char[n];
strcpy(commands[ncommands],arg[i]);
ncommands++;
}
for (int i = 0; i < ncommands; i++) input->one(commands[i]);
for (int i = 0; i < ncommands; i++) delete [] commands[i];
delete [] commands;
delete [] scopy;
return;
}
// done if no "elif" or "else"
if (iarg == narg) {
delete [] scopy;
return;
}
// check "elif" or "else" until find commands to execute
// substitute for variables and evaluate Boolean expression for "elif"
// must substitute on copy of arg else will step on subsequent args
// bound and execute "elif" or "else" commands
while (1) {
- if (iarg+2 > narg) error->all("Illegal if command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal if command");
if (strcmp(arg[iarg],"elif") == 0) {
strcpy(scopy,arg[iarg+1]);
substitute(scopy,0);
btest = variable->evaluate_boolean(scopy);
first = iarg+2;
} else {
btest = 1.0;
first = iarg+1;
}
iarg = first;
while (iarg < narg &&
(strcmp(arg[iarg],"elif") != 0 && strcmp(arg[iarg],"else") != 0))
iarg++;
last = iarg-1;
if (btest == 0.0) continue;
int ncommands = last-first + 1;
- if (ncommands <= 0) error->all("Illegal if command");
+ if (ncommands <= 0) error->all(FLERR,"Illegal if command");
char **commands = new char*[ncommands];
ncommands = 0;
for (int i = first; i <= last; i++) {
int n = strlen(arg[i]) + 1;
- if (n == 1) error->all("Illegal if command");
+ if (n == 1) error->all(FLERR,"Illegal if command");
commands[ncommands] = new char[n];
strcpy(commands[ncommands],arg[i]);
ncommands++;
}
// execute the list of commands
for (int i = 0; i < ncommands; i++) input->one(commands[i]);
// clean up
for (int i = 0; i < ncommands; i++) delete [] commands[i];
delete [] commands;
delete [] scopy;
return;
}
}
/* ---------------------------------------------------------------------- */
void Input::include()
{
- if (narg != 1) error->all("Illegal include command");
+ if (narg != 1) error->all(FLERR,"Illegal include command");
if (me == 0) {
if (nfile == maxfile) {
maxfile++;
infiles = (FILE **)
memory->srealloc(infiles,maxfile*sizeof(FILE *),"input:infiles");
}
infile = fopen(arg[0],"r");
if (infile == NULL) {
char str[128];
sprintf(str,"Cannot open input script %s",arg[0]);
- error->one(str);
+ error->one(FLERR,str);
}
infiles[nfile++] = infile;
}
}
/* ---------------------------------------------------------------------- */
void Input::jump()
{
- if (narg < 1 || narg > 2) error->all("Illegal jump command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal jump command");
if (jump_skip) {
jump_skip = 0;
return;
}
if (me == 0) {
if (strcmp(arg[0],"SELF") == 0) rewind(infile);
else {
if (infile != stdin) fclose(infile);
infile = fopen(arg[0],"r");
if (infile == NULL) {
char str[128];
sprintf(str,"Cannot open input script %s",arg[0]);
- error->one(str);
+ error->one(FLERR,str);
}
infiles[nfile-1] = infile;
}
}
if (narg == 2) {
label_active = 1;
if (labelstr) delete [] labelstr;
int n = strlen(arg[1]) + 1;
labelstr = new char[n];
strcpy(labelstr,arg[1]);
}
}
/* ---------------------------------------------------------------------- */
void Input::label()
{
- if (narg != 1) error->all("Illegal label command");
+ if (narg != 1) error->all(FLERR,"Illegal label command");
if (label_active && strcmp(labelstr,arg[0]) == 0) label_active = 0;
}
/* ---------------------------------------------------------------------- */
void Input::log()
{
- if (narg != 1) error->all("Illegal log command");
+ if (narg != 1) error->all(FLERR,"Illegal log command");
if (me == 0) {
if (logfile) fclose(logfile);
if (strcmp(arg[0],"none") == 0) logfile = NULL;
else {
logfile = fopen(arg[0],"w");
if (logfile == NULL) {
char str[128];
sprintf(str,"Cannot open logfile %s",arg[0]);
- error->one(str);
+ error->one(FLERR,str);
}
}
if (universe->nworlds == 1) universe->ulogfile = logfile;
}
}
/* ---------------------------------------------------------------------- */
void Input::next_command()
{
if (variable->next(narg,arg)) jump_skip = 1;
}
/* ---------------------------------------------------------------------- */
void Input::print()
{
- if (narg != 1) error->all("Illegal print command");
+ if (narg != 1) error->all(FLERR,"Illegal print command");
// substitute for $ variables (no printing) and print arg
substitute(arg[0],0);
if (me == 0) {
if (screen) fprintf(screen,"%s\n",arg[0]);
if (logfile) fprintf(logfile,"%s\n",arg[0]);
}
}
/* ---------------------------------------------------------------------- */
void Input::shell()
{
- if (narg < 1) error->all("Illegal shell command");
+ if (narg < 1) error->all(FLERR,"Illegal shell command");
if (strcmp(arg[0],"cd") == 0) {
- if (narg != 2) error->all("Illegal shell command");
+ if (narg != 2) error->all(FLERR,"Illegal shell command");
chdir(arg[1]);
} else if (strcmp(arg[0],"mkdir") == 0) {
- if (narg < 2) error->all("Illegal shell command");
+ if (narg < 2) error->all(FLERR,"Illegal shell command");
#if !defined(WINDOWS) && !defined(__MINGW32_VERSION)
if (me == 0)
for (int i = 1; i < narg; i++)
mkdir(arg[i], S_IRWXU | S_IRGRP | S_IXGRP);
#endif
} else if (strcmp(arg[0],"mv") == 0) {
- if (narg != 3) error->all("Illegal shell command");
+ if (narg != 3) error->all(FLERR,"Illegal shell command");
if (me == 0) rename(arg[1],arg[2]);
} else if (strcmp(arg[0],"rm") == 0) {
- if (narg < 2) error->all("Illegal shell command");
+ if (narg < 2) error->all(FLERR,"Illegal shell command");
if (me == 0)
for (int i = 1; i < narg; i++) unlink(arg[i]);
} else if (strcmp(arg[0],"rmdir") == 0) {
- if (narg < 2) error->all("Illegal shell command");
+ if (narg < 2) error->all(FLERR,"Illegal shell command");
if (me == 0)
for (int i = 1; i < narg; i++) rmdir(arg[i]);
// use work to concat args back into one string separated by spaces
// invoke string in shell via system()
} else {
strcpy(work,arg[0]);
for (int i = 1; i < narg; i++) {
strcat(work," ");
strcat(work,arg[i]);
}
if (me == 0) system(work);
}
}
/* ---------------------------------------------------------------------- */
void Input::variable_command()
{
variable->set(narg,arg);
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
one function for each LAMMPS-specific input script command
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void Input::angle_coeff()
{
if (domain->box_exist == 0)
- error->all("Angle_coeff command before simulation box is defined");
+ error->all(FLERR,"Angle_coeff command before simulation box is defined");
if (force->angle == NULL)
- error->all("Angle_coeff command before angle_style is defined");
+ error->all(FLERR,"Angle_coeff command before angle_style is defined");
if (atom->avec->angles_allow == 0)
- error->all("Angle_coeff command when no angles allowed");
+ error->all(FLERR,"Angle_coeff command when no angles allowed");
force->angle->coeff(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::angle_style()
{
- if (narg < 1) error->all("Illegal angle_style command");
+ if (narg < 1) error->all(FLERR,"Illegal angle_style command");
if (atom->avec->angles_allow == 0)
- error->all("Angle_style command when no angles allowed");
+ error->all(FLERR,"Angle_style command when no angles allowed");
force->create_angle(arg[0]);
if (force->angle) force->angle->settings(narg-1,&arg[1]);
}
/* ---------------------------------------------------------------------- */
void Input::atom_modify()
{
atom->modify_params(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::atom_style()
{
- if (narg < 1) error->all("Illegal atom_style command");
+ if (narg < 1) error->all(FLERR,"Illegal atom_style command");
if (domain->box_exist)
- error->all("Atom_style command after simulation box is defined");
+ error->all(FLERR,"Atom_style command after simulation box is defined");
atom->create_avec(arg[0],narg-1,&arg[1],lmp->suffix);
}
/* ---------------------------------------------------------------------- */
void Input::bond_coeff()
{
if (domain->box_exist == 0)
- error->all("Bond_coeff command before simulation box is defined");
+ error->all(FLERR,"Bond_coeff command before simulation box is defined");
if (force->bond == NULL)
- error->all("Bond_coeff command before bond_style is defined");
+ error->all(FLERR,"Bond_coeff command before bond_style is defined");
if (atom->avec->bonds_allow == 0)
- error->all("Bond_coeff command when no bonds allowed");
+ error->all(FLERR,"Bond_coeff command when no bonds allowed");
force->bond->coeff(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::bond_style()
{
- if (narg < 1) error->all("Illegal bond_style command");
+ if (narg < 1) error->all(FLERR,"Illegal bond_style command");
if (atom->avec->bonds_allow == 0)
- error->all("Bond_style command when no bonds allowed");
+ error->all(FLERR,"Bond_style command when no bonds allowed");
force->create_bond(arg[0]);
if (force->bond) force->bond->settings(narg-1,&arg[1]);
}
/* ---------------------------------------------------------------------- */
void Input::boundary()
{
if (domain->box_exist)
- error->all("Boundary command after simulation box is defined");
+ error->all(FLERR,"Boundary command after simulation box is defined");
domain->set_boundary(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::communicate()
{
comm->set(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::compute()
{
modify->add_compute(narg,arg,lmp->suffix);
}
/* ---------------------------------------------------------------------- */
void Input::compute_modify()
{
modify->modify_compute(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::dielectric()
{
- if (narg != 1) error->all("Illegal dielectric command");
+ if (narg != 1) error->all(FLERR,"Illegal dielectric command");
force->dielectric = atof(arg[0]);
}
/* ---------------------------------------------------------------------- */
void Input::dihedral_coeff()
{
if (domain->box_exist == 0)
- error->all("Dihedral_coeff command before simulation box is defined");
+ error->all(FLERR,"Dihedral_coeff command before simulation box is defined");
if (force->dihedral == NULL)
- error->all("Dihedral_coeff command before dihedral_style is defined");
+ error->all(FLERR,"Dihedral_coeff command before dihedral_style is defined");
if (atom->avec->dihedrals_allow == 0)
- error->all("Dihedral_coeff command when no dihedrals allowed");
+ error->all(FLERR,"Dihedral_coeff command when no dihedrals allowed");
force->dihedral->coeff(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::dihedral_style()
{
- if (narg < 1) error->all("Illegal dihedral_style command");
+ if (narg < 1) error->all(FLERR,"Illegal dihedral_style command");
if (atom->avec->dihedrals_allow == 0)
- error->all("Dihedral_style command when no dihedrals allowed");
+ error->all(FLERR,"Dihedral_style command when no dihedrals allowed");
force->create_dihedral(arg[0]);
if (force->dihedral) force->dihedral->settings(narg-1,&arg[1]);
}
/* ---------------------------------------------------------------------- */
void Input::dimension()
{
- if (narg != 1) error->all("Illegal dimension command");
+ if (narg != 1) error->all(FLERR,"Illegal dimension command");
if (domain->box_exist)
- error->all("Dimension command after simulation box is defined");
+ error->all(FLERR,"Dimension command after simulation box is defined");
domain->dimension = atoi(arg[0]);
if (domain->dimension != 2 && domain->dimension != 3)
- error->all("Illegal dimension command");
+ error->all(FLERR,"Illegal dimension command");
// must reset default extra_dof of all computes
// since some were created before dimension command is encountered
for (int i = 0; i < modify->ncompute; i++)
modify->compute[i]->reset_extra_dof();
}
/* ---------------------------------------------------------------------- */
void Input::dump()
{
output->add_dump(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::dump_modify()
{
output->modify_dump(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::fix()
{
modify->add_fix(narg,arg,lmp->suffix);
}
/* ---------------------------------------------------------------------- */
void Input::fix_modify()
{
modify->modify_fix(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::group_command()
{
group->assign(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::improper_coeff()
{
if (domain->box_exist == 0)
- error->all("Improper_coeff command before simulation box is defined");
+ error->all(FLERR,"Improper_coeff command before simulation box is defined");
if (force->improper == NULL)
- error->all("Improper_coeff command before improper_style is defined");
+ error->all(FLERR,"Improper_coeff command before improper_style is defined");
if (atom->avec->impropers_allow == 0)
- error->all("Improper_coeff command when no impropers allowed");
+ error->all(FLERR,"Improper_coeff command when no impropers allowed");
force->improper->coeff(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::improper_style()
{
- if (narg < 1) error->all("Illegal improper_style command");
+ if (narg < 1) error->all(FLERR,"Illegal improper_style command");
if (atom->avec->impropers_allow == 0)
- error->all("Improper_style command when no impropers allowed");
+ error->all(FLERR,"Improper_style command when no impropers allowed");
force->create_improper(arg[0]);
if (force->improper) force->improper->settings(narg-1,&arg[1]);
}
/* ---------------------------------------------------------------------- */
void Input::kspace_modify()
{
- if (force->kspace == NULL) error->all("KSpace style has not yet been set");
+ if (force->kspace == NULL) error->all(FLERR,"KSpace style has not yet been set");
force->kspace->modify_params(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::kspace_style()
{
force->create_kspace(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::lattice()
{
domain->set_lattice(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::mass()
{
- if (narg != 2) error->all("Illegal mass command");
+ if (narg != 2) error->all(FLERR,"Illegal mass command");
if (domain->box_exist == 0)
- error->all("Mass command before simulation box is defined");
+ error->all(FLERR,"Mass command before simulation box is defined");
atom->set_mass(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::min_modify()
{
update->minimize->modify_params(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::min_style()
{
if (domain->box_exist == 0)
- error->all("Min_style command before simulation box is defined");
+ error->all(FLERR,"Min_style command before simulation box is defined");
update->create_minimize(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::neigh_modify()
{
neighbor->modify_params(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::neighbor_command()
{
neighbor->set(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::newton()
{
int newton_pair,newton_bond;
if (narg == 1) {
if (strcmp(arg[0],"off") == 0) newton_pair = newton_bond = 0;
else if (strcmp(arg[0],"on") == 0) newton_pair = newton_bond = 1;
- else error->all("Illegal newton command");
+ else error->all(FLERR,"Illegal newton command");
} else if (narg == 2) {
if (strcmp(arg[0],"off") == 0) newton_pair = 0;
else if (strcmp(arg[0],"on") == 0) newton_pair= 1;
- else error->all("Illegal newton command");
+ else error->all(FLERR,"Illegal newton command");
if (strcmp(arg[1],"off") == 0) newton_bond = 0;
else if (strcmp(arg[1],"on") == 0) newton_bond = 1;
- else error->all("Illegal newton command");
- } else error->all("Illegal newton command");
+ else error->all(FLERR,"Illegal newton command");
+ } else error->all(FLERR,"Illegal newton command");
force->newton_pair = newton_pair;
if (newton_bond == 0) {
if (domain->box_exist && force->newton_bond == 1)
- error->all("Newton bond change after simulation box is defined");
+ error->all(FLERR,"Newton bond change after simulation box is defined");
force->newton_bond = 0;
} else {
if (domain->box_exist && force->newton_bond == 0)
- error->all("Newton bond change after simulation box is defined");
+ error->all(FLERR,"Newton bond change after simulation box is defined");
force->newton_bond = 1;
}
if (newton_pair || newton_bond) force->newton = 1;
else force->newton = 0;
}
/* ---------------------------------------------------------------------- */
void Input::package()
{
if (domain->box_exist)
- error->all("Package command after simulation box is defined");
- if (narg < 1) error->all("Illegal package command");
+ error->all(FLERR,"Package command after simulation box is defined");
+ if (narg < 1) error->all(FLERR,"Illegal package command");
if (strcmp(arg[0],"cuda") == 0) {
if (!lmp->cuda)
- error->all("Package cuda command without USER-CUDA installed");
+ error->all(FLERR,"Package cuda command without USER-CUDA installed");
lmp->cuda->accelerator(narg-1,&arg[1]);
} else if (strcmp(arg[0],"gpu") == 0) {
char **fixarg = new char*[2+narg];
fixarg[0] = "package_gpu";
fixarg[1] = "all";
fixarg[2] = "GPU";
for (int i = 1; i < narg; i++) fixarg[i+2] = arg[i];
modify->allow_early_fix = 1;
modify->add_fix(2+narg,fixarg,NULL);
modify->allow_early_fix = 0;
delete [] fixarg;
} else if (strcmp(arg[0],"omp") == 0) {
#ifdef _OPENMP
- if (narg != 2) error->all("Illegal package command");
+ if (narg != 2) error->all(FLERR,"Illegal package command");
comm->nthreads = atoi(arg[1]);
- if (comm->nthreads < 1) error->all("Illegal package command");
+ if (comm->nthreads < 1) error->all(FLERR,"Illegal package command");
omp_set_num_threads(comm->nthreads);
if (me == 0) {
if (screen)
fprintf(screen," reset %d OpenMP thread(s) per MPI task\n",
comm->nthreads);
if (logfile)
fprintf(logfile," reset %d OpenMP thread(s) per MPI task\n",
comm->nthreads);
}
#else
- error->all("Cannot use package omp command with no OpenMP support");
+ error->all(FLERR,"Cannot use package omp command with no OpenMP support");
#endif
- } else error->all("Illegal package command");
+ } else error->all(FLERR,"Illegal package command");
}
/* ---------------------------------------------------------------------- */
void Input::pair_coeff()
{
if (domain->box_exist == 0)
- error->all("Pair_coeff command before simulation box is defined");
+ error->all(FLERR,"Pair_coeff command before simulation box is defined");
if (force->pair == NULL)
- error->all("Pair_coeff command before pair_style is defined");
+ error->all(FLERR,"Pair_coeff command before pair_style is defined");
force->pair->coeff(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::pair_modify()
{
if (force->pair == NULL)
- error->all("Pair_modify command before pair_style is defined");
+ error->all(FLERR,"Pair_modify command before pair_style is defined");
force->pair->modify_params(narg,arg);
}
/* ----------------------------------------------------------------------
if old pair style exists and new style is same, just change settings
else create new pair class
------------------------------------------------------------------------- */
void Input::pair_style()
{
- if (narg < 1) error->all("Illegal pair_style command");
+ if (narg < 1) error->all(FLERR,"Illegal pair_style command");
if (force->pair && strcmp(arg[0],force->pair_style) == 0) {
force->pair->settings(narg-1,&arg[1]);
return;
}
force->create_pair(arg[0],lmp->suffix);
if (force->pair) force->pair->settings(narg-1,&arg[1]);
}
/* ---------------------------------------------------------------------- */
void Input::pair_write()
{
if (force->pair == NULL)
- error->all("Pair_write command before pair_style is defined");
+ error->all(FLERR,"Pair_write command before pair_style is defined");
force->pair->write_file(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::processors()
{
- if (narg != 3) error->all("Illegal processors command");
+ if (narg != 3) error->all(FLERR,"Illegal processors command");
if (domain->box_exist)
- error->all("Processors command after simulation box is defined");
+ error->all(FLERR,"Processors command after simulation box is defined");
if (strcmp(arg[0],"*") == 0) comm->user_procgrid[0] = 0;
else comm->user_procgrid[0] = atoi(arg[0]);
if (strcmp(arg[1],"*") == 0) comm->user_procgrid[1] = 0;
else comm->user_procgrid[1] = atoi(arg[1]);
if (strcmp(arg[2],"*") == 0) comm->user_procgrid[2] = 0;
else comm->user_procgrid[2] = atoi(arg[2]);
if (comm->user_procgrid[0] < 0 || comm->user_procgrid[1] < 0 ||
- comm->user_procgrid[2] < 0) error->all("Illegal processors command");
+ comm->user_procgrid[2] < 0) error->all(FLERR,"Illegal processors command");
}
/* ---------------------------------------------------------------------- */
void Input::region()
{
domain->add_region(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::reset_timestep()
{
update->reset_timestep(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::restart()
{
output->create_restart(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::run_style()
{
if (domain->box_exist == 0)
- error->all("Run_style command before simulation box is defined");
+ error->all(FLERR,"Run_style command before simulation box is defined");
update->create_integrate(narg,arg,lmp->suffix);
}
/* ---------------------------------------------------------------------- */
void Input::special_bonds()
{
// store 1-3,1-4 and dihedral/extra flag values before change
// change in 1-2 coeffs will not change the special list
double lj2 = force->special_lj[2];
double lj3 = force->special_lj[3];
double coul2 = force->special_coul[2];
double coul3 = force->special_coul[3];
int angle = force->special_angle;
int dihedral = force->special_dihedral;
int extra = force->special_extra;
force->set_special(narg,arg);
// if simulation box defined and saved values changed, redo special list
if (domain->box_exist && atom->molecular) {
if (lj2 != force->special_lj[2] || lj3 != force->special_lj[3] ||
coul2 != force->special_coul[2] || coul3 != force->special_coul[3] ||
angle != force->special_angle ||
dihedral != force->special_dihedral ||
extra != force->special_extra) {
Special special(lmp);
special.build();
}
}
}
/* ---------------------------------------------------------------------- */
void Input::suffix()
{
- if (narg != 1) error->all("Illegal suffix command");
+ if (narg != 1) error->all(FLERR,"Illegal suffix command");
if (strcmp(arg[0],"off") == 0) lmp->suffix_enable = 0;
else if (strcmp(arg[0],"on") == 0) lmp->suffix_enable = 1;
else {
delete [] lmp->suffix;
int n = strlen(arg[0]) + 1;
lmp->suffix = new char[n];
strcpy(lmp->suffix,arg[0]);
lmp->suffix_enable = 1;
}
}
/* ---------------------------------------------------------------------- */
void Input::thermo()
{
- if (narg != 1) error->all("Illegal thermo command");
+ if (narg != 1) error->all(FLERR,"Illegal thermo command");
output->thermo_every = atoi(arg[0]);
}
/* ---------------------------------------------------------------------- */
void Input::thermo_modify()
{
output->thermo->modify_params(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::thermo_style()
{
output->create_thermo(narg,arg);
}
/* ---------------------------------------------------------------------- */
void Input::timestep()
{
- if (narg != 1) error->all("Illegal timestep command");
+ if (narg != 1) error->all(FLERR,"Illegal timestep command");
update->dt = atof(arg[0]);
}
/* ---------------------------------------------------------------------- */
void Input::uncompute()
{
- if (narg != 1) error->all("Illegal uncompute command");
+ if (narg != 1) error->all(FLERR,"Illegal uncompute command");
modify->delete_compute(arg[0]);
}
/* ---------------------------------------------------------------------- */
void Input::undump()
{
- if (narg != 1) error->all("Illegal undump command");
+ if (narg != 1) error->all(FLERR,"Illegal undump command");
output->delete_dump(arg[0]);
}
/* ---------------------------------------------------------------------- */
void Input::unfix()
{
- if (narg != 1) error->all("Illegal unfix command");
+ if (narg != 1) error->all(FLERR,"Illegal unfix command");
modify->delete_fix(arg[0]);
}
/* ---------------------------------------------------------------------- */
void Input::units()
{
- if (narg != 1) error->all("Illegal units command");
+ if (narg != 1) error->all(FLERR,"Illegal units command");
if (domain->box_exist)
- error->all("Units command after simulation box is defined");
+ error->all(FLERR,"Units command after simulation box is defined");
update->set_units(arg[0]);
}
diff --git a/src/irregular.cpp b/src/irregular.cpp
index d9abe11b8..fe801ae45 100644
--- a/src/irregular.cpp
+++ b/src/irregular.cpp
@@ -1,676 +1,673 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "irregular.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "comm.h"
#include "memory.h"
using namespace LAMMPS_NS;
#define BUFFACTOR 1.5
#define BUFMIN 1000
#define BUFEXTRA 1000
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
Irregular::Irregular(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
triclinic = domain->triclinic;
map_style = atom->map_style;
procgrid = comm->procgrid;
grid2proc = comm->grid2proc;
aplan = NULL;
dplan = NULL;
// initialize buffers for atom comm, not used for datum comm
// these can persist for multiple irregular operations
maxsend = BUFMIN;
memory->create(buf_send,maxsend+BUFEXTRA,"comm:buf_send");
maxrecv = BUFMIN;
memory->create(buf_recv,maxrecv,"comm:buf_recv");
}
/* ---------------------------------------------------------------------- */
Irregular::~Irregular()
{
if (aplan) destroy_atom();
if (dplan) destroy_data();
memory->destroy(buf_send);
memory->destroy(buf_recv);
}
/* ----------------------------------------------------------------------
communicate atoms to new owning procs via irregular communication
can be used in place of comm->exchange()
unlike exchange(), allows atoms to have moved arbitrarily long distances
sets up irregular plan, invokes it, destroys it
atoms must be remapped to be inside simulation box before this is called
for triclinic: atoms must be in lamda coords (0-1) before this is called
------------------------------------------------------------------------- */
void Irregular::migrate_atoms()
{
// clear global->local map since atoms move to new procs
// clear old ghosts so map_set() at end will operate only on local atoms
// exchange() doesn't need to clear ghosts b/c borders()
// is called right after and it clears ghosts and calls map_set()
if (map_style) atom->map_clear();
atom->nghost = 0;
atom->avec->clear_bonus();
// subbox bounds for orthogonal or triclinic
double *sublo,*subhi;
if (triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
// loop over atoms, flag any that are not in my sub-box
// fill buffer with atoms leaving my box, using < and >=
// assign which proc it belongs to via coord2proc()
// if coord2proc() returns me, due to round-off
// in triclinic x2lamda(), then keep atom and don't send
// when atom is deleted, fill it in with last atom
AtomVec *avec = atom->avec;
double **x = atom->x;
int nlocal = atom->nlocal;
int nsend = 0;
int nsendatom = 0;
int *sizes = new int[nlocal];
int *proclist = new int[nlocal];
int i = 0;
while (i < nlocal) {
if (x[i][0] < sublo[0] || x[i][0] >= subhi[0] ||
x[i][1] < sublo[1] || x[i][1] >= subhi[1] ||
x[i][2] < sublo[2] || x[i][2] >= subhi[2]) {
proclist[nsendatom] = coord2proc(x[i]);
if (proclist[nsendatom] != me) {
if (nsend > maxsend) grow_send(nsend,1);
sizes[nsendatom] = avec->pack_exchange(i,&buf_send[nsend]);
nsend += sizes[nsendatom];
nsendatom++;
avec->copy(nlocal-1,i,1);
nlocal--;
} else i++;
} else i++;
}
atom->nlocal = nlocal;
// create irregular communication plan, perform comm, destroy plan
// returned nrecv = size of buffer needed for incoming atoms
int nrecv = create_atom(nsendatom,sizes,proclist);
if (nrecv > maxrecv) grow_recv(nrecv);
exchange_atom(buf_send,sizes,buf_recv);
destroy_atom();
delete [] sizes;
delete [] proclist;
// add received atoms to my list
int m = 0;
while (m < nrecv) m += avec->unpack_exchange(&buf_recv[m]);
// reset global->local map
if (map_style) atom->map_set();
}
/* ----------------------------------------------------------------------
create a communication plan for atoms
n = # of atoms to send
sizes = # of doubles for each atom
proclist = proc to send each atom to (not including self)
return total # of doubles I will recv (not including self)
------------------------------------------------------------------------- */
int Irregular::create_atom(int n, int *sizes, int *proclist)
{
int i;
// allocate plan and work vectors
if (aplan) destroy_atom();
aplan = (PlanAtom *) memory->smalloc(sizeof(PlanAtom),"irregular:aplan");
int *list = new int[nprocs];
int *count = new int[nprocs];
// nrecv = # of messages I receive
for (i = 0; i < nprocs; i++) {
list[i] = 0;
count[i] = 1;
}
for (i = 0; i < n; i++) list[proclist[i]] = 1;
int nrecv;
MPI_Reduce_scatter(list,&nrecv,count,MPI_INT,MPI_SUM,world);
// allocate receive arrays
int *proc_recv = new int[nrecv];
int *length_recv = new int[nrecv];
MPI_Request *request = new MPI_Request[nrecv];
MPI_Status *status = new MPI_Status[nrecv];
// nsend = # of messages I send
for (i = 0; i < nprocs; i++) list[i] = 0;
for (i = 0; i < n; i++) list[proclist[i]] += sizes[i];
int nsend = 0;
for (i = 0; i < nprocs; i++)
if (list[i]) nsend++;
// allocate send arrays
int *proc_send = new int[nsend];
int *length_send = new int[nsend];
int *num_send = new int[nsend];
int *index_send = new int[n];
int *offset_send = new int[n];
// list still stores size of message for procs I send to
// proc_send = procs I send to
// length_send = total size of message I send to each proc
// to balance pattern of send messages:
// each proc begins with iproc > me, continues until iproc = me
// reset list to store which send message each proc corresponds to
int iproc = me;
int isend = 0;
for (i = 0; i < nprocs; i++) {
iproc++;
if (iproc == nprocs) iproc = 0;
if (list[iproc] > 0) {
proc_send[isend] = iproc;
length_send[isend] = list[iproc];
list[iproc] = isend;
isend++;
}
}
// num_send = # of atoms I send to each proc
for (i = 0; i < nsend; i++) num_send[i] = 0;
for (i = 0; i < n; i++) {
isend = list[proclist[i]];
num_send[isend]++;
}
// count = offsets into index_send for each proc I send to
// index_send = list of which atoms to send to each proc
// 1st N1 values are atom indices for 1st proc,
// next N2 values are atom indices for 2nd proc, etc
// offset_send = where each atom starts in send buffer
count[0] = 0;
for (i = 1; i < nsend; i++) count[i] = count[i-1] + num_send[i-1];
for (i = 0; i < n; i++) {
isend = list[proclist[i]];
index_send[count[isend]++] = i;
if (i) offset_send[i] = offset_send[i-1] + sizes[i-1];
else offset_send[i] = 0;
}
// tell receivers how much data I send
// sendmax = largest # of doubles I send in a single message
int sendmax = 0;
for (i = 0; i < nsend; i++) {
MPI_Send(&length_send[i],1,MPI_INT,proc_send[i],0,world);
sendmax = MAX(sendmax,length_send[i]);
}
// receive incoming messages
// proc_recv = procs I recv from
// length_recv = total size of message each proc sends me
// nrecvsize = total size of data I recv
int nrecvsize = 0;
for (i = 0; i < nrecv; i++) {
MPI_Recv(&length_recv[i],1,MPI_INT,MPI_ANY_SOURCE,0,world,status);
proc_recv[i] = status->MPI_SOURCE;
nrecvsize += length_recv[i];
}
// barrier to insure all MPI_ANY_SOURCE messages are received
// else another proc could proceed to exchange_atom() and send to me
MPI_Barrier(world);
// free work vectors
delete [] count;
delete [] list;
// initialize plan
aplan->nsend = nsend;
aplan->nrecv = nrecv;
aplan->sendmax = sendmax;
aplan->proc_send = proc_send;
aplan->length_send = length_send;
aplan->num_send = num_send;
aplan->index_send = index_send;
aplan->offset_send = offset_send;
aplan->proc_recv = proc_recv;
aplan->length_recv = length_recv;
aplan->request = request;
aplan->status = status;
return nrecvsize;
}
/* ----------------------------------------------------------------------
communicate atoms via PlanAtom
sendbuf = list of atoms to send
sizes = # of doubles for each atom
recvbuf = received atoms
------------------------------------------------------------------------- */
void Irregular::exchange_atom(double *sendbuf, int *sizes, double *recvbuf)
{
int i,m,n,offset,num_send;
// post all receives
offset = 0;
for (int irecv = 0; irecv < aplan->nrecv; irecv++) {
MPI_Irecv(&recvbuf[offset],aplan->length_recv[irecv],MPI_DOUBLE,
aplan->proc_recv[irecv],0,world,&aplan->request[irecv]);
offset += aplan->length_recv[irecv];
}
// allocate buf for largest send
double *buf;
memory->create(buf,aplan->sendmax,"irregular:buf");
// send each message
// pack buf with list of atoms
// m = index of atom in sendbuf
int *index_send = aplan->index_send;
int nsend = aplan->nsend;
n = 0;
for (int isend = 0; isend < nsend; isend++) {
offset = 0;
num_send = aplan->num_send[isend];
for (i = 0; i < num_send; i++) {
m = index_send[n++];
memcpy(&buf[offset],&sendbuf[aplan->offset_send[m]],
sizes[m]*sizeof(double));
offset += sizes[m];
}
MPI_Send(buf,aplan->length_send[isend],MPI_DOUBLE,
aplan->proc_send[isend],0,world);
}
// free temporary send buffer
memory->destroy(buf);
// wait on all incoming messages
if (aplan->nrecv) MPI_Waitall(aplan->nrecv,aplan->request,aplan->status);
}
/* ----------------------------------------------------------------------
destroy communication plan for atoms
------------------------------------------------------------------------- */
void Irregular::destroy_atom()
{
delete [] aplan->proc_send;
delete [] aplan->length_send;
delete [] aplan->num_send;
delete [] aplan->index_send;
delete [] aplan->offset_send;
delete [] aplan->proc_recv;
delete [] aplan->length_recv;
delete [] aplan->request;
delete [] aplan->status;
memory->sfree(aplan);
aplan = NULL;
}
/* ----------------------------------------------------------------------
create a communication plan for datums
n = # of datums to send
proclist = proc to send each datum to (including self)
return total # of datums I will recv (including self)
------------------------------------------------------------------------- */
int Irregular::create_data(int n, int *proclist)
{
int i,m;
// allocate plan and work vectors
dplan = (PlanData *) memory->smalloc(sizeof(PlanData),"irregular:dplan");
int *list = new int[nprocs];
int *count = new int[nprocs];
// nrecv = # of messages I receive
for (i = 0; i < nprocs; i++) {
list[i] = 0;
count[i] = 1;
}
for (i = 0; i < n; i++) list[proclist[i]] = 1;
int nrecv;
MPI_Reduce_scatter(list,&nrecv,count,MPI_INT,MPI_SUM,world);
if (list[me]) nrecv--;
// allocate receive arrays
int *proc_recv = new int[nrecv];
int *num_recv = new int[nrecv];
MPI_Request *request = new MPI_Request[nrecv];
MPI_Status *status = new MPI_Status[nrecv];
// nsend = # of messages I send
for (i = 0; i < nprocs; i++) list[i] = 0;
for (i = 0; i < n; i++) list[proclist[i]]++;
int nsend = 0;
for (i = 0; i < nprocs; i++)
if (list[i]) nsend++;
if (list[me]) nsend--;
// allocate send and self arrays
int *proc_send = new int[nsend];
int *num_send = new int[nsend];
int *index_send = new int[n-list[me]];
int *index_self = new int[list[me]];
// proc_send = procs I send to
// num_send = # of datums I send to each proc
// num_self = # of datums I copy to self
// to balance pattern of send messages:
// each proc begins with iproc > me, continues until iproc = me
// reset list to store which send message each proc corresponds to
int num_self;
int iproc = me;
int isend = 0;
for (i = 0; i < nprocs; i++) {
iproc++;
if (iproc == nprocs) iproc = 0;
if (iproc == me) num_self = list[iproc];
else if (list[iproc] > 0) {
proc_send[isend] = iproc;
num_send[isend] = list[iproc];
list[iproc] = isend;
isend++;
}
}
list[me] = 0;
// count = offsets into index_send for each proc I send to
// m = ptr into index_self
// index_send = list of which datums to send to each proc
// 1st N1 values are datum indices for 1st proc,
// next N2 values are datum indices for 2nd proc, etc
count[0] = 0;
for (i = 1; i < nsend; i++) count[i] = count[i-1] + num_send[i-1];
m = 0;
for (i = 0; i < n; i++) {
iproc = proclist[i];
if (iproc == me) index_self[m++] = i;
else {
isend = list[iproc];
index_send[count[isend]++] = i;
}
}
// tell receivers how much data I send
// sendmax = largest # of datums I send in a single message
int sendmax = 0;
for (i = 0; i < nsend; i++) {
MPI_Send(&num_send[i],1,MPI_INT,proc_send[i],0,world);
sendmax = MAX(sendmax,num_send[i]);
}
// receive incoming messages
// proc_recv = procs I recv from
// num_recv = total size of message each proc sends me
// nrecvsize = total size of data I recv
int nrecvsize = 0;
for (i = 0; i < nrecv; i++) {
MPI_Recv(&num_recv[i],1,MPI_INT,MPI_ANY_SOURCE,0,world,status);
proc_recv[i] = status->MPI_SOURCE;
nrecvsize += num_recv[i];
}
nrecvsize += num_self;
// barrier to insure all MPI_ANY_SOURCE messages are received
// else another proc could proceed to exchange_data() and send to me
MPI_Barrier(world);
// free work vectors
delete [] count;
delete [] list;
// initialize plan and return it
dplan->nsend = nsend;
dplan->nrecv = nrecv;
dplan->sendmax = sendmax;
dplan->proc_send = proc_send;
dplan->num_send = num_send;
dplan->index_send = index_send;
dplan->proc_recv = proc_recv;
dplan->num_recv = num_recv;
dplan->num_self = num_self;
dplan->index_self = index_self;
dplan->request = request;
dplan->status = status;
return nrecvsize;
}
/* ----------------------------------------------------------------------
communicate datums via PlanData
sendbuf = list of datums to send
nbytes = size of each datum
recvbuf = received datums (including copied from me)
------------------------------------------------------------------------- */
void Irregular::exchange_data(char *sendbuf, int nbytes, char *recvbuf)
{
int i,m,n,offset,num_send;
// post all receives, starting after self copies
offset = dplan->num_self*nbytes;
for (int irecv = 0; irecv < dplan->nrecv; irecv++) {
MPI_Irecv(&recvbuf[offset],dplan->num_recv[irecv]*nbytes,MPI_CHAR,
dplan->proc_recv[irecv],0,world,&dplan->request[irecv]);
offset += dplan->num_recv[irecv]*nbytes;
}
// allocate buf for largest send
char *buf;
memory->create(buf,dplan->sendmax*nbytes,"irregular:buf");
// send each message
// pack buf with list of datums
// m = index of datum in sendbuf
int *index_send = dplan->index_send;
int nsend = dplan->nsend;
n = 0;
for (int isend = 0; isend < nsend; isend++) {
num_send = dplan->num_send[isend];
for (i = 0; i < num_send; i++) {
m = index_send[n++];
memcpy(&buf[i*nbytes],&sendbuf[m*nbytes],nbytes);
}
MPI_Send(buf,dplan->num_send[isend]*nbytes,MPI_CHAR,
dplan->proc_send[isend],0,world);
}
// free temporary send buffer
memory->destroy(buf);
// copy datums to self, put at beginning of recvbuf
int *index_self = dplan->index_self;
int num_self = dplan->num_self;
for (i = 0; i < num_self; i++) {
m = index_self[i];
memcpy(&recvbuf[i*nbytes],&sendbuf[m*nbytes],nbytes);
}
// wait on all incoming messages
if (dplan->nrecv) MPI_Waitall(dplan->nrecv,dplan->request,dplan->status);
}
/* ----------------------------------------------------------------------
destroy communication plan for datums
------------------------------------------------------------------------- */
void Irregular::destroy_data()
{
delete [] dplan->proc_send;
delete [] dplan->num_send;
delete [] dplan->index_send;
delete [] dplan->proc_recv;
delete [] dplan->num_recv;
delete [] dplan->index_self;
delete [] dplan->request;
delete [] dplan->status;
memory->sfree(dplan);
dplan = NULL;
}
/* ----------------------------------------------------------------------
determine which proc owns atom with coord x[3]
x will be in box (orthogonal) or lamda coords (triclinic)
------------------------------------------------------------------------- */
int Irregular::coord2proc(double *x)
{
int loc[3];
if (triclinic == 0) {
double *boxlo = domain->boxlo;
double *boxhi = domain->boxhi;
loc[0] = static_cast<int>
(procgrid[0] * (x[0]-boxlo[0]) / (boxhi[0]-boxlo[0]));
loc[1] = static_cast<int>
(procgrid[1] * (x[1]-boxlo[1]) / (boxhi[1]-boxlo[1]));
loc[2] = static_cast<int>
(procgrid[2] * (x[2]-boxlo[2]) / (boxhi[2]-boxlo[2]));
} else {
loc[0] = static_cast<int> (procgrid[0] * x[0]);
loc[1] = static_cast<int> (procgrid[1] * x[1]);
loc[2] = static_cast<int> (procgrid[2] * x[2]);
}
if (loc[0] < 0) loc[0] = 0;
if (loc[0] >= procgrid[0]) loc[0] = procgrid[0] - 1;
if (loc[1] < 0) loc[1] = 0;
if (loc[1] >= procgrid[1]) loc[1] = procgrid[1] - 1;
if (loc[2] < 0) loc[2] = 0;
if (loc[2] >= procgrid[2]) loc[2] = procgrid[2] - 1;
return grid2proc[loc[0]][loc[1]][loc[2]];
}
/* ----------------------------------------------------------------------
realloc the size of the send buffer as needed with BUFFACTOR & BUFEXTRA
if flag = 1, realloc
if flag = 0, don't need to realloc with copy, just free/malloc
------------------------------------------------------------------------- */
void Irregular::grow_send(int n, int flag)
{
maxsend = static_cast<int> (BUFFACTOR * n);
if (flag)
memory->grow(buf_send,maxsend+BUFEXTRA,"comm:buf_send");
else {
memory->destroy(buf_send);
memory->create(buf_send,maxsend+BUFEXTRA,"comm:buf_send");
}
}
/* ----------------------------------------------------------------------
free/malloc the size of the recv buffer as needed with BUFFACTOR
------------------------------------------------------------------------- */
void Irregular::grow_recv(int n)
{
maxrecv = static_cast<int> (BUFFACTOR * n);
memory->destroy(buf_recv);
memory->create(buf_recv,maxrecv,"comm:buf_recv");
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint Irregular::memory_usage()
{
bigint bytes = memory->usage(buf_send,maxsend);
bytes += memory->usage(buf_recv,maxrecv);
return bytes;
}
diff --git a/src/kspace.cpp b/src/kspace.cpp
index c0613140d..116535f8e 100644
--- a/src/kspace.cpp
+++ b/src/kspace.cpp
@@ -1,80 +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.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "kspace.h"
#include "error.h"
#include "comm.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
KSpace::KSpace(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
energy = 0.0;
order = 5;
gridflag = 0;
gewaldflag = 0;
slabflag = 0;
slab_volfactor = 1;
}
/* ----------------------------------------------------------------------
modify parameters of the KSpace style
------------------------------------------------------------------------- */
void KSpace::modify_params(int narg, char **arg)
{
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"mesh") == 0) {
- if (iarg+4 > narg) error->all("Illegal kspace_modify command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal kspace_modify command");
nx_pppm = atoi(arg[iarg+1]);
ny_pppm = atoi(arg[iarg+2]);
nz_pppm = atoi(arg[iarg+3]);
if (nx_pppm == 0 && ny_pppm == 0 && nz_pppm == 0) gridflag = 0;
else gridflag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"order") == 0) {
- if (iarg+2 > narg) error->all("Illegal kspace_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
order = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"gewald") == 0) {
- if (iarg+2 > narg) error->all("Illegal kspace_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
g_ewald = atof(arg[iarg+1]);
if (g_ewald == 0.0) gewaldflag = 0;
else gewaldflag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"slab") == 0) {
- if (iarg+2 > narg) error->all("Illegal kspace_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
slab_volfactor = atof(arg[iarg+1]);
iarg += 2;
if (slab_volfactor <= 1.0)
- error->all("Bad kspace_modify slab parameter");
+ error->all(FLERR,"Bad kspace_modify slab parameter");
if (slab_volfactor < 2.0 && comm->me == 0)
- error->warning("Kspace_modify slab param < 2.0 may "
+ error->warning(FLERR,"Kspace_modify slab param < 2.0 may "
"cause unphysical behavior");
slabflag = 1;
- } else error->all("Illegal kspace_modify command");
+ } else error->all(FLERR,"Illegal kspace_modify command");
}
}
/* ---------------------------------------------------------------------- */
void *KSpace::extract(char *str)
{
if (strcmp(str,"scale") == 0) return (void *) &scale;
return NULL;
}
diff --git a/src/lammps.cpp b/src/lammps.cpp
index e5342c1e3..09b6a487d 100644
--- a/src/lammps.cpp
+++ b/src/lammps.cpp
@@ -1,606 +1,606 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "string.h"
#include "lammps.h"
#include "style_angle.h"
#include "style_atom.h"
#include "style_bond.h"
#include "style_command.h"
#include "style_compute.h"
#include "style_dihedral.h"
#include "style_dump.h"
#include "style_fix.h"
#include "style_improper.h"
#include "style_integrate.h"
#include "style_kspace.h"
#include "style_minimize.h"
#include "style_pair.h"
#include "style_region.h"
#include "universe.h"
#include "input.h"
#include "atom.h"
#include "update.h"
#include "neighbor.h"
#include "comm.h"
#include "domain.h"
#include "force.h"
#include "modify.h"
#include "group.h"
#include "output.h"
#include "accelerator_cuda.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
start up LAMMPS
allocate fundamental classes (memory, error, universe, input)
parse input switches
initialize communicators, screen & logfile output
input is allocated at end after MPI info is setup
------------------------------------------------------------------------- */
LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator)
{
memory = new Memory(this);
error = new Error(this);
universe = new Universe(this,communicator);
output = NULL;
screen = NULL;
logfile = NULL;
// parse input switches
int inflag = 0;
int screenflag = 0;
int logflag = 0;
int partscreenflag = 0;
int partlogflag = 0;
int cudaflag = -1;
int helpflag = 0;
suffix = NULL;
suffix_enable = 0;
int iarg = 1;
while (iarg < narg) {
if (strcmp(arg[iarg],"-partition") == 0 ||
strcmp(arg[iarg],"-p") == 0) {
universe->existflag = 1;
- if (iarg+2 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument");
iarg++;
while (iarg < narg && arg[iarg][0] != '-') {
universe->add_world(arg[iarg]);
iarg++;
}
} else if (strcmp(arg[iarg],"-in") == 0 ||
strcmp(arg[iarg],"-i") == 0) {
- if (iarg+2 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument");
inflag = iarg + 1;
iarg += 2;
} else if (strcmp(arg[iarg],"-screen") == 0 ||
strcmp(arg[iarg],"-sc") == 0) {
- if (iarg+2 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument");
screenflag = iarg + 1;
iarg += 2;
} else if (strcmp(arg[iarg],"-log") == 0 ||
strcmp(arg[iarg],"-l") == 0) {
- if (iarg+2 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument");
logflag = iarg + 1;
iarg += 2;
} else if (strcmp(arg[iarg],"-var") == 0 ||
strcmp(arg[iarg],"-v") == 0) {
- if (iarg+3 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+3 > narg) error->universe_all(FLERR,"Invalid command-line argument");
iarg += 2;
while (iarg < narg && arg[iarg][0] != '-') iarg++;
} else if (strcmp(arg[iarg],"-echo") == 0 ||
strcmp(arg[iarg],"-e") == 0) {
- if (iarg+2 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument");
iarg += 2;
} else if (strcmp(arg[iarg],"-pscreen") == 0 ||
strcmp(arg[iarg],"-ps") == 0) {
if (iarg+2 > narg)
- error->universe_all("Invalid command-line argument");
+ error->universe_all(FLERR,"Invalid command-line argument");
partscreenflag = iarg + 1;
iarg += 2;
} else if (strcmp(arg[iarg],"-plog") == 0 ||
strcmp(arg[iarg],"-pl") == 0) {
if (iarg+2 > narg)
- error->universe_all("Invalid command-line argument");
+ error->universe_all(FLERR,"Invalid command-line argument");
partlogflag = iarg + 1;
iarg += 2;
} else if (strcmp(arg[iarg],"-cuda") == 0 ||
strcmp(arg[iarg],"-c") == 0) {
- if (iarg+2 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument");
if (strcmp(arg[iarg+1],"on") == 0) cudaflag = 1;
else if (strcmp(arg[iarg+1],"off") == 0) cudaflag = 0;
- else error->universe_all("Invalid command-line argument");
+ else error->universe_all(FLERR,"Invalid command-line argument");
iarg += 2;
} else if (strcmp(arg[iarg],"-suffix") == 0 ||
strcmp(arg[iarg],"-sf") == 0) {
- if (iarg+2 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+2 > narg) error->universe_all(FLERR,"Invalid command-line argument");
delete [] suffix;
int n = strlen(arg[iarg+1]) + 1;
suffix = new char[n];
strcpy(suffix,arg[iarg+1]);
suffix_enable = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"-help") == 0 ||
strcmp(arg[iarg],"-h") == 0) {
- if (iarg+1 > narg) error->universe_all("Invalid command-line argument");
+ if (iarg+1 > narg) error->universe_all(FLERR,"Invalid command-line argument");
helpflag = 1;
iarg += 1;
- } else error->universe_all("Invalid command-line argument");
+ } else error->universe_all(FLERR,"Invalid command-line argument");
}
// if no partition command-line switch, universe is one world w/ all procs
if (universe->existflag == 0) universe->add_world(NULL);
// sum of procs in all worlds must equal total # of procs
if (!universe->consistent())
- error->universe_all("Processor partitions are inconsistent");
+ error->universe_all(FLERR,"Processor partitions are inconsistent");
// universe cannot use stdin for input file
if (universe->existflag && inflag == 0)
- error->universe_all("Must use -in switch with multiple partitions");
+ error->universe_all(FLERR,"Must use -in switch with multiple partitions");
// if no partition command-line switch, cannot use -pscreen option
if (universe->existflag == 0 && partscreenflag)
- error->universe_all("Can only use -pscreen with multiple partitions");
+ error->universe_all(FLERR,"Can only use -pscreen with multiple partitions");
// if no partition command-line switch, cannot use -plog option
if (universe->existflag == 0 && partlogflag)
- error->universe_all("Can only use -plog with multiple partitions");
+ error->universe_all(FLERR,"Can only use -plog with multiple partitions");
// set universe screen and logfile
if (universe->me == 0) {
if (screenflag == 0)
universe->uscreen = stdout;
else if (strcmp(arg[screenflag],"none") == 0)
universe->uscreen = NULL;
else {
universe->uscreen = fopen(arg[screenflag],"w");
if (universe->uscreen == NULL)
- error->universe_one("Cannot open universe screen file");
+ error->universe_one(FLERR,"Cannot open universe screen file");
}
if (logflag == 0) {
universe->ulogfile = fopen("log.lammps","w");
if (universe->ulogfile == NULL)
- error->universe_one("Cannot open log.lammps");
+ error->universe_one(FLERR,"Cannot open log.lammps");
} else if (strcmp(arg[logflag],"none") == 0)
universe->ulogfile = NULL;
else {
universe->ulogfile = fopen(arg[logflag],"w");
if (universe->ulogfile == NULL)
- error->universe_one("Cannot open universe log file");
+ error->universe_one(FLERR,"Cannot open universe log file");
}
}
if (universe->me > 0) {
if (screenflag == 0) universe->uscreen = stdout;
else universe->uscreen = NULL;
universe->ulogfile = NULL;
}
// universe does not exist on its own, only a single world
// inherit settings from universe
// set world screen, logfile, communicator, infile
// open input script if from file
if (universe->existflag == 0) {
screen = universe->uscreen;
logfile = universe->ulogfile;
world = universe->uworld;
infile = NULL;
if (universe->me == 0) {
if (inflag == 0) infile = stdin;
else infile = fopen(arg[inflag],"r");
if (infile == NULL) {
char str[128];
sprintf(str,"Cannot open input script %s",arg[inflag]);
- error->one(str);
+ error->one(FLERR,str);
}
}
if (universe->me == 0) {
if (screen) fprintf(screen,"LAMMPS (%s)\n",universe->version);
if (logfile) fprintf(logfile,"LAMMPS (%s)\n",universe->version);
}
// universe is one or more worlds
// split into separate communicators
// set world screen, logfile, communicator, infile
// open input script
} else {
int me;
MPI_Comm_split(universe->uworld,universe->iworld,0,&world);
MPI_Comm_rank(world,&me);
if (me == 0)
if (partscreenflag == 0)
if (screenflag == 0) {
char str[32];
sprintf(str,"screen.%d",universe->iworld);
screen = fopen(str,"w");
- if (screen == NULL) error->one("Cannot open screen file");
+ if (screen == NULL) error->one(FLERR,"Cannot open screen file");
} else if (strcmp(arg[screenflag],"none") == 0)
screen = NULL;
else {
char str[128];
sprintf(str,"%s.%d",arg[screenflag],universe->iworld);
screen = fopen(str,"w");
- if (screen == NULL) error->one("Cannot open screen file");
+ if (screen == NULL) error->one(FLERR,"Cannot open screen file");
}
else if (strcmp(arg[partscreenflag],"none") == 0)
screen = NULL;
else {
char str[128];
sprintf(str,"%s.%d",arg[partscreenflag],universe->iworld);
screen = fopen(str,"w");
- if (screen == NULL) error->one("Cannot open screen file");
+ if (screen == NULL) error->one(FLERR,"Cannot open screen file");
} else screen = NULL;
if (me == 0)
if (partlogflag == 0)
if (logflag == 0) {
char str[32];
sprintf(str,"log.lammps.%d",universe->iworld);
logfile = fopen(str,"w");
- if (logfile == NULL) error->one("Cannot open logfile");
+ if (logfile == NULL) error->one(FLERR,"Cannot open logfile");
} else if (strcmp(arg[logflag],"none") == 0)
logfile = NULL;
else {
char str[128];
sprintf(str,"%s.%d",arg[logflag],universe->iworld);
logfile = fopen(str,"w");
- if (logfile == NULL) error->one("Cannot open logfile");
+ if (logfile == NULL) error->one(FLERR,"Cannot open logfile");
}
else if (strcmp(arg[partlogflag],"none") == 0)
logfile = NULL;
else {
char str[128];
sprintf(str,"%s.%d",arg[partlogflag],universe->iworld);
logfile = fopen(str,"w");
- if (logfile == NULL) error->one("Cannot open logfile");
+ if (logfile == NULL) error->one(FLERR,"Cannot open logfile");
} else logfile = NULL;
if (me == 0) {
infile = fopen(arg[inflag],"r");
if (infile == NULL) {
char str[128];
sprintf(str,"Cannot open input script %s",arg[inflag]);
- error->one(str);
+ error->one(FLERR,str);
}
} else infile = NULL;
// screen and logfile messages for universe and world
if (universe->me == 0) {
if (universe->uscreen) {
fprintf(universe->uscreen,"LAMMPS (%s)\n",universe->version);
fprintf(universe->uscreen,"Running on %d partitions of processors\n",
universe->nworlds);
}
if (universe->ulogfile) {
fprintf(universe->ulogfile,"LAMMPS (%s)\n",universe->version);
fprintf(universe->ulogfile,"Running on %d partitions of processors\n",
universe->nworlds);
}
}
if (me == 0) {
if (screen) {
fprintf(screen,"LAMMPS (%s)\n",universe->version);
fprintf(screen,"Processor partition = %d\n",universe->iworld);
}
if (logfile) {
fprintf(logfile,"LAMMPS (%s)\n",universe->version);
fprintf(logfile,"Processor partition = %d\n",universe->iworld);
}
}
}
// check datatype settings in lmptype.h
if (sizeof(smallint) != sizeof(int))
- error->all("Smallint setting in lmptype.h is invalid");
+ error->all(FLERR,"Smallint setting in lmptype.h is invalid");
if (sizeof(tagint) < sizeof(smallint))
- error->all("Tagint setting in lmptype.h is invalid");
+ error->all(FLERR,"Tagint setting in lmptype.h is invalid");
if (sizeof(bigint) < sizeof(tagint))
- error->all("Bigint setting in lmptype.h is invalid");
+ error->all(FLERR,"Bigint setting in lmptype.h is invalid");
int mpisize;
MPI_Type_size(MPI_LMP_TAGINT,&mpisize);
if (mpisize != sizeof(tagint))
- error->all("MPI_LMP_TAGINT and tagint in lmptype.h are not compatible");
+ error->all(FLERR,"MPI_LMP_TAGINT and tagint in lmptype.h are not compatible");
MPI_Type_size(MPI_LMP_BIGINT,&mpisize);
if (mpisize != sizeof(bigint))
- error->all("MPI_LMP_BIGINT and bigint in lmptype.h are not compatible");
+ error->all(FLERR,"MPI_LMP_BIGINT and bigint in lmptype.h are not compatible");
#ifdef LAMMPS_SMALLBIG
if (sizeof(smallint) != 4 || sizeof(tagint) != 4 || sizeof(bigint) != 8)
- error->all("Small, tag, big integers are not sized correctly");
+ error->all(FLERR,"Small, tag, big integers are not sized correctly");
#endif
#ifdef LAMMPS_BIGBIG
if (sizeof(smallint) != 4 || sizeof(tagint) != 8 || sizeof(bigint) != 8)
- error->all("Small, tag, big integers are not sized correctly");
+ error->all(FLERR,"Small, tag, big integers are not sized correctly");
#endif
#ifdef LAMMPS_SMALLSMALL
if (sizeof(smallint) != 4 || sizeof(tagint) != 4 || sizeof(bigint) != 4)
- error->all("Small, tag, big integers are not sized correctly");
+ error->all(FLERR,"Small, tag, big integers are not sized correctly");
#endif
- if (sizeof(tagint) == 8) error->all("64-bit atom IDs are not yet supported");
+ if (sizeof(tagint) == 8) error->all(FLERR,"64-bit atom IDs are not yet supported");
// create CUDA class if USER-CUDA installed, unless explicitly switched off
// instantiation creates dummy CUDA class if USER-CUDA is not installed
if (cudaflag == 0) {
cuda = NULL;
} else if (cudaflag == 1) {
cuda = new Cuda(this);
if (!cuda->cuda_exists)
- error->all("Cannot use -cuda on without USER-CUDA installed");
+ error->all(FLERR,"Cannot use -cuda on without USER-CUDA installed");
} else {
cuda = new Cuda(this);
if (!cuda->cuda_exists) {
delete cuda;
cuda = NULL;
}
}
int me;
MPI_Comm_rank(world,&me);
- if (cuda && me == 0) error->message("USER-CUDA mode is enabled");
+ if (cuda && me == 0) error->message(FLERR,"USER-CUDA mode is enabled");
// allocate input class now that MPI is fully setup
input = new Input(this,narg,arg);
// allocate top-level classes
create();
// if helpflag set, print help and exit
if (helpflag) {
if (universe->me == 0) print_styles();
error->done();
}
}
/* ----------------------------------------------------------------------
shutdown LAMMPS
delete top-level classes
close screen and log files in world and universe
output files were already closed in destroy()
delete fundamental classes
------------------------------------------------------------------------- */
LAMMPS::~LAMMPS()
{
destroy();
if (universe->nworlds == 1) {
if (logfile) fclose(logfile);
} else {
if (screen && screen != stdout) fclose(screen);
if (logfile) fclose(logfile);
if (universe->ulogfile) fclose(universe->ulogfile);
}
if (world != universe->uworld) MPI_Comm_free(&world);
delete cuda;
delete [] suffix;
delete input;
delete universe;
delete error;
delete memory;
}
/* ----------------------------------------------------------------------
allocate single instance of top-level classes
fundamental classes are allocated in constructor
some classes have package variants
------------------------------------------------------------------------- */
void LAMMPS::create()
{
atom = new Atom(this);
if (cuda) neighbor = new NeighborCuda(this);
else neighbor = new Neighbor(this);
if (cuda) comm = new CommCuda(this);
else comm = new Comm(this);
if (cuda) domain = new DomainCuda(this);
else domain = new Domain(this);
group = new Group(this);
force = new Force(this); // must be after group, to create temperature
if (cuda) modify = new ModifyCuda(this);
else modify = new Modify(this);
output = new Output(this); // must be after group, so "all" exists
// must be after modify so can create Computes
update = new Update(this); // must be after output, force, neighbor
timer = new Timer(this);
}
/* ----------------------------------------------------------------------
initialize top-level classes
------------------------------------------------------------------------- */
void LAMMPS::init()
{
if (cuda) cuda->accelerator(0,NULL);
update->init();
force->init(); // pair must come after update due to minimizer
domain->init();
atom->init(); // atom must come after force and domain
// atom deletes extra array
// used by fix shear_history::unpack_restart()
// when force->pair->gran_history creates fix ??
// atom_vec init uses deform_vremap
modify->init(); // modify must come after update, force, atom, domain
neighbor->init(); // neighbor must come after force, modify
comm->init(); // comm must come after force, modify, neighbor, atom
output->init(); // output must come after domain, force, modify
timer->init();
}
/* ----------------------------------------------------------------------
delete single instance of top-level classes
fundamental classes are deleted in destructor
------------------------------------------------------------------------- */
void LAMMPS::destroy()
{
delete update;
delete neighbor;
delete comm;
delete force;
delete group;
delete output;
delete modify; // modify must come after output, force, update
// since they delete fixes
delete domain; // domain must come after modify
// since fix destructors access domain
delete atom; // atom must come after modify, neighbor
// since fixes delete callbacks in atom
delete timer;
}
/* ----------------------------------------------------------------------
for each style, print name of all child classes build into executable
------------------------------------------------------------------------- */
void LAMMPS::print_styles()
{
printf("\nList of style options included in this executable:\n\n");
printf("Atom styles:");
#define ATOM_CLASS
#define AtomStyle(key,Class) printf(" %s",#key);
#include "style_atom.h"
#undef ATOM_CLASS
printf("\n\n");
printf("Integrate styles:");
#define INTEGRATE_CLASS
#define IntegrateStyle(key,Class) printf(" %s",#key);
#include "style_integrate.h"
#undef INTEGRATE_CLASS
printf("\n\n");
printf("Minimize styles:");
#define MINIMIZE_CLASS
#define MinimizeStyle(key,Class) printf(" %s",#key);
#include "style_minimize.h"
#undef MINIMIZE_CLASS
printf("\n\n");
printf("Pair styles:");
#define PAIR_CLASS
#define PairStyle(key,Class) printf(" %s",#key);
#include "style_pair.h"
#undef PAIR_CLASS
printf("\n\n");
printf("Bond styles:");
#define BOND_CLASS
#define BondStyle(key,Class) printf(" %s",#key);
#include "style_bond.h"
#undef BOND_CLASS
printf("\n\n");
printf("Angle styles:");
#define ANGLE_CLASS
#define AngleStyle(key,Class) printf(" %s",#key);
#include "style_angle.h"
#undef ANGLE_CLASS
printf("\n\n");
printf("Dihedral styles:");
#define DIHEDRAL_CLASS
#define DihedralStyle(key,Class) printf(" %s",#key);
#include "style_dihedral.h"
#undef DIHEDRAL_CLASS
printf("\n\n");
printf("Improper styles:");
#define IMPROPER_CLASS
#define ImproperStyle(key,Class) printf(" %s",#key);
#include "style_improper.h"
#undef IMPROPER_CLASS
printf("\n\n");
printf("KSpace styles:");
#define KSPACE_CLASS
#define KSpaceStyle(key,Class) printf(" %s",#key);
#include "style_kspace.h"
#undef KSPACE_CLASS
printf("\n\n");
printf("Fix styles (upper case are only for internal use):");
#define FIX_CLASS
#define FixStyle(key,Class) printf(" %s",#key);
#include "style_fix.h"
#undef FIX_CLASS
printf("\n\n");
printf("Compute styles:");
#define COMPUTE_CLASS
#define ComputeStyle(key,Class) printf(" %s",#key);
#include "style_compute.h"
#undef COMPUTE_CLASS
printf("\n\n");
printf("Region styles:");
#define REGION_CLASS
#define RegionStyle(key,Class) printf(" %s",#key);
#include "style_region.h"
#undef REGION_CLASS
printf("\n\n");
printf("Dump styles:");
#define DUMP_CLASS
#define DumpStyle(key,Class) printf(" %s",#key);
#include "style_dump.h"
#undef DUMP_CLASS
printf("\n\n");
printf("Command styles (add-on input script commands):");
#define COMMAND_CLASS
#define CommandStyle(key,Class) printf(" %s",#key);
#include "style_command.h"
#undef COMMAND_CLASS
printf("\n");
}
diff --git a/src/lattice.cpp b/src/lattice.cpp
index 48e749834..196074deb 100644
--- a/src/lattice.cpp
+++ b/src/lattice.cpp
@@ -1,558 +1,556 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "stdlib.h"
#include "lattice.h"
#include "update.h"
#include "domain.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
#define BIG 1.0e30
enum{NONE,SC,BCC,FCC,HCP,DIAMOND,SQ,SQ2,HEX,CUSTOM};
/* ---------------------------------------------------------------------- */
Lattice::Lattice(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
nbasis = 0;
basis = NULL;
// parse style arg
- if (narg < 1) error->all("Illegal lattice command");
+ if (narg < 1) error->all(FLERR,"Illegal lattice command");
if (strcmp(arg[0],"none") == 0) style = NONE;
else if (strcmp(arg[0],"sc") == 0) style = SC;
else if (strcmp(arg[0],"bcc") == 0) style = BCC;
else if (strcmp(arg[0],"fcc") == 0) style = FCC;
else if (strcmp(arg[0],"hcp") == 0) style = HCP;
else if (strcmp(arg[0],"diamond") == 0) style = DIAMOND;
else if (strcmp(arg[0],"sq") == 0) style = SQ;
else if (strcmp(arg[0],"sq2") == 0) style = SQ2;
else if (strcmp(arg[0],"hex") == 0) style = HEX;
else if (strcmp(arg[0],"custom") == 0) style = CUSTOM;
- else error->all("Illegal lattice command");
+ else error->all(FLERR,"Illegal lattice command");
if (style == NONE) {
- if (narg > 1) error->all("Illegal lattice command");
+ if (narg > 1) error->all(FLERR,"Illegal lattice command");
return;
}
// check that lattice matches dimension
// style CUSTOM can be either 2d or 3d
int dimension = domain->dimension;
if (dimension == 2) {
if (style == SC || style == BCC || style == FCC || style == HCP ||
style == DIAMOND)
- error->all("Lattice style incompatible with simulation dimension");
+ error->all(FLERR,"Lattice style incompatible with simulation dimension");
}
if (dimension == 3) {
if (style == SQ || style == SQ2 || style == HEX)
- error->all("Lattice style incompatible with simulation dimension");
+ error->all(FLERR,"Lattice style incompatible with simulation dimension");
}
// scale = conversion factor between lattice and box units
- if (narg < 2) error->all("Illegal lattice command");
+ if (narg < 2) error->all(FLERR,"Illegal lattice command");
scale = atof(arg[1]);
- if (scale <= 0.0) error->all("Illegal lattice command");
+ if (scale <= 0.0) error->all(FLERR,"Illegal lattice command");
// set basis atoms for each style
// x,y,z = fractional coords within unit cell
// style CUSTOM will be defined by optional args
if (style == SC) {
add_basis(0.0,0.0,0.0);
} else if (style == BCC) {
add_basis(0.0,0.0,0.0);
add_basis(0.5,0.5,0.5);
} else if (style == FCC) {
add_basis(0.0,0.0,0.0);
add_basis(0.5,0.5,0.0);
add_basis(0.5,0.0,0.5);
add_basis(0.0,0.5,0.5);
} else if (style == HCP) {
add_basis(0.0,0.0,0.0);
add_basis(0.5,0.5,0.0);
add_basis(0.5,5.0/6.0,0.5);
add_basis(0.0,1.0/3.0,0.5);
} else if (style == SQ) {
add_basis(0.0,0.0,0.0);
} else if (style == SQ2) {
add_basis(0.0,0.0,0.0);
add_basis(0.5,0.5,0.0);
} else if (style == HEX) {
add_basis(0.0,0.0,0.0);
add_basis(0.5,0.5,0.0);
} else if (style == DIAMOND) {
add_basis(0.0,0.0,0.0);
add_basis(0.0,0.5,0.5);
add_basis(0.5,0.0,0.5);
add_basis(0.5,0.5,0.0);
add_basis(0.25,0.25,0.25);
add_basis(0.25,0.75,0.75);
add_basis(0.75,0.25,0.75);
add_basis(0.75,0.75,0.25);
}
// set defaults for optional args
origin[0] = origin[1] = origin[2] = 0.0;
orientx[0] = 1; orientx[1] = 0; orientx[2] = 0;
orienty[0] = 0; orienty[1] = 1; orienty[2] = 0;
orientz[0] = 0; orientz[1] = 0; orientz[2] = 1;
int spaceflag = 0;
a1[0] = 1.0; a1[1] = 0.0; a1[2] = 0.0;
a2[0] = 0.0; a2[1] = 1.0; a2[2] = 0.0;
a3[0] = 0.0; a3[1] = 0.0; a3[2] = 1.0;
if (style == HEX) a2[1] = sqrt(3.0);
if (style == HCP) {
a2[1] = sqrt(3.0);
a3[2] = sqrt(8.0/3.0);
}
// process optional args
int iarg = 2;
while (iarg < narg) {
if (strcmp(arg[iarg],"origin") == 0) {
- if (iarg+4 > narg) error->all("Illegal lattice command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal lattice command");
origin[0] = atof(arg[iarg+1]);
origin[1] = atof(arg[iarg+2]);
origin[2] = atof(arg[iarg+3]);
if (origin[0] < 0.0 || origin[0] >= 1.0 ||
origin[1] < 0.0 || origin[1] >= 1.0 ||
origin[2] < 0.0 || origin[2] >= 1.0)
- error->all("Illegal lattice command");
+ error->all(FLERR,"Illegal lattice command");
iarg += 4;
} else if (strcmp(arg[iarg],"orient") == 0) {
- if (iarg+5 > narg) error->all("Illegal lattice command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal lattice command");
int dim;
if (strcmp(arg[iarg+1],"x") == 0) dim = 0;
else if (strcmp(arg[iarg+1],"y") == 0) dim = 1;
else if (strcmp(arg[iarg+1],"z") == 0) dim = 2;
- else error->all("Illegal lattice command");
+ else error->all(FLERR,"Illegal lattice command");
int *orient;
if (dim == 0) orient = orientx;
else if (dim == 1) orient = orienty;
else if (dim == 2) orient = orientz;
orient[0] = atoi(arg[iarg+2]);
orient[1] = atoi(arg[iarg+3]);
orient[2] = atoi(arg[iarg+4]);
iarg += 5;
} else if (strcmp(arg[iarg],"spacing") == 0) {
- if (iarg+4 > narg) error->all("Illegal lattice command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal lattice command");
spaceflag = 1;
xlattice = atof(arg[iarg+1]);
ylattice = atof(arg[iarg+2]);
zlattice = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"a1") == 0) {
- if (iarg+4 > narg) error->all("Illegal lattice command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal lattice command");
if (style != CUSTOM)
- error->all("Invalid option in lattice command for non-custom style");
+ error->all(FLERR,"Invalid option in lattice command for non-custom style");
a1[0] = atof(arg[iarg+1]);
a1[1] = atof(arg[iarg+2]);
a1[2] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"a2") == 0) {
- if (iarg+4 > narg) error->all("Illegal lattice command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal lattice command");
if (style != CUSTOM)
- error->all("Invalid option in lattice command for non-custom style");
+ error->all(FLERR,"Invalid option in lattice command for non-custom style");
a2[0] = atof(arg[iarg+1]);
a2[1] = atof(arg[iarg+2]);
a2[2] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"a3") == 0) {
- if (iarg+4 > narg) error->all("Illegal lattice command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal lattice command");
if (style != CUSTOM)
- error->all("Invalid option in lattice command for non-custom style");
+ error->all(FLERR,"Invalid option in lattice command for non-custom style");
a3[0] = atof(arg[iarg+1]);
a3[1] = atof(arg[iarg+2]);
a3[2] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"basis") == 0) {
- if (iarg+4 > narg) error->all("Illegal lattice command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal lattice command");
if (style != CUSTOM)
- error->all("Invalid option in lattice command for non-custom style");
+ error->all(FLERR,"Invalid option in lattice command for non-custom style");
double x = atof(arg[iarg+1]);
double y = atof(arg[iarg+2]);
double z = atof(arg[iarg+3]);
if (x < 0.0 || x >= 1.0 || y < 0.0 || y >= 1.0 || z < 0.0 || z >= 1.0)
- error->all("Illegal lattice command");
+ error->all(FLERR,"Illegal lattice command");
add_basis(x,y,z);
iarg += 4;
- } else error->all("Illegal lattice command");
+ } else error->all(FLERR,"Illegal lattice command");
}
// check settings for errors
- if (nbasis == 0) error->all("No basis atoms in lattice");
+ if (nbasis == 0) error->all(FLERR,"No basis atoms in lattice");
if (!orthogonal())
- error->all("Lattice orient vectors are not orthogonal");
+ error->all(FLERR,"Lattice orient vectors are not orthogonal");
if (!right_handed())
- error->all("Lattice orient vectors are not right-handed");
+ error->all(FLERR,"Lattice orient vectors are not right-handed");
if (collinear())
- error->all("Lattice primitive vectors are collinear");
+ error->all(FLERR,"Lattice primitive vectors are collinear");
if (dimension == 2) {
if (origin[2] != 0.0)
- error->all("Lattice settings are not compatible with 2d simulation");
+ error->all(FLERR,"Lattice settings are not compatible with 2d simulation");
if (orientx[2] != 0 || orienty[2] != 0 ||
orientz[0] != 0 || orientz[1] != 0)
- error->all("Lattice settings are not compatible with 2d simulation");
+ error->all(FLERR,"Lattice settings are not compatible with 2d simulation");
if (a1[2] != 0.0 || a2[2] != 0.0 || a3[0] != 0.0 || a3[1] != 0.0)
- error->all("Lattice settings are not compatible with 2d simulation");
+ error->all(FLERR,"Lattice settings are not compatible with 2d simulation");
}
if (spaceflag) {
if (xlattice <= 0.0 || ylattice <= 0.0 || zlattice <= 0.0)
- error->all("Lattice spacings are invalid");
+ error->all(FLERR,"Lattice spacings are invalid");
}
// reset scale for LJ units (input scale is rho*)
// scale = (Nbasis/(Vprimitive * rho*)) ^ (1/dim)
if (strcmp(update->unit_style,"lj") == 0) {
double vec[3];
cross(a2,a3,vec);
double volume = dot(a1,vec);
scale = pow(nbasis/volume/scale,1.0/dimension);
}
// initialize lattice <-> box transformation matrices
setup_transform();
// convert 8 corners of primitive unit cell from lattice coords to box coords
// min to max = bounding box around the pts in box space
// xlattice,ylattice,zlattice = extent of bbox in box space
// set xlattice,ylattice,zlattice to 0.0 initially
// since bbox uses them to shift origin (irrelevant for this computation)
if (spaceflag == 0) {
double xmin,ymin,zmin,xmax,ymax,zmax;
xmin = ymin = zmin = BIG;
xmax = ymax = zmax = -BIG;
xlattice = ylattice = zlattice = 0.0;
bbox(0,0.0,0.0,0.0,xmin,ymin,zmin,xmax,ymax,zmax);
bbox(0,1.0,0.0,0.0,xmin,ymin,zmin,xmax,ymax,zmax);
bbox(0,0.0,1.0,0.0,xmin,ymin,zmin,xmax,ymax,zmax);
bbox(0,1.0,1.0,0.0,xmin,ymin,zmin,xmax,ymax,zmax);
bbox(0,0.0,0.0,1.0,xmin,ymin,zmin,xmax,ymax,zmax);
bbox(0,1.0,0.0,1.0,xmin,ymin,zmin,xmax,ymax,zmax);
bbox(0,0.0,1.0,1.0,xmin,ymin,zmin,xmax,ymax,zmax);
bbox(0,1.0,1.0,1.0,xmin,ymin,zmin,xmax,ymax,zmax);
xlattice = xmax - xmin;
ylattice = ymax - ymin;
zlattice = zmax - zmin;
} else {
xlattice *= scale;
ylattice *= scale;
zlattice *= scale;
}
// print lattice spacings
if (comm->me == 0) {
if (screen)
fprintf(screen,"Lattice spacing in x,y,z = %g %g %g\n",
xlattice,ylattice,zlattice);
if (logfile)
fprintf(logfile,"Lattice spacing in x,y,z = %g %g %g\n",
xlattice,ylattice,zlattice);
}
}
/* ---------------------------------------------------------------------- */
Lattice::~Lattice()
{
memory->destroy(basis);
}
/* ----------------------------------------------------------------------
check if 3 orientation vectors are mutually orthogonal
------------------------------------------------------------------------- */
int Lattice::orthogonal()
{
if (orientx[0]*orienty[0] + orientx[1]*orienty[1] +
orientx[2]*orienty[2]) return 0;
if (orienty[0]*orientz[0] + orienty[1]*orientz[1] +
orienty[2]*orientz[2]) return 0;
if (orientx[0]*orientz[0] + orientx[1]*orientz[1] +
orientx[2]*orientz[2]) return 0;
return 1;
}
/* ----------------------------------------------------------------------
check righthandedness of orientation vectors
x cross y must be in same direction as z
------------------------------------------------------------------------- */
int Lattice::right_handed()
{
int xy0 = orientx[1]*orienty[2] - orientx[2]*orienty[1];
int xy1 = orientx[2]*orienty[0] - orientx[0]*orienty[2];
int xy2 = orientx[0]*orienty[1] - orientx[1]*orienty[0];
if (xy0*orientz[0] + xy1*orientz[1] + xy2*orientz[2] <= 0) return 0;
return 1;
}
/* ----------------------------------------------------------------------
check collinearity of each pair of primitive vectors
------------------------------------------------------------------------- */
int Lattice::collinear()
{
double vec[3];
cross(a1,a2,vec);
if (dot(vec,vec) == 0.0) return 1;
cross(a2,a3,vec);
if (dot(vec,vec) == 0.0) return 1;
cross(a1,a3,vec);
if (dot(vec,vec) == 0.0) return 1;
return 0;
}
/* ----------------------------------------------------------------------
initialize lattice <-> box transformation matrices
------------------------------------------------------------------------- */
void Lattice::setup_transform()
{
double length;
// primitive = 3x3 matrix with primitive vectors as columns
primitive[0][0] = a1[0];
primitive[1][0] = a1[1];
primitive[2][0] = a1[2];
primitive[0][1] = a2[0];
primitive[1][1] = a2[1];
primitive[2][1] = a2[2];
primitive[0][2] = a3[0];
primitive[1][2] = a3[1];
primitive[2][2] = a3[2];
// priminv = inverse of primitive
double determinant = primitive[0][0]*primitive[1][1]*primitive[2][2] +
primitive[0][1]*primitive[1][2]*primitive[2][0] +
primitive[0][2]*primitive[1][0]*primitive[2][1] -
primitive[0][0]*primitive[1][2]*primitive[2][1] -
primitive[0][1]*primitive[1][0]*primitive[2][2] -
primitive[0][2]*primitive[1][1]*primitive[2][0];
- if (determinant == 0.0) error->all("Degenerate lattice primitive vectors");
+ if (determinant == 0.0) error->all(FLERR,"Degenerate lattice primitive vectors");
priminv[0][0] = (primitive[1][1]*primitive[2][2] -
primitive[1][2]*primitive[2][1]) / determinant;
priminv[1][0] = (primitive[1][2]*primitive[2][0] -
primitive[1][0]*primitive[2][2]) / determinant;
priminv[2][0] = (primitive[1][0]*primitive[2][1] -
primitive[1][1]*primitive[2][0]) / determinant;
priminv[0][1] = (primitive[0][2]*primitive[2][1] -
primitive[0][1]*primitive[2][2]) / determinant;
priminv[1][1] = (primitive[0][0]*primitive[2][2] -
primitive[0][2]*primitive[2][0]) / determinant;
priminv[2][1] = (primitive[0][1]*primitive[2][0] -
primitive[0][0]*primitive[2][1]) / determinant;
priminv[0][2] = (primitive[0][1]*primitive[1][2] -
primitive[0][2]*primitive[1][1]) / determinant;
priminv[1][2] = (primitive[0][2]*primitive[1][0] -
primitive[0][0]*primitive[1][2]) / determinant;
priminv[2][2] = (primitive[0][0]*primitive[1][1] -
primitive[0][1]*primitive[1][0]) / determinant;
// rotaterow = 3x3 matrix with normalized orient vectors as rows
int lensq = orientx[0]*orientx[0] + orientx[1]*orientx[1] +
orientx[2]*orientx[2];
length = sqrt((double) lensq);
- if (length == 0.0) error->all("Zero-length lattice orient vector");
+ if (length == 0.0) error->all(FLERR,"Zero-length lattice orient vector");
rotaterow[0][0] = orientx[0] / length;
rotaterow[0][1] = orientx[1] / length;
rotaterow[0][2] = orientx[2] / length;
lensq = orienty[0]*orienty[0] + orienty[1]*orienty[1] +
orienty[2]*orienty[2];
length = sqrt((double) lensq);
- if (length == 0.0) error->all("Zero-length lattice orient vector");
+ if (length == 0.0) error->all(FLERR,"Zero-length lattice orient vector");
rotaterow[1][0] = orienty[0] / length;
rotaterow[1][1] = orienty[1] / length;
rotaterow[1][2] = orienty[2] / length;
lensq = orientz[0]*orientz[0] + orientz[1]*orientz[1] +
orientz[2]*orientz[2];
length = sqrt((double) lensq);
- if (length == 0.0) error->all("Zero-length lattice orient vector");
+ if (length == 0.0) error->all(FLERR,"Zero-length lattice orient vector");
rotaterow[2][0] = orientz[0] / length;
rotaterow[2][1] = orientz[1] / length;
rotaterow[2][2] = orientz[2] / length;
// rotatecol = 3x3 matrix with normalized orient vectors as columns
rotatecol[0][0] = rotaterow[0][0];
rotatecol[1][0] = rotaterow[0][1];
rotatecol[2][0] = rotaterow[0][2];
rotatecol[0][1] = rotaterow[1][0];
rotatecol[1][1] = rotaterow[1][1];
rotatecol[2][1] = rotaterow[1][2];
rotatecol[0][2] = rotaterow[2][0];
rotatecol[1][2] = rotaterow[2][1];
rotatecol[2][2] = rotaterow[2][2];
}
/* ----------------------------------------------------------------------
convert lattice coords to box coords
input x,y,z = point in lattice coords
output x,y,z = point in box coords
transformation: xyz_box = Rotate_row * scale * P * xyz_lattice + offset
xyz_box = 3-vector of output box coords
Rotate_row = 3x3 matrix = normalized orient vectors as rows
scale = scale factor
P = 3x3 matrix = primitive vectors as columns
xyz_lattice = 3-vector of input lattice coords
offset = 3-vector = (xlatt*origin[0], ylatt*origin[1], zlatt*origin[2])
------------------------------------------------------------------------- */
void Lattice::lattice2box(double &x, double &y, double &z)
{
double x1 = primitive[0][0]*x + primitive[0][1]*y + primitive[0][2]*z;
double y1 = primitive[1][0]*x + primitive[1][1]*y + primitive[1][2]*z;
double z1 = primitive[2][0]*x + primitive[2][1]*y + primitive[2][2]*z;
x1 *= scale;
y1 *= scale;
z1 *= scale;
double xnew = rotaterow[0][0]*x1 + rotaterow[0][1]*y1 + rotaterow[0][2]*z1;
double ynew = rotaterow[1][0]*x1 + rotaterow[1][1]*y1 + rotaterow[1][2]*z1;
double znew = rotaterow[2][0]*x1 + rotaterow[2][1]*y1 + rotaterow[2][2]*z1;
x = xnew + xlattice*origin[0];
y = ynew + ylattice*origin[1];
z = znew + zlattice*origin[2];
}
/* ----------------------------------------------------------------------
convert box coords to lattice coords
input x,y,z = point in box coords
output x,y,z = point in lattice coords
transformation: xyz_latt = P_inv * 1/scale * Rotate_col * (xyz_box - offset)
xyz_lattice = 3-vector of output lattice coords
P_inv = 3x3 matrix = inverse of primitive vectors as columns
scale = scale factor
Rotate_col = 3x3 matrix = normalized orient vectors as columns
xyz_box = 3-vector of input box coords
offset = 3-vector = (xlatt*origin[0], ylatt*origin[1], zlatt*origin[2])
------------------------------------------------------------------------- */
void Lattice::box2lattice(double &x, double &y, double &z)
{
x -= xlattice*origin[0];
y -= ylattice*origin[1];
z -= zlattice*origin[2];
double x1 = rotatecol[0][0]*x + rotatecol[0][1]*y + rotatecol[0][2]*z;
double y1 = rotatecol[1][0]*x + rotatecol[1][1]*y + rotatecol[1][2]*z;
double z1 = rotatecol[2][0]*x + rotatecol[2][1]*y + rotatecol[2][2]*z;
x1 /= scale;
y1 /= scale;
z1 /= scale;
x = priminv[0][0]*x1 + priminv[0][1]*y1 + priminv[0][2]*z1;
y = priminv[1][0]*x1 + priminv[1][1]*y1 + priminv[1][2]*z1;
z = priminv[2][0]*x1 + priminv[2][1]*y1 + priminv[2][2]*z1;
}
/* ----------------------------------------------------------------------
add a basis atom to list
x,y,z = fractional coords within unit cell
------------------------------------------------------------------------- */
void Lattice::add_basis(double x, double y, double z)
{
memory->grow(basis,nbasis+1,3,"lattice:basis");
basis[nbasis][0] = x;
basis[nbasis][1] = y;
basis[nbasis][2] = z;
nbasis++;
}
/* ----------------------------------------------------------------------
return x dot y
------------------------------------------------------------------------- */
double Lattice::dot(double *x, double *y)
{
return x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
}
/* ----------------------------------------------------------------------
z = x cross y
------------------------------------------------------------------------- */
void Lattice::cross(double *x, double *y, double *z)
{
z[0] = x[1]*y[2] - x[2]*y[1];
z[1] = x[2]*y[0] - x[0]*y[2];
z[2] = x[0]*y[1] - x[1]*y[0];
}
/* ----------------------------------------------------------------------
convert x,y,z from lattice coords to box coords (flag = 0) or vice versa
use new point to expand bounding box (min to max)
------------------------------------------------------------------------- */
void Lattice::bbox(int flag, double x, double y, double z,
double &xmin, double &ymin, double &zmin,
double &xmax, double &ymax, double &zmax)
{
if (flag == 0) lattice2box(x,y,z);
else box2lattice(x,y,z);
xmin = MIN(x,xmin); ymin = MIN(y,ymin); zmin = MIN(z,zmin);
xmax = MAX(x,xmax); ymax = MAX(y,ymax); zmax = MAX(z,zmax);
}
diff --git a/src/memory.cpp b/src/memory.cpp
index 6af16e68e..11e15f10e 100644
--- a/src/memory.cpp
+++ b/src/memory.cpp
@@ -1,85 +1,85 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Memory::Memory(LAMMPS *lmp) : Pointers(lmp) {}
/* ----------------------------------------------------------------------
safe malloc
------------------------------------------------------------------------- */
void *Memory::smalloc(bigint nbytes, const char *name)
{
if (nbytes == 0) return NULL;
void *ptr = malloc(nbytes);
if (ptr == NULL) {
char str[128];
sprintf(str,"Failed to allocate " BIGINT_FORMAT " bytes for array %s",
nbytes,name);
- error->one(str);
+ error->one(FLERR,str);
}
return ptr;
}
/* ----------------------------------------------------------------------
safe realloc
------------------------------------------------------------------------- */
void *Memory::srealloc(void *ptr, bigint nbytes, const char *name)
{
if (nbytes == 0) {
destroy(ptr);
return NULL;
}
ptr = realloc(ptr,nbytes);
if (ptr == NULL) {
char str[128];
sprintf(str,"Failed to reallocate " BIGINT_FORMAT " bytes for array %s",
nbytes,name);
- error->one(str);
+ error->one(FLERR,str);
}
return ptr;
}
/* ----------------------------------------------------------------------
safe free
------------------------------------------------------------------------- */
void Memory::sfree(void *ptr)
{
if (ptr == NULL) return;
free(ptr);
}
/* ----------------------------------------------------------------------
erroneous usage of templated create/grow functions
------------------------------------------------------------------------- */
void Memory::fail(const char *name)
{
char str[128];
sprintf(str,"Cannot create/grow a vector/array of pointers for %s",name);
- error->one(str);
+ error->one(FLERR,str);
}
diff --git a/src/min.cpp b/src/min.cpp
index 55253f11e..bf8306526 100644
--- a/src/min.cpp
+++ b/src/min.cpp
@@ -1,775 +1,772 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
improved CG and backtrack ls, added quadratic ls
Sources: Numerical Recipes frprmn routine
"Conjugate Gradient Method Without the Agonizing Pain" by
JR Shewchuk, http://www-2.cs.cmu.edu/~jrs/jrspapers.html#cg
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "min.h"
#include "atom.h"
#include "domain.h"
#include "comm.h"
#include "update.h"
#include "modify.h"
#include "fix_minimize.h"
#include "compute.h"
#include "neighbor.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "output.h"
#include "thermo.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
Min::Min(LAMMPS *lmp) : Pointers(lmp)
{
dmax = 0.1;
searchflag = 0;
linestyle = 0;
elist_global = elist_atom = NULL;
vlist_global = vlist_atom = NULL;
nextra_global = 0;
fextra = NULL;
nextra_atom = 0;
xextra_atom = fextra_atom = NULL;
extra_peratom = extra_nlen = NULL;
extra_max = NULL;
requestor = NULL;
}
/* ---------------------------------------------------------------------- */
Min::~Min()
{
delete [] elist_global;
delete [] elist_atom;
delete [] vlist_global;
delete [] vlist_atom;
delete [] fextra;
memory->sfree(xextra_atom);
memory->sfree(fextra_atom);
memory->destroy(extra_peratom);
memory->destroy(extra_nlen);
memory->destroy(extra_max);
memory->sfree(requestor);
}
/* ---------------------------------------------------------------------- */
void Min::init()
{
// create fix needed for storing atom-based quantities
// will delete it at end of run
char **fixarg = new char*[3];
fixarg[0] = (char *) "MINIMIZE";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "MINIMIZE";
modify->add_fix(3,fixarg);
delete [] fixarg;
fix_minimize = (FixMinimize *) modify->fix[modify->nfix-1];
// clear out extra global and per-atom dof
// will receive requests for new per-atom dof during pair init()
// can then add vectors to fix_minimize in setup()
nextra_global = 0;
delete [] fextra;
fextra = NULL;
nextra_atom = 0;
memory->sfree(xextra_atom);
memory->sfree(fextra_atom);
memory->destroy(extra_peratom);
memory->destroy(extra_nlen);
memory->destroy(extra_max);
memory->sfree(requestor);
xextra_atom = fextra_atom = NULL;
extra_peratom = extra_nlen = NULL;
extra_max = NULL;
requestor = NULL;
// virial_style:
// 1 if computed explicitly by pair->compute via sum over pair interactions
// 2 if computed implicitly by pair->virial_compute via sum over ghost atoms
if (force->newton_pair) virial_style = 2;
else virial_style = 1;
// setup lists of computes for global and per-atom PE and pressure
ev_setup();
// set flags for what arrays to clear in force_clear()
// need to clear additionals arrays if they exist
torqueflag = 0;
if (atom->torque_flag) torqueflag = 1;
erforceflag = 0;
if (atom->erforce_flag) erforceflag = 1;
e_flag = 0;
if (atom->e_flag) e_flag = 1;
rho_flag = 0;
if (atom->rho_flag) rho_flag = 1;
// orthogonal vs triclinic simulation box
triclinic = domain->triclinic;
// reset reneighboring criteria if necessary
neigh_every = neighbor->every;
neigh_delay = neighbor->delay;
neigh_dist_check = neighbor->dist_check;
if (neigh_every != 1 || neigh_delay != 0 || neigh_dist_check != 1) {
if (comm->me == 0)
- error->warning("Resetting reneighboring criteria during minimization");
+ error->warning(FLERR,"Resetting reneighboring criteria during minimization");
}
neighbor->every = 1;
neighbor->delay = 0;
neighbor->dist_check = 1;
niter = neval = 0;
// style-specific initialization
init_style();
}
/* ----------------------------------------------------------------------
setup before run
------------------------------------------------------------------------- */
void Min::setup()
{
if (comm->me == 0 && screen) fprintf(screen,"Setting up minimization ...\n");
// setup extra global dof due to fixes
// cannot be done in init() b/c update init() is before modify init()
nextra_global = modify->min_dof();
if (nextra_global) fextra = new double[nextra_global];
// compute for potential energy
int id = modify->find_compute("thermo_pe");
- if (id < 0) error->all("Minimization could not find thermo_pe compute");
+ if (id < 0) error->all(FLERR,"Minimization could not find thermo_pe compute");
pe_compute = modify->compute[id];
// style-specific setup does two tasks
// setup extra global dof vectors
// setup extra per-atom dof vectors due to requests from Pair classes
// cannot be done in init() b/c update init() is before modify/pair init()
setup_style();
// ndoftotal = total dof for entire minimization problem
// dof for atoms, extra per-atom, extra global
bigint ndofme = 3*atom->nlocal;
for (int m = 0; m < nextra_atom; m++)
ndofme += extra_peratom[m]*atom->nlocal;
MPI_Allreduce(&ndofme,&ndoftotal,1,MPI_LMP_BIGINT,MPI_SUM,world);
ndoftotal += nextra_global;
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
atom->setup();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
if (atom->sortfreq > 0) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
neighbor->build();
neighbor->ncalls = 0;
// remove these restriction eventually
if (nextra_global && searchflag == 0)
- error->all("Cannot use a damped dynamics min style with fix box/relax");
+ error->all(FLERR,"Cannot use a damped dynamics min style with fix box/relax");
if (nextra_atom && searchflag == 0)
- error->all("Cannot use a damped dynamics min style with per-atom DOF");
+ error->all(FLERR,"Cannot use a damped dynamics min style with per-atom DOF");
// atoms may have migrated in comm->exchange()
reset_vectors();
// compute all forces
ev_set(update->ntimestep);
force_clear();
modify->setup_pre_force(vflag);
if (force->pair) force->pair->compute(eflag,vflag);
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if (force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if (force->newton) comm->reverse_comm();
// update per-atom minimization variables stored by pair styles
if (nextra_atom)
for (int m = 0; m < nextra_atom; m++)
requestor[m]->min_xf_get(m);
modify->setup(vflag);
output->setup(1);
// stats for Finish to print
ecurrent = pe_compute->compute_scalar();
if (nextra_global) ecurrent += modify->min_energy(fextra);
if (output->thermo->normflag) ecurrent /= atom->natoms;
einitial = ecurrent;
fnorm2_init = sqrt(fnorm_sqr());
fnorminf_init = fnorm_inf();
}
/* ----------------------------------------------------------------------
setup without output or one-time post-init setup
flag = 0 = just force calculation
flag = 1 = reneighbor and force calculation
------------------------------------------------------------------------- */
void Min::setup_minimal(int flag)
{
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
if (flag) {
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
neighbor->build();
neighbor->ncalls = 0;
}
// atoms may have migrated in comm->exchange()
reset_vectors();
// compute all forces
ev_set(update->ntimestep);
force_clear();
modify->setup_pre_force(vflag);
if (force->pair) force->pair->compute(eflag,vflag);
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if (force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if (force->newton) comm->reverse_comm();
// update per-atom minimization variables stored by pair styles
if (nextra_atom)
for (int m = 0; m < nextra_atom; m++)
requestor[m]->min_xf_get(m);
modify->setup(vflag);
// stats for Finish to print
ecurrent = pe_compute->compute_scalar();
if (nextra_global) ecurrent += modify->min_energy(fextra);
if (output->thermo->normflag) ecurrent /= atom->natoms;
einitial = ecurrent;
fnorm2_init = sqrt(fnorm_sqr());
fnorminf_init = fnorm_inf();
}
/* ----------------------------------------------------------------------
perform minimization, calling iterate() for N steps
------------------------------------------------------------------------- */
void Min::run(int n)
{
// minimizer iterations
stop_condition = iterate(n);
stopstr = stopstrings(stop_condition);
// if early exit from iterate loop:
// set update->nsteps to niter for Finish stats to print
// set output->next values to this timestep
// call energy_force() to insure vflag is set when forces computed
// output->write does final output for thermo, dump, restart files
// add ntimestep to all computes that store invocation times
// since are hardwiring call to thermo/dumps and computes may not be ready
if (stop_condition) {
update->nsteps = niter;
if (update->restrict_output == 0) {
for (int idump = 0; idump < output->ndump; idump++)
output->next_dump[idump] = update->ntimestep;
output->next_dump_any = update->ntimestep;
if (output->restart_every) output->next_restart = update->ntimestep;
}
output->next_thermo = update->ntimestep;
modify->addstep_compute_all(update->ntimestep);
ecurrent = energy_force(0);
output->write(update->ntimestep);
}
}
/* ---------------------------------------------------------------------- */
void Min::cleanup()
{
// stats for Finish to print
efinal = ecurrent;
fnorm2_final = sqrt(fnorm_sqr());
fnorminf_final = fnorm_inf();
// reset reneighboring criteria
neighbor->every = neigh_every;
neighbor->delay = neigh_delay;
neighbor->dist_check = neigh_dist_check;
// delete fix at end of run, so its atom arrays won't persist
modify->delete_fix("MINIMIZE");
}
/* ----------------------------------------------------------------------
evaluate potential energy and forces
may migrate atoms due to reneighboring
return new energy, which should include nextra_global dof
return negative gradient stored in atom->f
return negative gradient for nextra_global dof in fextra
------------------------------------------------------------------------- */
double Min::energy_force(int resetflag)
{
// check for reneighboring
// always communicate since minimizer moved atoms
int nflag = neighbor->decide();
if (nflag == 0) {
timer->stamp();
comm->forward_comm();
timer->stamp(TIME_COMM);
} else {
if (modify->n_min_pre_exchange) modify->min_pre_exchange();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
if (domain->box_change) {
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
}
timer->stamp();
comm->exchange();
if (atom->sortfreq > 0 &&
update->ntimestep >= atom->nextsort) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
timer->stamp(TIME_COMM);
neighbor->build();
timer->stamp(TIME_NEIGHBOR);
}
ev_set(update->ntimestep);
force_clear();
if (modify->n_min_pre_force) modify->min_pre_force(vflag);
timer->stamp();
if (force->pair) {
force->pair->compute(eflag,vflag);
timer->stamp(TIME_PAIR);
}
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
timer->stamp(TIME_BOND);
}
if (force->kspace) {
force->kspace->compute(eflag,vflag);
timer->stamp(TIME_KSPACE);
}
if (force->newton) {
comm->reverse_comm();
timer->stamp(TIME_COMM);
}
// update per-atom minimization variables stored by pair styles
if (nextra_atom)
for (int m = 0; m < nextra_atom; m++)
requestor[m]->min_xf_get(m);
// fixes that affect minimization
if (modify->n_min_post_force) modify->min_post_force(vflag);
// compute potential energy of system
// normalize if thermo PE does
double energy = pe_compute->compute_scalar();
if (nextra_global) energy += modify->min_energy(fextra);
if (output->thermo->normflag) energy /= atom->natoms;
// if reneighbored, atoms migrated
// if resetflag = 1, update x0 of atoms crossing PBC
// reset vectors used by lo-level minimizer
if (nflag) {
if (resetflag) fix_minimize->reset_coords();
reset_vectors();
}
return energy;
}
/* ----------------------------------------------------------------------
clear force on own & ghost atoms
setup and clear other arrays as needed
------------------------------------------------------------------------- */
void Min::force_clear()
{
int i;
// clear global force array
// nall includes ghosts only if either newton flag is set
int nall;
if (force->newton) nall = atom->nlocal + atom->nghost;
else nall = atom->nlocal;
int ntot = nall * comm->nthreads;
double **f = atom->f;
for (i = 0; i < ntot; i++) {
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
}
if (torqueflag) {
double **torque = atom->torque;
for (i = 0; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
if (erforceflag) {
double *erforce = atom->erforce;
for (i = 0; i < nall; i++) erforce[i] = 0.0;
}
if (e_flag) {
double *de = atom->de;
for (i = 0; i < nall; i++) de[i] = 0.0;
}
if (rho_flag) {
double *drho = atom->drho;
for (i = 0; i < nall; i++) drho[i] = 0.0;
}
}
/* ----------------------------------------------------------------------
pair style makes request to add a per-atom variables to minimization
requestor stores callback to pair class to invoke during min
to get current variable and forces on it and to update the variable
return flag that pair can use if it registers multiple variables
------------------------------------------------------------------------- */
int Min::request(Pair *pair, int peratom, double maxvalue)
{
int n = nextra_atom + 1;
xextra_atom = (double **) memory->srealloc(xextra_atom,n*sizeof(double *),
"min:xextra_atom");
fextra_atom = (double **) memory->srealloc(fextra_atom,n*sizeof(double *),
"min:fextra_atom");
memory->grow(extra_peratom,n,"min:extra_peratom");
memory->grow(extra_nlen,n,"min:extra_nlen");
memory->grow(extra_max,n,"min:extra_max");
requestor = (Pair **) memory->srealloc(requestor,n*sizeof(Pair *),
"min:requestor");
requestor[nextra_atom] = pair;
extra_peratom[nextra_atom] = peratom;
extra_max[nextra_atom] = maxvalue;
nextra_atom++;
return nextra_atom-1;
}
/* ---------------------------------------------------------------------- */
void Min::modify_params(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal min_modify command");
+ if (narg == 0) error->all(FLERR,"Illegal min_modify command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"dmax") == 0) {
- if (iarg+2 > narg) error->all("Illegal min_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command");
dmax = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"line") == 0) {
- if (iarg+2 > narg) error->all("Illegal min_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command");
if (strcmp(arg[iarg+1],"backtrack") == 0) linestyle = 0;
else if (strcmp(arg[iarg+1],"quadratic") == 0) linestyle = 1;
- else error->all("Illegal min_modify command");
+ else error->all(FLERR,"Illegal min_modify command");
iarg += 2;
- } else error->all("Illegal min_modify command");
+ } else error->all(FLERR,"Illegal min_modify command");
}
}
/* ----------------------------------------------------------------------
setup lists of computes for global and per-atom PE and pressure
------------------------------------------------------------------------- */
void Min::ev_setup()
{
delete [] elist_global;
delete [] elist_atom;
delete [] vlist_global;
delete [] vlist_atom;
elist_global = elist_atom = NULL;
vlist_global = vlist_atom = NULL;
nelist_global = nelist_atom = 0;
nvlist_global = nvlist_atom = 0;
for (int i = 0; i < modify->ncompute; i++) {
if (modify->compute[i]->peflag) nelist_global++;
if (modify->compute[i]->peatomflag) nelist_atom++;
if (modify->compute[i]->pressflag) nvlist_global++;
if (modify->compute[i]->pressatomflag) nvlist_atom++;
}
if (nelist_global) elist_global = new Compute*[nelist_global];
if (nelist_atom) elist_atom = new Compute*[nelist_atom];
if (nvlist_global) vlist_global = new Compute*[nvlist_global];
if (nvlist_atom) vlist_atom = new Compute*[nvlist_atom];
nelist_global = nelist_atom = 0;
nvlist_global = nvlist_atom = 0;
for (int i = 0; i < modify->ncompute; i++) {
if (modify->compute[i]->peflag)
elist_global[nelist_global++] = modify->compute[i];
if (modify->compute[i]->peatomflag)
elist_atom[nelist_atom++] = modify->compute[i];
if (modify->compute[i]->pressflag)
vlist_global[nvlist_global++] = modify->compute[i];
if (modify->compute[i]->pressatomflag)
vlist_atom[nvlist_atom++] = modify->compute[i];
}
}
/* ----------------------------------------------------------------------
set eflag,vflag for current iteration
invoke matchstep() on all timestep-dependent computes to clear their arrays
eflag/vflag based on computes that need info on this ntimestep
always set eflag_global = 1, since need energy every iteration
eflag = 0 = no energy computation
eflag = 1 = global energy only
eflag = 2 = per-atom energy only
eflag = 3 = both global and per-atom energy
vflag = 0 = no virial computation (pressure)
vflag = 1 = global virial with pair portion via sum of pairwise interactions
vflag = 2 = global virial with pair portion via F dot r including ghosts
vflag = 4 = per-atom virial only
vflag = 5 or 6 = both global and per-atom virial
------------------------------------------------------------------------- */
void Min::ev_set(bigint ntimestep)
{
int i,flag;
int eflag_global = 1;
for (i = 0; i < nelist_global; i++)
elist_global[i]->matchstep(ntimestep);
flag = 0;
int eflag_atom = 0;
for (i = 0; i < nelist_atom; i++)
if (elist_atom[i]->matchstep(ntimestep)) flag = 1;
if (flag) eflag_atom = 2;
if (eflag_global) update->eflag_global = update->ntimestep;
if (eflag_atom) update->eflag_atom = update->ntimestep;
eflag = eflag_global + eflag_atom;
flag = 0;
int vflag_global = 0;
for (i = 0; i < nvlist_global; i++)
if (vlist_global[i]->matchstep(ntimestep)) flag = 1;
if (flag) vflag_global = virial_style;
flag = 0;
int vflag_atom = 0;
for (i = 0; i < nvlist_atom; i++)
if (vlist_atom[i]->matchstep(ntimestep)) flag = 1;
if (flag) vflag_atom = 4;
if (vflag_global) update->vflag_global = update->ntimestep;
if (vflag_atom) update->vflag_atom = update->ntimestep;
vflag = vflag_global + vflag_atom;
}
/* ----------------------------------------------------------------------
compute and return ||force||_2^2
------------------------------------------------------------------------- */
double Min::fnorm_sqr()
{
int i,n;
double *fatom;
double local_norm2_sqr = 0.0;
for (i = 0; i < nvec; i++) local_norm2_sqr += fvec[i]*fvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++)
local_norm2_sqr += fatom[i]*fatom[i];
}
}
double norm2_sqr = 0.0;
MPI_Allreduce(&local_norm2_sqr,&norm2_sqr,1,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++)
norm2_sqr += fextra[i]*fextra[i];
return norm2_sqr;
}
/* ----------------------------------------------------------------------
compute and return ||force||_inf
------------------------------------------------------------------------- */
double Min::fnorm_inf()
{
int i,n;
double *fatom;
double local_norm_inf = 0.0;
for (i = 0; i < nvec; i++)
local_norm_inf = MAX(fabs(fvec[i]),local_norm_inf);
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++)
local_norm_inf = MAX(fabs(fatom[i]),local_norm_inf);
}
}
double norm_inf = 0.0;
MPI_Allreduce(&local_norm_inf,&norm_inf,1,MPI_DOUBLE,MPI_MAX,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++)
norm_inf = MAX(fabs(fextra[i]),norm_inf);
return norm_inf;
}
/* ----------------------------------------------------------------------
possible stop conditions
------------------------------------------------------------------------- */
char *Min::stopstrings(int n)
{
char *strings[] = {"max iterations",
"max force evaluations",
"energy tolerance",
"force tolerance",
"search direction is not downhill",
"linesearch alpha is zero",
"forces are zero",
"quadratic factors are zero",
"trust region too small",
"HFTN minimizer error"};
return strings[n];
}
diff --git a/src/min_cg.cpp b/src/min_cg.cpp
index 9ef3c8c4a..f2b1a666f 100644
--- a/src/min_cg.cpp
+++ b/src/min_cg.cpp
@@ -1,187 +1,184 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "string.h"
#include "min_cg.h"
#include "atom.h"
#include "update.h"
#include "output.h"
#include "timer.h"
using namespace LAMMPS_NS;
// EPS_ENERGY = minimum normalization for energy tolerance
#define EPS_ENERGY 1.0e-8
// same as in other min classes
enum{MAXITER,MAXEVAL,ETOL,FTOL,DOWNHILL,ZEROALPHA,ZEROFORCE,ZEROQUAD};
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
MinCG::MinCG(LAMMPS *lmp) : MinLineSearch(lmp) {}
/* ----------------------------------------------------------------------
minimization via conjugate gradient iterations
------------------------------------------------------------------------- */
int MinCG::iterate(int maxiter)
{
int i,m,n,fail,ntimestep;
double beta,gg,dot[2],dotall[2];
double *fatom,*gatom,*hatom;
// nlimit = max # of CG iterations before restarting
// set to ndoftotal unless too big
int nlimit = static_cast<int> (MIN(MAXSMALLINT,ndoftotal));
// initialize working vectors
for (i = 0; i < nvec; i++) h[i] = g[i] = fvec[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) hatom[i] = gatom[i] = fatom[i];
}
if (nextra_global)
for (i = 0; i < nextra_global; i++) hextra[i] = gextra[i] = fextra[i];
gg = fnorm_sqr();
for (int iter = 0; iter < maxiter; iter++) {
ntimestep = ++update->ntimestep;
niter++;
// line minimization along direction h from current atom->x
eprevious = ecurrent;
fail = (this->*linemin)(ecurrent,alpha_final);
if (fail) return fail;
// function evaluation criterion
if (neval >= update->max_eval) return MAXEVAL;
// energy tolerance criterion
if (fabs(ecurrent-eprevious) <
update->etol * 0.5*(fabs(ecurrent) + fabs(eprevious) + EPS_ENERGY))
return ETOL;
// force tolerance criterion
dot[0] = dot[1] = 0.0;
for (i = 0; i < nvec; i++) {
dot[0] += fvec[i]*fvec[i];
dot[1] += fvec[i]*g[i];
}
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
gatom = gextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) {
dot[0] += fatom[i]*fatom[i];
dot[1] += fatom[i]*gatom[i];
}
}
MPI_Allreduce(dot,dotall,2,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++) {
dotall[0] += fextra[i]*fextra[i];
dotall[1] += fextra[i]*gextra[i];
}
if (dotall[0] < update->ftol*update->ftol) return FTOL;
// update new search direction h from new f = -Grad(x) and old g
// this is Polak-Ribieri formulation
// beta = dotall[0]/gg would be Fletcher-Reeves
// reinitialize CG every ndof iterations by setting beta = 0.0
beta = MAX(0.0,(dotall[0] - dotall[1])/gg);
if ((niter+1) % nlimit == 0) beta = 0.0;
gg = dotall[0];
for (i = 0; i < nvec; i++) {
g[i] = fvec[i];
h[i] = g[i] + beta*h[i];
}
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) {
gatom[i] = fatom[i];
hatom[i] = gatom[i] + beta*hatom[i];
}
}
if (nextra_global)
for (i = 0; i < nextra_global; i++) {
gextra[i] = fextra[i];
hextra[i] = gextra[i] + beta*hextra[i];
}
// reinitialize CG if new search direction h is not downhill
dot[0] = 0.0;
for (i = 0; i < nvec; i++) dot[0] += g[i]*h[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) dot[0] += gatom[i]*hatom[i];
}
MPI_Allreduce(dot,dotall,1,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++)
dotall[0] += gextra[i]*hextra[i];
if (dotall[0] <= 0.0) {
for (i = 0; i < nvec; i++) h[i] = g[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
gatom = gextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) hatom[i] = gatom[i];
}
if (nextra_global)
for (i = 0; i < nextra_global; i++) hextra[i] = gextra[i];
}
// output for thermo, dump, restart files
if (output->next == ntimestep) {
timer->stamp();
output->write(ntimestep);
timer->stamp(TIME_OUTPUT);
}
}
return MAXITER;
}
diff --git a/src/min_fire.cpp b/src/min_fire.cpp
index 0c4e73dc2..18081f17b 100644
--- a/src/min_fire.cpp
+++ b/src/min_fire.cpp
@@ -1,273 +1,270 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "min_fire.h"
#include "universe.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "output.h"
#include "timer.h"
#include "error.h"
using namespace LAMMPS_NS;
// EPS_ENERGY = minimum normalization for energy tolerance
#define EPS_ENERGY 1.0e-8
// same as in other min classes
enum{MAXITER,MAXEVAL,ETOL,FTOL,DOWNHILL,ZEROALPHA,ZEROFORCE,ZEROQUAD};
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define DELAYSTEP 5
#define DT_GROW 1.1
#define DT_SHRINK 0.5
#define ALPHA0 0.1
#define ALPHA_SHRINK 0.99
#define TMAX 10.0
/* ---------------------------------------------------------------------- */
MinFire::MinFire(LAMMPS *lmp) : Min(lmp) {}
/* ---------------------------------------------------------------------- */
void MinFire::init_style()
{
dt = update->dt;
}
/* ---------------------------------------------------------------------- */
void MinFire::setup_style()
{
double **v = atom->v;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
v[i][0] = v[i][1] = v[i][2] = 0.0;
}
/* ----------------------------------------------------------------------
set current vector lengths and pointers
called after atoms have migrated
------------------------------------------------------------------------- */
void MinFire::reset_vectors()
{
// atomic dof
nvec = 3 * atom->nlocal;
if (nvec) xvec = atom->x[0];
if (nvec) fvec = atom->f[0];
}
/* ---------------------------------------------------------------------- */
int MinFire::iterate(int maxiter)
{
bigint ntimestep;
double vmax,vdotf,vdotfall,vdotv,vdotvall,fdotf,fdotfall;
double scale1,scale2;
double dtvone,dtv,dtfm;
int flag,flagall;
alpha_final = 0.0;
double alpha = ALPHA0;
double dtmax = TMAX * dt;
bigint last_negative = update->ntimestep;
for (int iter = 0; iter < maxiter; iter++) {
ntimestep = ++update->ntimestep;
niter++;
// vdotfall = v dot f
double **v = atom->v;
double **f = atom->f;
int nlocal = atom->nlocal;
vdotf = 0.0;
for (int i = 0; i < nlocal; i++)
vdotf += v[i][0]*f[i][0] + v[i][1]*f[i][1] + v[i][2]*f[i][2];
MPI_Allreduce(&vdotf,&vdotfall,1,MPI_DOUBLE,MPI_SUM,world);
// sum vdotf over replicas, if necessary
// this communicator would be invalid for multiprocess replicas
if (update->multireplica == 1) {
vdotf = vdotfall;
MPI_Allreduce(&vdotf,&vdotfall,1,MPI_DOUBLE,MPI_SUM,universe->uworld);
}
// if (v dot f) > 0:
// v = (1-alpha) v + alpha |v| Fhat
// |v| = length of v, Fhat = unit f
// if more than DELAYSTEP since v dot f was negative:
// increase timestep and decrease alpha
if (vdotfall > 0.0) {
vdotv = 0.0;
for (int i = 0; i < nlocal; i++)
vdotv += v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
MPI_Allreduce(&vdotv,&vdotvall,1,MPI_DOUBLE,MPI_SUM,world);
// sum vdotv over replicas, if necessary
// this communicator would be invalid for multiprocess replicas
if (update->multireplica == 1) {
vdotv = vdotvall;
MPI_Allreduce(&vdotv,&vdotvall,1,MPI_DOUBLE,MPI_SUM,universe->uworld);
}
fdotf = 0.0;
for (int i = 0; i < nlocal; i++)
fdotf += f[i][0]*f[i][0] + f[i][1]*f[i][1] + f[i][2]*f[i][2];
MPI_Allreduce(&fdotf,&fdotfall,1,MPI_DOUBLE,MPI_SUM,world);
// sum fdotf over replicas, if necessary
// this communicator would be invalid for multiprocess replicas
if (update->multireplica == 1) {
fdotf = fdotfall;
MPI_Allreduce(&fdotf,&fdotfall,1,MPI_DOUBLE,MPI_SUM,universe->uworld);
}
scale1 = 1.0 - alpha;
if (fdotfall == 0.0) scale2 = 0.0;
else scale2 = alpha * sqrt(vdotvall/fdotfall);
for (int i = 0; i < nlocal; i++) {
v[i][0] = scale1*v[i][0] + scale2*f[i][0];
v[i][1] = scale1*v[i][1] + scale2*f[i][1];
v[i][2] = scale1*v[i][2] + scale2*f[i][2];
}
if (ntimestep - last_negative > DELAYSTEP) {
dt = MIN(dt*DT_GROW,dtmax);
alpha *= ALPHA_SHRINK;
}
// else (v dot f) <= 0:
// decrease timestep, reset alpha, set v = 0
} else {
last_negative = ntimestep;
dt *= DT_SHRINK;
alpha = ALPHA0;
for (int i = 0; i < nlocal; i++)
v[i][0] = v[i][1] = v[i][2] = 0.0;
}
// limit timestep so no particle moves further than dmax
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
dtvone = dt;
for (int i = 0; i < nlocal; i++) {
vmax = MAX(fabs(v[i][0]),fabs(v[i][1]));
vmax = MAX(vmax,fabs(v[i][2]));
if (dtvone*vmax > dmax) dtvone = dmax/vmax;
}
MPI_Allreduce(&dtvone,&dtv,1,MPI_DOUBLE,MPI_MIN,world);
// min dtv over replicas, if necessary
// this communicator would be invalid for multiprocess replicas
if (update->multireplica == 1) {
dtvone = dtv;
MPI_Allreduce(&dtvone,&dtv,1,MPI_DOUBLE,MPI_MIN,universe->uworld);
}
// Euler integration step
double **x = atom->x;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
dtfm = dtv / rmass[i];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
} else {
for (int i = 0; i < nlocal; i++) {
dtfm = dtv / mass[type[i]];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
}
eprevious = ecurrent;
ecurrent = energy_force(0);
neval++;
// energy tolerance criterion
// only check after DELAYSTEP elapsed since velocties reset to 0
// sync across replicas if running multi-replica minimization
if (update->etol > 0.0 && ntimestep-last_negative > DELAYSTEP) {
if (update->multireplica == 0) {
if (fabs(ecurrent-eprevious) <
update->etol * 0.5*(fabs(ecurrent) + fabs(eprevious) + EPS_ENERGY))
return ETOL;
} else {
if (fabs(ecurrent-eprevious) <
update->etol * 0.5*(fabs(ecurrent) + fabs(eprevious) + EPS_ENERGY))
flag = 0;
else flag = 1;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,universe->uworld);
if (flagall == 0) return ETOL;
}
}
// force tolerance criterion
// sync across replicas if running multi-replica minimization
if (update->ftol > 0.0) {
fdotf = fnorm_sqr();
if (update->multireplica == 0) {
if (fdotf < update->ftol*update->ftol) return FTOL;
} else {
if (fdotf < update->ftol*update->ftol) flag = 0;
else flag = 1;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,universe->uworld);
if (flagall == 0) return FTOL;
}
}
// output for thermo, dump, restart files
if (output->next == ntimestep) {
timer->stamp();
output->write(ntimestep);
timer->stamp(TIME_OUTPUT);
}
}
return MAXITER;
}
diff --git a/src/min_hftn.cpp b/src/min_hftn.cpp
index 99c8cef3b..da92ade46 100644
--- a/src/min_hftn.cpp
+++ b/src/min_hftn.cpp
@@ -1,1694 +1,1691 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Author: Todd Plantenga (SNL)
Sources: "Numerical Optimization", Nocedal and Wright, 2nd Ed, p170
"Parallel Unconstrained Min", Plantenga, SAND98-8201
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "atom.h"
#include "fix_minimize.h"
#include "min_hftn.h"
#include "modify.h"
#include "output.h"
#include "pair.h"
#include "update.h"
#include "timer.h"
-#define MIN(A,B) (((A) < (B)) ? (A) : (B))
-#define MAX(A,B) (((A) > (B)) ? (A) : (B))
-
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
* This class performs Hessian-free truncated Newton minimization on an
* unconstrained molecular potential. The algorithm avoids computing the
* Hessian matrix, but obtains a near-quadratic rate of convergence.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
File local data
------------------------------------------------------------------------- */
//---- CONSTANTS MAP TO stopstrings DECLARED IN Min.run (min.cpp).
static const int STOP_MAX_ITER = 0; //-- MAX ITERATIONS EXCEEDED
static const int STOP_MAX_FORCE_EVALS = 1; //-- MAX FORCE EVALUATIONS EXCEEDED
static const int STOP_ENERGY_TOL = 2; //-- STEP DID NOT CHANGE ENERGY
static const int STOP_FORCE_TOL = 3; //-- CONVERGED TO DESIRED FORCE TOL
static const int STOP_TR_TOO_SMALL = 8; //-- TRUST REGION TOO SMALL
static const int STOP_ERROR = 9; //-- INTERNAL ERROR
static const int NO_CGSTEP_BECAUSE_F_TOL_SATISFIED = 0;
static const int CGSTEP_NEWTON = 1;
static const int CGSTEP_TO_TR = 2;
static const int CGSTEP_TO_DMAX = 3;
static const int CGSTEP_NEGATIVE_CURVATURE = 4;
static const int CGSTEP_MAX_INNER_ITERS = 5;
static const int CGSTEP_UNDETERMINED = 6;
//---- WHEN TESTING ENERGY_TOL, THE ENERGY MAGNITUDE MUST BE AT LEAST THIS BIG.
static const double MIN_ETOL_MAG = 1.0e-8;
//---- MACHINE PRECISION IS SOMETIMES DEFINED BY THE C RUNTIME.
#ifdef DBL_EPSILON
#define MACHINE_EPS DBL_EPSILON
#else
#define MACHINE_EPS 2.220446049250313e-16
#endif
/* ----------------------------------------------------------------------
Constructor
------------------------------------------------------------------------- */
MinHFTN::MinHFTN(LAMMPS *lmp) : Min(lmp)
{
searchflag = 1;
for (int i = 1; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
_daExtraGlobal[i] = NULL;
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
_daExtraAtom[i] = NULL;
_fpPrint = NULL;
return;
}
/* ----------------------------------------------------------------------
Destructor
------------------------------------------------------------------------- */
MinHFTN::~MinHFTN (void)
{
for (int i = 1; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
if (_daExtraGlobal[i] != NULL)
delete [] _daExtraGlobal[i];
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
if (_daExtraAtom[i] != NULL)
delete [] _daExtraAtom[i];
return;
}
/* ----------------------------------------------------------------------
Public method init_style
------------------------------------------------------------------------- */
void MinHFTN::init_style()
{
for (int i = 1; i < NUM_HFTN_ATOM_BASED_VECTORS; i++) {
if (_daExtraGlobal[i] != NULL)
delete [] _daExtraGlobal[i];
_daExtraGlobal[i] = NULL;
}
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++) {
if (_daExtraAtom[i] != NULL)
delete [] _daExtraAtom[i];
_daExtraAtom[i] = NULL;
}
return;
}
/* ----------------------------------------------------------------------
Public method setup_style
------------------------------------------------------------------------- */
void MinHFTN::setup_style()
{
//---- ALLOCATE MEMORY FOR ATOMIC DEGREES OF FREEDOM.
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
fix_minimize->add_vector(3);
//---- ALLOCATE MEMORY FOR EXTRA GLOBAL DEGREES OF FREEDOM.
//---- THE FIX MODULE TAKES CARE OF THE FIRST VECTOR, X0 (XK).
if (nextra_global) {
for (int i = 1; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
_daExtraGlobal[i] = new double[nextra_global];
}
//---- ALLOCATE MEMORY FOR EXTRA PER-ATOM DEGREES OF FREEDOM.
if (nextra_atom) {
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
_daExtraAtom[i] = new double*[nextra_atom];
for (int m = 0; m < nextra_atom; m++) {
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
fix_minimize->add_vector (extra_peratom[m]);
}
}
return;
}
/* ----------------------------------------------------------------------
Public method reset_vectors
After an energy/force calculation, atoms may migrate from one processor
to another. Any local vector correlated with atom positions or forces
must also be migrated. This is accomplished by a subclass of Fix.
This method updates local pointers to the latest Fix copies.
------------------------------------------------------------------------- */
void MinHFTN::reset_vectors()
{
nvec = 3 * atom->nlocal;
//---- ATOMIC DEGREES OF FREEDOM.
if (nvec > 0) {
xvec = atom->x[0];
fvec = atom->f[0];
}
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
_daAVectors[i] = fix_minimize->request_vector (i);
//---- EXTRA PER-ATOM DEGREES OF FREEDOM.
if (nextra_atom) {
int n = NUM_HFTN_ATOM_BASED_VECTORS;
for (int m = 0; m < nextra_atom; m++) {
extra_nlen[m] = extra_peratom[m] * atom->nlocal;
requestor[m]->min_xf_pointers(m,&xextra_atom[m],&fextra_atom[m]);
for (int i = 0; i < NUM_HFTN_ATOM_BASED_VECTORS; i++)
_daExtraAtom[i][m] = fix_minimize->request_vector (n++);
}
}
return;
}
/* ----------------------------------------------------------------------
Public method iterate
Upon entry, Min::setup() and Min::run have executed, and energy has
already been evaluated at the initial point. Return an integer code
that maps to a stop condition in min.cpp.
------------------------------------------------------------------------- */
int MinHFTN::iterate(int)
{
//---- TURN THIS ON TO GENERATE AN OPTIMIZATION PROGRESS FILE.
bool bPrintProgress = false;
if (bPrintProgress)
open_hftn_print_file_();
double dFinalEnergy = 0.0;
double dFinalFnorm2 = 0.0;
modify->min_clearstore();
int nStopCode = execute_hftn_ (bPrintProgress,
einitial,
fnorm2_init,
dFinalEnergy,
dFinalFnorm2);
modify->min_clearstore();
if (bPrintProgress)
close_hftn_print_file_();
return( nStopCode );
}
/* ----------------------------------------------------------------------
Private method execute_hftn_
@param[in] bPrintProgress - if true then print progress to a file
@param[in] dInitialEnergy - energy at input x
@param[in] dInitialForce2 - |F|_2 at input x
@param[out] dFinalEnergy - energy at output x
@param[out] dFinalForce2 - |F|_2 at output x
Return stop code described in the enumeration at the top of this file,
and the following:
atom->x - positions at output x
atom->f - forces evaluated at output x
------------------------------------------------------------------------- */
int MinHFTN::execute_hftn_(const bool bPrintProgress,
const double dInitialEnergy,
const double dInitialForce2,
double & dFinalEnergy,
double & dFinalForce2)
{
//---- DEFINE OUTPUTS PRINTED BY "Finish".
eprevious = dInitialEnergy;
alpha_final = 0.0;
dFinalEnergy = dInitialEnergy;
dFinalForce2 = dInitialForce2;
if (dInitialForce2 < update->ftol)
return( STOP_FORCE_TOL );
//---- SAVE ATOM POSITIONS BEFORE AN ITERATION.
fix_minimize->store_box();
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_XK][i] = xvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * xkAtom = _daExtraAtom[VEC_XK][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xkAtom[i] = xatom[i];
}
}
if (nextra_global)
modify->min_store();
double dXInf = calc_xinf_using_mpi_();
//---- FIND THE NUMBER OF UNKNOWNS.
int nLocalNumUnknowns = nvec + nextra_atom;
MPI_Allreduce (&nLocalNumUnknowns, &_nNumUnknowns,
1, MPI_INT, MPI_SUM, world);
//---- INITIALIZE THE TRUST RADIUS BASED ON THE GRADIENT.
double dTrustRadius = 1.5 * dInitialForce2;
//---- TRUST RADIUS MUST KEEP STEPS FROM LETTING ATOMS MOVE SO FAR THEY
//---- VIOLATE PHYSICS OR JUMP BEYOND A PARALLEL PROCESSING DOMAIN.
//---- LINE SEARCH METHODS DO THIS BY RESTRICTING THE LARGEST CHANGE
//---- OF ANY ATOM'S COMPONENT TO dmax. AN EXACT CHECK IS MADE LATER,
//---- BUT THIS GUIDES DETERMINATION OF A MAX TRUST RADIUS.
double dMaxTrustRadius = dmax * sqrt (_nNumUnknowns);
dTrustRadius = MIN (dTrustRadius, dMaxTrustRadius);
double dLastNewtonStep2 = dMaxTrustRadius;
if (bPrintProgress)
hftn_print_line_ (false, -1, neval, dInitialEnergy, dInitialForce2,
-1, dTrustRadius, 0.0, 0.0, 0.0);
bool bHaveEvaluatedAtX = true;
double dCurrentEnergy = dInitialEnergy;
double dCurrentForce2 = dInitialForce2;
for (niter = 0; niter < update->nsteps; niter++) {
(update->ntimestep)++;
//---- CALL THE INNER LOOP TO GET THE NEXT TRUST REGION STEP.
double dCgForce2StopTol = MIN ((dCurrentForce2 / 2.0), 0.1 / (niter+1));
dCgForce2StopTol = MAX (dCgForce2StopTol, update->ftol);
double dNewEnergy;
double dNewForce2;
int nStepType;
double dStepLength2;
double dStepLengthInf;
if (compute_inner_cg_step_ (dTrustRadius,
dCgForce2StopTol,
update->max_eval,
bHaveEvaluatedAtX,
dCurrentEnergy, dCurrentForce2,
dNewEnergy, dNewForce2,
nStepType,
dStepLength2, dStepLengthInf) == false) {
//---- THERE WAS AN ERROR. RESTORE TO LAST ACCEPTED STEP.
if (nextra_global)
modify->min_step (0.0, _daExtraGlobal[VEC_CG_P]);
for (int i = 0; i < nvec; i++)
xvec[i] = _daAVectors[VEC_XK][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * xkAtom = _daExtraAtom[VEC_XK][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] = xkAtom[i];
requestor[m]->min_x_set(m);
}
}
dFinalEnergy = energy_force (0);
neval++;
dFinalForce2 = sqrt (fnorm_sqr());
return( STOP_ERROR );
}
//---- STOP IF THE CURRENT POSITION WAS FOUND TO BE ALREADY GOOD ENOUGH.
//---- IN THIS CASE THE ENERGY AND FORCES ARE ALREADY COMPUTED.
if (nStepType == NO_CGSTEP_BECAUSE_F_TOL_SATISFIED) {
if (bPrintProgress)
hftn_print_line_ (true, niter+1, neval, dNewEnergy, dNewForce2,
nStepType, dTrustRadius, dStepLength2,
0.0, 0.0);
dFinalEnergy = dNewEnergy;
dFinalForce2 = dNewForce2;
return( STOP_FORCE_TOL );
}
//---- COMPUTE THE DIRECTIONAL DERIVATIVE H(x_k) p.
bool bUseForwardDiffs = (dCurrentForce2 > 1000.0 * sqrt (MACHINE_EPS));
evaluate_dir_der_ (bUseForwardDiffs,
VEC_CG_P,
VEC_CG_HD,
true,
dCurrentEnergy);
//---- COMPUTE p^T grad(x_k) AND SAVE IT FOR PRED.
double dGradDotP = calc_grad_dot_v_using_mpi_ (VEC_CG_P);
//---- MOVE TO THE NEW POINT AND EVALUATE ENERGY AND FORCES.
//---- THIS IS THE PLACE WHERE energy_force IS ALLOWED TO RESET.
for (int i = 0; i < nvec; i++)
xvec[i] = _daAVectors[VEC_XK][i] + _daAVectors[VEC_CG_P][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * xkAtom = _daExtraAtom[VEC_XK][m];
double * pAtom = _daExtraAtom[VEC_CG_P][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] = xkAtom[i] + pAtom[i];
requestor[m]->min_x_set(m);
}
}
if (nextra_global)
modify->min_step (1.0, _daExtraGlobal[VEC_CG_P]);
dNewEnergy = energy_force (1);
neval++;
dNewForce2 = sqrt (fnorm_sqr());
double dAred = dCurrentEnergy - dNewEnergy;
//---- STOP IF THE FORCE TOLERANCE IS MET.
if (dNewForce2 < update->ftol) {
if (bPrintProgress)
hftn_print_line_ (true, niter+1, neval, dNewEnergy, dNewForce2,
nStepType, dTrustRadius, dStepLength2,
dAred, -1.0);
//---- (IMPLICITLY ACCEPT THE LAST STEP TO THE NEW POINT.)
dFinalEnergy = dNewEnergy;
dFinalForce2 = dNewForce2;
return( STOP_FORCE_TOL );
}
//---- STOP IF THE ACTUAL ENERGY REDUCTION IS TINY.
if (nStepType != CGSTEP_TO_DMAX) {
double dMag = 0.5 * (fabs (dCurrentEnergy) + fabs (dNewEnergy));
dMag = MAX (dMag, MIN_ETOL_MAG);
if ( (fabs (dAred) < (update->etol * dMag))
|| (dStepLengthInf == 0.0) ) {
if (bPrintProgress)
hftn_print_line_ (true, niter+1, neval,
dNewEnergy, dNewForce2,
nStepType, dTrustRadius, dStepLength2,
dAred, -1.0);
//---- (IMPLICITLY ACCEPT THE LAST STEP TO THE NEW POINT.)
dFinalEnergy = dNewEnergy;
dFinalForce2 = dNewForce2;
return( STOP_ENERGY_TOL );
}
}
//---- COMPUTE THE PREDICTED REDUCTION - p^T grad - 0.5 p^T Hp
double dPHP = calc_dot_prod_using_mpi_ (VEC_CG_P, VEC_CG_HD);
double dPred = - dGradDotP - (0.5 * dPHP);
//---- ACCEPT OR REJECT THE STEP PROPOSED BY THE INNER CG LOOP.
//---- WHEN NEAR A SOLUTION, THE FORCE NORM IS PROBABLY MORE ACCURATE,
//---- SO DON'T ACCEPT A STEP THAT REDUCES ENERGY SOME TINY AMOUNT
//---- WHILE INCREASING THE FORCE NORM.
bool bStepAccepted = (dAred > 0.0)
&& ( (dNewForce2 < dCurrentForce2)
|| (dCurrentForce2 > 1.0e-6));
if (bStepAccepted) {
//---- THE STEP IS ACCEPTED.
if (bPrintProgress)
hftn_print_line_ (true, niter+1, neval, dNewEnergy, dNewForce2,
nStepType, dTrustRadius, dStepLength2,
dAred, dPred);
fix_minimize->store_box();
modify->min_clearstore();
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_XK][i] = xvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * xkAtom = _daExtraAtom[VEC_XK][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xkAtom[i] = xatom[i];
}
}
if (nextra_global)
modify->min_store();
if (niter > 0)
eprevious = dCurrentEnergy;
dCurrentEnergy = dNewEnergy;
dCurrentForce2 = dNewForce2;
bHaveEvaluatedAtX = true;
if (nStepType == CGSTEP_NEWTON)
dLastNewtonStep2 = dStepLength2;
//---- UPDATE THE TRUST REGION BASED ON AGREEMENT BETWEEN
//---- THE ACTUAL REDUCTION AND THE PREDICTED MODEL REDUCTION.
if ((dAred > 0.75 * dPred) && (dStepLength2 >= 0.99 * dTrustRadius))
dTrustRadius = 2.0 * dTrustRadius;
dTrustRadius = MIN (dTrustRadius, dMaxTrustRadius);
//---- DMAX VIOLATIONS TRUNCATE THE CG STEP WITHOUT COMPARISONS;
//---- BETTER TO ADJUST THE TRUST REGION SO DMAX STOPS HAPPENING.
if (nStepType == CGSTEP_TO_DMAX) {
if (dStepLength2 <= MACHINE_EPS)
dTrustRadius = 0.1 * dTrustRadius;
else
dTrustRadius = MIN (dTrustRadius, 2.0 * dStepLength2);
}
}
else {
//---- THE STEP IS REJECTED.
if (bPrintProgress)
hftn_print_line_ (false, niter+1, neval,
dCurrentEnergy, dCurrentForce2,
nStepType, dTrustRadius, dStepLength2,
dAred, dPred);
//---- RESTORE THE LAST X_K POSITION.
if (nextra_global)
modify->min_step (0.0, _daExtraGlobal[VEC_CG_P]);
for (int i = 0; i < nvec; i++)
xvec[i] = _daAVectors[VEC_XK][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * xkAtom = _daExtraAtom[VEC_XK][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] = xkAtom[i];
requestor[m]->min_x_set(m);
}
}
modify->min_clearstore();
bHaveEvaluatedAtX = false;
//---- UPDATE THE TRUST REGION.
//---- EXPERIMENTS INDICATE NEGATIVE CURVATURE CAN TAKE A BAD
//---- STEP A LONG WAY, SO BE MORE AGGRESSIVE IN THIS CASE.
//---- ALSO, IF NEAR A SOLUTION AND DONE WITH NEWTON STEPS,
//---- THEN REDUCE TO SOMETHING NEAR THE LAST GOOD NEWTON STEP.
if ((nStepType == CGSTEP_NEGATIVE_CURVATURE) && (-dAred > dPred))
dTrustRadius = 0.10 * MIN (dTrustRadius, dStepLength2);
else if ( (nStepType == CGSTEP_TO_DMAX)
&& (dStepLength2 <= MACHINE_EPS))
dTrustRadius = 0.10 * dTrustRadius;
else if (-dAred > dPred)
dTrustRadius = 0.20 * MIN (dTrustRadius, dStepLength2);
else
dTrustRadius = 0.25 * MIN (dTrustRadius, dStepLength2);
if ( (nStepType != CGSTEP_NEWTON)
&& (dCurrentForce2 < sqrt (MACHINE_EPS)))
dTrustRadius = MIN (dTrustRadius, 2.0 * dLastNewtonStep2);
dLastNewtonStep2 = dMaxTrustRadius;
//---- STOP IF THE TRUST RADIUS IS TOO SMALL TO CONTINUE.
if ( (dTrustRadius <= 0.0)
|| (dTrustRadius <= MACHINE_EPS * MAX (1.0, dXInf))) {
dFinalEnergy = dCurrentEnergy;
dFinalForce2 = dCurrentForce2;
return( STOP_TR_TOO_SMALL );
}
}
//---- OUTPUT FOR thermo, dump, restart FILES.
if (output->next == update->ntimestep) {
//---- IF THE LAST STEP WAS REJECTED, THEN REEVALUATE ENERGY AND
//---- FORCES AT THE OLD POINT SO THE OUTPUT DOES NOT DISPLAY
//---- THE INCREASED ENERGY OF THE REJECTED STEP.
if (bStepAccepted == false) {
dCurrentEnergy = energy_force (1);
neval++;
}
timer->stamp();
output->write (update->ntimestep);
timer->stamp (TIME_OUTPUT);
}
//---- RETURN IF NUMBER OF EVALUATIONS EXCEEDED.
if (neval >= update->max_eval) {
dFinalEnergy = dCurrentEnergy;
dFinalForce2 = dCurrentForce2;
return( STOP_MAX_FORCE_EVALS );
}
} //-- END for LOOP OVER niter
dFinalEnergy = dCurrentEnergy;
dFinalForce2 = dCurrentForce2;
return( STOP_MAX_ITER );
}
/* ----------------------------------------------------------------------
Private method compute_inner_cg_step_
Execute CG using Hessian-vector products approximated by finite difference
directional derivatives.
On input these must be defined:
atom->x - positions at x
atom->f - ignored
VEC_XK - positions at x
On output these are defined:
atom->x - unchanged
atom->f - forces evaluated at x, but only if nStepType == NO_CGSTEP
VEC_XK - unchanged
VEC_CG_P - step from VEC_XK to new positions
During processing these are modified:
VEC_CG_D - conjugate gradient inner loop step
VEC_CG_HD - Hessian-vector product
VEC_CG_R - residual of inner loop step
VEC_DIF1 - temp storage
VEC_DIF2 - temp storage
@param[in] dTrustRadius - trust region radius for this subiteration
@param[in] dForceTol - stop tolerance on |F|_2 for this subiteration
@param[in] nMaxEvals - total energy/force evaluations allowed
@param[in] bHaveEvalAtXin - true if forces are valid at input x
@param[in] dEnergyAtXin - energy at input x, if bHaveEvalAtXin is true
@param[in] dForce2AtXin - |F|_2 at input x, if bHaveEvalAtXin is true
@param[out] dEnergyAtXout - energy at output x, if NO_CGSTEP (see below)
@param[out] dForce2AtXout - |F|_2 at output x, if NO_CGSTEP (see below)
@param[out] nStepType - step type for hftn_print_line_()
@param[out] dStepLength2 - |step|_2
@param[out] dStepLengthInf - |step|_inf
Return false if there was a fatal error.
If nStepType equals NO_CGSTEP_BECAUSE_F_TOL_SATISFIED, then the energy
and forces are evaluated and returned in dEnergyAtXout, dForce2AtXout;
else energy and forces are not evaluated.
------------------------------------------------------------------------- */
bool MinHFTN::compute_inner_cg_step_(const double dTrustRadius,
const double dForceTol,
const int nMaxEvals,
const bool bHaveEvalAtXin,
const double dEnergyAtXin,
const double dForce2AtXin,
double & dEnergyAtXout,
double & dForce2AtXout,
int & nStepType,
double & dStepLength2,
double & dStepLengthInf)
{
//---- SET p_0 = 0.
if (nextra_global) {
for (int i = 0; i < nextra_global; i++)
_daExtraGlobal[VEC_CG_P][i] = 0.0;
}
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_CG_P][i] = 0.0;
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * pAtom = _daExtraAtom[VEC_CG_P][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
pAtom[i] = 0.0;
}
}
double dPP = 0.0;
//---- OBTAIN THE ENERGY AND FORCES AT THE INPUT POSITION.
double dEnergyAtX = dEnergyAtXin;
double dForce2AtX = dForce2AtXin;
if (bHaveEvalAtXin == false) {
dEnergyAtX = energy_force (0);
neval++;
dForce2AtX = sqrt (fnorm_sqr());
}
//---- RETURN IMMEDIATELY IF THE FORCE TOLERANCE IS ALREADY MET.
//---- THE STEP TYPE INFORMS THE CALLER THAT ENERGY AND FORCES HAVE
//---- BEEN EVALUATED.
if (dForce2AtX <= dForceTol) {
dEnergyAtXout = dEnergyAtX;
dForce2AtXout = dForce2AtX;
nStepType = NO_CGSTEP_BECAUSE_F_TOL_SATISFIED;
dStepLength2 = 0.0;
dStepLengthInf = 0.0;
return( true );
}
//---- r_0 = -grad (FIRST SEARCH DIRECTION IS STEEPEST DESCENT)
//---- d_0 = r_0
//---- REMEMBER THAT FORCES = -GRADIENT.
if (nextra_global) {
for (int i = 0; i < nextra_global; i++) {
_daExtraGlobal[VEC_CG_R][i] = fextra[i];
_daExtraGlobal[VEC_CG_D][i] = fextra[i];
}
}
for (int i = 0; i < nvec; i++) {
_daAVectors[VEC_CG_R][i] = fvec[i];
_daAVectors[VEC_CG_D][i] = fvec[i];
}
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * fatom = fextra_atom[m];
double * rAtom = _daExtraAtom[VEC_CG_R][m];
double * dAtom = _daExtraAtom[VEC_CG_D][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++) {
rAtom[i] = fatom[i];
dAtom[i] = fatom[i];
}
}
}
double dRR = dForce2AtX * dForce2AtX;
double dR0norm2 = sqrt (dRR);
//---- LIMIT THE NUMBER OF INNER CG ITERATIONS.
//---- BASE IT ON THE NUMBER OF UNKNOWNS, OR MAXIMUM EVALUATIONS ASSUMING
//---- FORWARD DIFFERENCES ARE USED.
//---- NOTE THAT SETTING MAX=1 GIVES STEEPEST DESCENT.
int nLimit1 = _nNumUnknowns / 5;
if (nLimit1 < 100)
nLimit1 = MIN (_nNumUnknowns, 100);
int nLimit2 = (nMaxEvals - neval) / 2;
int nMaxInnerIters = MIN (nLimit1, nLimit2);
//---- FURTHER LIMIT ITERATIONS IF NEAR MACHINE ROUNDOFF.
//---- THE METHOD CAN WASTE A LOT EVALUATIONS WITH LITTLE PAYOFF PROSPECT.
if (dForce2AtX < (sqrt (MACHINE_EPS) * MAX (1.0, fabs (dEnergyAtX))) )
nMaxInnerIters = MIN (nMaxInnerIters, _nNumUnknowns / 20);
bool bUseForwardDiffs = (dForce2AtX > 1000.0 * sqrt (MACHINE_EPS));
//---- MAIN CG LOOP.
for (int nInnerIter = 0; nInnerIter < nMaxInnerIters; nInnerIter++) {
//---- COMPUTE HESSIAN-VECTOR PRODUCT: H(x_k) d_i.
double dDummyEnergy;
evaluate_dir_der_ (bUseForwardDiffs,
VEC_CG_D,
VEC_CG_HD,
false,
dDummyEnergy);
//---- CALCULATE d_i^T H d_i AND d_i^T d_i.
double dDHD;
double dDD;
calc_dhd_dd_using_mpi_ (dDHD, dDD);
//---- HANDLE NEGATIVE CURVATURE.
if (dDHD <= (MACHINE_EPS * dDD)) {
//---- PROJECT BOTH DIRECTIONS TO THE TRUST RADIUS AND DECIDE
//---- WHICH MAKES A BETTER PREDICTED REDUCTION.
//---- p_i^T H(x_k) d_i AND grad_i^T d_i.
double dPdotD = calc_dot_prod_using_mpi_ (VEC_CG_P, VEC_CG_D);
double dPdotHD = calc_dot_prod_using_mpi_ (VEC_CG_P, VEC_CG_HD);
//---- MOVE TO X_K AND COMPUTE ENERGY AND FORCES.
if (nextra_global)
modify->min_step (0.0, _daExtraGlobal[VEC_CG_P]);
for (int i = 0; i < nvec; i++)
xvec[i] = _daAVectors[VEC_XK][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * xkAtom = _daExtraAtom[VEC_XK][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] = xkAtom[i];
requestor[m]->min_x_set(m);
}
}
dEnergyAtX = energy_force (0);
neval++;
double dGradDotD = calc_grad_dot_v_using_mpi_ (VEC_CG_D);
double tau = compute_to_tr_ (dPP, dPdotD, dDD, dTrustRadius,
true, dDHD, dPdotHD, dGradDotD);
//---- MOVE THE POINT.
if (nextra_global) {
double * pGlobal = _daExtraGlobal[VEC_CG_P];
double * dGlobal = _daExtraGlobal[VEC_CG_D];
for (int i = 0; i < nextra_global; i++) {
pGlobal[i] += tau * dGlobal[i];
}
}
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_CG_P][i] += tau * _daAVectors[VEC_CG_D][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * pAtom = _daExtraAtom[VEC_CG_P][m];
double * dAtom = _daExtraAtom[VEC_CG_D][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
pAtom[i] += tau * dAtom[i];
}
}
nStepType = CGSTEP_NEGATIVE_CURVATURE;
calc_plengths_using_mpi_ (dStepLength2, dStepLengthInf);
return( true );
}
//---- COMPUTE THE OPTIMAL STEP LENGTH BASED ON THE QUADRATIC CG MODEL.
double dAlpha = dRR / dDHD;
//---- MIGHT WANT TO ENABLE THIS TO DEBUG INTERNAL CG STEPS.
//fprintf (_fpPrint, " alpha = %11.8f neval=%4d\n", dAlpha, neval);
//---- p_i+1 = p_i + alpha_i d_i
//---- (SAVE THE CURRENT p_i IN CASE THE STEP HAS TO BE SHORTENED.)
if (nextra_global) {
double * pGlobal = _daExtraGlobal[VEC_CG_P];
double * dGlobal = _daExtraGlobal[VEC_CG_D];
double * d1Global = _daExtraGlobal[VEC_DIF1];
for (int i = 0; i < nextra_global; i++) {
d1Global[i] = pGlobal[i];
pGlobal[i] += dAlpha * dGlobal[i];
}
}
for (int i = 0; i < nvec; i++) {
_daAVectors[VEC_DIF1][i] = _daAVectors[VEC_CG_P][i];
_daAVectors[VEC_CG_P][i] += dAlpha * _daAVectors[VEC_CG_D][i];
}
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * pAtom = _daExtraAtom[VEC_CG_P][m];
double * dAtom = _daExtraAtom[VEC_CG_D][m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++) {
d1Atom[i] = pAtom[i];
pAtom[i] += dAlpha * dAtom[i];
}
}
}
//---- COMPUTE VECTOR PRODUCTS p_i+1^T p_i+1 AND p_i^T d_i.
double dPnewDotPnew;
double dPoldDotD;
calc_ppnew_pdold_using_mpi_ (dPnewDotPnew, dPoldDotD);
nStepType = CGSTEP_UNDETERMINED;
//---- IF STEP LENGTH IS TOO LARGE, THEN REDUCE IT AND RETURN.
double tau;
if (step_exceeds_TR_ (dTrustRadius, dPP, dPoldDotD, dDD, tau)) {
adjust_step_to_tau_ (tau);
nStepType = CGSTEP_TO_TR;
}
if (step_exceeds_DMAX_()) {
adjust_step_to_tau_ (0.0);
nStepType = CGSTEP_TO_DMAX;
}
if ((nStepType == CGSTEP_TO_TR) || (nStepType == CGSTEP_TO_DMAX)) {
calc_plengths_using_mpi_ (dStepLength2, dStepLengthInf);
return( true );
}
dStepLength2 = sqrt (dPnewDotPnew);
//---- r_i+1 = r_i - alpha * H d_i
if (nextra_global) {
double * rGlobal = _daExtraGlobal[VEC_CG_R];
double * hdGlobal = _daExtraGlobal[VEC_CG_HD];
for (int i = 0; i < nextra_global; i++)
rGlobal[i] -= dAlpha * hdGlobal[i];
}
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_CG_R][i] -= dAlpha * _daAVectors[VEC_CG_HD][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * rAtom = _daExtraAtom[VEC_CG_R][m];
double * hdAtom = _daExtraAtom[VEC_CG_HD][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
rAtom[i] -= dAlpha * hdAtom[i];
}
}
double dRnewDotRnew = calc_dot_prod_using_mpi_ (VEC_CG_R, VEC_CG_R);
//---- IF RESIDUAL IS SMALL ENOUGH, THEN RETURN THE CURRENT STEP.
if (sqrt (dRnewDotRnew) < dForceTol * dR0norm2) {
nStepType = CGSTEP_NEWTON;
calc_plengths_using_mpi_ (dStepLength2, dStepLengthInf);
return( true );
}
//---- beta = r_i+1^T r_i+1 / r_i^T r_i
//---- d_i+1 = r_i+1 + beta d_i
double dBeta = dRnewDotRnew / dRR;
if (nextra_global) {
double * rGlobal = _daExtraGlobal[VEC_CG_R];
double * dGlobal = _daExtraGlobal[VEC_CG_D];
for (int i = 0; i < nextra_global; i++)
dGlobal[i] = rGlobal[i] + dBeta * dGlobal[i];
}
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_CG_D][i] = _daAVectors[VEC_CG_R][i]
+ dBeta * _daAVectors[VEC_CG_D][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * rAtom = _daExtraAtom[VEC_CG_R][m];
double * dAtom = _daExtraAtom[VEC_CG_D][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
dAtom[i] = rAtom[i] + dBeta * dAtom[i];
}
}
//---- CONTINUE THE LOOP.
dRR = dRnewDotRnew;
dPP = dPnewDotPnew;
}
nStepType = CGSTEP_MAX_INNER_ITERS;
calc_plengths_using_mpi_ (dStepLength2, dStepLengthInf);
return( true );
}
/* ----------------------------------------------------------------------
Private method calc_xinf_using_mpi_
------------------------------------------------------------------------- */
double MinHFTN::calc_xinf_using_mpi_(void) const
{
double dXInfLocal = 0.0;
for (int i = 0; i < nvec; i++)
dXInfLocal = MAX(dXInfLocal,fabs(xvec[i]));
double dXInf;
MPI_Allreduce (&dXInfLocal, &dXInf, 1, MPI_DOUBLE, MPI_MAX, world);
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
int n = extra_nlen[m];
double dXInfLocalExtra = 0.0;
for (int i = 0; i < n; i++)
dXInfLocalExtra = MAX (dXInfLocalExtra, fabs (xatom[i]));
double dXInfExtra;
MPI_Allreduce (&dXInfLocalExtra, &dXInfExtra,
1, MPI_DOUBLE, MPI_MAX, world);
dXInf = MAX (dXInf, dXInfExtra);
}
}
return( dXInf );
}
/* ----------------------------------------------------------------------
Private method calc_dot_prod_using_mpi_
------------------------------------------------------------------------- */
double MinHFTN::calc_dot_prod_using_mpi_(const int nIx1,
const int nIx2) const
{
double dDotLocal = 0.0;
for (int i = 0; i < nvec; i++)
dDotLocal += _daAVectors[nIx1][i] * _daAVectors[nIx2][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * i1Atom = _daExtraAtom[nIx1][m];
double * i2Atom = _daExtraAtom[nIx2][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
dDotLocal += i1Atom[i] * i2Atom[i];
}
}
double dDot;
MPI_Allreduce (&dDotLocal, &dDot, 1, MPI_DOUBLE, MPI_SUM, world);
if (nextra_global) {
for (int i = 0; i < nextra_global; i++) {
double * i1Global = _daExtraGlobal[nIx1];
double * i2Global = _daExtraGlobal[nIx2];
dDot += i1Global[i] * i2Global[i];
}
}
return( dDot );
}
/* ----------------------------------------------------------------------
Private method calc_grad_dot_v_using_mpi_
------------------------------------------------------------------------- */
double MinHFTN::calc_grad_dot_v_using_mpi_(const int nIx) const
{
//---- ASSUME THAT FORCES HAVE BEEN EVALUATED AT DESIRED ATOM POSITIONS.
//---- REMEMBER THAT FORCES = -GRADIENT.
double dGradDotVLocal = 0.0;
for (int i = 0; i < nvec; i++)
dGradDotVLocal += - _daAVectors[nIx][i] * fvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * fatom = fextra_atom[m];
double * iAtom = _daExtraAtom[nIx][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
dGradDotVLocal += - iAtom[i] * fatom[i];
}
}
double dGradDotV;
MPI_Allreduce (&dGradDotVLocal, &dGradDotV, 1, MPI_DOUBLE, MPI_SUM, world);
if (nextra_global) {
for (int i = 0; i < nextra_global; i++) {
double * iGlobal = _daExtraGlobal[nIx];
dGradDotV += - iGlobal[i] * fextra[i];
}
}
return( dGradDotV );
}
/* ----------------------------------------------------------------------
Private method calc_dhd_dd_using_mpi_
------------------------------------------------------------------------- */
void MinHFTN::calc_dhd_dd_using_mpi_(double & dDHD,
double & dDD) const
{
double dDHDLocal = 0.0;
double dDDLocal = 0.0;
for (int i = 0; i < nvec; i++) {
dDHDLocal += _daAVectors[VEC_CG_D][i] * _daAVectors[VEC_CG_HD][i];
dDDLocal += _daAVectors[VEC_CG_D][i] * _daAVectors[VEC_CG_D][i];
}
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * dAtom = _daExtraAtom[VEC_CG_D][m];
double * hdAtom = _daExtraAtom[VEC_CG_HD][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++) {
dDHDLocal += dAtom[i] * hdAtom[i];
dDDLocal += dAtom[i] * dAtom[i];
}
}
}
double daDotsLocal[2];
daDotsLocal[0] = dDHDLocal;
daDotsLocal[1] = dDDLocal;
double daDots[2];
MPI_Allreduce (daDotsLocal, daDots, 2, MPI_DOUBLE, MPI_SUM, world);
if (nextra_global) {
double * dGlobal = _daExtraGlobal[VEC_CG_D];
double * hdGlobal = _daExtraGlobal[VEC_CG_HD];
for (int i = 0; i < nextra_global; i++) {
daDots[0] += dGlobal[i] * hdGlobal[i];
daDots[1] += dGlobal[i] * dGlobal[i];
}
}
dDHD = daDots[0];
dDD = daDots[1];
return;
}
/* ----------------------------------------------------------------------
Private method calc_ppnew_pdold_using_mpi_
------------------------------------------------------------------------- */
void MinHFTN::calc_ppnew_pdold_using_mpi_(double & dPnewDotPnew,
double & dPoldDotD) const
{
double dPnewDotPnewLocal = 0.0;
double dPoldDotDLocal = 0.0;
for (int i = 0; i < nvec; i++) {
dPnewDotPnewLocal
+= _daAVectors[VEC_CG_P][i] * _daAVectors[VEC_CG_P][i];
dPoldDotDLocal
+= _daAVectors[VEC_DIF1][i] * _daAVectors[VEC_CG_D][i];
}
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * dAtom = _daExtraAtom[VEC_CG_D][m];
double * pAtom = _daExtraAtom[VEC_CG_P][m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++) {
dPnewDotPnewLocal += pAtom[i] * pAtom[i];
dPoldDotDLocal += d1Atom[i] * dAtom[i];
}
}
}
double daDotsLocal[2];
daDotsLocal[0] = dPnewDotPnewLocal;
daDotsLocal[1] = dPoldDotDLocal;
double daDots[2];
MPI_Allreduce (daDotsLocal, daDots, 2, MPI_DOUBLE, MPI_SUM, world);
if (nextra_global) {
for (int i = 0; i < nextra_global; i++) {
double * dGlobal = _daExtraGlobal[VEC_CG_D];
double * pGlobal = _daExtraGlobal[VEC_CG_P];
double * d1Global = _daExtraGlobal[VEC_DIF1];
daDots[0] += pGlobal[i] * pGlobal[i];
daDots[1] += d1Global[i] * dGlobal[i];
}
}
dPnewDotPnew = daDots[0];
dPoldDotD = daDots[1];
return;
}
/* ----------------------------------------------------------------------
Private method calc_plengths_using_mpi_
------------------------------------------------------------------------- */
void MinHFTN::calc_plengths_using_mpi_(double & dStepLength2,
double & dStepLengthInf) const
{
double dPPLocal = 0.0;
double dPInfLocal = 0.0;
for (int i = 0; i < nvec; i++) {
dPPLocal += _daAVectors[VEC_CG_P][i] * _daAVectors[VEC_CG_P][i];
dPInfLocal = MAX (dPInfLocal, fabs (_daAVectors[VEC_CG_P][i]));
}
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * pAtom = _daExtraAtom[VEC_CG_P][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++) {
dPPLocal += pAtom[i] * pAtom[i];
dPInfLocal = MAX (dPInfLocal, fabs (pAtom[i]));
}
}
}
double dPP;
MPI_Allreduce (&dPPLocal, &dPP, 1, MPI_DOUBLE, MPI_SUM, world);
double dPInf;
MPI_Allreduce (&dPInfLocal, &dPInf, 1, MPI_DOUBLE, MPI_MAX, world);
if (nextra_global) {
for (int i = 0; i < nextra_global; i++) {
double * pGlobal = _daExtraGlobal[VEC_CG_P];
dPP += pGlobal[i] * pGlobal[i];
dPInf = MAX (dPInf, fabs (pGlobal[i]));
}
}
dStepLength2 = sqrt (dPP);
dStepLengthInf = dPInf;
return;
}
/* ----------------------------------------------------------------------
Private method step_exceeds_TR_
------------------------------------------------------------------------- */
bool MinHFTN::step_exceeds_TR_(const double dTrustRadius,
const double dPP,
const double dPD,
const double dDD,
double & dTau) const
{
double dPnewNorm2;
double dPnewNormInf;
calc_plengths_using_mpi_ (dPnewNorm2, dPnewNormInf);
if (dPnewNorm2 > dTrustRadius) {
dTau = compute_to_tr_ (dPP, dPD, dDD, dTrustRadius,
false, 0.0, 0.0, 0.0);
return( true );
}
//---- STEP LENGTH IS NOT TOO LONG.
dTau = 0.0;
return( false );
}
/* ----------------------------------------------------------------------
Private method step_exceeds_DMAX_
Check that atoms do not move too far:
for atom coordinates: limit is dmax
for extra per-atom DOF: limit is extra_max[]
for extra global DOF: limit is set by modify->max_alpha,
which calls fix_box_relax->max_alpha
------------------------------------------------------------------------- */
bool MinHFTN::step_exceeds_DMAX_(void) const
{
double dAlpha = dmax * sqrt (_nNumUnknowns);
double dPInfLocal = 0.0;
for (int i = 0; i < nvec; i++)
dPInfLocal = MAX (dPInfLocal, fabs (_daAVectors[VEC_CG_P][i]));
double dPInf;
MPI_Allreduce (&dPInfLocal, &dPInf, 1, MPI_DOUBLE, MPI_MAX, world);
if (dPInf > dmax)
return( true );
if (dPInf > MACHINE_EPS)
dAlpha = MIN (dAlpha, dmax / dPInf);
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * pAtom = _daExtraAtom[VEC_CG_P][m];
dPInfLocal = 0.0;
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
dPInfLocal = MAX (dPInfLocal, fabs (pAtom[i]));
MPI_Allreduce (&dPInfLocal, &dPInf, 1, MPI_DOUBLE, MPI_MAX, world);
if (dPInf > extra_max[m])
return( true );
if (dPInf > MACHINE_EPS)
dAlpha = MIN (dAlpha, extra_max[m] / dPInf);
}
}
if (nextra_global) {
//---- IF THE MAXIMUM DISTANCE THAT THE GLOBAL BOX CONSTRAINT WILL
//---- ALLOW IS SMALLER THAN THE PROPOSED DISTANCE, THEN THE STEP
//---- IS TOO LONG. PROPOSED DISTANCE IS ESTIMATED BY |P|_INF.
double dAlphaExtra = modify->max_alpha (_daExtraGlobal[VEC_CG_P]);
if (dAlphaExtra < dAlpha)
return( true );
}
//---- STEP LENGTH IS NOT TOO LONG.
return( false );
}
/* ----------------------------------------------------------------------
Private method adjust_step_to_tau_
Adjust the step so that VEC_CG_P = VEC_DIF1 + tau * VEC_CG_D.
------------------------------------------------------------------------- */
void MinHFTN::adjust_step_to_tau_(const double tau)
{
if (nextra_global) {
double * pGlobal = _daExtraGlobal[VEC_CG_P];
double * dGlobal = _daExtraGlobal[VEC_CG_D];
double * d1Global = _daExtraGlobal[VEC_DIF1];
for (int i = 0; i < nextra_global; i++)
pGlobal[i] = d1Global[i] + (tau * dGlobal[i]);
}
for (int i = 0; i < nvec; i++) {
_daAVectors[VEC_CG_P][i] = _daAVectors[VEC_DIF1][i]
+ (tau * _daAVectors[VEC_CG_D][i]);
}
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * pAtom = _daExtraAtom[VEC_CG_P][m];
double * dAtom = _daExtraAtom[VEC_CG_D][m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
pAtom[i] = d1Atom[i] + (tau * dAtom[i]);
}
}
return;
}
/* ----------------------------------------------------------------------
Private method compute_to_tr_
Return the value tau that solves
|| p + tau*d ||_2 = dTrustRadius
If both roots are considered, the TR method chooses the one that minimizes
grad^T (p + tau*d) + 0.5 (p + tau*d)^T H (p + tau*d)
@param[in] dPP - p^T p
@param[in] dPD - p^T d
@param[in] dDD - d^T d
@param[in] dTrustRadius - distance to match
@param[in] bConsiderBothRoots - evaluate both roots, or return the positive
@param[in] dDHD - d^T H d
@param[in] dPdotHD - p^T H d
@param[in] dGradDotD - grad(x_k)^T d
------------------------------------------------------------------------- */
double MinHFTN::compute_to_tr_(const double dPP,
const double dPD,
const double dDD,
const double dTrustRadius,
const bool bConsiderBothRoots,
const double dDHD,
const double dPdotHD,
const double dGradDotD) const
{
//---- SOLVE A QUADRATIC EQUATION FOR TAU.
//---- THE COEFFICIENTS ARE SUCH THAT THERE ARE ALWAYS TWO REAL ROOTS,
//---- ONE POSITIVE AND ONE NEGATIVE.
//---- CHECK FOR ERRONEOUS DATA.
if ( (dDD <= 0.0) || (dPP < 0.0) || (dTrustRadius < 0.0)
|| (dTrustRadius * dTrustRadius < dPP) ) {
printf ("HFTN internal error - bad data given to compute_to_tr_()\n");
return( 0.0 );
}
double dTRsqrd = dTrustRadius * dTrustRadius;
double dDiscr = (dPD * dPD) - (dDD * (dPP - dTRsqrd));
dDiscr = MAX (0.0, dDiscr); //-- SHOULD NEVER BE NEGATIVE
dDiscr = sqrt (dDiscr);
double dRootPos = (-dPD + dDiscr) / dDD;
double dRootNeg = (-dPD - dDiscr) / dDD;
if (bConsiderBothRoots == false)
return( dRootPos );
//---- EVALUATE THE CG OBJECTIVE FUNCTION FOR EACH ROOT.
double dTmpTerm = dGradDotD + dPdotHD;
double dCgRedPos = (dRootPos * dTmpTerm) + (0.5 * dRootPos*dRootPos * dDHD);
double dCgRedNeg = (dRootNeg * dTmpTerm) + (0.5 * dRootNeg*dRootNeg * dDHD);
if ((-dCgRedPos) > (-dCgRedNeg))
return( dRootPos );
else
return( dRootNeg );
}
/* ----------------------------------------------------------------------
Private method evaluate_dir_der_
Compute the directional derivative using a finite difference approximation.
This is equivalent to the Hessian times direction vector p.
As a side effect, the method computes the energy and forces at x.
On input these must be defined:
atom->x - positions at x
atom->f - ignored
nIxDir - VEC_ index of the direction p
nIxResult - ignored
On output these are defined:
atom->x - unchanged
atom->f - forces evaluated at x, only if bEvaluateAtX is true
nIxDir - unchanged
nIxResult - directional derivative Hp
During processing these are modified:
VEC_DIF1
VEC_DIF2
@param[in] bUseForwardDiffs - if true use forward difference approximation,
else use central difference
@param[in] nIxDir - VEC_ index of the direction
@param[in] nIxResult - VEC_ index to place the result
(it is acceptable for nIxDir = nIxResult)
@param[in] bEvaluateAtX - if true, then evaluate at x before returning
@param[out] dNewEnergy - energy at x, if bEvaluateAtX is true
@param[out] dNewForce2 - |F|_2 at x, if bEvaluateAtX is true
------------------------------------------------------------------------- */
void MinHFTN::evaluate_dir_der_(const bool bUseForwardDiffs,
const int nIxDir,
const int nIxResult,
const bool bEvaluateAtX,
double & dNewEnergy)
{
//---- COMPUTE THE MAGNITUDE OF THE DIRECTION VECTOR: |p|_2.
double dDirNorm2SqrdLocal = 0.0;
for (int i = 0; i < nvec; i++)
dDirNorm2SqrdLocal
+= _daAVectors[nIxDir][i] * _daAVectors[nIxDir][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * iAtom = _daExtraAtom[nIxDir][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
dDirNorm2SqrdLocal += iAtom[i] * iAtom[i];
}
}
double dDirNorm2Sqrd = 0.0;
MPI_Allreduce (&dDirNorm2SqrdLocal, &dDirNorm2Sqrd,
1, MPI_DOUBLE, MPI_SUM, world);
if (nextra_global) {
for (int i = 0; i < nextra_global; i++) {
double * iGlobal = _daExtraGlobal[nIxDir];
dDirNorm2Sqrd += iGlobal[i] * iGlobal[i];
}
}
double dDirNorm2 = sqrt (dDirNorm2Sqrd);
//---- IF THE STEP IS TOO SMALL, RETURN ZERO FOR THE DERIVATIVE.
if (dDirNorm2 == 0.0) {
for (int i = 0; i < nvec; i++)
_daAVectors[nIxResult][i] = 0.0;
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * iAtom = _daExtraAtom[nIxDir][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
iAtom[i] = 0;
}
}
if (nextra_global) {
for (int i = 0; i < nextra_global; i++)
_daExtraGlobal[nIxDir][i] = 0.0;
}
if (bEvaluateAtX) {
dNewEnergy = energy_force (0);
neval++;
}
return;
}
//---- FORWARD DIFFERENCES ARE LESS ACCURATE THAN CENTRAL DIFFERENCES,
//---- BUT REQUIRE ONLY 2 ENERGY+FORCE EVALUATIONS VERSUS 3 EVALUATIONS.
//---- STORAGE REQUIREMENTS ARE THE SAME.
if (bUseForwardDiffs) {
//---- EQUATION IS FROM THE OLD LAMMPS VERSION, SAND98-8201.
double dEps = 2.0 * sqrt (1000.0 * MACHINE_EPS) / dDirNorm2;
//---- SAVE A COPY OF x.
fix_minimize->store_box();
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_DIF1][i] = xvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
d1Atom[i] = xatom[i];
}
}
if (nextra_global) {
modify->min_pushstore();
modify->min_store();
}
//---- EVALUATE FORCES AT x + eps*p.
if (nextra_global)
modify->min_step (dEps, _daExtraGlobal[nIxDir]);
for (int i = 0; i < nvec; i++)
xvec[i] += dEps * _daAVectors[nIxDir][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * iAtom = _daExtraAtom[nIxDir][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] += dEps * iAtom[i];
requestor[m]->min_x_set(m);
}
}
energy_force (0);
neval++;
//---- STORE THE FORCE IN DIF2.
if (nextra_global) {
for (int i = 0; i < nextra_global; i++)
_daExtraGlobal[VEC_DIF2][i] = fextra[i];
}
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_DIF2][i] = fvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * fatom = fextra_atom[m];
double * d2Atom = _daExtraAtom[VEC_DIF2][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
d2Atom[i] = fatom[i];
}
}
//---- MOVE BACK TO x AND EVALUATE FORCES.
if (nextra_global) {
modify->min_step (0.0, _daExtraGlobal[VEC_DIF1]);
modify->min_popstore();
}
for (int i = 0; i < nvec; i++)
xvec[i] = _daAVectors[VEC_DIF1][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] += d1Atom[i];
requestor[m]->min_x_set(m);
}
}
dNewEnergy = energy_force (0);
neval++;
//---- COMPUTE THE DIFFERENCE VECTOR: [grad(x + eps*p) - grad(x)] / eps.
//---- REMEMBER THAT FORCES = -GRADIENT.
for (int i = 0; i < nvec; i++)
_daAVectors[nIxResult][i] = (fvec[i] - _daAVectors[VEC_DIF2][i]) / dEps;
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * iAtom = _daExtraAtom[nIxResult][m];
double * d2Atom = _daExtraAtom[VEC_DIF2][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
iAtom[i] = (fextra_atom[m][i] - d2Atom[i]) / dEps;
}
}
if (nextra_global) {
for (int i = 0; i < nextra_global; i++)
_daExtraGlobal[nIxResult][i]
= (fextra[i] - _daExtraGlobal[VEC_DIF2][i]) / dEps;
}
}
else { //-- bUseForwardDiffs == false
//---- EQUATION IS FROM THE OLD LAMMPS VERSION, SAND98-8201.
double dEps = pow (3000.0 * MACHINE_EPS, 0.33333333) / dDirNorm2;
//---- SAVE A COPY OF x.
fix_minimize->store_box();
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_DIF1][i] = xvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
d1Atom[i] = xatom[i];
}
}
if (nextra_global) {
modify->min_pushstore();
modify->min_store();
}
//---- EVALUATE FORCES AT x + eps*p.
if (nextra_global)
modify->min_step (dEps, _daExtraGlobal[nIxDir]);
for (int i = 0; i < nvec; i++)
xvec[i] += dEps * _daAVectors[nIxDir][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * iAtom = _daExtraAtom[nIxDir][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] += dEps * iAtom[i];
requestor[m]->min_x_set(m);
}
}
energy_force (0);
neval++;
//---- STORE THE FORCE IN DIF2.
if (nextra_global) {
for (int i = 0; i < nextra_global; i++)
_daExtraGlobal[VEC_DIF2][i] = fextra[i];
}
for (int i = 0; i < nvec; i++)
_daAVectors[VEC_DIF2][i] = fvec[i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * fatom = fextra_atom[m];
double * d2Atom = _daExtraAtom[VEC_DIF2][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
d2Atom[i] = fatom[i];
}
}
//---- EVALUATE FORCES AT x - eps*p.
if (nextra_global)
modify->min_step (-dEps, _daExtraGlobal[nIxDir]);
for (int i = 0; i < nvec; i++)
xvec[i] = _daAVectors[VEC_DIF1][i]
- dEps * _daAVectors[nIxDir][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * iAtom = _daExtraAtom[nIxDir][m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] = d1Atom[i] - dEps * iAtom[i];
requestor[m]->min_x_set(m);
}
}
energy_force (0);
neval++;
//---- COMPUTE THE DIFFERENCE VECTOR:
//---- [grad(x + eps*p) - grad(x - eps*p)] / 2*eps.
//---- REMEMBER THAT FORCES = -GRADIENT.
if (nextra_global) {
double * iGlobal = _daExtraGlobal[nIxResult];
double * d2Global = _daExtraGlobal[VEC_DIF2];
for (int i = 0; i < nextra_global; i++)
iGlobal[i] = (fextra[i] - d2Global[i]) / (2.0 + dEps);
}
for (int i = 0; i < nvec; i++)
_daAVectors[nIxResult][i] =
(fvec[i] - _daAVectors[VEC_DIF2][i]) / (2.0 * dEps);
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * fatom = fextra_atom[m];
double * iAtom = _daExtraAtom[nIxResult][m];
double * d2Atom = _daExtraAtom[VEC_DIF2][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
iAtom[i] = (fatom[i] - d2Atom[i]) / (2.0 + dEps);
}
}
if (bEvaluateAtX) {
//---- EVALUATE FORCES AT x.
if (nextra_global) {
modify->min_step (0.0, _daExtraGlobal[VEC_DIF1]);
modify->min_popstore();
}
for (int i = 0; i < nvec; i++)
xvec[i] = _daAVectors[VEC_DIF1][i];
if (nextra_atom) {
for (int m = 0; m < nextra_atom; m++) {
double * xatom = xextra_atom[m];
double * d1Atom = _daExtraAtom[VEC_DIF1][m];
int n = extra_nlen[m];
for (int i = 0; i < n; i++)
xatom[i] = d1Atom[i];
requestor[m]->min_x_set(m);
}
}
dNewEnergy = energy_force (0);
neval++;
}
}
return;
}
/* ----------------------------------------------------------------------
Private method open_hftn_print_file_
------------------------------------------------------------------------- */
void MinHFTN::open_hftn_print_file_(void)
{
int nMyRank;
MPI_Comm_rank (world, &nMyRank);
char szTmp[50];
sprintf (szTmp, "progress_MinHFTN_%d.txt", nMyRank);
_fpPrint = fopen (szTmp, "w");
if (_fpPrint == NULL) {
printf ("*** MinHFTN cannot open file '%s'\n", szTmp);
printf ("*** continuing...\n");
return;
}
fprintf (_fpPrint, " Iter Evals Energy |F|_2"
" Step TR used |step|_2 ared pred\n");
return;
}
/* ----------------------------------------------------------------------
Private method hftn_print_line_
Step types:
1 - Nw (inner iteration converged like a Newton step)
2 - TR (inner iteration reached the trust region boundary)
3 - Neg (inner iteration ended with negative curvature)
------------------------------------------------------------------------- */
void MinHFTN::hftn_print_line_(const bool bIsStepAccepted,
const int nIteration,
const int nTotalEvals,
const double dEnergy,
const double dForce2,
const int nStepType,
const double dTrustRadius,
const double dStepLength2,
const double dActualRed,
const double dPredictedRed) const
{
const char sFormat1[]
= " %4d %5d %14.8f %11.5e\n";
const char sFormatA[]
= " %4d %5d %14.8f %11.5e %3s %9.3e %8.2e %10.3e %10.3e\n";
const char sFormatR[]
= "r %4d %5d %14.8f %11.5e %3s %9.3e %8.2e %10.3e %10.3e\n";
if (_fpPrint == NULL)
return;
char sStepType[4];
if (nStepType == NO_CGSTEP_BECAUSE_F_TOL_SATISFIED)
strcpy (sStepType, " - ");
else if (nStepType == CGSTEP_NEWTON)
strcpy (sStepType, "Nw ");
else if (nStepType == CGSTEP_TO_TR)
strcpy (sStepType, "TR ");
else if (nStepType == CGSTEP_TO_DMAX)
strcpy (sStepType, "dmx");
else if (nStepType == CGSTEP_NEGATIVE_CURVATURE)
strcpy (sStepType, "Neg");
else if (nStepType == CGSTEP_MAX_INNER_ITERS)
strcpy (sStepType, "its");
else
strcpy (sStepType, "???");
if (nIteration == -1) {
fprintf (_fpPrint, sFormat1,
0, nTotalEvals, dEnergy, dForce2);
}
else {
if (bIsStepAccepted)
fprintf (_fpPrint, sFormatA,
nIteration, nTotalEvals, dEnergy, dForce2,
sStepType, dTrustRadius, dStepLength2,
dActualRed, dPredictedRed);
else
fprintf (_fpPrint, sFormatR,
nIteration, nTotalEvals, dEnergy, dForce2,
sStepType, dTrustRadius, dStepLength2,
dActualRed, dPredictedRed);
}
fflush (_fpPrint);
return;
}
/* ----------------------------------------------------------------------
Private method close_hftn_print_file_
------------------------------------------------------------------------- */
void MinHFTN::close_hftn_print_file_(void)
{
if (_fpPrint != NULL) fclose (_fpPrint);
return;
}
diff --git a/src/min_linesearch.cpp b/src/min_linesearch.cpp
index f3ae5782a..1736b066e 100644
--- a/src/min_linesearch.cpp
+++ b/src/min_linesearch.cpp
@@ -1,547 +1,544 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
improved CG and backtrack ls, added quadratic ls
Sources: Numerical Recipes frprmn routine
"Conjugate Gradient Method Without the Agonizing Pain" by
JR Shewchuk, http://www-2.cs.cmu.edu/~jrs/jrspapers.html#cg
------------------------------------------------------------------------- */
#include "math.h"
#include "min_linesearch.h"
#include "atom.h"
#include "update.h"
#include "neighbor.h"
#include "domain.h"
#include "modify.h"
#include "fix_minimize.h"
#include "pair.h"
#include "output.h"
#include "thermo.h"
#include "timer.h"
#include "error.h"
using namespace LAMMPS_NS;
// ALPHA_MAX = max alpha allowed to avoid long backtracks
// ALPHA_REDUCE = reduction ratio, should be in range [0.5,1)
// BACKTRACK_SLOPE, should be in range (0,0.5]
// QUADRATIC_TOL = tolerance on alpha0, should be in range [0.1,1)
// EMACH = machine accuracy limit of energy changes (1.0e-8)
// EPS_QUAD = tolerance for quadratic projection
#define ALPHA_MAX 1.0
#define ALPHA_REDUCE 0.5
#define BACKTRACK_SLOPE 0.4
#define EMACH 1.0e-8
#define QUADRATIC_TOL 0.1
#define EPS_QUAD 1.0e-28
// same as in other min classes
enum{MAXITER,MAXEVAL,ETOL,FTOL,DOWNHILL,ZEROALPHA,ZEROFORCE,ZEROQUAD};
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
MinLineSearch::MinLineSearch(LAMMPS *lmp) : Min(lmp)
{
searchflag = 1;
gextra = hextra = NULL;
x0extra_atom = gextra_atom = hextra_atom = NULL;
}
/* ---------------------------------------------------------------------- */
MinLineSearch::~MinLineSearch()
{
delete [] gextra;
delete [] hextra;
delete [] x0extra_atom;
delete [] gextra_atom;
delete [] hextra_atom;
}
/* ---------------------------------------------------------------------- */
void MinLineSearch::init_style()
{
if (linestyle == 0) linemin = &MinLineSearch::linemin_backtrack;
else if (linestyle == 1) linemin = &MinLineSearch::linemin_quadratic;
delete [] gextra;
delete [] hextra;
gextra = hextra = NULL;
delete [] x0extra_atom;
delete [] gextra_atom;
delete [] hextra_atom;
x0extra_atom = gextra_atom = hextra_atom = NULL;
}
/* ---------------------------------------------------------------------- */
void MinLineSearch::setup_style()
{
// memory for x0,g,h for atomic dof
fix_minimize->add_vector(3);
fix_minimize->add_vector(3);
fix_minimize->add_vector(3);
// memory for g,h for extra global dof, fix stores x0
if (nextra_global) {
gextra = new double[nextra_global];
hextra = new double[nextra_global];
}
// memory for x0,g,h for extra per-atom dof
if (nextra_atom) {
x0extra_atom = new double*[nextra_atom];
gextra_atom = new double*[nextra_atom];
hextra_atom = new double*[nextra_atom];
for (int m = 0; m < nextra_atom; m++) {
fix_minimize->add_vector(extra_peratom[m]);
fix_minimize->add_vector(extra_peratom[m]);
fix_minimize->add_vector(extra_peratom[m]);
}
}
}
/* ----------------------------------------------------------------------
set current vector lengths and pointers
called after atoms have migrated
------------------------------------------------------------------------- */
void MinLineSearch::reset_vectors()
{
// atomic dof
nvec = 3 * atom->nlocal;
if (nvec) xvec = atom->x[0];
if (nvec) fvec = atom->f[0];
x0 = fix_minimize->request_vector(0);
g = fix_minimize->request_vector(1);
h = fix_minimize->request_vector(2);
// extra per-atom dof
if (nextra_atom) {
int n = 3;
for (int m = 0; m < nextra_atom; m++) {
extra_nlen[m] = extra_peratom[m] * atom->nlocal;
requestor[m]->min_xf_pointers(m,&xextra_atom[m],&fextra_atom[m]);
x0extra_atom[m] = fix_minimize->request_vector(n++);
gextra_atom[m] = fix_minimize->request_vector(n++);
hextra_atom[m] = fix_minimize->request_vector(n++);
}
}
}
/* ----------------------------------------------------------------------
line minimization methods
find minimum-energy starting at x along h direction
input args: eoriginal = energy at initial x
input extra: n,x,x0,f,h for atomic, extra global, extra per-atom dof
output args: return 0 if successful move, non-zero alpha
return non-zero if failed
alpha = distance moved along h for x at min eng config
update neval counter of eng/force function evaluations
output extra: if fail, energy_force() of original x
if succeed, energy_force() at x + alpha*h
atom->x = coords at new configuration
atom->f = force at new configuration
ecurrent = energy of new configuration
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
linemin: backtracking line search (Proc 3.1, p 41 in Nocedal and Wright)
uses no gradient info, but should be very robust
start at maxdist, backtrack until energy decrease is sufficient
------------------------------------------------------------------------- */
int MinLineSearch::linemin_backtrack(double eoriginal, double &alpha)
{
int i,m,n;
double fdothall,fdothme,hme,hmax,hmaxall;
double de_ideal,de;
double *xatom,*x0atom,*fatom,*hatom;
// fdothall = projection of search dir along downhill gradient
// if search direction is not downhill, exit with error
fdothme = 0.0;
for (i = 0; i < nvec; i++) fdothme += fvec[i]*h[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) fdothme += fatom[i]*hatom[i];
}
MPI_Allreduce(&fdothme,&fdothall,1,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++) fdothall += fextra[i]*hextra[i];
if (output->thermo->normflag) fdothall /= atom->natoms;
if (fdothall <= 0.0) return DOWNHILL;
// set alpha so no dof is changed by more than max allowed amount
// for atom coords, max amount = dmax
// for extra per-atom dof, max amount = extra_max[]
// for extra global dof, max amount is set by fix
// also insure alpha <= ALPHA_MAX
// else will have to backtrack from huge value when forces are tiny
// if all search dir components are already 0.0, exit with error
hme = 0.0;
for (i = 0; i < nvec; i++) hme = MAX(hme,fabs(h[i]));
MPI_Allreduce(&hme,&hmaxall,1,MPI_DOUBLE,MPI_MAX,world);
alpha = MIN(ALPHA_MAX,dmax/hmaxall);
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
hatom = hextra_atom[m];
n = extra_nlen[m];
hme = 0.0;
for (i = 0; i < n; i++) hme = MAX(hme,fabs(hatom[i]));
MPI_Allreduce(&hme,&hmax,1,MPI_DOUBLE,MPI_MAX,world);
alpha = MIN(alpha,extra_max[m]/hmax);
hmaxall = MAX(hmaxall,hmax);
}
if (nextra_global) {
double alpha_extra = modify->max_alpha(hextra);
alpha = MIN(alpha,alpha_extra);
for (i = 0; i < nextra_global; i++)
hmaxall = MAX(hmaxall,fabs(hextra[i]));
}
if (hmaxall == 0.0) return ZEROFORCE;
// store box and values of all dof at start of linesearch
fix_minimize->store_box();
for (i = 0; i < nvec; i++) x0[i] = xvec[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
xatom = xextra_atom[m];
x0atom = x0extra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) x0atom[i] = xatom[i];
}
if (nextra_global) modify->min_store();
// Important diagnostic: test the gradient against energy
// double etmp;
// double alphatmp = alphamax*1.0e-4;
// etmp = alpha_step(alphatmp,1);
// printf("alpha = %g dele = %g dele_force = %g err = %g\n",
// alphatmp,etmp-eoriginal,-alphatmp*fdothall,
// etmp-eoriginal+alphatmp*fdothall);
// alpha_step(0.0,1);
// backtrack with alpha until energy decrease is sufficient
while (1) {
ecurrent = alpha_step(alpha,1);
// if energy change is better than ideal, exit with success
de_ideal = -BACKTRACK_SLOPE*alpha*fdothall;
de = ecurrent - eoriginal;
if (de <= de_ideal) {
if (nextra_global) {
int itmp = modify->min_reset_ref();
if (itmp) ecurrent = energy_force(1);
}
return 0;
}
// reduce alpha
alpha *= ALPHA_REDUCE;
// backtracked all the way to 0.0
// reset to starting point, exit with error
if (alpha <= 0.0 || de_ideal >= -EMACH) {
ecurrent = alpha_step(0.0,0);
return ZEROALPHA;
}
}
}
/* ----------------------------------------------------------------------
// linemin: quadratic line search (adapted from Dennis and Schnabel)
// The objective function is approximated by a quadratic
// function in alpha, for sufficiently small alpha.
// This idea is the same as that used in the well-known secant
// method. However, since the change in the objective function
// (difference of two finite numbers) is not known as accurately
// as the gradient (which is close to zero), all the expressions
// are written in terms of gradients. In this way, we can converge
// the LAMMPS forces much closer to zero.
//
// We know E,Eprev,fh,fhprev. The Taylor series about alpha_prev
// truncated at the quadratic term is:
//
// E = Eprev - del_alpha*fhprev + (1/2)del_alpha^2*Hprev
//
// and
//
// fh = fhprev - del_alpha*Hprev
//
// where del_alpha = alpha-alpha_prev
//
// We solve these two equations for Hprev and E=Esolve, giving:
//
// Esolve = Eprev - del_alpha*(f+fprev)/2
//
// We define relerr to be:
//
// relerr = |(Esolve-E)/Eprev|
// = |1.0 - (0.5*del_alpha*(f+fprev)+E)/Eprev|
//
// If this is accurate to within a reasonable tolerance, then
// we go ahead and use a secant step to fh = 0:
//
// alpha0 = alpha - (alpha-alphaprev)*fh/delfh;
//
------------------------------------------------------------------------- */
int MinLineSearch::linemin_quadratic(double eoriginal, double &alpha)
{
int i,m,n;
double fdothall,fdothme,hme,hmax,hmaxall;
double de_ideal,de;
double delfh,engprev,relerr,alphaprev,fhprev,ff,fh,alpha0;
double dot[2],dotall[2];
double *xatom,*x0atom,*fatom,*hatom;
double alphamax;
// fdothall = projection of search dir along downhill gradient
// if search direction is not downhill, exit with error
fdothme = 0.0;
for (i = 0; i < nvec; i++) fdothme += fvec[i]*h[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) fdothme += fatom[i]*hatom[i];
}
MPI_Allreduce(&fdothme,&fdothall,1,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global)
for (i = 0; i < nextra_global; i++) fdothall += fextra[i]*hextra[i];
if (output->thermo->normflag) fdothall /= atom->natoms;
if (fdothall <= 0.0) return DOWNHILL;
// set alphamax so no dof is changed by more than max allowed amount
// for atom coords, max amount = dmax
// for extra per-atom dof, max amount = extra_max[]
// for extra global dof, max amount is set by fix
// also insure alphamax <= ALPHA_MAX
// else will have to backtrack from huge value when forces are tiny
// if all search dir components are already 0.0, exit with error
hme = 0.0;
for (i = 0; i < nvec; i++) hme = MAX(hme,fabs(h[i]));
MPI_Allreduce(&hme,&hmaxall,1,MPI_DOUBLE,MPI_MAX,world);
alphamax = MIN(ALPHA_MAX,dmax/hmaxall);
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
hatom = hextra_atom[m];
n = extra_nlen[m];
hme = 0.0;
for (i = 0; i < n; i++) hme = MAX(hme,fabs(hatom[i]));
MPI_Allreduce(&hme,&hmax,1,MPI_DOUBLE,MPI_MAX,world);
alphamax = MIN(alphamax,extra_max[m]/hmax);
hmaxall = MAX(hmaxall,hmax);
}
if (nextra_global) {
double alpha_extra = modify->max_alpha(hextra);
alphamax = MIN(alphamax,alpha_extra);
for (i = 0; i < nextra_global; i++)
hmaxall = MAX(hmaxall,fabs(hextra[i]));
}
if (hmaxall == 0.0) return ZEROFORCE;
// store box and values of all dof at start of linesearch
fix_minimize->store_box();
for (i = 0; i < nvec; i++) x0[i] = xvec[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
xatom = xextra_atom[m];
x0atom = x0extra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) x0atom[i] = xatom[i];
}
if (nextra_global) modify->min_store();
// backtrack with alpha until energy decrease is sufficient
// or until get to small energy change, then perform quadratic projection
alpha = alphamax;
fhprev = fdothall;
engprev = eoriginal;
alphaprev = 0.0;
// important diagnostic: test the gradient against energy
// double etmp;
// double alphatmp = alphamax*1.0e-4;
// etmp = alpha_step(alphatmp,1);
// printf("alpha = %g dele = %g dele_force = %g err = %g\n",
// alphatmp,etmp-eoriginal,-alphatmp*fdothall,
// etmp-eoriginal+alphatmp*fdothall);
// alpha_step(0.0,1);
while (1) {
ecurrent = alpha_step(alpha,1);
// compute new fh, alpha, delfh
dot[0] = dot[1] = 0.0;
for (i = 0; i < nvec; i++) {
dot[0] += fvec[i]*fvec[i];
dot[1] += fvec[i]*h[i];
}
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
fatom = fextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) {
dot[0] += fatom[i]*fatom[i];
dot[1] += fatom[i]*hatom[i];
}
}
MPI_Allreduce(dot,dotall,2,MPI_DOUBLE,MPI_SUM,world);
if (nextra_global) {
for (i = 0; i < nextra_global; i++) {
dotall[0] += fextra[i]*fextra[i];
dotall[1] += fextra[i]*hextra[i];
}
}
ff = dotall[0];
fh = dotall[1];
if (output->thermo->normflag) {
ff /= atom->natoms;
fh /= atom->natoms;
}
delfh = fh - fhprev;
// if fh or delfh is epsilon, reset to starting point, exit with error
if (fabs(fh) < EPS_QUAD || fabs(delfh) < EPS_QUAD) {
ecurrent = alpha_step(0.0,0);
return ZEROQUAD;
}
// Check if ready for quadratic projection, equivalent to secant method
// alpha0 = projected alpha
relerr = fabs(1.0-(0.5*(alpha-alphaprev)*(fh+fhprev)+ecurrent)/engprev);
alpha0 = alpha - (alpha-alphaprev)*fh/delfh;
if (relerr <= QUADRATIC_TOL && alpha0 > 0.0 && alpha0 < alphamax) {
ecurrent = alpha_step(alpha0,1);
if (ecurrent - eoriginal < EMACH) {
if (nextra_global) {
int itmp = modify->min_reset_ref();
if (itmp) ecurrent = energy_force(1);
}
return 0;
}
}
// if backtracking energy change is better than ideal, exit with success
de_ideal = -BACKTRACK_SLOPE*alpha*fdothall;
de = ecurrent - eoriginal;
if (de <= de_ideal) {
if (nextra_global) {
int itmp = modify->min_reset_ref();
if (itmp) ecurrent = energy_force(1);
}
return 0;
}
// save previous state
fhprev = fh;
engprev = ecurrent;
alphaprev = alpha;
// reduce alpha
alpha *= ALPHA_REDUCE;
// backtracked all the way to 0.0
// reset to starting point, exit with error
if (alpha <= 0.0 || de_ideal >= -EMACH) {
ecurrent = alpha_step(0.0,0);
return ZEROALPHA;
}
}
}
/* ---------------------------------------------------------------------- */
double MinLineSearch::alpha_step(double alpha, int resetflag)
{
int i,n,m;
double *xatom,*x0atom,*hatom;
// reset to starting point
if (nextra_global) modify->min_step(0.0,hextra);
for (i = 0; i < nvec; i++) xvec[i] = x0[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
xatom = xextra_atom[m];
x0atom = x0extra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) xatom[i] = x0atom[i];
requestor[m]->min_x_set(m);
}
// step forward along h
if (alpha > 0.0) {
if (nextra_global) modify->min_step(alpha,hextra);
for (i = 0; i < nvec; i++) xvec[i] += alpha*h[i];
if (nextra_atom)
for (m = 0; m < nextra_atom; m++) {
xatom = xextra_atom[m];
hatom = hextra_atom[m];
n = extra_nlen[m];
for (i = 0; i < n; i++) xatom[i] += alpha*hatom[i];
requestor[m]->min_x_set(m);
}
}
// compute and return new energy
neval++;
return energy_force(resetflag);
}
diff --git a/src/min_quickmin.cpp b/src/min_quickmin.cpp
index 5ed10f863..fe9df160b 100644
--- a/src/min_quickmin.cpp
+++ b/src/min_quickmin.cpp
@@ -1,240 +1,237 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "min_quickmin.h"
#include "universe.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "output.h"
#include "timer.h"
#include "error.h"
using namespace LAMMPS_NS;
// EPS_ENERGY = minimum normalization for energy tolerance
#define EPS_ENERGY 1.0e-8
// same as in other min classes
enum{MAXITER,MAXEVAL,ETOL,FTOL,DOWNHILL,ZEROALPHA,ZEROFORCE,ZEROQUAD};
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define DELAYSTEP 5
/* ---------------------------------------------------------------------- */
MinQuickMin::MinQuickMin(LAMMPS *lmp) : Min(lmp) {}
/* ---------------------------------------------------------------------- */
void MinQuickMin::init_style()
{
dt = update->dt;
}
/* ---------------------------------------------------------------------- */
void MinQuickMin::setup_style()
{
double **v = atom->v;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
v[i][0] = v[i][1] = v[i][2] = 0.0;
}
/* ----------------------------------------------------------------------
set current vector lengths and pointers
called after atoms have migrated
------------------------------------------------------------------------- */
void MinQuickMin::reset_vectors()
{
// atomic dof
nvec = 3 * atom->nlocal;
if (nvec) xvec = atom->x[0];
if (nvec) fvec = atom->f[0];
}
/* ----------------------------------------------------------------------
minimization via QuickMin damped dynamics
------------------------------------------------------------------------- */
int MinQuickMin::iterate(int maxiter)
{
bigint ntimestep;
double vmax,vdotf,vdotfall,fdotf,fdotfall,scale;
double dtvone,dtv,dtfm;
int flag,flagall;
alpha_final = 0.0;
bigint last_negative = update->ntimestep;
for (int iter = 0; iter < maxiter; iter++) {
ntimestep = ++update->ntimestep;
niter++;
// zero velocity if anti-parallel to force
// else project velocity in direction of force
double **v = atom->v;
double **f = atom->f;
int nlocal = atom->nlocal;
vdotf = 0.0;
for (int i = 0; i < nlocal; i++)
vdotf += v[i][0]*f[i][0] + v[i][1]*f[i][1] + v[i][2]*f[i][2];
MPI_Allreduce(&vdotf,&vdotfall,1,MPI_DOUBLE,MPI_SUM,world);
// sum vdotf over replicas, if necessary
// this communicator would be invalid for multiprocess replicas
if (update->multireplica == 1) {
vdotf = vdotfall;
MPI_Allreduce(&vdotf,&vdotfall,1,MPI_DOUBLE,MPI_SUM,universe->uworld);
}
if (vdotfall < 0.0) {
last_negative = ntimestep;
for (int i = 0; i < nlocal; i++)
v[i][0] = v[i][1] = v[i][2] = 0.0;
} else {
fdotf = 0.0;
for (int i = 0; i < nlocal; i++)
fdotf += f[i][0]*f[i][0] + f[i][1]*f[i][1] + f[i][2]*f[i][2];
MPI_Allreduce(&fdotf,&fdotfall,1,MPI_DOUBLE,MPI_SUM,world);
// sum fdotf over replicas, if necessary
// this communicator would be invalid for multiprocess replicas
if (update->multireplica == 1) {
fdotf = fdotfall;
MPI_Allreduce(&fdotf,&fdotfall,1,MPI_DOUBLE,MPI_SUM,universe->uworld);
}
if (fdotfall == 0.0) scale = 0.0;
else scale = vdotfall/fdotfall;
for (int i = 0; i < nlocal; i++) {
v[i][0] = scale * f[i][0];
v[i][1] = scale * f[i][1];
v[i][2] = scale * f[i][2];
}
}
// limit timestep so no particle moves further than dmax
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
dtvone = dt;
for (int i = 0; i < nlocal; i++) {
vmax = MAX(fabs(v[i][0]),fabs(v[i][1]));
vmax = MAX(vmax,fabs(v[i][2]));
if (dtvone*vmax > dmax) dtvone = dmax/vmax;
}
MPI_Allreduce(&dtvone,&dtv,1,MPI_DOUBLE,MPI_MIN,world);
// min dtv over replicas, if necessary
// this communicator would be invalid for multiprocess replicas
if (update->multireplica == 1) {
dtvone = dtv;
MPI_Allreduce(&dtvone,&dtv,1,MPI_DOUBLE,MPI_MIN,universe->uworld);
}
// Euler integration step
double **x = atom->x;
if (rmass) {
for (int i = 0; i < nlocal; i++) {
dtfm = dtv / rmass[i];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
} else {
for (int i = 0; i < nlocal; i++) {
dtfm = dtv / mass[type[i]];
x[i][0] += dtv * v[i][0];
x[i][1] += dtv * v[i][1];
x[i][2] += dtv * v[i][2];
v[i][0] += dtfm * f[i][0];
v[i][1] += dtfm * f[i][1];
v[i][2] += dtfm * f[i][2];
}
}
eprevious = ecurrent;
ecurrent = energy_force(0);
neval++;
// energy tolerance criterion
// only check after DELAYSTEP elapsed since velocties reset to 0
// sync across replicas if running multi-replica minimization
if (update->etol > 0.0 && ntimestep-last_negative > DELAYSTEP) {
if (update->multireplica == 0) {
if (fabs(ecurrent-eprevious) <
update->etol * 0.5*(fabs(ecurrent) + fabs(eprevious) + EPS_ENERGY))
return ETOL;
} else {
if (fabs(ecurrent-eprevious) <
update->etol * 0.5*(fabs(ecurrent) + fabs(eprevious) + EPS_ENERGY))
flag = 0;
else flag = 1;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,universe->uworld);
if (flagall == 0) return ETOL;
}
}
// force tolerance criterion
// sync across replicas if running multi-replica minimization
if (update->ftol > 0.0) {
fdotf = fnorm_sqr();
if (update->multireplica == 0) {
if (fdotf < update->ftol*update->ftol) return FTOL;
} else {
if (fdotf < update->ftol*update->ftol) flag = 0;
else flag = 1;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,universe->uworld);
if (flagall == 0) return FTOL;
}
}
// output for thermo, dump, restart files
if (output->next == ntimestep) {
timer->stamp();
output->write(ntimestep);
timer->stamp(TIME_OUTPUT);
}
}
return MAXITER;
}
diff --git a/src/minimize.cpp b/src/minimize.cpp
index dcee996dc..f93fbf538 100644
--- a/src/minimize.cpp
+++ b/src/minimize.cpp
@@ -1,68 +1,68 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "minimize.h"
#include "domain.h"
#include "update.h"
#include "min.h"
#include "finish.h"
#include "timer.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Minimize::Minimize(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void Minimize::command(int narg, char **arg)
{
- if (narg != 4) error->all("Illegal minimize command");
+ if (narg != 4) error->all(FLERR,"Illegal minimize command");
if (domain->box_exist == 0)
- error->all("Minimize command before simulation box is defined");
+ error->all(FLERR,"Minimize command before simulation box is defined");
update->etol = atof(arg[0]);
update->ftol = atof(arg[1]);
update->nsteps = atoi(arg[2]);
update->max_eval = atoi(arg[3]);
if (update->etol < 0.0 || update->ftol < 0.0)
- error->all("Illegal minimize command");
+ error->all(FLERR,"Illegal minimize command");
update->whichflag = 2;
update->beginstep = update->firststep = update->ntimestep;
update->endstep = update->laststep = update->firststep + update->nsteps;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many iterations");
+ error->all(FLERR,"Too many iterations");
lmp->init();
update->minimize->setup();
timer->barrier_start(TIME_LOOP);
update->minimize->run(update->nsteps);
timer->barrier_stop(TIME_LOOP);
update->minimize->cleanup();
Finish finish(lmp);
finish.end(1);
update->whichflag = 0;
update->firststep = update->laststep = 0;
update->beginstep = update->endstep = 0;
}
diff --git a/src/modify.cpp b/src/modify.cpp
index afad1579a..c07416ac4 100644
--- a/src/modify.cpp
+++ b/src/modify.cpp
@@ -1,1169 +1,1166 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdio.h"
#include "string.h"
#include "modify.h"
#include "style_compute.h"
#include "style_fix.h"
#include "atom.h"
#include "comm.h"
#include "fix.h"
#include "compute.h"
#include "group.h"
#include "update.h"
#include "domain.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 4
// mask settings - same as in fix.cpp
#define INITIAL_INTEGRATE 1
#define POST_INTEGRATE 2
#define PRE_EXCHANGE 4
#define PRE_NEIGHBOR 8
#define PRE_FORCE 16
#define POST_FORCE 32
#define FINAL_INTEGRATE 64
#define END_OF_STEP 128
#define THERMO_ENERGY 256
#define INITIAL_INTEGRATE_RESPA 512
#define POST_INTEGRATE_RESPA 1024
#define PRE_FORCE_RESPA 2048
#define POST_FORCE_RESPA 4096
#define FINAL_INTEGRATE_RESPA 8192
#define MIN_PRE_EXCHANGE 16384
#define MIN_PRE_FORCE 32768
#define MIN_POST_FORCE 65536
#define MIN_ENERGY 131072
#define POST_RUN 262144
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
Modify::Modify(LAMMPS *lmp) : Pointers(lmp)
{
nfix = maxfix = 0;
n_initial_integrate = n_post_integrate = 0;
n_pre_exchange = n_pre_neighbor = 0;
n_pre_force = n_post_force = 0;
n_final_integrate = n_end_of_step = n_thermo_energy = 0;
n_initial_integrate_respa = n_post_integrate_respa = 0;
n_pre_force_respa = n_post_force_respa = n_final_integrate_respa = 0;
n_min_pre_exchange = n_min_pre_force = n_min_post_force = n_min_energy = 0;
fix = NULL;
fmask = NULL;
list_initial_integrate = list_post_integrate = NULL;
list_pre_exchange = list_pre_neighbor = NULL;
list_pre_force = list_post_force = NULL;
list_final_integrate = list_end_of_step = NULL;
list_thermo_energy = NULL;
list_initial_integrate_respa = list_post_integrate_respa = NULL;
list_pre_force_respa = list_post_force_respa = NULL;
list_final_integrate_respa = NULL;
list_min_pre_exchange = list_min_pre_force =
list_min_post_force = list_min_energy = NULL;
end_of_step_every = NULL;
list_timeflag = NULL;
nfix_restart_global = 0;
id_restart_global = style_restart_global = state_restart_global = NULL;
nfix_restart_peratom = 0;
id_restart_peratom = style_restart_peratom = NULL;
index_restart_peratom = NULL;
allow_early_fix = 0;
ncompute = maxcompute = 0;
compute = NULL;
}
/* ---------------------------------------------------------------------- */
Modify::~Modify()
{
// delete all fixes
// do it via delete_fix() so callbacks in Atom are also updated correctly
while (nfix) delete_fix(fix[0]->id);
memory->sfree(fix);
memory->destroy(fmask);
// delete all computes
for (int i = 0; i < ncompute; i++) delete compute[i];
memory->sfree(compute);
delete [] list_initial_integrate;
delete [] list_post_integrate;
delete [] list_pre_exchange;
delete [] list_pre_neighbor;
delete [] list_pre_force;
delete [] list_post_force;
delete [] list_final_integrate;
delete [] list_end_of_step;
delete [] list_thermo_energy;
delete [] list_initial_integrate_respa;
delete [] list_post_integrate_respa;
delete [] list_pre_force_respa;
delete [] list_post_force_respa;
delete [] list_final_integrate_respa;
delete [] list_min_pre_exchange;
delete [] list_min_pre_force;
delete [] list_min_post_force;
delete [] list_min_energy;
delete [] end_of_step_every;
delete [] list_timeflag;
restart_deallocate();
}
/* ----------------------------------------------------------------------
initialize all fixes and computes
------------------------------------------------------------------------- */
void Modify::init()
{
int i,j;
// delete storage of restart info since it is not valid after 1st run
restart_deallocate();
// create lists of fixes to call at each stage of run
list_init(INITIAL_INTEGRATE,n_initial_integrate,list_initial_integrate);
list_init(POST_INTEGRATE,n_post_integrate,list_post_integrate);
list_init(PRE_EXCHANGE,n_pre_exchange,list_pre_exchange);
list_init(PRE_NEIGHBOR,n_pre_neighbor,list_pre_neighbor);
list_init(PRE_FORCE,n_pre_force,list_pre_force);
list_init(POST_FORCE,n_post_force,list_post_force);
list_init(FINAL_INTEGRATE,n_final_integrate,list_final_integrate);
list_init_end_of_step(END_OF_STEP,n_end_of_step,list_end_of_step);
list_init_thermo_energy(THERMO_ENERGY,n_thermo_energy,list_thermo_energy);
list_init(INITIAL_INTEGRATE_RESPA,
n_initial_integrate_respa,list_initial_integrate_respa);
list_init(POST_INTEGRATE_RESPA,
n_post_integrate_respa,list_post_integrate_respa);
list_init(POST_FORCE_RESPA,
n_post_force_respa,list_post_force_respa);
list_init(PRE_FORCE_RESPA,
n_pre_force_respa,list_pre_force_respa);
list_init(FINAL_INTEGRATE_RESPA,
n_final_integrate_respa,list_final_integrate_respa);
list_init(MIN_PRE_EXCHANGE,n_min_pre_exchange,list_min_pre_exchange);
list_init(MIN_PRE_FORCE,n_min_pre_force,list_min_pre_force);
list_init(MIN_POST_FORCE,n_min_post_force,list_min_post_force);
list_init(MIN_ENERGY,n_min_energy,list_min_energy);
// init each fix
// needs to come before compute init
// this is b/c some computes call fix->dof()
// FixRigid::dof() depends on its own init having been called
for (i = 0; i < nfix; i++) fix[i]->init();
// set global flag if any fix has its restart_pbc flag set
restart_pbc_any = 0;
for (i = 0; i < nfix; i++)
if (fix[i]->restart_pbc) restart_pbc_any = 1;
// create list of computes that store invocation times
list_init_compute();
// init each compute
// set invoked_scalar,vector,etc to -1 to force new run to re-compute them
// add initial timestep to all computes that store invocation times
// since any of them may be invoked by initial thermo
// do not clear out invocation times stored within a compute,
// b/c some may be holdovers from previous run, like for ave fixes
for (i = 0; i < ncompute; i++) {
compute[i]->init();
compute[i]->invoked_scalar = -1;
compute[i]->invoked_vector = -1;
compute[i]->invoked_array = -1;
compute[i]->invoked_peratom = -1;
compute[i]->invoked_local = -1;
}
addstep_compute_all(update->ntimestep);
// warn if any particle is time integrated more than once
int nlocal = atom->nlocal;
int *mask = atom->mask;
int *flag = new int[nlocal];
for (i = 0; i < nlocal; i++) flag[i] = 0;
int groupbit;
for (i = 0; i < nfix; i++) {
if (fix[i]->time_integrate == 0) continue;
groupbit = fix[i]->groupbit;
for (j = 0; j < nlocal; j++)
if (mask[j] & groupbit) flag[j]++;
}
int check = 0;
for (i = 0; i < nlocal; i++)
if (flag[i] > 1) check = 1;
delete [] flag;
int checkall;
MPI_Allreduce(&check,&checkall,1,MPI_INT,MPI_SUM,world);
if (comm->me == 0 && checkall)
- error->warning("One or more atoms are time integrated more than once");
+ error->warning(FLERR,"One or more atoms are time integrated more than once");
}
/* ----------------------------------------------------------------------
setup for run, calls setup() of all fixes
------------------------------------------------------------------------- */
void Modify::setup(int vflag)
{
if (update->whichflag == 1)
for (int i = 0; i < nfix; i++) fix[i]->setup(vflag);
else if (update->whichflag == 2)
for (int i = 0; i < nfix; i++) fix[i]->min_setup(vflag);
}
/* ----------------------------------------------------------------------
setup pre_exchange call, only for fixes that define pre_exchange
------------------------------------------------------------------------- */
void Modify::setup_pre_exchange()
{
for (int i = 0; i < n_pre_exchange; i++)
fix[list_pre_exchange[i]]->setup_pre_exchange();
}
/* ----------------------------------------------------------------------
setup pre_force call, only for fixes that define pre_force
------------------------------------------------------------------------- */
void Modify::setup_pre_force(int vflag)
{
if (update->whichflag == 1)
for (int i = 0; i < n_pre_force; i++)
fix[list_pre_force[i]]->setup_pre_force(vflag);
else if (update->whichflag == 2)
for (int i = 0; i < n_min_pre_force; i++)
fix[list_min_pre_force[i]]->min_setup_pre_force(vflag);
}
/* ----------------------------------------------------------------------
1st half of integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::initial_integrate(int vflag)
{
for (int i = 0; i < n_initial_integrate; i++)
fix[list_initial_integrate[i]]->initial_integrate(vflag);
}
/* ----------------------------------------------------------------------
post_integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::post_integrate()
{
for (int i = 0; i < n_post_integrate; i++)
fix[list_post_integrate[i]]->post_integrate();
}
/* ----------------------------------------------------------------------
pre_exchange call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::pre_exchange()
{
for (int i = 0; i < n_pre_exchange; i++)
fix[list_pre_exchange[i]]->pre_exchange();
}
/* ----------------------------------------------------------------------
pre_neighbor call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::pre_neighbor()
{
for (int i = 0; i < n_pre_neighbor; i++)
fix[list_pre_neighbor[i]]->pre_neighbor();
}
/* ----------------------------------------------------------------------
pre_force call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::pre_force(int vflag)
{
for (int i = 0; i < n_pre_force; i++)
fix[list_pre_force[i]]->pre_force(vflag);
}
/* ----------------------------------------------------------------------
post_force call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::post_force(int vflag)
{
for (int i = 0; i < n_post_force; i++)
fix[list_post_force[i]]->post_force(vflag);
}
/* ----------------------------------------------------------------------
2nd half of integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::final_integrate()
{
for (int i = 0; i < n_final_integrate; i++)
fix[list_final_integrate[i]]->final_integrate();
}
/* ----------------------------------------------------------------------
end-of-timestep call, only for relevant fixes
only call fix->end_of_step() on timesteps that are multiples of nevery
------------------------------------------------------------------------- */
void Modify::end_of_step()
{
for (int i = 0; i < n_end_of_step; i++)
if (update->ntimestep % end_of_step_every[i] == 0)
fix[list_end_of_step[i]]->end_of_step();
}
/* ----------------------------------------------------------------------
thermo energy call, only for relevant fixes
called by Thermo class
compute_scalar() is fix call to return energy
------------------------------------------------------------------------- */
double Modify::thermo_energy()
{
double energy = 0.0;
for (int i = 0; i < n_thermo_energy; i++)
energy += fix[list_thermo_energy[i]]->compute_scalar();
return energy;
}
/* ----------------------------------------------------------------------
post_run call
------------------------------------------------------------------------- */
void Modify::post_run()
{
for (int i = 0; i < nfix; i++) fix[i]->post_run();
}
/* ----------------------------------------------------------------------
setup rRESPA pre_force call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::setup_pre_force_respa(int vflag, int ilevel)
{
for (int i = 0; i < n_pre_force; i++)
fix[list_pre_force[i]]->setup_pre_force_respa(vflag,ilevel);
}
/* ----------------------------------------------------------------------
1st half of rRESPA integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::initial_integrate_respa(int vflag, int ilevel, int iloop)
{
for (int i = 0; i < n_initial_integrate_respa; i++)
fix[list_initial_integrate_respa[i]]->
initial_integrate_respa(vflag,ilevel,iloop);
}
/* ----------------------------------------------------------------------
rRESPA post_integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::post_integrate_respa(int ilevel, int iloop)
{
for (int i = 0; i < n_post_integrate_respa; i++)
fix[list_post_integrate_respa[i]]->post_integrate_respa(ilevel,iloop);
}
/* ----------------------------------------------------------------------
rRESPA pre_force call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::pre_force_respa(int vflag, int ilevel, int iloop)
{
for (int i = 0; i < n_pre_force_respa; i++)
fix[list_pre_force_respa[i]]->pre_force_respa(vflag,ilevel,iloop);
}
/* ----------------------------------------------------------------------
rRESPA post_force call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::post_force_respa(int vflag, int ilevel, int iloop)
{
for (int i = 0; i < n_post_force_respa; i++)
fix[list_post_force_respa[i]]->post_force_respa(vflag,ilevel,iloop);
}
/* ----------------------------------------------------------------------
2nd half of rRESPA integrate call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::final_integrate_respa(int ilevel, int iloop)
{
for (int i = 0; i < n_final_integrate_respa; i++)
fix[list_final_integrate_respa[i]]->final_integrate_respa(ilevel,iloop);
}
/* ----------------------------------------------------------------------
minimizer pre-exchange call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::min_pre_exchange()
{
for (int i = 0; i < n_min_pre_exchange; i++)
fix[list_min_pre_exchange[i]]->min_pre_exchange();
}
/* ----------------------------------------------------------------------
minimizer pre-force call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::min_pre_force(int vflag)
{
for (int i = 0; i < n_min_pre_force; i++)
fix[list_min_pre_force[i]]->min_pre_force(vflag);
}
/* ----------------------------------------------------------------------
minimizer force adjustment call, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::min_post_force(int vflag)
{
for (int i = 0; i < n_min_post_force; i++)
fix[list_min_post_force[i]]->min_post_force(vflag);
}
/* ----------------------------------------------------------------------
minimizer energy/force evaluation, only for relevant fixes
return energy and forces on extra degrees of freedom
------------------------------------------------------------------------- */
double Modify::min_energy(double *fextra)
{
int ifix,index;
index = 0;
double eng = 0.0;
for (int i = 0; i < n_min_energy; i++) {
ifix = list_min_energy[i];
eng += fix[ifix]->min_energy(&fextra[index]);
index += fix[ifix]->min_dof();
}
return eng;
}
/* ----------------------------------------------------------------------
store current state of extra dof, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::min_store()
{
for (int i = 0; i < n_min_energy; i++)
fix[list_min_energy[i]]->min_store();
}
/* ----------------------------------------------------------------------
mange state of extra dof on a stack, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::min_clearstore()
{
for (int i = 0; i < n_min_energy; i++)
fix[list_min_energy[i]]->min_clearstore();
}
void Modify::min_pushstore()
{
for (int i = 0; i < n_min_energy; i++)
fix[list_min_energy[i]]->min_pushstore();
}
void Modify::min_popstore()
{
for (int i = 0; i < n_min_energy; i++)
fix[list_min_energy[i]]->min_popstore();
}
/* ----------------------------------------------------------------------
displace extra dof along vector hextra, only for relevant fixes
------------------------------------------------------------------------- */
void Modify::min_step(double alpha, double *hextra)
{
int ifix,index;
index = 0;
for (int i = 0; i < n_min_energy; i++) {
ifix = list_min_energy[i];
fix[ifix]->min_step(alpha,&hextra[index]);
index += fix[ifix]->min_dof();
}
}
/* ----------------------------------------------------------------------
compute max allowed step size along vector hextra, only for relevant fixes
------------------------------------------------------------------------- */
double Modify::max_alpha(double *hextra)
{
int ifix,index;
double alpha = BIG;
index = 0;
for (int i = 0; i < n_min_energy; i++) {
ifix = list_min_energy[i];
double alpha_one = fix[ifix]->max_alpha(&hextra[index]);
alpha = MIN(alpha,alpha_one);
index += fix[ifix]->min_dof();
}
return alpha;
}
/* ----------------------------------------------------------------------
extract extra dof for minimization, only for relevant fixes
------------------------------------------------------------------------- */
int Modify::min_dof()
{
int ndof = 0;
for (int i = 0; i < n_min_energy; i++)
ndof += fix[list_min_energy[i]]->min_dof();
return ndof;
}
/* ----------------------------------------------------------------------
reset reference state of fix, only for relevant fixes
------------------------------------------------------------------------- */
int Modify::min_reset_ref()
{
int itmp,itmpall;
itmpall = 0;
for (int i = 0; i < n_min_energy; i++) {
itmp = fix[list_min_energy[i]]->min_reset_ref();
if (itmp) itmpall = 1;
}
return itmpall;
}
/* ----------------------------------------------------------------------
add a new fix or replace one with same ID
------------------------------------------------------------------------- */
void Modify::add_fix(int narg, char **arg, char *suffix)
{
if (domain->box_exist == 0 && allow_early_fix == 0)
- error->all("Fix command before simulation box is defined");
- if (narg < 3) error->all("Illegal fix command");
+ error->all(FLERR,"Fix command before simulation box is defined");
+ if (narg < 3) error->all(FLERR,"Illegal fix command");
// check group ID
int igroup = group->find(arg[1]);
- if (igroup == -1) error->all("Could not find fix group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find fix group ID");
// if fix ID exists:
// set newflag = 0 so create new fix in same location in fix list
// error if new style does not match old style
// since can't replace it (all when-to-invoke ptrs would be invalid)
// warn if new group != old group
// delete old fix, but do not call update_callback(),
// since will replace this fix and thus other fix locs will not change
// set ptr to NULL in case new fix scans list of fixes,
// e.g. scan will occur in add_callback() if called by new fix
// if fix ID does not exist:
// set newflag = 1 so create new fix
// extend fix and fmask lists as necessary
int ifix,newflag;
for (ifix = 0; ifix < nfix; ifix++)
if (strcmp(arg[0],fix[ifix]->id) == 0) break;
if (ifix < nfix) {
newflag = 0;
if (strcmp(arg[2],fix[ifix]->style) != 0)
- error->all("Replacing a fix, but new style != old style");
+ error->all(FLERR,"Replacing a fix, but new style != old style");
if (fix[ifix]->igroup != igroup && comm->me == 0)
- error->warning("Replacing a fix, but new group != old group");
+ error->warning(FLERR,"Replacing a fix, but new group != old group");
delete fix[ifix];
fix[ifix] = NULL;
} else {
newflag = 1;
if (nfix == maxfix) {
maxfix += DELTA;
fix = (Fix **) memory->srealloc(fix,maxfix*sizeof(Fix *),"modify:fix");
memory->grow(fmask,maxfix,"modify:fmask");
}
}
// create the Fix, first with suffix appended
int success = 0;
if (suffix && lmp->suffix_enable) {
char estyle[256];
sprintf(estyle,"%s/%s",arg[2],suffix);
success = 1;
if (0) return;
#define FIX_CLASS
#define FixStyle(key,Class) \
else if (strcmp(estyle,#key) == 0) fix[ifix] = new Class(lmp,narg,arg);
#include "style_fix.h"
#undef FixStyle
#undef FIX_CLASS
else success = 0;
}
if (!success) {
if (0) return;
#define FIX_CLASS
#define FixStyle(key,Class) \
else if (strcmp(arg[2],#key) == 0) fix[ifix] = new Class(lmp,narg,arg);
#include "style_fix.h"
#undef FixStyle
#undef FIX_CLASS
- else error->all("Invalid fix style");
+ else error->all(FLERR,"Invalid fix style");
}
// set fix mask values and increment nfix (if new)
fmask[ifix] = fix[ifix]->setmask();
if (newflag) nfix++;
// check if Fix is in restart_global list
// if yes, pass state info to the Fix so it can reset itself
for (int i = 0; i < nfix_restart_global; i++)
if (strcmp(id_restart_global[i],fix[ifix]->id) == 0 &&
strcmp(style_restart_global[i],fix[ifix]->style) == 0) {
fix[ifix]->restart(state_restart_global[i]);
if (comm->me == 0) {
char *str = (char *) ("Resetting global state of Fix %s Style %s "
"from restart file info\n");
if (screen) fprintf(screen,str,fix[ifix]->id,fix[ifix]->style);
if (logfile) fprintf(logfile,str,fix[ifix]->id,fix[ifix]->style);
}
}
// check if Fix is in restart_peratom list
// if yes, loop over atoms so they can extract info from atom->extra array
for (int i = 0; i < nfix_restart_peratom; i++)
if (strcmp(id_restart_peratom[i],fix[ifix]->id) == 0 &&
strcmp(style_restart_peratom[i],fix[ifix]->style) == 0) {
for (int j = 0; j < atom->nlocal; j++)
fix[ifix]->unpack_restart(j,index_restart_peratom[i]);
if (comm->me == 0) {
char *str = (char *) ("Resetting per-atom state of Fix %s Style %s "
"from restart file info\n");
if (screen) fprintf(screen,str,fix[ifix]->id,fix[ifix]->style);
if (logfile) fprintf(logfile,str,fix[ifix]->id,fix[ifix]->style);
}
}
}
/* ----------------------------------------------------------------------
modify a Fix's parameters
------------------------------------------------------------------------- */
void Modify::modify_fix(int narg, char **arg)
{
- if (narg < 2) error->all("Illegal fix_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal fix_modify command");
// lookup Fix ID
int ifix;
for (ifix = 0; ifix < nfix; ifix++)
if (strcmp(arg[0],fix[ifix]->id) == 0) break;
- if (ifix == nfix) error->all("Could not find fix_modify ID");
+ if (ifix == nfix) error->all(FLERR,"Could not find fix_modify ID");
fix[ifix]->modify_params(narg-1,&arg[1]);
}
/* ----------------------------------------------------------------------
delete a Fix from list of Fixes
Atom class must update indices in its list of callbacks to fixes
------------------------------------------------------------------------- */
void Modify::delete_fix(const char *id)
{
int ifix = find_fix(id);
- if (ifix < 0) error->all("Could not find fix ID to delete");
+ if (ifix < 0) error->all(FLERR,"Could not find fix ID to delete");
delete fix[ifix];
atom->update_callback(ifix);
// move other Fixes and fmask down in list one slot
for (int i = ifix+1; i < nfix; i++) fix[i-1] = fix[i];
for (int i = ifix+1; i < nfix; i++) fmask[i-1] = fmask[i];
nfix--;
}
/* ----------------------------------------------------------------------
find a fix by ID
return index of fix or -1 if not found
------------------------------------------------------------------------- */
int Modify::find_fix(const char *id)
{
int ifix;
for (ifix = 0; ifix < nfix; ifix++)
if (strcmp(id,fix[ifix]->id) == 0) break;
if (ifix == nfix) return -1;
return ifix;
}
/* ----------------------------------------------------------------------
add a new compute
------------------------------------------------------------------------- */
void Modify::add_compute(int narg, char **arg, char *suffix)
{
- if (narg < 3) error->all("Illegal compute command");
+ if (narg < 3) error->all(FLERR,"Illegal compute command");
// error check
for (int icompute = 0; icompute < ncompute; icompute++)
if (strcmp(arg[0],compute[icompute]->id) == 0)
- error->all("Reuse of compute ID");
+ error->all(FLERR,"Reuse of compute ID");
// extend Compute list if necessary
if (ncompute == maxcompute) {
maxcompute += DELTA;
compute = (Compute **)
memory->srealloc(compute,maxcompute*sizeof(Compute *),"modify:compute");
}
// create the Compute, first with suffix appended
int success = 0;
if (suffix && lmp->suffix_enable) {
char estyle[256];
sprintf(estyle,"%s/%s",arg[2],suffix);
success = 1;
if (0) return;
#define COMPUTE_CLASS
#define ComputeStyle(key,Class) \
else if (strcmp(estyle,#key) == 0) \
compute[ncompute] = new Class(lmp,narg,arg);
#include "style_compute.h"
#undef ComputeStyle
#undef COMPUTE_CLASS
else success = 0;
}
if (!success) {
if (0) return;
#define COMPUTE_CLASS
#define ComputeStyle(key,Class) \
else if (strcmp(arg[2],#key) == 0) \
compute[ncompute] = new Class(lmp,narg,arg);
#include "style_compute.h"
#undef ComputeStyle
#undef COMPUTE_CLASS
- else error->all("Invalid compute style");
+ else error->all(FLERR,"Invalid compute style");
}
ncompute++;
}
/* ----------------------------------------------------------------------
modify a Compute's parameters
------------------------------------------------------------------------- */
void Modify::modify_compute(int narg, char **arg)
{
- if (narg < 2) error->all("Illegal compute_modify command");
+ if (narg < 2) error->all(FLERR,"Illegal compute_modify command");
// lookup Compute ID
int icompute;
for (icompute = 0; icompute < ncompute; icompute++)
if (strcmp(arg[0],compute[icompute]->id) == 0) break;
- if (icompute == ncompute) error->all("Could not find compute_modify ID");
+ if (icompute == ncompute) error->all(FLERR,"Could not find compute_modify ID");
compute[icompute]->modify_params(narg-1,&arg[1]);
}
/* ----------------------------------------------------------------------
delete a Compute from list of Computes
------------------------------------------------------------------------- */
void Modify::delete_compute(char *id)
{
int icompute = find_compute(id);
- if (icompute < 0) error->all("Could not find compute ID to delete");
+ if (icompute < 0) error->all(FLERR,"Could not find compute ID to delete");
delete compute[icompute];
// move other Computes down in list one slot
for (int i = icompute+1; i < ncompute; i++) compute[i-1] = compute[i];
ncompute--;
}
/* ----------------------------------------------------------------------
find a compute by ID
return index of compute or -1 if not found
------------------------------------------------------------------------- */
int Modify::find_compute(char *id)
{
int icompute;
for (icompute = 0; icompute < ncompute; icompute++)
if (strcmp(id,compute[icompute]->id) == 0) break;
if (icompute == ncompute) return -1;
return icompute;
}
/* ----------------------------------------------------------------------
clear invoked flag of all computes
called everywhere that computes are used, before computes are invoked
invoked flag used to avoid re-invoking same compute multiple times
and to flag computes that store invocation times as having been invoked
------------------------------------------------------------------------- */
void Modify::clearstep_compute()
{
for (int icompute = 0; icompute < ncompute; icompute++)
compute[icompute]->invoked_flag = 0;
}
/* ----------------------------------------------------------------------
loop over computes that store invocation times
if its invoked flag set on this timestep, schedule next invocation
called everywhere that computes are used, after computes are invoked
------------------------------------------------------------------------- */
void Modify::addstep_compute(bigint newstep)
{
for (int icompute = 0; icompute < n_timeflag; icompute++)
if (compute[list_timeflag[icompute]]->invoked_flag)
compute[list_timeflag[icompute]]->addstep(newstep);
}
/* ----------------------------------------------------------------------
loop over all computes
schedule next invocation for those that store invocation times
called when not sure what computes will be needed on newstep
do not loop only over n_timeflag, since may not be set yet
------------------------------------------------------------------------- */
void Modify::addstep_compute_all(bigint newstep)
{
for (int icompute = 0; icompute < ncompute; icompute++)
if (compute[icompute]->timeflag) compute[icompute]->addstep(newstep);
}
/* ----------------------------------------------------------------------
write to restart file for all Fixes with restart info
(1) fixes that have global state
(2) fixes that store per-atom quantities
------------------------------------------------------------------------- */
void Modify::write_restart(FILE *fp)
{
int me = comm->me;
int count = 0;
for (int i = 0; i < nfix; i++)
if (fix[i]->restart_global) count++;
if (me == 0) fwrite(&count,sizeof(int),1,fp);
int n;
for (int i = 0; i < nfix; i++)
if (fix[i]->restart_global) {
if (me == 0) {
n = strlen(fix[i]->id) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(fix[i]->id,sizeof(char),n,fp);
n = strlen(fix[i]->style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(fix[i]->style,sizeof(char),n,fp);
}
fix[i]->write_restart(fp);
}
count = 0;
for (int i = 0; i < nfix; i++)
if (fix[i]->restart_peratom) count++;
if (me == 0) fwrite(&count,sizeof(int),1,fp);
for (int i = 0; i < nfix; i++)
if (fix[i]->restart_peratom) {
if (me == 0) {
n = strlen(fix[i]->id) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(fix[i]->id,sizeof(char),n,fp);
n = strlen(fix[i]->style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(fix[i]->style,sizeof(char),n,fp);
n = fix[i]->maxsize_restart();
fwrite(&n,sizeof(int),1,fp);
}
}
}
/* ----------------------------------------------------------------------
read in restart file data on all previously defined Fixes with restart info
(1) fixes that have global state
(2) fixes that store per-atom quantities
return maxsize of extra info that will be stored with any atom
------------------------------------------------------------------------- */
int Modify::read_restart(FILE *fp)
{
// nfix_restart_global = # of restart entries with global state info
int me = comm->me;
if (me == 0) fread(&nfix_restart_global,sizeof(int),1,fp);
MPI_Bcast(&nfix_restart_global,1,MPI_INT,0,world);
// allocate space for each entry
if (nfix_restart_global) {
id_restart_global = new char*[nfix_restart_global];
style_restart_global = new char*[nfix_restart_global];
state_restart_global = new char*[nfix_restart_global];
}
// read each entry and Bcast to all procs
// each entry has id string, style string, chunk of state data
int n;
for (int i = 0; i < nfix_restart_global; i++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
id_restart_global[i] = new char[n];
if (me == 0) fread(id_restart_global[i],sizeof(char),n,fp);
MPI_Bcast(id_restart_global[i],n,MPI_CHAR,0,world);
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
style_restart_global[i] = new char[n];
if (me == 0) fread(style_restart_global[i],sizeof(char),n,fp);
MPI_Bcast(style_restart_global[i],n,MPI_CHAR,0,world);
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
state_restart_global[i] = new char[n];
if (me == 0) fread(state_restart_global[i],sizeof(char),n,fp);
MPI_Bcast(state_restart_global[i],n,MPI_CHAR,0,world);
}
// nfix_restart_peratom = # of restart entries with peratom info
int maxsize = 0;
if (me == 0) fread(&nfix_restart_peratom,sizeof(int),1,fp);
MPI_Bcast(&nfix_restart_peratom,1,MPI_INT,0,world);
// allocate space for each entry
if (nfix_restart_peratom) {
id_restart_peratom = new char*[nfix_restart_peratom];
style_restart_peratom = new char*[nfix_restart_peratom];
index_restart_peratom = new int[nfix_restart_peratom];
}
// read each entry and Bcast to all procs
// each entry has id string, style string, maxsize of one atom's data
// set index = which set of extra data this fix represents
for (int i = 0; i < nfix_restart_peratom; i++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
id_restart_peratom[i] = new char[n];
if (me == 0) fread(id_restart_peratom[i],sizeof(char),n,fp);
MPI_Bcast(id_restart_peratom[i],n,MPI_CHAR,0,world);
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
style_restart_peratom[i] = new char[n];
if (me == 0) fread(style_restart_peratom[i],sizeof(char),n,fp);
MPI_Bcast(style_restart_peratom[i],n,MPI_CHAR,0,world);
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
maxsize += n;
index_restart_peratom[i] = i;
}
return maxsize;
}
/* ----------------------------------------------------------------------
delete all lists of restart file Fix info
------------------------------------------------------------------------- */
void Modify::restart_deallocate()
{
if (nfix_restart_global) {
for (int i = 0; i < nfix_restart_global; i++) {
delete [] id_restart_global[i];
delete [] style_restart_global[i];
delete [] state_restart_global[i];
}
delete [] id_restart_global;
delete [] style_restart_global;
delete [] state_restart_global;
}
if (nfix_restart_peratom) {
for (int i = 0; i < nfix_restart_peratom; i++) {
delete [] id_restart_peratom[i];
delete [] style_restart_peratom[i];
}
delete [] id_restart_peratom;
delete [] style_restart_peratom;
delete [] index_restart_peratom;
}
nfix_restart_global = nfix_restart_peratom = 0;
}
/* ----------------------------------------------------------------------
create list of fix indices for fixes which match mask
------------------------------------------------------------------------- */
void Modify::list_init(int mask, int &n, int *&list)
{
delete [] list;
n = 0;
for (int i = 0; i < nfix; i++) if (fmask[i] & mask) n++;
list = new int[n];
n = 0;
for (int i = 0; i < nfix; i++) if (fmask[i] & mask) list[n++] = i;
}
/* ----------------------------------------------------------------------
create list of fix indices for end_of_step fixes
also create end_of_step_every[]
------------------------------------------------------------------------- */
void Modify::list_init_end_of_step(int mask, int &n, int *&list)
{
delete [] list;
delete [] end_of_step_every;
n = 0;
for (int i = 0; i < nfix; i++) if (fmask[i] & mask) n++;
list = new int[n];
end_of_step_every = new int[n];
n = 0;
for (int i = 0; i < nfix; i++)
if (fmask[i] & mask) {
list[n] = i;
end_of_step_every[n++] = fix[i]->nevery;
}
}
/* ----------------------------------------------------------------------
create list of fix indices for thermo energy fixes
only added to list if fix has THERMO_ENERGY mask
and its thermo_energy flag was set via fix_modify
------------------------------------------------------------------------- */
void Modify::list_init_thermo_energy(int mask, int &n, int *&list)
{
delete [] list;
n = 0;
for (int i = 0; i < nfix; i++)
if (fmask[i] & mask && fix[i]->thermo_energy) n++;
list = new int[n];
n = 0;
for (int i = 0; i < nfix; i++)
if (fmask[i] & mask && fix[i]->thermo_energy) list[n++] = i;
}
/* ----------------------------------------------------------------------
create list of compute indices for computes which store invocation times
------------------------------------------------------------------------- */
void Modify::list_init_compute()
{
delete [] list_timeflag;
n_timeflag = 0;
for (int i = 0; i < ncompute; i++)
if (compute[i]->timeflag) n_timeflag++;
list_timeflag = new int[n_timeflag];
n_timeflag = 0;
for (int i = 0; i < ncompute; i++)
if (compute[i]->timeflag) list_timeflag[n_timeflag++] = i;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory from all fixes
------------------------------------------------------------------------- */
bigint Modify::memory_usage()
{
bigint bytes = 0;
for (int i = 0; i < nfix; i++)
bytes += static_cast<bigint> (fix[i]->memory_usage());
for (int i = 0; i < ncompute; i++)
bytes += static_cast<bigint> (compute[i]->memory_usage());
return bytes;
}
diff --git a/src/neigh_bond.cpp b/src/neigh_bond.cpp
index b16598011..f9ff7f07e 100644
--- a/src/neigh_bond.cpp
+++ b/src/neigh_bond.cpp
@@ -1,388 +1,388 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "neighbor.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BONDDELTA 10000
/* ---------------------------------------------------------------------- */
void Neighbor::bond_all()
{
int i,m,atom1;
int nlocal = atom->nlocal;
int *num_bond = atom->num_bond;
int **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int *tag = atom->tag;
int newton_bond = force->newton_bond;
nbondlist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_bond[i]; m++) {
atom1 = atom->map(bond_atom[i][m]);
if (atom1 == -1) {
char str[128];
sprintf(str,
"Bond atoms %d %d missing on proc %d at step " BIGINT_FORMAT,
tag[i],bond_atom[i][m],me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond || i < atom1) {
if (nbondlist == maxbond) {
maxbond += BONDDELTA;
memory->grow(bondlist,maxbond,3,"neighbor:bondlist");
}
bondlist[nbondlist][0] = i;
bondlist[nbondlist][1] = atom1;
bondlist[nbondlist][2] = bond_type[i][m];
nbondlist++;
}
}
}
/* ---------------------------------------------------------------------- */
void Neighbor::bond_partial()
{
int i,m,atom1;
int nlocal = atom->nlocal;
int *num_bond = atom->num_bond;
int **bond_atom = atom->bond_atom;
int **bond_type = atom->bond_type;
int *tag = atom->tag;
int newton_bond = force->newton_bond;
nbondlist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_bond[i]; m++) {
if (bond_type[i][m] <= 0) continue;
atom1 = atom->map(bond_atom[i][m]);
if (atom1 == -1) {
char str[128];
sprintf(str,
"Bond atoms %d %d missing on proc %d at step " BIGINT_FORMAT,
tag[i],bond_atom[i][m],me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond || i < atom1) {
if (nbondlist == maxbond) {
maxbond += BONDDELTA;
memory->grow(bondlist,maxbond,3,"neighbor:bondlist");
}
bondlist[nbondlist][0] = i;
bondlist[nbondlist][1] = atom1;
bondlist[nbondlist][2] = bond_type[i][m];
nbondlist++;
}
}
}
/* ---------------------------------------------------------------------- */
void Neighbor::angle_all()
{
int i,m,atom1,atom2,atom3;
int nlocal = atom->nlocal;
int *num_angle = atom->num_angle;
int **angle_atom1 = atom->angle_atom1;
int **angle_atom2 = atom->angle_atom2;
int **angle_atom3 = atom->angle_atom3;
int **angle_type = atom->angle_type;
int newton_bond = force->newton_bond;
nanglelist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_angle[i]; m++) {
atom1 = atom->map(angle_atom1[i][m]);
atom2 = atom->map(angle_atom2[i][m]);
atom3 = atom->map(angle_atom3[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1) {
char str[128];
sprintf(str,
"Angle atoms %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
angle_atom1[i][m],angle_atom2[i][m],angle_atom3[i][m],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond || (i <= atom1 && i <= atom2 && i <= atom3)) {
if (nanglelist == maxangle) {
maxangle += BONDDELTA;
memory->grow(anglelist,maxangle,4,"neighbor:anglelist");
}
anglelist[nanglelist][0] = atom1;
anglelist[nanglelist][1] = atom2;
anglelist[nanglelist][2] = atom3;
anglelist[nanglelist][3] = angle_type[i][m];
nanglelist++;
}
}
}
/* ---------------------------------------------------------------------- */
void Neighbor::angle_partial()
{
int i,m,atom1,atom2,atom3;
int nlocal = atom->nlocal;
int *num_angle = atom->num_angle;
int **angle_atom1 = atom->angle_atom1;
int **angle_atom2 = atom->angle_atom2;
int **angle_atom3 = atom->angle_atom3;
int **angle_type = atom->angle_type;
int newton_bond = force->newton_bond;
nanglelist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_angle[i]; m++) {
if (angle_type[i][m] <= 0) continue;
atom1 = atom->map(angle_atom1[i][m]);
atom2 = atom->map(angle_atom2[i][m]);
atom3 = atom->map(angle_atom3[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1) {
char str[128];
sprintf(str,
"Angle atoms %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
angle_atom1[i][m],angle_atom2[i][m],angle_atom3[i][m],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond || (i <= atom1 && i <= atom2 && i <= atom3)) {
if (nanglelist == maxangle) {
maxangle += BONDDELTA;
memory->grow(anglelist,maxangle,4,"neighbor:anglelist");
}
anglelist[nanglelist][0] = atom1;
anglelist[nanglelist][1] = atom2;
anglelist[nanglelist][2] = atom3;
anglelist[nanglelist][3] = angle_type[i][m];
nanglelist++;
}
}
}
/* ---------------------------------------------------------------------- */
void Neighbor::dihedral_all()
{
int i,m,atom1,atom2,atom3,atom4;
int nlocal = atom->nlocal;
int *num_dihedral = atom->num_dihedral;
int **dihedral_atom1 = atom->dihedral_atom1;
int **dihedral_atom2 = atom->dihedral_atom2;
int **dihedral_atom3 = atom->dihedral_atom3;
int **dihedral_atom4 = atom->dihedral_atom4;
int **dihedral_type = atom->dihedral_type;
int newton_bond = force->newton_bond;
ndihedrallist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_dihedral[i]; m++) {
atom1 = atom->map(dihedral_atom1[i][m]);
atom2 = atom->map(dihedral_atom2[i][m]);
atom3 = atom->map(dihedral_atom3[i][m]);
atom4 = atom->map(dihedral_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) {
char str[128];
sprintf(str,
"Dihedral atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
dihedral_atom1[i][m],dihedral_atom2[i][m],
dihedral_atom3[i][m],dihedral_atom4[i][m],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond ||
(i <= atom1 && i <= atom2 && i <= atom3 && i <= atom4)) {
if (ndihedrallist == maxdihedral) {
maxdihedral += BONDDELTA;
memory->grow(dihedrallist,maxdihedral,5,"neighbor:dihedrallist");
}
dihedrallist[ndihedrallist][0] = atom1;
dihedrallist[ndihedrallist][1] = atom2;
dihedrallist[ndihedrallist][2] = atom3;
dihedrallist[ndihedrallist][3] = atom4;
dihedrallist[ndihedrallist][4] = dihedral_type[i][m];
ndihedrallist++;
}
}
}
/* ---------------------------------------------------------------------- */
void Neighbor::dihedral_partial()
{
int i,m,atom1,atom2,atom3,atom4;
int nlocal = atom->nlocal;
int *num_dihedral = atom->num_dihedral;
int **dihedral_atom1 = atom->dihedral_atom1;
int **dihedral_atom2 = atom->dihedral_atom2;
int **dihedral_atom3 = atom->dihedral_atom3;
int **dihedral_atom4 = atom->dihedral_atom4;
int **dihedral_type = atom->dihedral_type;
int newton_bond = force->newton_bond;
ndihedrallist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_dihedral[i]; m++) {
if (dihedral_type[i][m] <= 0) continue;
atom1 = atom->map(dihedral_atom1[i][m]);
atom2 = atom->map(dihedral_atom2[i][m]);
atom3 = atom->map(dihedral_atom3[i][m]);
atom4 = atom->map(dihedral_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) {
char str[128];
sprintf(str,
"Dihedral atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
dihedral_atom1[i][m],dihedral_atom2[i][m],
dihedral_atom3[i][m],dihedral_atom4[i][m],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond ||
(i <= atom1 && i <= atom2 && i <= atom3 && i <= atom4)) {
if (ndihedrallist == maxdihedral) {
maxdihedral += BONDDELTA;
memory->grow(dihedrallist,maxdihedral,5,"neighbor:dihedrallist");
}
dihedrallist[ndihedrallist][0] = atom1;
dihedrallist[ndihedrallist][1] = atom2;
dihedrallist[ndihedrallist][2] = atom3;
dihedrallist[ndihedrallist][3] = atom4;
dihedrallist[ndihedrallist][4] = dihedral_type[i][m];
ndihedrallist++;
}
}
}
/* ---------------------------------------------------------------------- */
void Neighbor::improper_all()
{
int i,m,atom1,atom2,atom3,atom4;
int nlocal = atom->nlocal;
int *num_improper = atom->num_improper;
int **improper_atom1 = atom->improper_atom1;
int **improper_atom2 = atom->improper_atom2;
int **improper_atom3 = atom->improper_atom3;
int **improper_atom4 = atom->improper_atom4;
int **improper_type = atom->improper_type;
int newton_bond = force->newton_bond;
nimproperlist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_improper[i]; m++) {
atom1 = atom->map(improper_atom1[i][m]);
atom2 = atom->map(improper_atom2[i][m]);
atom3 = atom->map(improper_atom3[i][m]);
atom4 = atom->map(improper_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) {
char str[128];
sprintf(str,
"Improper atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
improper_atom1[i][m],improper_atom2[i][m],
improper_atom3[i][m],improper_atom4[i][m],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond ||
(i <= atom1 && i <= atom2 && i <= atom3 && i <= atom4)) {
if (nimproperlist == maximproper) {
maximproper += BONDDELTA;
memory->grow(improperlist,maximproper,5,"neighbor:improperlist");
}
improperlist[nimproperlist][0] = atom1;
improperlist[nimproperlist][1] = atom2;
improperlist[nimproperlist][2] = atom3;
improperlist[nimproperlist][3] = atom4;
improperlist[nimproperlist][4] = improper_type[i][m];
nimproperlist++;
}
}
}
/* ---------------------------------------------------------------------- */
void Neighbor::improper_partial()
{
int i,m,atom1,atom2,atom3,atom4;
int nlocal = atom->nlocal;
int *num_improper = atom->num_improper;
int **improper_atom1 = atom->improper_atom1;
int **improper_atom2 = atom->improper_atom2;
int **improper_atom3 = atom->improper_atom3;
int **improper_atom4 = atom->improper_atom4;
int **improper_type = atom->improper_type;
int newton_bond = force->newton_bond;
nimproperlist = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_improper[i]; m++) {
if (improper_type[i][m] <= 0) continue;
atom1 = atom->map(improper_atom1[i][m]);
atom2 = atom->map(improper_atom2[i][m]);
atom3 = atom->map(improper_atom3[i][m]);
atom4 = atom->map(improper_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1) {
char str[128];
sprintf(str,
"Improper atoms %d %d %d %d missing on proc %d at step "
BIGINT_FORMAT,
improper_atom1[i][m],improper_atom2[i][m],
improper_atom3[i][m],improper_atom4[i][m],
me,update->ntimestep);
- error->one(str);
+ error->one(FLERR,str);
}
if (newton_bond ||
(i <= atom1 && i <= atom2 && i <= atom3 && i <= atom4)) {
if (nimproperlist == maximproper) {
maximproper += BONDDELTA;
memory->grow(improperlist,maximproper,5,"neighbor:improperlist");
}
improperlist[nimproperlist][0] = atom1;
improperlist[nimproperlist][1] = atom2;
improperlist[nimproperlist][2] = atom3;
improperlist[nimproperlist][3] = atom4;
improperlist[nimproperlist][4] = improper_type[i][m];
nimproperlist++;
}
}
}
diff --git a/src/neigh_derive.cpp b/src/neigh_derive.cpp
index c3d3eb024..21e7c0c6c 100644
--- a/src/neigh_derive.cpp
+++ b/src/neigh_derive.cpp
@@ -1,504 +1,504 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "neighbor.h"
#include "neigh_list.h"
#include "atom.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
build half list from full list
pair stored once if i,j are both owned and i < j
pair stored by me if j is ghost (also stored by proc owning j)
works if full list is a skip list
------------------------------------------------------------------------- */
void Neighbor::half_from_full_no_newton(NeighList *list)
{
int i,j,ii,jj,n,jnum,joriginal;
int *neighptr,*jlist;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *ilist_full = list->listfull->ilist;
int *numneigh_full = list->listfull->numneigh;
int **firstneigh_full = list->listfull->firstneigh;
int inum_full = list->listfull->inum;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over atoms in full list
for (ii = 0; ii < inum_full; ii++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
// loop over parent full list
i = ilist_full[ii];
jlist = firstneigh_full[i];
jnum = numneigh_full[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (j > i) neighptr[n++] = joriginal;
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
build half list from full list
pair stored once if i,j are both owned and i < j
if j is ghost, only store if j coords are "above and to the right" of i
works if full list is a skip list
------------------------------------------------------------------------- */
void Neighbor::half_from_full_newton(NeighList *list)
{
int i,j,ii,jj,n,jnum,joriginal;
int *neighptr,*jlist;
double xtmp,ytmp,ztmp;
double **x = atom->x;
int nlocal = atom->nlocal;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *ilist_full = list->listfull->ilist;
int *numneigh_full = list->listfull->numneigh;
int **firstneigh_full = list->listfull->firstneigh;
int inum_full = list->listfull->inum;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over parent full list
for (ii = 0; ii < inum_full; ii++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
i = ilist_full[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over full neighbor list
jlist = firstneigh_full[i];
jnum = numneigh_full[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (j < nlocal) {
if (i > j) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
neighptr[n++] = joriginal;
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
build skip list for subset of types from parent list
iskip and ijskip flag which atom types and type pairs to skip
this is for half and full lists
if ghostflag, also store neighbors of ghost atoms & set inum,gnum correctly
------------------------------------------------------------------------- */
void Neighbor::skip_from(NeighList *list)
{
int i,j,ii,jj,n,itype,jnum,joriginal;
int *neighptr,*jlist;
int *type = atom->type;
int nlocal = atom->nlocal;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *ilist_skip = list->listskip->ilist;
int *numneigh_skip = list->listskip->numneigh;
int **firstneigh_skip = list->listskip->firstneigh;
int num_skip = list->listskip->inum;
if (list->ghostflag) num_skip += list->listskip->gnum;
int *iskip = list->iskip;
int **ijskip = list->ijskip;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over atoms in other list
// skip I atom entirely if iskip is set for type[I]
// skip I,J pair if ijskip is set for type[I],type[J]
for (ii = 0; ii < num_skip; ii++) {
i = ilist_skip[ii];
itype = type[i];
if (iskip[itype]) continue;
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
// loop over parent non-skip list
jlist = firstneigh_skip[i];
jnum = numneigh_skip[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (ijskip[itype][type[j]]) continue;
neighptr[n++] = joriginal;
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
if (list->ghostflag) {
int num = 0;
for (i = 0; i < inum; i++)
if (ilist[i] < nlocal) num++;
else break;
list->inum = num;
list->gnum = inum - num;
}
}
/* ----------------------------------------------------------------------
build skip list for subset of types from parent list
iskip and ijskip flag which atom types and type pairs to skip
this is for granular lists with history, copy the history values from parent
------------------------------------------------------------------------- */
void Neighbor::skip_from_granular(NeighList *list)
{
int i,j,ii,jj,n,nn,itype,jnum,joriginal;
int *neighptr,*jlist,*touchptr,*touchptr_skip;
double *shearptr,*shearptr_skip;
int *type = atom->type;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *ilist_skip = list->listskip->ilist;
int *numneigh_skip = list->listskip->numneigh;
int **firstneigh_skip = list->listskip->firstneigh;
int **firsttouch_skip = list->listskip->listgranhistory->firstneigh;
double **firstshear_skip = list->listskip->listgranhistory->firstdouble;
int inum_skip = list->listskip->inum;
int *iskip = list->iskip;
int **ijskip = list->ijskip;
NeighList *listgranhistory = list->listgranhistory;
int **firsttouch = listgranhistory->firstneigh;
double **firstshear = listgranhistory->firstdouble;
int **pages_touch = listgranhistory->pages;
double **pages_shear = listgranhistory->dpages;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over atoms in other list
// skip I atom entirely if iskip is set for type[I]
// skip I,J pair if ijskip is set for type[I],type[J]
for (ii = 0; ii < inum_skip; ii++) {
i = ilist_skip[ii];
itype = type[i];
if (iskip[itype]) continue;
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) {
pages = list->add_pages();
pages_touch = listgranhistory->add_pages();
pages_shear = listgranhistory->dpages;
}
}
n = 0;
neighptr = &pages[npage][npnt];
nn = 0;
touchptr = &pages_touch[npage][npnt];
shearptr = &pages_shear[npage][3*npnt];
// loop over parent non-skip granular list and its history info
touchptr_skip = firsttouch_skip[i];
shearptr_skip = firstshear_skip[i];
jlist = firstneigh_skip[i];
jnum = numneigh_skip[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (ijskip[itype][type[j]]) continue;
neighptr[n] = joriginal;
touchptr[n++] = touchptr_skip[jj];
shearptr[nn++] = shearptr_skip[3*jj];
shearptr[nn++] = shearptr_skip[3*jj+1];
shearptr[nn++] = shearptr_skip[3*jj+2];
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
firsttouch[i] = touchptr;
firstshear[i] = shearptr;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
build skip list for subset of types from parent list
iskip and ijskip flag which atom types and type pairs to skip
this is for respa lists, copy the inner/middle values from parent
------------------------------------------------------------------------- */
void Neighbor::skip_from_respa(NeighList *list)
{
int i,j,ii,jj,n,itype,jnum,joriginal,n_inner,n_middle;
int *neighptr,*jlist,*neighptr_inner,*neighptr_middle;
int *type = atom->type;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *ilist_skip = list->listskip->ilist;
int *numneigh_skip = list->listskip->numneigh;
int **firstneigh_skip = list->listskip->firstneigh;
int inum_skip = list->listskip->inum;
int *iskip = list->iskip;
int **ijskip = list->ijskip;
NeighList *listinner = list->listinner;
int *numneigh_inner = listinner->numneigh;
int **firstneigh_inner = listinner->firstneigh;
int **pages_inner = listinner->pages;
int *numneigh_inner_skip = list->listskip->listinner->numneigh;
int **firstneigh_inner_skip = list->listskip->listinner->firstneigh;
NeighList *listmiddle;
int *numneigh_middle,**firstneigh_middle,**pages_middle;
int *numneigh_middle_skip,**firstneigh_middle_skip;
int respamiddle = list->respamiddle;
if (respamiddle) {
listmiddle = list->listmiddle;
numneigh_middle = listmiddle->numneigh;
firstneigh_middle = listmiddle->firstneigh;
pages_middle = listmiddle->pages;
numneigh_middle_skip = list->listskip->listmiddle->numneigh;
firstneigh_middle_skip = list->listskip->listmiddle->firstneigh;
}
int inum = 0;
int npage = 0;
int npnt = 0;
int npage_inner = 0;
int npnt_inner = 0;
int npage_middle = 0;
int npnt_middle = 0;
// loop over atoms in other list
// skip I atom entirely if iskip is set for type[I]
// skip I,J pair if ijskip is set for type[I],type[J]
for (ii = 0; ii < inum_skip; ii++) {
i = ilist_skip[ii];
itype = type[i];
if (iskip[itype]) continue;
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
if (pgsize - npnt_inner < oneatom) {
npnt_inner = 0;
npage_inner++;
if (npage_inner == listinner->maxpage)
pages_inner = listinner->add_pages();
}
neighptr_inner = &pages_inner[npage_inner][npnt_inner];
n_inner = 0;
if (respamiddle) {
if (pgsize - npnt_middle < oneatom) {
npnt_middle = 0;
npage_middle++;
if (npage_middle == listmiddle->maxpage)
pages_middle = listmiddle->add_pages();
}
neighptr_middle = &pages_middle[npage_middle][npnt_middle];
n_middle = 0;
}
// loop over parent outer rRESPA list
jlist = firstneigh_skip[i];
jnum = numneigh_skip[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (ijskip[itype][type[j]]) continue;
neighptr[n++] = joriginal;
}
// loop over parent inner rRESPA list
jlist = firstneigh_inner_skip[i];
jnum = numneigh_inner_skip[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (ijskip[itype][type[j]]) continue;
neighptr_inner[n_inner++] = joriginal;
}
// loop over parent middle rRESPA list
if (respamiddle) {
jlist = firstneigh_middle_skip[i];
jnum = numneigh_middle_skip[i];
for (jj = 0; jj < jnum; jj++) {
joriginal = jlist[jj];
j = joriginal & NEIGHMASK;
if (ijskip[itype][type[j]]) continue;
neighptr_middle[n_middle++] = joriginal;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
firstneigh_inner[i] = neighptr_inner;
numneigh_inner[i] = n_inner;
npnt_inner += n_inner;
if (npnt_inner >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
if (respamiddle) {
firstneigh_middle[i] = neighptr_middle;
numneigh_middle[i] = n_middle;
npnt_middle += n_middle;
if (npnt_middle >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
create list which is simply a copy of parent list
------------------------------------------------------------------------- */
void Neighbor::copy_from(NeighList *list)
{
NeighList *listcopy = list->listcopy;
list->inum = listcopy->inum;
list->gnum = listcopy->gnum;
list->ilist = listcopy->ilist;
list->numneigh = listcopy->numneigh;
list->firstneigh = listcopy->firstneigh;
list->firstdouble = listcopy->firstdouble;
list->pages = listcopy->pages;
list->dpages = listcopy->dpages;
}
diff --git a/src/neigh_full.cpp b/src/neigh_full.cpp
index c667ab616..b4b7fd0ae 100644
--- a/src/neigh_full.cpp
+++ b/src/neigh_full.cpp
@@ -1,533 +1,533 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "neighbor.h"
#include "neigh_list.h"
#include "atom.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
N^2 search for all neighbors
every neighbor pair appears in list of both atoms i and j
------------------------------------------------------------------------- */
void Neighbor::full_nsq(NeighList *list)
{
int i,j,n,itype,jtype,which,bitmask;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int molecular = atom->molecular;
if (includegroup) {
nlocal = atom->nfirst;
bitmask = group->bitmask[includegroup];
}
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over owned atoms, storing neighbors
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms, owned and ghost
// skip i = j
for (j = 0; j < nall; j++) {
if (includegroup && !(mask[j] & bitmask)) continue;
if (i == j) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
list->gnum = 0;
}
/* ----------------------------------------------------------------------
N^2 search for all neighbors
include neighbors of ghost atoms
every neighbor pair appears in list of both atoms i and j
------------------------------------------------------------------------- */
void Neighbor::full_nsq_ghost(NeighList *list)
{
int i,j,n,itype,jtype,which;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int molecular = atom->molecular;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over owned & ghost atoms, storing neighbors
for (i = 0; i < nall; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms, owned and ghost
// skip i = j
if (i < nlocal) {
for (j = 0; j < nall; j++) {
if (i == j) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
} else {
for (j = 0; j < nall; j++) {
if (i == j) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighghostsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = atom->nlocal;
list->gnum = inum - atom->nlocal;
}
/* ----------------------------------------------------------------------
binned neighbor list construction for all neighbors
every neighbor pair appears in list of both atoms i and j
------------------------------------------------------------------------- */
void Neighbor::full_bin(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
// bin owned & ghost atoms
bin_atoms();
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over owned atoms, storing neighbors
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in surrounding bins in stencil including self
// skip i = j
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (i == j) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
list->gnum = 0;
}
/* ----------------------------------------------------------------------
binned neighbor list construction for all neighbors
include neighbors of ghost atoms
every neighbor pair appears in list of both atoms i and j
------------------------------------------------------------------------- */
void Neighbor::full_bin_ghost(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int xbin,ybin,zbin,xbin2,ybin2,zbin2;
int *neighptr;
// bin owned & ghost atoms
bin_atoms();
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int molecular = atom->molecular;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
int **stencilxyz = list->stencilxyz;
int inum = 0;
int npage = 0;
int npnt = 0;
// loop over owned & ghost atoms, storing neighbors
for (i = 0; i < nall; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in surrounding bins in stencil including self
// when i is a ghost atom, must check if stencil bin is out of bounds
// skip i = j
if (i < nlocal) {
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (i == j) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
} else {
ibin = coord2bin(x[i],xbin,ybin,zbin);
for (k = 0; k < nstencil; k++) {
xbin2 = xbin + stencilxyz[k][0];
ybin2 = ybin + stencilxyz[k][1];
zbin2 = zbin + stencilxyz[k][2];
if (xbin2 < 0 || xbin2 >= mbinx ||
ybin2 < 0 || ybin2 >= mbiny ||
zbin2 < 0 || zbin2 >= mbinz) continue;
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (i == j) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighghostsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = atom->nlocal;
list->gnum = inum - atom->nlocal;
}
/* ----------------------------------------------------------------------
binned neighbor list construction for all neighbors
multi-type stencil is itype dependent and is distance checked
every neighbor pair appears in list of both atoms i and j
------------------------------------------------------------------------- */
void Neighbor::full_multi(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which,ns;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*s;
double *cutsq,*distsq;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *nstencil_multi = list->nstencil_multi;
int **stencil_multi = list->stencil_multi;
double **distsq_multi = list->distsq_multi;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in other bins in stencil, including self
// skip if i,j neighbor cutoff is less than bin distance
// skip i = j
ibin = coord2bin(x[i]);
s = stencil_multi[itype];
distsq = distsq_multi[itype];
cutsq = cutneighsq[itype];
ns = nstencil_multi[itype];
for (k = 0; k < ns; k++) {
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
jtype = type[j];
if (cutsq[jtype] < distsq[k]) continue;
if (i == j) continue;
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
list->gnum = 0;
}
diff --git a/src/neigh_gran.cpp b/src/neigh_gran.cpp
index ce75b16af..7e7c282f5 100644
--- a/src/neigh_gran.cpp
+++ b/src/neigh_gran.cpp
@@ -1,624 +1,624 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "neighbor.h"
#include "neigh_list.h"
#include "atom.h"
#include "group.h"
#include "fix_shear_history.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
granular particles
N^2 / 2 search for neighbor pairs with partial Newton's 3rd law
shear history must be accounted for when a neighbor pair is added
pair added to list if atoms i and j are both owned and i < j
pair added if j is ghost (also stored by proc owning j)
------------------------------------------------------------------------- */
void Neighbor::granular_nsq_no_newton(NeighList *list)
{
int i,j,m,n,nn,bitmask;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr,*touchptr;
double *shearptr;
NeighList *listgranhistory;
int *npartner,**partner;
double ***shearpartner;
int **firsttouch;
double **firstshear;
int **pages_touch;
double **pages_shear;
double **x = atom->x;
double *radius = atom->radius;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (includegroup) {
nlocal = atom->nfirst;
bitmask = group->bitmask[includegroup];
}
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
FixShearHistory *fix_history = list->fix_history;
if (fix_history) {
npartner = fix_history->npartner;
partner = fix_history->partner;
shearpartner = fix_history->shearpartner;
listgranhistory = list->listgranhistory;
firsttouch = listgranhistory->firstneigh;
firstshear = listgranhistory->firstdouble;
pages_touch = listgranhistory->pages;
pages_shear = listgranhistory->dpages;
}
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) {
pages = list->add_pages();
if (fix_history) {
pages_touch = listgranhistory->add_pages();
pages_shear = listgranhistory->dpages;
}
}
}
n = 0;
neighptr = &pages[npage][npnt];
if (fix_history) {
nn = 0;
touchptr = &pages_touch[npage][npnt];
shearptr = &pages_shear[npage][3*npnt];
}
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
// loop over remaining atoms, owned and ghost
for (j = i+1; j < nall; j++) {
if (includegroup && !(mask[j] & bitmask)) continue;
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radi + radius[j];
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
neighptr[n] = j;
if (fix_history) {
if (rsq < radsum*radsum) {
for (m = 0; m < npartner[i]; m++)
if (partner[i][m] == tag[j]) break;
if (m < npartner[i]) {
touchptr[n] = 1;
shearptr[nn++] = shearpartner[i][m][0];
shearptr[nn++] = shearpartner[i][m][1];
shearptr[nn++] = shearpartner[i][m][2];
} else {
touchptr[n] = 0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
}
} else {
touchptr[n] = 0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
}
}
n++;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
if (fix_history) {
firsttouch[i] = touchptr;
firstshear[i] = shearptr;
}
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
granular particles
N^2 / 2 search for neighbor pairs with full Newton's 3rd law
no shear history is allowed for this option
pair added to list if atoms i and j are both owned and i < j
if j is ghost only me or other proc adds pair
decision based on itag,jtag tests
------------------------------------------------------------------------- */
void Neighbor::granular_nsq_newton(NeighList *list)
{
int i,j,n,itag,jtag,bitmask;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
double **x = atom->x;
double *radius = atom->radius;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (includegroup) {
nlocal = atom->nfirst;
bitmask = group->bitmask[includegroup];
}
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
n = 0;
neighptr = &pages[npage][npnt];
itag = tag[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
// loop over remaining atoms, owned and ghost
for (j = i+1; j < nall; j++) {
if (includegroup && !(mask[j] & bitmask)) continue;
if (j >= nlocal) {
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
}
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radi + radius[j];
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) neighptr[n++] = j;
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
granular particles
binned neighbor list construction with partial Newton's 3rd law
shear history must be accounted for when a neighbor pair is added
each owned atom i checks own bin and surrounding bins in non-Newton stencil
pair stored once if i,j are both owned and i < j
pair stored by me if j is ghost (also stored by proc owning j)
------------------------------------------------------------------------- */
void Neighbor::granular_bin_no_newton(NeighList *list)
{
int i,j,k,m,n,nn,ibin;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr,*touchptr;
double *shearptr;
NeighList *listgranhistory;
int *npartner,**partner;
double ***shearpartner;
int **firsttouch;
double **firstshear;
int **pages_touch;
double **pages_shear;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
double **x = atom->x;
double *radius = atom->radius;
int *tag = atom->tag;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
FixShearHistory *fix_history = list->fix_history;
if (fix_history) {
npartner = fix_history->npartner;
partner = fix_history->partner;
shearpartner = fix_history->shearpartner;
listgranhistory = list->listgranhistory;
firsttouch = listgranhistory->firstneigh;
firstshear = listgranhistory->firstdouble;
pages_touch = listgranhistory->pages;
pages_shear = listgranhistory->dpages;
}
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) {
pages = list->add_pages();
if (fix_history) {
pages_touch = listgranhistory->add_pages();
pages_shear = listgranhistory->dpages;
}
}
}
n = 0;
neighptr = &pages[npage][npnt];
if (fix_history) {
nn = 0;
touchptr = &pages_touch[npage][npnt];
shearptr = &pages_shear[npage][3*npnt];
}
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
ibin = coord2bin(x[i]);
// loop over all atoms in surrounding bins in stencil including self
// only store pair if i < j
// stores own/own pairs only once
// stores own/ghost pairs on both procs
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (j <= i) continue;
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radi + radius[j];
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) {
neighptr[n] = j;
if (fix_history) {
if (rsq < radsum*radsum) {
for (m = 0; m < npartner[i]; m++)
if (partner[i][m] == tag[j]) break;
if (m < npartner[i]) {
touchptr[n] = 1;
shearptr[nn++] = shearpartner[i][m][0];
shearptr[nn++] = shearpartner[i][m][1];
shearptr[nn++] = shearpartner[i][m][2];
} else {
touchptr[n] = 0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
}
} else {
touchptr[n] = 0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
shearptr[nn++] = 0.0;
}
}
n++;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
if (fix_history) {
firsttouch[i] = touchptr;
firstshear[i] = shearptr;
}
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
granular particles
binned neighbor list construction with full Newton's 3rd law
no shear history is allowed for this option
each owned atom i checks its own bin and other bins in Newton stencil
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::granular_bin_newton(NeighList *list)
{
int i,j,k,n,ibin;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
double **x = atom->x;
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
n = 0;
neighptr = &pages[npage][npnt];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
// loop over rest of atoms in i's bin, ghosts are at end of linked list
// if j is owned atom, store it, since j is beyond i in linked list
// if j is ghost, only store if j coords are "above and to the right" of i
for (j = bins[i]; j >= 0; j = bins[j]) {
if (j >= nlocal) {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radi + radius[j];
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) neighptr[n++] = j;
}
// loop over all atoms in other bins in stencil, store every pair
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radi + radius[j];
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) neighptr[n++] = j;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
granular particles
binned neighbor list construction with Newton's 3rd law for triclinic
no shear history is allowed for this option
each owned atom i checks its own bin and other bins in triclinic stencil
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::granular_bin_newton_tri(NeighList *list)
{
int i,j,k,n,ibin;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
double radi,radsum,cutsq;
int *neighptr;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
double **x = atom->x;
double *radius = atom->radius;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
n = 0;
neighptr = &pages[npage][npnt];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
radi = radius[i];
// loop over all atoms in bins in stencil
// pairs for atoms j "below" i are excluded
// below = lower z or (equal z and lower y) or (equal zy and lower x)
// (equal zyx and j <= i)
// latter excludes self-self interaction but allows superposed atoms
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp) {
if (x[j][0] < xtmp) continue;
if (x[j][0] == xtmp && j <= i) continue;
}
}
if (exclude && exclusion(i,j,type[i],type[j],mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radi + radius[j];
cutsq = (radsum+skin) * (radsum+skin);
if (rsq <= cutsq) neighptr[n++] = j;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
diff --git a/src/neigh_half_bin.cpp b/src/neigh_half_bin.cpp
index e776b8203..e1487897f 100644
--- a/src/neigh_half_bin.cpp
+++ b/src/neigh_half_bin.cpp
@@ -1,338 +1,338 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "neighbor.h"
#include "neigh_list.h"
#include "atom.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
binned neighbor list construction with partial Newton's 3rd law
each owned atom i checks own bin and other bins in stencil
pair stored once if i,j are both owned and i < j
pair stored by me if j is ghost (also stored by proc owning j)
------------------------------------------------------------------------- */
void Neighbor::half_bin_no_newton(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int molecular = atom->molecular;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in other bins in stencil including self
// only store pair if i < j
// stores own/own pairs only once
// stores own/ghost pairs on both procs
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (j <= i) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
binned neighbor list construction with full Newton's 3rd law
each owned atom i checks its own bin and other bins in Newton stencil
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::half_bin_newton(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int molecular = atom->molecular;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over rest of atoms in i's bin, ghosts are at end of linked list
// if j is owned atom, store it, since j is beyond i in linked list
// if j is ghost, only store if j coords are "above and to the right" of i
for (j = bins[i]; j >= 0; j = bins[j]) {
if (j >= nlocal) {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
// loop over all atoms in other bins in stencil, store every pair
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
binned neighbor list construction with Newton's 3rd law for triclinic
each owned atom i checks its own bin and other bins in triclinic stencil
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::half_bin_newton_tri(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int molecular = atom->molecular;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in bins in stencil
// pairs for atoms j "below" i are excluded
// below = lower z or (equal z and lower y) or (equal zy and lower x)
// (equal zyx and j <= i)
// latter excludes self-self interaction but allows superposed atoms
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp) {
if (x[j][0] < xtmp) continue;
if (x[j][0] == xtmp && j <= i) continue;
}
}
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
diff --git a/src/neigh_half_multi.cpp b/src/neigh_half_multi.cpp
index d0a8efcd2..04e25931b 100644
--- a/src/neigh_half_multi.cpp
+++ b/src/neigh_half_multi.cpp
@@ -1,366 +1,366 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "neighbor.h"
#include "neigh_list.h"
#include "atom.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
binned neighbor list construction with partial Newton's 3rd law
each owned atom i checks own bin and other bins in stencil
multi-type stencil is itype dependent and is distance checked
pair stored once if i,j are both owned and i < j
pair stored by me if j is ghost (also stored by proc owning j)
------------------------------------------------------------------------- */
void Neighbor::half_multi_no_newton(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which,ns;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*s;
double *cutsq,*distsq;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *nstencil_multi = list->nstencil_multi;
int **stencil_multi = list->stencil_multi;
double **distsq_multi = list->distsq_multi;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in other bins in stencil including self
// only store pair if i < j
// skip if i,j neighbor cutoff is less than bin distance
// stores own/own pairs only once
// stores own/ghost pairs on both procs
ibin = coord2bin(x[i]);
s = stencil_multi[itype];
distsq = distsq_multi[itype];
cutsq = cutneighsq[itype];
ns = nstencil_multi[itype];
for (k = 0; k < ns; k++) {
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
if (j <= i) continue;
jtype = type[j];
if (cutsq[jtype] < distsq[k]) continue;
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
binned neighbor list construction with full Newton's 3rd law
each owned atom i checks its own bin and other bins in Newton stencil
multi-type stencil is itype dependent and is distance checked
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::half_multi_newton(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which,ns;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*s;
double *cutsq,*distsq;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *nstencil_multi = list->nstencil_multi;
int **stencil_multi = list->stencil_multi;
double **distsq_multi = list->distsq_multi;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over rest of atoms in i's bin, ghosts are at end of linked list
// if j is owned atom, store it, since j is beyond i in linked list
// if j is ghost, only store if j coords are "above and to the right" of i
for (j = bins[i]; j >= 0; j = bins[j]) {
if (j >= nlocal) {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
// loop over all atoms in other bins in stencil, store every pair
// skip if i,j neighbor cutoff is less than bin distance
ibin = coord2bin(x[i]);
s = stencil_multi[itype];
distsq = distsq_multi[itype];
cutsq = cutneighsq[itype];
ns = nstencil_multi[itype];
for (k = 0; k < ns; k++) {
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
jtype = type[j];
if (cutsq[jtype] < distsq[k]) continue;
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
binned neighbor list construction with Newton's 3rd law for triclinic
each owned atom i checks its own bin and other bins in triclinic stencil
multi-type stencil is itype dependent and is distance checked
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::half_multi_newton_tri(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which,ns;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*s;
double *cutsq,*distsq;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int *nstencil_multi = list->nstencil_multi;
int **stencil_multi = list->stencil_multi;
double **distsq_multi = list->distsq_multi;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in bins, including self, in stencil
// skip if i,j neighbor cutoff is less than bin distance
// bins below self are excluded from stencil
// pairs for atoms j "below" i are excluded
// below = lower z or (equal z and lower y) or (equal zy and lower x)
// (equal zyx and j <= i)
// latter excludes self-self interaction but allows superposed atoms
ibin = coord2bin(x[i]);
s = stencil_multi[itype];
distsq = distsq_multi[itype];
cutsq = cutneighsq[itype];
ns = nstencil_multi[itype];
for (k = 0; k < ns; k++) {
for (j = binhead[ibin+s[k]]; j >= 0; j = bins[j]) {
jtype = type[j];
if (cutsq[jtype] < distsq[k]) continue;
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp) {
if (x[j][0] < xtmp) continue;
if (x[j][0] == xtmp && j <= i) continue;
}
}
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
diff --git a/src/neigh_half_nsq.cpp b/src/neigh_half_nsq.cpp
index 1df486598..32792a678 100644
--- a/src/neigh_half_nsq.cpp
+++ b/src/neigh_half_nsq.cpp
@@ -1,210 +1,210 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "neighbor.h"
#include "neigh_list.h"
#include "atom.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
N^2 / 2 search for neighbor pairs with partial Newton's 3rd law
pair stored once if i,j are both owned and i < j
pair stored by me if j is ghost (also stored by proc owning j)
------------------------------------------------------------------------- */
void Neighbor::half_nsq_no_newton(NeighList *list)
{
int i,j,n,itype,jtype,which,bitmask;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int molecular = atom->molecular;
if (includegroup) {
nlocal = atom->nfirst;
bitmask = group->bitmask[includegroup];
}
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over remaining atoms, owned and ghost
for (j = i+1; j < nall; j++) {
if (includegroup && !(mask[j] & bitmask)) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
/* ----------------------------------------------------------------------
N^2 / 2 search for neighbor pairs with full Newton's 3rd law
every pair stored exactly once by some processor
decision on ghost atoms based on itag,jtag tests
------------------------------------------------------------------------- */
void Neighbor::half_nsq_newton(NeighList *list)
{
int i,j,n,itype,jtype,itag,jtag,which,bitmask;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr;
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int molecular = atom->molecular;
if (includegroup) {
nlocal = atom->nfirst;
bitmask = group->bitmask[includegroup];
}
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int inum = 0;
int npage = 0;
int npnt = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
itag = tag[i];
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over remaining atoms, owned and ghost
// itag = jtag is possible for long cutoffs that include images of self
for (j = i+1; j < nall; j++) {
if (includegroup && !(mask[j] & bitmask)) continue;
if (j >= nlocal) {
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
}
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
}
}
ilist[inum++] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
list->inum = inum;
}
diff --git a/src/neigh_respa.cpp b/src/neigh_respa.cpp
index a5190316f..8e1e7b79e 100644
--- a/src/neigh_respa.cpp
+++ b/src/neigh_respa.cpp
@@ -1,907 +1,907 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "neighbor.h"
#include "neigh_list.h"
#include "atom.h"
#include "group.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ----------------------------------------------------------------------
multiple respa lists
N^2 / 2 search for neighbor pairs with partial Newton's 3rd law
pair added to list if atoms i and j are both owned and i < j
pair added if j is ghost (also stored by proc owning j)
------------------------------------------------------------------------- */
void Neighbor::respa_nsq_no_newton(NeighList *list)
{
int i,j,n,itype,jtype,which,n_inner,n_middle,bitmask;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*neighptr_inner,*neighptr_middle;
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int molecular = atom->molecular;
if (includegroup) {
nlocal = atom->nfirst;
bitmask = group->bitmask[includegroup];
}
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
NeighList *listinner = list->listinner;
int *ilist_inner = listinner->ilist;
int *numneigh_inner = listinner->numneigh;
int **firstneigh_inner = listinner->firstneigh;
int **pages_inner = listinner->pages;
NeighList *listmiddle;
int *ilist_middle,*numneigh_middle,**firstneigh_middle,**pages_middle;
int respamiddle = list->respamiddle;
if (respamiddle) {
listmiddle = list->listmiddle;
ilist_middle = listmiddle->ilist;
numneigh_middle = listmiddle->numneigh;
firstneigh_middle = listmiddle->firstneigh;
pages_middle = listmiddle->pages;
}
int inum = 0;
int npage = 0;
int npnt = 0;
int npage_inner = 0;
int npnt_inner = 0;
int npage_middle = 0;
int npnt_middle = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
if (pgsize - npnt_inner < oneatom) {
npnt_inner = 0;
npage_inner++;
if (npage_inner == listinner->maxpage)
pages_inner = listinner->add_pages();
}
neighptr_inner = &pages_inner[npage_inner][npnt_inner];
n_inner = 0;
if (respamiddle) {
if (pgsize - npnt_middle < oneatom) {
npnt_middle = 0;
npage_middle++;
if (npage_middle == listmiddle->maxpage)
pages_middle = listmiddle->add_pages();
}
neighptr_middle = &pages_middle[npage_middle][npnt_middle];
n_middle = 0;
}
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over remaining atoms, owned and ghost
for (j = i+1; j < nall; j++) {
if (includegroup && !(mask[j] & bitmask)) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
if (rsq < cut_inner_sq) {
if (which == 0) neighptr_inner[n_inner++] = j;
else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS);
}
if (respamiddle && rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
if (which == 0) neighptr_middle[n_middle++] = j;
else if (which > 0)
neighptr_middle[n_middle++] = j ^ (which << SBBITS);
}
}
}
ilist[inum] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
ilist_inner[inum] = i;
firstneigh_inner[i] = neighptr_inner;
numneigh_inner[i] = n_inner;
npnt_inner += n_inner;
if (npnt_inner >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
if (respamiddle) {
ilist_middle[inum] = i;
firstneigh_middle[i] = neighptr_middle;
numneigh_middle[i] = n_middle;
npnt_middle += n_middle;
if (npnt_middle >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
inum++;
}
list->inum = inum;
listinner->inum = inum;
if (respamiddle) listmiddle->inum = inum;
}
/* ----------------------------------------------------------------------
multiple respa lists
N^2 / 2 search for neighbor pairs with full Newton's 3rd law
pair added to list if atoms i and j are both owned and i < j
if j is ghost only me or other proc adds pair
decision based on itag,jtag tests
------------------------------------------------------------------------- */
void Neighbor::respa_nsq_newton(NeighList *list)
{
int i,j,n,itype,jtype,itag,jtag,which,n_inner,n_middle,bitmask;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*neighptr_inner,*neighptr_middle;
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
int molecular = atom->molecular;
if (includegroup) {
nlocal = atom->nfirst;
bitmask = group->bitmask[includegroup];
}
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
NeighList *listinner = list->listinner;
int *ilist_inner = listinner->ilist;
int *numneigh_inner = listinner->numneigh;
int **firstneigh_inner = listinner->firstneigh;
int **pages_inner = listinner->pages;
NeighList *listmiddle;
int *ilist_middle,*numneigh_middle,**firstneigh_middle,**pages_middle;
int respamiddle = list->respamiddle;
if (respamiddle) {
listmiddle = list->listmiddle;
ilist_middle = listmiddle->ilist;
numneigh_middle = listmiddle->numneigh;
firstneigh_middle = listmiddle->firstneigh;
pages_middle = listmiddle->pages;
}
int inum = 0;
int npage = 0;
int npnt = 0;
int npage_inner = 0;
int npnt_inner = 0;
int npage_middle = 0;
int npnt_middle = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
if (pgsize - npnt_inner < oneatom) {
npnt_inner = 0;
npage_inner++;
if (npage_inner == listinner->maxpage)
pages_inner = listinner->add_pages();
}
neighptr_inner = &pages_inner[npage_inner][npnt_inner];
n_inner = 0;
if (respamiddle) {
if (pgsize - npnt_middle < oneatom) {
npnt_middle = 0;
npage_middle++;
if (npage_middle == listmiddle->maxpage)
pages_middle = listmiddle->add_pages();
}
neighptr_middle = &pages_middle[npage_middle][npnt_middle];
n_middle = 0;
}
itag = tag[i];
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over remaining atoms, owned and ghost
for (j = i+1; j < nall; j++) {
if (includegroup && !(mask[j] & bitmask)) continue;
if (j >= nlocal) {
jtag = tag[j];
if (itag > jtag) {
if ((itag+jtag) % 2 == 0) continue;
} else if (itag < jtag) {
if ((itag+jtag) % 2 == 1) continue;
} else {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
}
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
if (rsq < cut_inner_sq) {
if (which == 0) neighptr_inner[n_inner++] = j;
else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS);
}
if (respamiddle &&
rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
if (which == 0) neighptr_middle[n_middle++] = j;
else if (which > 0)
neighptr_middle[n_middle++] = j ^ (which << SBBITS);
}
}
}
ilist[inum] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
ilist_inner[inum] = i;
firstneigh_inner[i] = neighptr_inner;
numneigh_inner[i] = n_inner;
npnt_inner += n_inner;
if (npnt_inner >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
if (respamiddle) {
ilist_middle[inum] = i;
firstneigh_middle[i] = neighptr_middle;
numneigh_middle[i] = n_middle;
npnt_middle += n_middle;
if (npnt_middle >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
inum++;
}
list->inum = inum;
listinner->inum = inum;
if (respamiddle) listmiddle->inum = inum;
}
/* ----------------------------------------------------------------------
multiple respa lists
binned neighbor list construction with partial Newton's 3rd law
each owned atom i checks own bin and surrounding bins in non-Newton stencil
pair stored once if i,j are both owned and i < j
pair stored by me if j is ghost (also stored by proc owning j)
------------------------------------------------------------------------- */
void Neighbor::respa_bin_no_newton(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which,n_inner,n_middle;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*neighptr_inner,*neighptr_middle;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
NeighList *listinner = list->listinner;
int *ilist_inner = listinner->ilist;
int *numneigh_inner = listinner->numneigh;
int **firstneigh_inner = listinner->firstneigh;
int **pages_inner = listinner->pages;
NeighList *listmiddle;
int *ilist_middle,*numneigh_middle,**firstneigh_middle,**pages_middle;
int respamiddle = list->respamiddle;
if (respamiddle) {
listmiddle = list->listmiddle;
ilist_middle = listmiddle->ilist;
numneigh_middle = listmiddle->numneigh;
firstneigh_middle = listmiddle->firstneigh;
pages_middle = listmiddle->pages;
}
int inum = 0;
int npage = 0;
int npnt = 0;
int npage_inner = 0;
int npnt_inner = 0;
int npage_middle = 0;
int npnt_middle = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
if (pgsize - npnt_inner < oneatom) {
npnt_inner = 0;
npage_inner++;
if (npage_inner == listinner->maxpage)
pages_inner = listinner->add_pages();
}
neighptr_inner = &pages_inner[npage_inner][npnt_inner];
n_inner = 0;
if (respamiddle) {
if (pgsize - npnt_middle < oneatom) {
npnt_middle = 0;
npage_middle++;
if (npage_middle == listmiddle->maxpage)
pages_middle = listmiddle->add_pages();
}
neighptr_middle = &pages_middle[npage_middle][npnt_middle];
n_middle = 0;
}
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
ibin = coord2bin(x[i]);
// loop over all atoms in surrounding bins in stencil including self
// only store pair if i < j
// stores own/own pairs only once
// stores own/ghost pairs on both procs
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (j <= i) continue;
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
if (rsq < cut_inner_sq) {
if (which == 0) neighptr_inner[n_inner++] = j;
else if (which > 0)
neighptr_inner[n_inner++] = j ^ (which << SBBITS);
}
if (respamiddle &&
rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
if (which == 0) neighptr_middle[n_middle++] = j;
else if (which > 0)
neighptr_middle[n_middle++] = j ^ (which << SBBITS);
}
}
}
}
ilist[inum] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
ilist_inner[inum] = i;
firstneigh_inner[i] = neighptr_inner;
numneigh_inner[i] = n_inner;
npnt_inner += n_inner;
if (npnt_inner >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
if (respamiddle) {
ilist_middle[inum] = i;
firstneigh_middle[i] = neighptr_middle;
numneigh_middle[i] = n_middle;
npnt_middle += n_middle;
if (npnt_middle >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
inum++;
}
list->inum = inum;
listinner->inum = inum;
if (respamiddle) listmiddle->inum = inum;
}
/* ----------------------------------------------------------------------
multiple respa lists
binned neighbor list construction with full Newton's 3rd law
each owned atom i checks its own bin and other bins in Newton stencil
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::respa_bin_newton(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which,n_inner,n_middle;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*neighptr_inner,*neighptr_middle;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
NeighList *listinner = list->listinner;
int *ilist_inner = listinner->ilist;
int *numneigh_inner = listinner->numneigh;
int **firstneigh_inner = listinner->firstneigh;
int **pages_inner = listinner->pages;
NeighList *listmiddle;
int *ilist_middle,*numneigh_middle,**firstneigh_middle,**pages_middle;
int respamiddle = list->respamiddle;
if (respamiddle) {
listmiddle = list->listmiddle;
ilist_middle = listmiddle->ilist;
numneigh_middle = listmiddle->numneigh;
firstneigh_middle = listmiddle->firstneigh;
pages_middle = listmiddle->pages;
}
int inum = 0;
int npage = 0;
int npnt = 0;
int npage_inner = 0;
int npnt_inner = 0;
int npage_middle = 0;
int npnt_middle = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
if (pgsize - npnt_inner < oneatom) {
npnt_inner = 0;
npage_inner++;
if (npage_inner == listinner->maxpage)
pages_inner = listinner->add_pages();
}
neighptr_inner = &pages_inner[npage_inner][npnt_inner];
n_inner = 0;
if (respamiddle) {
if (pgsize - npnt_middle < oneatom) {
npnt_middle = 0;
npage_middle++;
if (npage_middle == listmiddle->maxpage)
pages_middle = listmiddle->add_pages();
}
neighptr_middle = &pages_middle[npage_middle][npnt_middle];
n_middle = 0;
}
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over rest of atoms in i's bin, ghosts are at end of linked list
// if j is owned atom, store it, since j is beyond i in linked list
// if j is ghost, only store if j coords are "above and to the right" of i
for (j = bins[i]; j >= 0; j = bins[j]) {
if (j >= nlocal) {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp && x[j][0] < xtmp) continue;
}
}
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
if (rsq < cut_inner_sq) {
if (which == 0) neighptr_inner[n_inner++] = j;
else if (which > 0) neighptr_inner[n_inner++] = j ^ (which << SBBITS);
}
if (respamiddle &&
rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
if (which == 0) neighptr_middle[n_middle++] = j;
else if (which > 0)
neighptr_middle[n_middle++] = j ^ (which << SBBITS);
}
}
}
// loop over all atoms in other bins in stencil, store every pair
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
if (rsq < cut_inner_sq) {
if (which == 0) neighptr_inner[n_inner++] = j;
else if (which > 0)
neighptr_inner[n_inner++] = j ^ (which << SBBITS);
}
if (respamiddle &&
rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
if (which == 0) neighptr_middle[n_middle++] = j;
else if (which > 0)
neighptr_middle[n_middle++] = j ^ (which << SBBITS);
}
}
}
}
ilist[inum] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
ilist_inner[inum] = i;
firstneigh_inner[i] = neighptr_inner;
numneigh_inner[i] = n_inner;
npnt_inner += n_inner;
if (npnt_inner >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
if (respamiddle) {
ilist_middle[inum] = i;
firstneigh_middle[i] = neighptr_middle;
numneigh_middle[i] = n_middle;
npnt_middle += n_middle;
if (npnt_middle >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
inum++;
}
list->inum = inum;
listinner->inum = inum;
if (respamiddle) listmiddle->inum = inum;
}
/* ----------------------------------------------------------------------
multiple respa lists
binned neighbor list construction with Newton's 3rd law for triclinic
each owned atom i checks its own bin and other bins in triclinic stencil
every pair stored exactly once by some processor
------------------------------------------------------------------------- */
void Neighbor::respa_bin_newton_tri(NeighList *list)
{
int i,j,k,n,itype,jtype,ibin,which,n_inner,n_middle;
double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
int *neighptr,*neighptr_inner,*neighptr_middle;
// bin local & ghost atoms
bin_atoms();
// loop over each atom, storing neighbors
int **special = atom->special;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
double **x = atom->x;
int *type = atom->type;
int *mask = atom->mask;
int *molecule = atom->molecule;
int nlocal = atom->nlocal;
int molecular = atom->molecular;
if (includegroup) nlocal = atom->nfirst;
int *ilist = list->ilist;
int *numneigh = list->numneigh;
int **firstneigh = list->firstneigh;
int **pages = list->pages;
int nstencil = list->nstencil;
int *stencil = list->stencil;
NeighList *listinner = list->listinner;
int *ilist_inner = listinner->ilist;
int *numneigh_inner = listinner->numneigh;
int **firstneigh_inner = listinner->firstneigh;
int **pages_inner = listinner->pages;
NeighList *listmiddle;
int *ilist_middle,*numneigh_middle,**firstneigh_middle,**pages_middle;
int respamiddle = list->respamiddle;
if (respamiddle) {
listmiddle = list->listmiddle;
ilist_middle = listmiddle->ilist;
numneigh_middle = listmiddle->numneigh;
firstneigh_middle = listmiddle->firstneigh;
pages_middle = listmiddle->pages;
}
int inum = 0;
int npage = 0;
int npnt = 0;
int npage_inner = 0;
int npnt_inner = 0;
int npage_middle = 0;
int npnt_middle = 0;
for (i = 0; i < nlocal; i++) {
if (pgsize - npnt < oneatom) {
npnt = 0;
npage++;
if (npage == list->maxpage) pages = list->add_pages();
}
neighptr = &pages[npage][npnt];
n = 0;
if (pgsize - npnt_inner < oneatom) {
npnt_inner = 0;
npage_inner++;
if (npage_inner == listinner->maxpage)
pages_inner = listinner->add_pages();
}
neighptr_inner = &pages_inner[npage_inner][npnt_inner];
n_inner = 0;
if (respamiddle) {
if (pgsize - npnt_middle < oneatom) {
npnt_middle = 0;
npage_middle++;
if (npage_middle == listmiddle->maxpage)
pages_middle = listmiddle->add_pages();
}
neighptr_middle = &pages_middle[npage_middle][npnt_middle];
n_middle = 0;
}
itype = type[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
// loop over all atoms in bins in stencil
// pairs for atoms j "below" i are excluded
// below = lower z or (equal z and lower y) or (equal zy and lower x)
// (equal zyx and j <= i)
// latter excludes self-self interaction but allows superposed atoms
ibin = coord2bin(x[i]);
for (k = 0; k < nstencil; k++) {
for (j = binhead[ibin+stencil[k]]; j >= 0; j = bins[j]) {
if (x[j][2] < ztmp) continue;
if (x[j][2] == ztmp) {
if (x[j][1] < ytmp) continue;
if (x[j][1] == ytmp) {
if (x[j][0] < xtmp) continue;
if (x[j][0] == xtmp && j <= i) continue;
}
}
jtype = type[j];
if (exclude && exclusion(i,j,itype,jtype,mask,molecule)) continue;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq <= cutneighsq[itype][jtype]) {
if (molecular) {
which = find_special(special[i],nspecial[i],tag[j]);
if (which >= 0) neighptr[n++] = j ^ (which << SBBITS);
} else neighptr[n++] = j;
if (rsq < cut_inner_sq) {
if (which == 0) neighptr_inner[n_inner++] = j;
else if (which > 0)
neighptr_inner[n_inner++] = j ^ (which << SBBITS);
}
if (respamiddle &&
rsq < cut_middle_sq && rsq > cut_middle_inside_sq) {
if (which == 0) neighptr_middle[n_middle++] = j;
else if (which > 0)
neighptr_middle[n_middle++] = j ^ (which << SBBITS);
}
}
}
}
ilist[inum] = i;
firstneigh[i] = neighptr;
numneigh[i] = n;
npnt += n;
if (n > oneatom || npnt >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
ilist_inner[inum] = i;
firstneigh_inner[i] = neighptr_inner;
numneigh_inner[i] = n_inner;
npnt_inner += n_inner;
if (npnt_inner >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
if (respamiddle) {
ilist_middle[inum] = i;
firstneigh_middle[i] = neighptr_middle;
numneigh_middle[i] = n_middle;
npnt_middle += n_middle;
if (npnt_middle >= pgsize)
- error->one("Neighbor list overflow, boost neigh_modify one or page");
+ error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page");
}
inum++;
}
list->inum = inum;
listinner->inum = inum;
if (respamiddle) listmiddle->inum = inum;
}
diff --git a/src/neighbor.cpp b/src/neighbor.cpp
index 141841d80..58f8ad94d 100644
--- a/src/neighbor.cpp
+++ b/src/neighbor.cpp
@@ -1,1749 +1,1746 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author (triclinic and multi-neigh) : Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "group.h"
#include "modify.h"
#include "fix.h"
#include "compute.h"
#include "update.h"
#include "respa.h"
#include "output.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define RQDELTA 1
#define EXDELTA 1
#define LB_FACTOR 1.5
#define SMALL 1.0e-6
#define BIG 1.0e20
#define CUT2BIN_RATIO 100
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
enum{NSQ,BIN,MULTI}; // also in neigh_list.cpp
//#define NEIGH_LIST_DEBUG 1
/* ---------------------------------------------------------------------- */
Neighbor::Neighbor(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
style = BIN;
every = 1;
delay = 10;
dist_check = 1;
pgsize = 100000;
oneatom = 2000;
binsizeflag = 0;
build_once = 0;
cutneighsq = NULL;
cutneighghostsq = NULL;
cuttype = NULL;
cuttypesq = NULL;
fixchecklist = NULL;
// coords at last neighboring
maxhold = 0;
xhold = NULL;
// binning
maxhead = 0;
binhead = NULL;
maxbin = 0;
bins = NULL;
// pair exclusion list info
includegroup = 0;
nex_type = maxex_type = 0;
ex1_type = ex2_type = NULL;
ex_type = NULL;
nex_group = maxex_group = 0;
ex1_group = ex2_group = ex1_bit = ex2_bit = NULL;
nex_mol = maxex_mol = 0;
ex_mol_group = ex_mol_bit = NULL;
// pair lists
maxatom = 0;
nblist = nglist = nslist = 0;
nlist = 0;
lists = NULL;
pair_build = NULL;
stencil_create = NULL;
blist = glist = slist = NULL;
anyghostlist = 0;
nrequest = maxrequest = 0;
requests = NULL;
old_style = BIN;
old_triclinic = 0;
old_nrequest = 0;
old_requests = NULL;
// bond lists
maxbond = 0;
bondlist = NULL;
maxangle = 0;
anglelist = NULL;
maxdihedral = 0;
dihedrallist = NULL;
maximproper = 0;
improperlist = NULL;
}
/* ---------------------------------------------------------------------- */
Neighbor::~Neighbor()
{
memory->destroy(cutneighsq);
memory->destroy(cutneighghostsq);
delete [] cuttype;
delete [] cuttypesq;
delete [] fixchecklist;
memory->destroy(xhold);
memory->destroy(binhead);
memory->destroy(bins);
memory->destroy(ex1_type);
memory->destroy(ex2_type);
memory->destroy(ex_type);
memory->destroy(ex1_group);
memory->destroy(ex2_group);
delete [] ex1_bit;
delete [] ex2_bit;
memory->destroy(ex_mol_group);
delete [] ex_mol_bit;
for (int i = 0; i < nlist; i++) delete lists[i];
delete [] lists;
delete [] pair_build;
delete [] stencil_create;
delete [] blist;
delete [] glist;
delete [] slist;
for (int i = 0; i < nrequest; i++) delete requests[i];
memory->sfree(requests);
for (int i = 0; i < old_nrequest; i++) delete old_requests[i];
memory->sfree(old_requests);
memory->destroy(bondlist);
memory->destroy(anglelist);
memory->destroy(dihedrallist);
memory->destroy(improperlist);
}
/* ---------------------------------------------------------------------- */
void Neighbor::init()
{
int i,j,m,n;
ncalls = ndanger = 0;
dimension = domain->dimension;
triclinic = domain->triclinic;
newton_pair = force->newton_pair;
// error check
if (delay > 0 && (delay % every) != 0)
- error->all("Neighbor delay must be 0 or multiple of every setting");
+ error->all(FLERR,"Neighbor delay must be 0 or multiple of every setting");
if (pgsize < 10*oneatom)
- error->all("Neighbor page size must be >= 10x the one atom setting");
+ error->all(FLERR,"Neighbor page size must be >= 10x the one atom setting");
// ------------------------------------------------------------------
// settings
// bbox lo/hi = bounding box of entire domain, stored by Domain
if (triclinic == 0) {
bboxlo = domain->boxlo;
bboxhi = domain->boxhi;
} else {
bboxlo = domain->boxlo_bound;
bboxhi = domain->boxhi_bound;
}
// set neighbor cutoffs (force cutoff + skin)
// trigger determines when atoms migrate and neighbor lists are rebuilt
// needs to be non-zero for migration distance check
// even if pair = NULL and no neighbor lists are used
// cutneigh = force cutoff + skin if cutforce > 0, else cutneigh = 0
triggersq = 0.25*skin*skin;
boxcheck = 0;
if (domain->box_change && (domain->xperiodic || domain->yperiodic ||
(dimension == 3 && domain->zperiodic)))
boxcheck = 1;
n = atom->ntypes;
if (cutneighsq == NULL) {
memory->create(cutneighsq,n+1,n+1,"neigh:cutneighsq");
memory->create(cutneighghostsq,n+1,n+1,"neigh:cutneighghostsq");
cuttype = new double[n+1];
cuttypesq = new double[n+1];
}
double cutoff,delta,cut;
cutneighmin = BIG;
cutneighmax = 0.0;
for (i = 1; i <= n; i++) {
cuttype[i] = cuttypesq[i] = 0.0;
for (j = 1; j <= n; j++) {
if (force->pair) cutoff = sqrt(force->pair->cutsq[i][j]);
else cutoff = 0.0;
if (cutoff > 0.0) delta = skin;
else delta = 0.0;
cut = cutoff + delta;
cutneighsq[i][j] = cut*cut;
cuttype[i] = MAX(cuttype[i],cut);
cuttypesq[i] = MAX(cuttypesq[i],cut*cut);
cutneighmin = MIN(cutneighmin,cut);
cutneighmax = MAX(cutneighmax,cut);
if (force->pair && force->pair->ghostneigh) {
cut = force->pair->cutghost[i][j] + skin;
cutneighghostsq[i][j] = cut*cut;
}
}
}
cutneighmaxsq = cutneighmax * cutneighmax;
// check other classes that can induce reneighboring in decide()
// don't check if build_once is set
restart_check = 0;
if (output->restart_every) restart_check = 1;
delete [] fixchecklist;
fixchecklist = NULL;
fixchecklist = new int[modify->nfix];
fix_check = 0;
for (i = 0; i < modify->nfix; i++)
if (modify->fix[i]->force_reneighbor)
fixchecklist[fix_check++] = i;
must_check = 0;
if (restart_check || fix_check) must_check = 1;
if (build_once) must_check = 0;
// set special_flag for 1-2, 1-3, 1-4 neighbors
// flag[0] is not used, flag[1] = 1-2, flag[2] = 1-3, flag[3] = 1-4
// flag = 0 if both LJ/Coulomb special values are 0.0
// flag = 1 if both LJ/Coulomb special values are 1.0
// flag = 2 otherwise or if KSpace solver is enabled
// pairwise portion of KSpace solver uses all 1-2,1-3,1-4 neighbors
if (force->special_lj[1] == 0.0 && force->special_coul[1] == 0.0)
special_flag[1] = 0;
else if (force->special_lj[1] == 1.0 && force->special_coul[1] == 1.0)
special_flag[1] = 1;
else special_flag[1] = 2;
if (force->special_lj[2] == 0.0 && force->special_coul[2] == 0.0)
special_flag[2] = 0;
else if (force->special_lj[2] == 1.0 && force->special_coul[2] == 1.0)
special_flag[2] = 1;
else special_flag[2] = 2;
if (force->special_lj[3] == 0.0 && force->special_coul[3] == 0.0)
special_flag[3] = 0;
else if (force->special_lj[3] == 1.0 && force->special_coul[3] == 1.0)
special_flag[3] = 1;
else special_flag[3] = 2;
if (force->kspace) special_flag[1] = special_flag[2] = special_flag[3] = 2;
// maxwt = max multiplicative factor on atom indices stored in neigh list
maxwt = 0;
if (special_flag[1] == 2) maxwt = 2;
if (special_flag[2] == 2) maxwt = 3;
if (special_flag[3] == 2) maxwt = 4;
// rRESPA cutoffs
int respa = 0;
if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) {
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
}
if (respa) {
double *cut_respa = ((Respa *) update->integrate)->cutoff;
cut_inner_sq = (cut_respa[1] + skin) * (cut_respa[1] + skin);
cut_middle_sq = (cut_respa[3] + skin) * (cut_respa[3] + skin);
cut_middle_inside_sq = (cut_respa[0] - skin) * (cut_respa[0] - skin);
}
// ------------------------------------------------------------------
// xhold, bins, exclusion lists
// free xhold and bins if not needed for this run
if (dist_check == 0) {
memory->destroy(xhold);
maxhold = 0;
xhold = NULL;
}
if (style == NSQ) {
memory->destroy(bins);
memory->destroy(binhead);
maxbin = maxhead = 0;
binhead = NULL;
bins = NULL;
}
// 1st time allocation of xhold and bins
if (dist_check) {
if (maxhold == 0) {
maxhold = atom->nmax;
memory->create(xhold,maxhold,3,"neigh:xhold");
}
}
if (style != NSQ) {
if (maxbin == 0) {
maxbin = atom->nmax;
memory->create(bins,maxbin,"bins");
}
}
// exclusion lists for type, group, molecule settings from neigh_modify
n = atom->ntypes;
if (nex_type == 0 && nex_group == 0 && nex_mol == 0) exclude = 0;
else exclude = 1;
if (nex_type) {
memory->destroy(ex_type);
memory->create(ex_type,n+1,n+1,"neigh:ex_type");
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
ex_type[i][j] = 0;
for (i = 0; i < nex_type; i++) {
if (ex1_type[i] <= 0 || ex1_type[i] > n ||
ex2_type[i] <= 0 || ex2_type[i] > n)
- error->all("Invalid atom type in neighbor exclusion list");
+ error->all(FLERR,"Invalid atom type in neighbor exclusion list");
ex_type[ex1_type[i]][ex2_type[i]] = 1;
ex_type[ex2_type[i]][ex1_type[i]] = 1;
}
}
if (nex_group) {
delete [] ex1_bit;
delete [] ex2_bit;
ex1_bit = new int[nex_group];
ex2_bit = new int[nex_group];
for (i = 0; i < nex_group; i++) {
ex1_bit[i] = group->bitmask[ex1_group[i]];
ex2_bit[i] = group->bitmask[ex2_group[i]];
}
}
if (nex_mol) {
delete [] ex_mol_bit;
ex_mol_bit = new int[nex_mol];
for (i = 0; i < nex_mol; i++)
ex_mol_bit[i] = group->bitmask[ex_mol_group[i]];
}
// ------------------------------------------------------------------
// pairwise lists
// test if pairwise lists need to be re-created
// no need to re-create if:
// neigh style and triclinic has not changed and
// current requests = old requests
int same = 1;
if (style != old_style) same = 0;
if (triclinic != old_triclinic) same = 0;
if (nrequest != old_nrequest) same = 0;
else
for (i = 0; i < nrequest; i++)
if (requests[i]->identical(old_requests[i]) == 0) same = 0;
#ifdef NEIGH_LIST_DEBUG
if (comm->me == 0) printf("SAME flag %d\n",same);
#endif
// if old and new are not the same, create new pairwise lists
if (!same) {
// delete old lists and create new ones
for (i = 0; i < nlist; i++) delete lists[i];
delete [] lists;
delete [] pair_build;
delete [] stencil_create;
nlist = nrequest;
lists = new NeighList*[nlist];
pair_build = new PairPtr[nlist];
stencil_create = new StencilPtr[nlist];
// create individual lists, one per request
// copy dnum setting from request to list
// pass list ptr back to requestor (except for Command class)
for (i = 0; i < nlist; i++) {
lists[i] = new NeighList(lmp,pgsize);
lists[i]->index = i;
lists[i]->dnum = requests[i]->dnum;
if (requests[i]->pair) {
Pair *pair = (Pair *) requests[i]->requestor;
pair->init_list(requests[i]->id,lists[i]);
} else if (requests[i]->fix) {
Fix *fix = (Fix *) requests[i]->requestor;
fix->init_list(requests[i]->id,lists[i]);
} else if (requests[i]->compute) {
Compute *compute = (Compute *) requests[i]->requestor;
compute->init_list(requests[i]->id,lists[i]);
}
}
// detect lists that are connected to other lists
// if-then-else sequence is important
// since don't want to re-process skip or copy lists further down
// copy: point this list at request->otherlist, could be a skip list
// skip: point this list at request->otherlist, copy skip info from request
// half_from_full: point this list at preceeding full list
// granhistory: set preceeding list's listgranhistory to this list
// also set preceeding list's ptr to FixShearHistory
// respaouter: point this list at preceeding 1/2 inner/middle lists
// pair and half: if there is a full non-occasional non-skip list
// change this list to half_from_full and point at the full list
// parent could be copy list or pair or fix
// fix/compute requests:
// kind of request = half or full, occasional or not doesn't matter
// if request = half and non-skip pair half/respaouter exists,
// become copy of that list if cudable flag matches
// if request = full and non-skip pair full exists,
// become copy of that list if cudable flag matches
// if request = half and non-skip pair full exists,
// become half_from_full of that list if cudable flag matches
// if no matches, do nothing, fix/compute list will be built directly
// ok if parent is copy list
for (i = 0; i < nlist; i++) {
if (requests[i]->copy)
lists[i]->listcopy = lists[requests[i]->otherlist];
else if (requests[i]->skip) {
lists[i]->listskip = lists[requests[i]->otherlist];
lists[i]->copy_skip_info(requests[i]->iskip,requests[i]->ijskip);
} else if (requests[i]->half_from_full)
lists[i]->listfull = lists[i-1];
else if (requests[i]->granhistory) {
lists[i-1]->listgranhistory = lists[i];
for (int ifix = 0; ifix < modify->nfix; ifix++)
if (strcmp(modify->fix[ifix]->style,"SHEAR_HISTORY") == 0)
lists[i-1]->fix_history = (FixShearHistory *) modify->fix[ifix];
} else if (requests[i]->respaouter) {
if (requests[i-1]->respainner) {
lists[i]->respamiddle = 0;
lists[i]->listinner = lists[i-1];
} else {
lists[i]->respamiddle = 1;
lists[i]->listmiddle = lists[i-1];
lists[i]->listinner = lists[i-2];
}
} else if (requests[i]->pair && requests[i]->half) {
for (j = 0; j < nlist; j++)
if (requests[j]->full && requests[j]->occasional == 0 &&
requests[j]->skip == 0) break;
if (j < nlist) {
requests[i]->half = 0;
requests[i]->half_from_full = 1;
lists[i]->listfull = lists[j];
}
} else if (requests[i]->fix || requests[i]->compute) {
for (j = 0; j < nlist; j++) {
if (requests[i]->half && requests[j]->pair &&
requests[j]->skip == 0 && requests[j]->half) break;
if (requests[i]->full && requests[j]->pair &&
requests[j]->skip == 0 && requests[j]->full) break;
if (requests[i]->half && requests[j]->pair &&
requests[j]->skip == 0 && requests[j]->respaouter) break;
}
if (j < nlist && requests[j]->cudable != requests[i]->cudable)
j = nlist;
if (j < nlist) {
requests[i]->copy = 1;
lists[i]->listcopy = lists[j];
} else {
for (j = 0; j < nlist; j++) {
if (requests[i]->half && requests[j]->pair &&
requests[j]->skip == 0 && requests[j]->full) break;
}
if (j < nlist && requests[j]->cudable != requests[i]->cudable)
j = nlist;
if (j < nlist) {
requests[i]->half = 0;
requests[i]->half_from_full = 1;
lists[i]->listfull = lists[j];
}
}
}
}
// set ptrs to pair_build and stencil_create functions for each list
// ptrs set to NULL if not set explicitly
// also set cudable to 0 if any neigh list request is not cudable
for (i = 0; i < nlist; i++) {
choose_build(i,requests[i]);
if (style != NSQ) choose_stencil(i,requests[i]);
else stencil_create[i] = NULL;
if (!requests[i]->cudable) cudable = 0;
}
// set each list's build/grow/stencil/ghost flags based on neigh request
// buildflag = 1 if its pair_build() invoked every reneighbor
// growflag = 1 if it stores atom-based arrays and pages
// stencilflag = 1 if it stores stencil arrays
// ghostflag = 1 if it stores neighbors of ghosts
// anyghostlist = 1 if any non-occasional list stores neighbors of ghosts
anyghostlist = 0;
for (i = 0; i < nlist; i++) {
lists[i]->buildflag = 1;
if (pair_build[i] == NULL) lists[i]->buildflag = 0;
if (requests[i]->occasional) lists[i]->buildflag = 0;
lists[i]->growflag = 1;
if (requests[i]->copy) lists[i]->growflag = 0;
lists[i]->stencilflag = 1;
if (style == NSQ) lists[i]->stencilflag = 0;
if (stencil_create[i] == NULL) lists[i]->stencilflag = 0;
lists[i]->ghostflag = 0;
if (requests[i]->ghost) lists[i]->ghostflag = 1;
if (requests[i]->ghost && !requests[i]->occasional) anyghostlist = 1;
}
#ifdef NEIGH_LIST_DEBUG
for (i = 0; i < nlist; i++) lists[i]->print_attributes();
#endif
// allocate atom arrays and 1st pages of lists that store them
maxatom = atom->nmax;
for (i = 0; i < nlist; i++)
if (lists[i]->growflag) {
lists[i]->grow(maxatom);
lists[i]->add_pages();
}
// setup 3 vectors of pairwise neighbor lists
// blist = lists whose pair_build() is invoked every reneighbor
// glist = lists who store atom arrays which are used every reneighbor
// slist = lists who store stencil arrays which are used every reneighbor
// blist and glist vectors are used by neighbor::build()
// slist vector is used by neighbor::setup_bins()
nblist = nglist = nslist = 0;
delete [] blist;
delete [] glist;
delete [] slist;
blist = new int[nlist];
glist = new int[nlist];
slist = new int[nlist];
for (i = 0; i < nlist; i++) {
if (lists[i]->buildflag) blist[nblist++] = i;
if (lists[i]->growflag && requests[i]->occasional == 0)
glist[nglist++] = i;
if (lists[i]->stencilflag && requests[i]->occasional == 0)
slist[nslist++] = i;
}
#ifdef NEIGH_LIST_DEBUG
print_lists_of_lists();
#endif
// reorder build vector if necessary
// relevant for lists that copy/skip/half-full from parent
// the derived list must appear in blist after the parent list
// no occasional lists are in build vector
// swap two lists within blist when dependency is mis-ordered
// done when entire pass thru blist results in no swaps
int done = 0;
while (!done) {
done = 1;
for (i = 0; i < nblist; i++) {
NeighList *ptr = NULL;
if (lists[blist[i]]->listfull) ptr = lists[blist[i]]->listfull;
if (lists[blist[i]]->listcopy) ptr = lists[blist[i]]->listcopy;
if (lists[blist[i]]->listskip) ptr = lists[blist[i]]->listskip;
if (ptr == NULL) continue;
for (m = 0; m < nlist; m++)
if (ptr == lists[m]) break;
for (j = 0; j < nblist; j++)
if (m == blist[j]) break;
if (j < i) continue;
int tmp = blist[i];
blist[i] = blist[j];
blist[j] = tmp;
done = 0;
break;
}
}
#ifdef NEIGH_LIST_DEBUG
print_lists_of_lists();
#endif
}
// delete old requests
// copy current requests and style to old for next run
for (i = 0; i < old_nrequest; i++) delete old_requests[i];
memory->sfree(old_requests);
old_nrequest = nrequest;
old_requests = requests;
nrequest = maxrequest = 0;
requests = NULL;
old_style = style;
old_triclinic = triclinic;
// ------------------------------------------------------------------
// topology lists
// 1st time allocation of topology lists
if (atom->molecular && atom->nbonds && maxbond == 0) {
if (nprocs == 1) maxbond = atom->nbonds;
else maxbond = static_cast<int> (LB_FACTOR * atom->nbonds / nprocs);
memory->create(bondlist,maxbond,3,"neigh:bondlist");
}
if (atom->molecular && atom->nangles && maxangle == 0) {
if (nprocs == 1) maxangle = atom->nangles;
else maxangle = static_cast<int> (LB_FACTOR * atom->nangles / nprocs);
memory->create(anglelist,maxangle,4,"neigh:anglelist");
}
if (atom->molecular && atom->ndihedrals && maxdihedral == 0) {
if (nprocs == 1) maxdihedral = atom->ndihedrals;
else maxdihedral = static_cast<int>
(LB_FACTOR * atom->ndihedrals / nprocs);
memory->create(dihedrallist,maxdihedral,5,"neigh:dihedrallist");
}
if (atom->molecular && atom->nimpropers && maximproper == 0) {
if (nprocs == 1) maximproper = atom->nimpropers;
else maximproper = static_cast<int>
(LB_FACTOR * atom->nimpropers / nprocs);
memory->create(improperlist,maximproper,5,"neigh:improperlist");
}
// set flags that determine which topology neighboring routines to use
// SHAKE sets bonds and angles negative
// bond_quartic sets bonds to 0
// delete_bonds sets all interactions negative
int bond_off = 0;
int angle_off = 0;
for (i = 0; i < modify->nfix; i++)
if (strcmp(modify->fix[i]->style,"shake") == 0)
bond_off = angle_off = 1;
if (force->bond && force->bond_match("quartic")) bond_off = 1;
if (atom->avec->bonds_allow) {
for (i = 0; i < atom->nlocal; i++) {
if (bond_off) break;
for (m = 0; m < atom->num_bond[i]; m++)
if (atom->bond_type[i][m] <= 0) bond_off = 1;
}
}
if (atom->avec->angles_allow) {
for (i = 0; i < atom->nlocal; i++) {
if (angle_off) break;
for (m = 0; m < atom->num_angle[i]; m++)
if (atom->angle_type[i][m] <= 0) angle_off = 1;
}
}
int dihedral_off = 0;
if (atom->avec->dihedrals_allow) {
for (i = 0; i < atom->nlocal; i++) {
if (dihedral_off) break;
for (m = 0; m < atom->num_dihedral[i]; m++)
if (atom->dihedral_type[i][m] <= 0) dihedral_off = 1;
}
}
int improper_off = 0;
if (atom->avec->impropers_allow) {
for (i = 0; i < atom->nlocal; i++) {
if (improper_off) break;
for (m = 0; m < atom->num_improper[i]; m++)
if (atom->improper_type[i][m] <= 0) improper_off = 1;
}
}
// set ptrs to topology build functions
if (bond_off) bond_build = &Neighbor::bond_partial;
else bond_build = &Neighbor::bond_all;
if (angle_off) angle_build = &Neighbor::angle_partial;
else angle_build = &Neighbor::angle_all;
if (dihedral_off) dihedral_build = &Neighbor::dihedral_partial;
else dihedral_build = &Neighbor::dihedral_all;
if (improper_off) improper_build = &Neighbor::improper_partial;
else improper_build = &Neighbor::improper_all;
// set topology neighbor list counts to 0
// in case all are turned off but potential is still defined
nbondlist = nanglelist = ndihedrallist = nimproperlist = 0;
}
/* ---------------------------------------------------------------------- */
int Neighbor::request(void *requestor)
{
if (nrequest == maxrequest) {
maxrequest += RQDELTA;
requests = (NeighRequest **)
memory->srealloc(requests,maxrequest*sizeof(NeighRequest *),
"neighbor:requests");
}
requests[nrequest] = new NeighRequest(lmp);
requests[nrequest]->requestor = requestor;
nrequest++;
return nrequest-1;
}
/* ----------------------------------------------------------------------
determine which pair_build function each neigh list needs
based on settings of neigh request
copy -> copy_from function
skip -> granular function if gran with granhistory,
respa function if respaouter,
skip_from function for everything else
half_from_full, half, full, gran, respaouter ->
choose by newton and rq->newton and tri settings
style NSQ options = newton off, newton on
style BIN options = newton off, newton on and not tri, newton on and tri
stlye MULTI options = same options as BIN
if none of these, ptr = NULL since pair_build is not invoked for this list
use "else if" b/c skip,copy can be set in addition to half,full,etc
------------------------------------------------------------------------- */
void Neighbor::choose_build(int index, NeighRequest *rq)
{
PairPtr pb = NULL;
if (rq->copy) pb = &Neighbor::copy_from;
else if (rq->skip) {
if (rq->gran && lists[index]->listgranhistory)
pb = &Neighbor::skip_from_granular;
else if (rq->respaouter) pb = &Neighbor::skip_from_respa;
else pb = &Neighbor::skip_from;
} else if (rq->half_from_full) {
if (newton_pair == 0) pb = &Neighbor::half_from_full_no_newton;
else if (newton_pair == 1) pb = &Neighbor::half_from_full_newton;
} else if (rq->half) {
if (style == NSQ) {
if (rq->newton == 0) {
if (newton_pair == 0) pb = &Neighbor::half_nsq_no_newton;
else if (newton_pair == 1) pb = &Neighbor::half_nsq_newton;
} else if (rq->newton == 1) {
pb = &Neighbor::half_nsq_newton;
} else if (rq->newton == 2) {
pb = &Neighbor::half_nsq_no_newton;
}
} else if (style == BIN) {
if (rq->newton == 0) {
if (newton_pair == 0) pb = &Neighbor::half_bin_no_newton;
else if (triclinic == 0) pb = &Neighbor::half_bin_newton;
else if (triclinic == 1) pb = &Neighbor::half_bin_newton_tri;
} else if (rq->newton == 1) {
if (triclinic == 0) pb = &Neighbor::half_bin_newton;
else if (triclinic == 1) pb = &Neighbor::half_bin_newton_tri;
} else if (rq->newton == 2) pb = &Neighbor::half_bin_no_newton;
} else if (style == MULTI) {
if (rq->newton == 0) {
if (newton_pair == 0) pb = &Neighbor::half_multi_no_newton;
else if (triclinic == 0) pb = &Neighbor::half_multi_newton;
else if (triclinic == 1) pb = &Neighbor::half_multi_newton_tri;
} else if (rq->newton == 1) {
if (triclinic == 0) pb = &Neighbor::half_multi_newton;
else if (triclinic == 1) pb = &Neighbor::half_multi_newton_tri;
} else if (rq->newton == 2) pb = &Neighbor::half_multi_no_newton;
}
} else if (rq->full) {
if (style == NSQ) {
if (rq->ghost == 0) pb = &Neighbor::full_nsq;
else if (includegroup)
- error->all("Neighbor include group not allowed with ghost neighbors");
+ error->all(FLERR,"Neighbor include group not allowed with ghost neighbors");
else if (rq->ghost == 1) pb = &Neighbor::full_nsq_ghost;
} else if (style == BIN) {
if (rq->ghost == 0) pb = &Neighbor::full_bin;
else if (includegroup)
- error->all("Neighbor include group not allowed with ghost neighbors");
+ error->all(FLERR,"Neighbor include group not allowed with ghost neighbors");
else if (rq->ghost == 1) pb = &Neighbor::full_bin_ghost;
} else if (style == MULTI) {
if (rq->ghost == 0) pb = &Neighbor::full_multi;
- else error->all("Neighbor multi not yet enabled for ghost neighbors");
+ else error->all(FLERR,"Neighbor multi not yet enabled for ghost neighbors");
}
} else if (rq->gran) {
if (style == NSQ) {
if (newton_pair == 0) pb = &Neighbor::granular_nsq_no_newton;
else if (newton_pair == 1) pb = &Neighbor::granular_nsq_newton;
} else if (style == BIN) {
if (newton_pair == 0) pb = &Neighbor::granular_bin_no_newton;
else if (triclinic == 0) pb = &Neighbor::granular_bin_newton;
else if (triclinic == 1) pb = &Neighbor::granular_bin_newton_tri;
} else if (style == MULTI)
- error->all("Neighbor multi not yet enabled for granular");
+ error->all(FLERR,"Neighbor multi not yet enabled for granular");
} else if (rq->respaouter) {
if (style == NSQ) {
if (newton_pair == 0) pb = &Neighbor::respa_nsq_no_newton;
else if (newton_pair == 1) pb = &Neighbor::respa_nsq_newton;
} else if (style == BIN) {
if (newton_pair == 0) pb = &Neighbor::respa_bin_no_newton;
else if (triclinic == 0) pb = &Neighbor::respa_bin_newton;
else if (triclinic == 1) pb = &Neighbor::respa_bin_newton_tri;
} else if (style == MULTI)
- error->all("Neighbor multi not yet enabled for rRESPA");
+ error->all(FLERR,"Neighbor multi not yet enabled for rRESPA");
}
// general error check
if (rq->ghost && !rq->full)
- error->all("Neighbors of ghost atoms only allowed for full neighbor lists");
+ error->all(FLERR,"Neighbors of ghost atoms only allowed for full neighbor lists");
pair_build[index] = pb;
}
/* ----------------------------------------------------------------------
determine which stencil_create function each neigh list needs
based on settings of neigh request, only called if style != NSQ
skip or copy or half_from_full -> no stencil
half, gran, respaouter, full -> choose by newton and tri and dimension
if none of these, ptr = NULL since this list needs no stencils
use "else if" b/c skip,copy can be set in addition to half,full,etc
------------------------------------------------------------------------- */
void Neighbor::choose_stencil(int index, NeighRequest *rq)
{
StencilPtr sc = NULL;
if (rq->skip || rq->copy || rq->half_from_full) sc = NULL;
else if (rq->half || rq->gran || rq->respaouter) {
if (style == BIN) {
if (rq->newton == 0) {
if (newton_pair == 0) {
if (dimension == 2)
sc = &Neighbor::stencil_half_bin_2d_no_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_bin_3d_no_newton;
} else if (triclinic == 0) {
if (dimension == 2)
sc = &Neighbor::stencil_half_bin_2d_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_bin_3d_newton;
} else if (triclinic == 1) {
if (dimension == 2)
sc = &Neighbor::stencil_half_bin_2d_newton_tri;
else if (dimension == 3)
sc = &Neighbor::stencil_half_bin_3d_newton_tri;
}
} else if (rq->newton == 1) {
if (triclinic == 0) {
if (dimension == 2)
sc = &Neighbor::stencil_half_bin_2d_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_bin_3d_newton;
} else if (triclinic == 1) {
if (dimension == 2)
sc = &Neighbor::stencil_half_bin_2d_newton_tri;
else if (dimension == 3)
sc = &Neighbor::stencil_half_bin_3d_newton_tri;
}
} else if (rq->newton == 2) {
if (dimension == 2)
sc = &Neighbor::stencil_half_bin_2d_no_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_bin_3d_no_newton;
}
} else if (style == MULTI) {
if (rq->newton == 0) {
if (newton_pair == 0) {
if (dimension == 2)
sc = &Neighbor::stencil_half_multi_2d_no_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_multi_3d_no_newton;
} else if (triclinic == 0) {
if (dimension == 2)
sc = &Neighbor::stencil_half_multi_2d_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_multi_3d_newton;
} else if (triclinic == 1) {
if (dimension == 2)
sc = &Neighbor::stencil_half_multi_2d_newton_tri;
else if (dimension == 3)
sc = &Neighbor::stencil_half_multi_3d_newton_tri;
}
} else if (rq->newton == 1) {
if (triclinic == 0) {
if (dimension == 2)
sc = &Neighbor::stencil_half_multi_2d_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_multi_3d_newton;
} else if (triclinic == 1) {
if (dimension == 2)
sc = &Neighbor::stencil_half_multi_2d_newton_tri;
else if (dimension == 3)
sc = &Neighbor::stencil_half_multi_3d_newton_tri;
}
} else if (rq->newton == 2) {
if (dimension == 2)
sc = &Neighbor::stencil_half_multi_2d_no_newton;
else if (dimension == 3)
sc = &Neighbor::stencil_half_multi_3d_no_newton;
}
}
} else if (rq->full) {
if (style == BIN) {
if (dimension == 2) {
if (rq->ghost) sc = &Neighbor::stencil_full_ghost_bin_2d;
else sc = &Neighbor::stencil_full_bin_2d;
}
else if (dimension == 3) {
if (rq->ghost) sc = &Neighbor::stencil_full_ghost_bin_3d;
else sc = &Neighbor::stencil_full_bin_3d;
}
} else if (style == MULTI) {
if (dimension == 2) sc = &Neighbor::stencil_full_multi_2d;
else if (dimension == 3) sc = &Neighbor::stencil_full_multi_3d;
}
}
stencil_create[index] = sc;
}
/* ---------------------------------------------------------------------- */
void Neighbor::print_lists_of_lists()
{
if (comm->me == 0) {
printf("Build lists = %d: ",nblist);
for (int i = 0; i < nblist; i++) printf("%d ",blist[i]);
printf("\n");
printf("Grow lists = %d: ",nglist);
for (int i = 0; i < nglist; i++) printf("%d ",glist[i]);
printf("\n");
printf("Stencil lists = %d: ",nslist);
for (int i = 0; i < nslist; i++) printf("%d ",slist[i]);
printf("\n");
}
}
/* ---------------------------------------------------------------------- */
int Neighbor::decide()
{
if (must_check) {
int n = update->ntimestep;
if (restart_check && n == output->next_restart) return 1;
for (int i = 0; i < fix_check; i++)
if (n == modify->fix[fixchecklist[i]]->next_reneighbor) return 1;
}
ago++;
if (ago >= delay && ago % every == 0) {
if (build_once) return 0;
if (dist_check == 0) return 1;
return check_distance();
} else return 0;
}
/* ----------------------------------------------------------------------
if any atom moved trigger distance (half of neighbor skin) return 1
shrink trigger distance if box size has changed
conservative shrink procedure:
compute distance each of 8 corners of box has moved since last reneighbor
reduce skin distance by sum of 2 largest of the 8 values
new trigger = 1/2 of reduced skin distance
for orthogonal box, only need 2 lo/hi corners
for triclinic, need all 8 corners since deformations can displace all 8
------------------------------------------------------------------------- */
int Neighbor::check_distance()
{
double delx,dely,delz,rsq;
double delta,deltasq,delta1,delta2;
if (boxcheck) {
if (triclinic == 0) {
delx = bboxlo[0] - boxlo_hold[0];
dely = bboxlo[1] - boxlo_hold[1];
delz = bboxlo[2] - boxlo_hold[2];
delta1 = sqrt(delx*delx + dely*dely + delz*delz);
delx = bboxhi[0] - boxhi_hold[0];
dely = bboxhi[1] - boxhi_hold[1];
delz = bboxhi[2] - boxhi_hold[2];
delta2 = sqrt(delx*delx + dely*dely + delz*delz);
delta = 0.5 * (skin - (delta1+delta2));
deltasq = delta*delta;
} else {
domain->box_corners();
delta1 = delta2 = 0.0;
for (int i = 0; i < 8; i++) {
delx = corners[i][0] - corners_hold[i][0];
dely = corners[i][1] - corners_hold[i][1];
delz = corners[i][2] - corners_hold[i][2];
delta = sqrt(delx*delx + dely*dely + delz*delz);
if (delta > delta1) delta1 = delta;
else if (delta > delta2) delta2 = delta;
}
delta = 0.5 * (skin - (delta1+delta2));
deltasq = delta*delta;
}
} else deltasq = triggersq;
double **x = atom->x;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
int flag = 0;
for (int i = 0; i < nlocal; i++) {
delx = x[i][0] - xhold[i][0];
dely = x[i][1] - xhold[i][1];
delz = x[i][2] - xhold[i][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq > deltasq) flag = 1;
}
int flagall;
MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_MAX,world);
if (flagall && ago == MAX(every,delay)) ndanger++;
return flagall;
}
/* ----------------------------------------------------------------------
build all perpetual neighbor lists every few timesteps
pairwise & topology lists are created as needed
------------------------------------------------------------------------- */
void Neighbor::build()
{
int i;
ago = 0;
ncalls++;
// store current atom positions and box size if needed
if (dist_check) {
double **x = atom->x;
int nlocal = atom->nlocal;
if (includegroup) nlocal = atom->nfirst;
if (nlocal > maxhold) {
maxhold = atom->nmax;
memory->destroy(xhold);
memory->create(xhold,maxhold,3,"neigh:xhold");
}
for (i = 0; i < nlocal; i++) {
xhold[i][0] = x[i][0];
xhold[i][1] = x[i][1];
xhold[i][2] = x[i][2];
}
if (boxcheck) {
if (triclinic == 0) {
boxlo_hold[0] = bboxlo[0];
boxlo_hold[1] = bboxlo[1];
boxlo_hold[2] = bboxlo[2];
boxhi_hold[0] = bboxhi[0];
boxhi_hold[1] = bboxhi[1];
boxhi_hold[2] = bboxhi[2];
} else {
domain->box_corners();
corners = domain->corners;
for (i = 0; i < 8; i++) {
corners_hold[i][0] = corners[i][0];
corners_hold[i][1] = corners[i][1];
corners_hold[i][2] = corners[i][2];
}
}
}
}
// if any lists store neighbors of ghosts:
// invoke grow() if nlocal+nghost exceeds previous list size
// else only invoke grow() if nlocal exceeds previous list size
// only done for lists with growflag set and which are perpetual
if (anyghostlist && atom->nlocal+atom->nghost > maxatom) {
maxatom = atom->nmax;
for (i = 0; i < nglist; i++) lists[glist[i]]->grow(maxatom);
} else if (atom->nlocal > maxatom) {
maxatom = atom->nmax;
for (i = 0; i < nglist; i++) lists[glist[i]]->grow(maxatom);
}
// extend atom bin list if necessary
if (style != NSQ && atom->nmax > maxbin) {
maxbin = atom->nmax;
memory->destroy(bins);
memory->create(bins,maxbin,"bins");
}
// check that neighbor list with special bond flags will not overflow
if (atom->nlocal+atom->nghost > NEIGHMASK)
- error->one("Too many local+ghost atoms for neighbor list");
+ error->one(FLERR,"Too many local+ghost atoms for neighbor list");
// invoke building of pair and molecular neighbor lists
// only for pairwise lists with buildflag set
for (i = 0; i < nblist; i++)
(this->*pair_build[blist[i]])(lists[blist[i]]);
if (atom->molecular) {
if (force->bond) (this->*bond_build)();
if (force->angle) (this->*angle_build)();
if (force->dihedral) (this->*dihedral_build)();
if (force->improper) (this->*improper_build)();
}
}
/* ----------------------------------------------------------------------
build a single occasional pairwise neighbor list indexed by I
called by other classes
------------------------------------------------------------------------- */
void Neighbor::build_one(int i)
{
// update stencils and grow atom arrays and bins as needed
// only for relevant settings of stencilflag and growflag
// grow atom array for this list to current size of perpetual lists
if (lists[i]->stencilflag) {
lists[i]->stencil_allocate(smax,style);
(this->*stencil_create[i])(lists[i],sx,sy,sz);
}
if (lists[i]->growflag) lists[i]->grow(maxatom);
if (style != NSQ && atom->nmax > maxbin) {
maxbin = atom->nmax;
memory->destroy(bins);
memory->create(bins,maxbin,"bins");
}
// check that neighbor list with special bond flags will not overflow
if (atom->nlocal+atom->nghost > NEIGHMASK)
- error->one("Too many local+ghost atoms for neighbor list");
+ error->one(FLERR,"Too many local+ghost atoms for neighbor list");
// when occasional list built, LAMMPS can crash if atoms have moved too far
// why is this?, give warning if this is the case
// no easy workaround b/c all neighbor lists really need to be rebuilt
// solution is for input script to check more often for rebuild
// only check_distance if running a simulation, not between simulations
int flag = 0;
if (dist_check && update->whichflag) flag = check_distance();
if (flag && me == 0)
- error->warning("Building an occasional neighobr list when "
+ error->warning(FLERR,"Building an occasional neighobr list when "
"atoms may have moved too far");
(this->*pair_build[i])(lists[i]);
}
/* ----------------------------------------------------------------------
setup neighbor binning parameters
bin numbering in each dimension is global:
0 = 0.0 to binsize, 1 = binsize to 2*binsize, etc
nbin-1,nbin,etc = bbox-binsize to bbox, bbox to bbox+binsize, etc
-1,-2,etc = -binsize to 0.0, -2*binsize to -binsize, etc
code will work for any binsize
since next(xyz) and stencil extend as far as necessary
binsize = 1/2 of cutoff is roughly optimal
for orthogonal boxes:
a dim must be filled exactly by integer # of bins
in periodic, procs on both sides of PBC must see same bin boundary
in non-periodic, coord2bin() still assumes this by use of nbin xyz
for triclinic boxes:
tilted simulation box cannot contain integer # of bins
stencil & neigh list built differently to account for this
mbinlo = lowest global bin any of my ghost atoms could fall into
mbinhi = highest global bin any of my ghost atoms could fall into
mbin = number of bins I need in a dimension
------------------------------------------------------------------------- */
void Neighbor::setup_bins()
{
// bbox = size of bbox of entire domain
// bsubbox lo/hi = bounding box of my subdomain extended by comm->cutghost
// for triclinic:
// bbox bounds all 8 corners of tilted box
// subdomain is in lamda coords
// include dimension-dependent extension via comm->cutghost
// domain->bbox() converts lamda extent to box coords and computes bbox
double bbox[3],bsubboxlo[3],bsubboxhi[3];
double *cutghost = comm->cutghost;
if (triclinic == 0) {
bsubboxlo[0] = domain->sublo[0] - cutghost[0];
bsubboxlo[1] = domain->sublo[1] - cutghost[1];
bsubboxlo[2] = domain->sublo[2] - cutghost[2];
bsubboxhi[0] = domain->subhi[0] + cutghost[0];
bsubboxhi[1] = domain->subhi[1] + cutghost[1];
bsubboxhi[2] = domain->subhi[2] + cutghost[2];
} else {
double lo[3],hi[3];
lo[0] = domain->sublo_lamda[0] - cutghost[0];
lo[1] = domain->sublo_lamda[1] - cutghost[1];
lo[2] = domain->sublo_lamda[2] - cutghost[2];
hi[0] = domain->subhi_lamda[0] + cutghost[0];
hi[1] = domain->subhi_lamda[1] + cutghost[1];
hi[2] = domain->subhi_lamda[2] + cutghost[2];
domain->bbox(lo,hi,bsubboxlo,bsubboxhi);
}
bbox[0] = bboxhi[0] - bboxlo[0];
bbox[1] = bboxhi[1] - bboxlo[1];
bbox[2] = bboxhi[2] - bboxlo[2];
// optimal bin size is roughly 1/2 the cutoff
// for BIN style, binsize = 1/2 of max neighbor cutoff
// for MULTI style, binsize = 1/2 of min neighbor cutoff
// special case of all cutoffs = 0.0, binsize = box size
double binsize_optimal;
if (binsizeflag) binsize_optimal = binsize_user;
else if (style == BIN) binsize_optimal = 0.5*cutneighmax;
else binsize_optimal = 0.5*cutneighmin;
if (binsize_optimal == 0.0) binsize_optimal = bbox[0];
double binsizeinv = 1.0/binsize_optimal;
// test for too many global bins in any dimension due to huge global domain
if (bbox[0]*binsizeinv > MAXSMALLINT || bbox[1]*binsizeinv > MAXSMALLINT ||
bbox[2]*binsizeinv > MAXSMALLINT)
- error->all("Domain too large for neighbor bins");
+ error->all(FLERR,"Domain too large for neighbor bins");
// create actual bins
// always have one bin even if cutoff > bbox
// for 2d, nbinz = 1
nbinx = static_cast<int> (bbox[0]*binsizeinv);
nbiny = static_cast<int> (bbox[1]*binsizeinv);
if (dimension == 3) nbinz = static_cast<int> (bbox[2]*binsizeinv);
else nbinz = 1;
if (nbinx == 0) nbinx = 1;
if (nbiny == 0) nbiny = 1;
if (nbinz == 0) nbinz = 1;
// compute actual bin size for nbins to fit into box exactly
// error if actual bin size << cutoff, since will create a zillion bins
// this happens when nbin = 1 and box size << cutoff
// typically due to non-periodic, flat system in a particular dim
// in that extreme case, should use NSQ not BIN neighbor style
binsizex = bbox[0]/nbinx;
binsizey = bbox[1]/nbiny;
binsizez = bbox[2]/nbinz;
bininvx = 1.0 / binsizex;
bininvy = 1.0 / binsizey;
bininvz = 1.0 / binsizez;
if (binsize_optimal*bininvx > CUT2BIN_RATIO ||
binsize_optimal*bininvy > CUT2BIN_RATIO ||
binsize_optimal*bininvz > CUT2BIN_RATIO)
- error->all("Cannot use neighbor bins - box size << cutoff");
+ error->all(FLERR,"Cannot use neighbor bins - box size << cutoff");
// mbinlo/hi = lowest and highest global bins my ghost atoms could be in
// coord = lowest and highest values of coords for my ghost atoms
// static_cast(-1.5) = -1, so subract additional -1
// add in SMALL for round-off safety
int mbinxhi,mbinyhi,mbinzhi;
double coord;
coord = bsubboxlo[0] - SMALL*bbox[0];
mbinxlo = static_cast<int> ((coord-bboxlo[0])*bininvx);
if (coord < bboxlo[0]) mbinxlo = mbinxlo - 1;
coord = bsubboxhi[0] + SMALL*bbox[0];
mbinxhi = static_cast<int> ((coord-bboxlo[0])*bininvx);
coord = bsubboxlo[1] - SMALL*bbox[1];
mbinylo = static_cast<int> ((coord-bboxlo[1])*bininvy);
if (coord < bboxlo[1]) mbinylo = mbinylo - 1;
coord = bsubboxhi[1] + SMALL*bbox[1];
mbinyhi = static_cast<int> ((coord-bboxlo[1])*bininvy);
if (dimension == 3) {
coord = bsubboxlo[2] - SMALL*bbox[2];
mbinzlo = static_cast<int> ((coord-bboxlo[2])*bininvz);
if (coord < bboxlo[2]) mbinzlo = mbinzlo - 1;
coord = bsubboxhi[2] + SMALL*bbox[2];
mbinzhi = static_cast<int> ((coord-bboxlo[2])*bininvz);
}
// extend bins by 1 to insure stencil extent is included
// if 2d, only 1 bin in z
mbinxlo = mbinxlo - 1;
mbinxhi = mbinxhi + 1;
mbinx = mbinxhi - mbinxlo + 1;
mbinylo = mbinylo - 1;
mbinyhi = mbinyhi + 1;
mbiny = mbinyhi - mbinylo + 1;
if (dimension == 3) {
mbinzlo = mbinzlo - 1;
mbinzhi = mbinzhi + 1;
} else mbinzlo = mbinzhi = 0;
mbinz = mbinzhi - mbinzlo + 1;
// memory for bin ptrs
bigint bbin = mbinx*mbiny*mbinz;
- if (bbin > MAXSMALLINT) error->one("Too many neighbor bins");
+ if (bbin > MAXSMALLINT) error->one(FLERR,"Too many neighbor bins");
mbins = bbin;
if (mbins > maxhead) {
maxhead = mbins;
memory->destroy(binhead);
memory->create(binhead,maxhead,"neigh:binhead");
}
// create stencil of bins to search over in neighbor list construction
// sx,sy,sz = max range of stencil in each dim
// smax = max possible size of entire 3d stencil
// stencil is empty if cutneighmax = 0.0
sx = static_cast<int> (cutneighmax*bininvx);
if (sx*binsizex < cutneighmax) sx++;
sy = static_cast<int> (cutneighmax*bininvy);
if (sy*binsizey < cutneighmax) sy++;
sz = static_cast<int> (cutneighmax*bininvz);
if (sz*binsizez < cutneighmax) sz++;
if (dimension == 2) sz = 0;
smax = (2*sx+1) * (2*sy+1) * (2*sz+1);
// create stencils for pairwise neighbor lists
// only done for lists with stencilflag and buildflag set
for (int i = 0; i < nslist; i++) {
lists[slist[i]]->stencil_allocate(smax,style);
(this->*stencil_create[slist[i]])(lists[slist[i]],sx,sy,sz);
}
}
/* ----------------------------------------------------------------------
compute closest distance between central bin (0,0,0) and bin (i,j,k)
------------------------------------------------------------------------- */
double Neighbor::bin_distance(int i, int j, int k)
{
double delx,dely,delz;
if (i > 0) delx = (i-1)*binsizex;
else if (i == 0) delx = 0.0;
else delx = (i+1)*binsizex;
if (j > 0) dely = (j-1)*binsizey;
else if (j == 0) dely = 0.0;
else dely = (j+1)*binsizey;
if (k > 0) delz = (k-1)*binsizez;
else if (k == 0) delz = 0.0;
else delz = (k+1)*binsizez;
return (delx*delx + dely*dely + delz*delz);
}
/* ----------------------------------------------------------------------
set neighbor style and skin distance
------------------------------------------------------------------------- */
void Neighbor::set(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal neighbor command");
+ if (narg != 2) error->all(FLERR,"Illegal neighbor command");
skin = atof(arg[0]);
- if (skin < 0.0) error->all("Illegal neighbor command");
+ if (skin < 0.0) error->all(FLERR,"Illegal neighbor command");
if (strcmp(arg[1],"nsq") == 0) style = NSQ;
else if (strcmp(arg[1],"bin") == 0) style = BIN;
else if (strcmp(arg[1],"multi") == 0) style = MULTI;
- else error->all("Illegal neighbor command");
+ else error->all(FLERR,"Illegal neighbor command");
}
/* ----------------------------------------------------------------------
modify parameters of the pair-wise neighbor build
------------------------------------------------------------------------- */
void Neighbor::modify_params(int narg, char **arg)
{
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"every") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
every = atoi(arg[iarg+1]);
- if (every <= 0) error->all("Illegal neigh_modify command");
+ if (every <= 0) error->all(FLERR,"Illegal neigh_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"delay") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
delay = atoi(arg[iarg+1]);
- if (delay < 0) error->all("Illegal neigh_modify command");
+ if (delay < 0) error->all(FLERR,"Illegal neigh_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"check") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) dist_check = 1;
else if (strcmp(arg[iarg+1],"no") == 0) dist_check = 0;
- else error->all("Illegal neigh_modify command");
+ else error->all(FLERR,"Illegal neigh_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"once") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) build_once = 1;
else if (strcmp(arg[iarg+1],"no") == 0) build_once = 0;
- else error->all("Illegal neigh_modify command");
+ else error->all(FLERR,"Illegal neigh_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"page") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
pgsize = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"one") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
oneatom = atoi(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"binsize") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
binsize_user = atof(arg[iarg+1]);
if (binsize_user <= 0.0) binsizeflag = 0;
else binsizeflag = 1;
iarg += 2;
} else if (strcmp(arg[iarg],"include") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
includegroup = group->find(arg[iarg+1]);
if (includegroup < 0)
- error->all("Invalid group ID in neigh_modify command");
+ error->all(FLERR,"Invalid group ID in neigh_modify command");
if (includegroup && (atom->firstgroupname == NULL ||
strcmp(arg[iarg+1],atom->firstgroupname) != 0))
- error->all("Neigh_modify include group != atom_modify first group");
+ error->all(FLERR,"Neigh_modify include group != atom_modify first group");
iarg += 2;
} else if (strcmp(arg[iarg],"exclude") == 0) {
- if (iarg+2 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal neigh_modify command");
if (strcmp(arg[iarg+1],"type") == 0) {
- if (iarg+4 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal neigh_modify command");
if (nex_type == maxex_type) {
maxex_type += EXDELTA;
memory->grow(ex1_type,maxex_type,"neigh:ex1_type");
memory->grow(ex2_type,maxex_type,"neigh:ex2_type");
}
ex1_type[nex_type] = atoi(arg[iarg+2]);
ex2_type[nex_type] = atoi(arg[iarg+3]);
nex_type++;
iarg += 4;
} else if (strcmp(arg[iarg+1],"group") == 0) {
- if (iarg+4 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal neigh_modify command");
if (nex_group == maxex_group) {
maxex_group += EXDELTA;
memory->grow(ex1_group,maxex_group,"neigh:ex1_group");
memory->grow(ex2_group,maxex_group,"neigh:ex2_group");
}
ex1_group[nex_group] = group->find(arg[iarg+2]);
ex2_group[nex_group] = group->find(arg[iarg+3]);
if (ex1_group[nex_group] == -1 || ex2_group[nex_group] == -1)
- error->all("Invalid group ID in neigh_modify command");
+ error->all(FLERR,"Invalid group ID in neigh_modify command");
nex_group++;
iarg += 4;
} else if (strcmp(arg[iarg+1],"molecule") == 0) {
- if (iarg+3 > narg) error->all("Illegal neigh_modify command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal neigh_modify command");
if (atom->molecule_flag == 0) {
char *str = (char *)
"Neigh_modify exclude molecule requires atom attribute molecule";
- error->all(str);
+ error->all(FLERR,str);
}
if (nex_mol == maxex_mol) {
maxex_mol += EXDELTA;
memory->grow(ex_mol_group,maxex_mol,"neigh:ex_mol_group");
}
ex_mol_group[nex_mol] = group->find(arg[iarg+2]);
if (ex_mol_group[nex_mol] == -1)
- error->all("Invalid group ID in neigh_modify command");
+ error->all(FLERR,"Invalid group ID in neigh_modify command");
nex_mol++;
iarg += 3;
} else if (strcmp(arg[iarg+1],"none") == 0) {
nex_type = nex_group = nex_mol = 0;
iarg += 2;
- } else error->all("Illegal neigh_modify command");
+ } else error->all(FLERR,"Illegal neigh_modify command");
- } else error->all("Illegal neigh_modify command");
+ } else error->all(FLERR,"Illegal neigh_modify command");
}
}
/* ----------------------------------------------------------------------
bin owned and ghost atoms
------------------------------------------------------------------------- */
void Neighbor::bin_atoms()
{
int i,ibin;
for (i = 0; i < mbins; i++) binhead[i] = -1;
// bin in reverse order so linked list will be in forward order
// also puts ghost atoms at end of list, which is necessary
double **x = atom->x;
int *mask = atom->mask;
int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost;
if (includegroup) {
int bitmask = group->bitmask[includegroup];
for (i = nall-1; i >= nlocal; i--) {
if (mask[i] & bitmask) {
ibin = coord2bin(x[i]);
bins[i] = binhead[ibin];
binhead[ibin] = i;
}
}
for (i = atom->nfirst-1; i >= 0; i--) {
ibin = coord2bin(x[i]);
bins[i] = binhead[ibin];
binhead[ibin] = i;
}
} else {
for (i = nall-1; i >= 0; i--) {
ibin = coord2bin(x[i]);
bins[i] = binhead[ibin];
binhead[ibin] = i;
}
}
}
/* ----------------------------------------------------------------------
convert atom coords into local bin #
for orthogonal, only ghost atoms will have coord >= bboxhi or coord < bboxlo
take special care to insure ghosts are in correct bins even w/ roundoff
hi ghost atoms = nbin,nbin+1,etc
owned atoms = 0 to nbin-1
lo ghost atoms = -1,-2,etc
this is necessary so that both procs on either side of PBC
treat a pair of atoms straddling the PBC in a consistent way
for triclinic, doesn't matter since stencil & neigh list built differently
------------------------------------------------------------------------- */
int Neighbor::coord2bin(double *x)
{
int ix,iy,iz;
if (x[0] >= bboxhi[0])
ix = static_cast<int> ((x[0]-bboxhi[0])*bininvx) + nbinx;
else if (x[0] >= bboxlo[0]) {
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx);
ix = MIN(ix,nbinx-1);
} else
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx) - 1;
if (x[1] >= bboxhi[1])
iy = static_cast<int> ((x[1]-bboxhi[1])*bininvy) + nbiny;
else if (x[1] >= bboxlo[1]) {
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy);
iy = MIN(iy,nbiny-1);
} else
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy) - 1;
if (x[2] >= bboxhi[2])
iz = static_cast<int> ((x[2]-bboxhi[2])*bininvz) + nbinz;
else if (x[2] >= bboxlo[2]) {
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz);
iz = MIN(iz,nbinz-1);
} else
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz) - 1;
return (iz-mbinzlo)*mbiny*mbinx + (iy-mbinylo)*mbinx + (ix-mbinxlo);
}
/* ----------------------------------------------------------------------
same as coord2bin, but also return ix,iy,iz offsets in each dim
------------------------------------------------------------------------- */
int Neighbor::coord2bin(double *x, int &ix, int &iy, int &iz)
{
if (x[0] >= bboxhi[0])
ix = static_cast<int> ((x[0]-bboxhi[0])*bininvx) + nbinx;
else if (x[0] >= bboxlo[0]) {
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx);
ix = MIN(ix,nbinx-1);
} else
ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx) - 1;
if (x[1] >= bboxhi[1])
iy = static_cast<int> ((x[1]-bboxhi[1])*bininvy) + nbiny;
else if (x[1] >= bboxlo[1]) {
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy);
iy = MIN(iy,nbiny-1);
} else
iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy) - 1;
if (x[2] >= bboxhi[2])
iz = static_cast<int> ((x[2]-bboxhi[2])*bininvz) + nbinz;
else if (x[2] >= bboxlo[2]) {
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz);
iz = MIN(iz,nbinz-1);
} else
iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz) - 1;
ix -= mbinxlo;
iy -= mbinylo;
iz -= mbinzlo;
return iz*mbiny*mbinx + iy*mbinx + ix;
}
/* ----------------------------------------------------------------------
test if atom pair i,j is excluded from neighbor list
due to type, group, molecule settings from neigh_modify command
return 1 if should be excluded, 0 if included
------------------------------------------------------------------------- */
int Neighbor::exclusion(int i, int j, int itype, int jtype,
int *mask, int *molecule)
{
int m;
if (nex_type && ex_type[itype][jtype]) return 1;
if (nex_group) {
for (m = 0; m < nex_group; m++) {
if (mask[i] & ex1_bit[m] && mask[j] & ex2_bit[m]) return 1;
if (mask[i] & ex2_bit[m] && mask[j] & ex1_bit[m]) return 1;
}
}
if (nex_mol) {
for (m = 0; m < nex_mol; m++)
if (mask[i] & ex_mol_bit[m] && mask[j] & ex_mol_bit[m] &&
molecule[i] == molecule[j]) return 1;
}
return 0;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory
------------------------------------------------------------------------- */
bigint Neighbor::memory_usage()
{
bigint bytes = 0;
bytes += memory->usage(xhold,maxhold,3);
if (style != NSQ) {
bytes += memory->usage(bins,maxbin);
bytes += memory->usage(binhead,maxhead);
}
for (int i = 0; i < nlist; i++) bytes += lists[i]->memory_usage();
bytes += memory->usage(bondlist,maxbond,3);
bytes += memory->usage(anglelist,maxangle,4);
bytes += memory->usage(dihedrallist,maxdihedral,5);
bytes += memory->usage(improperlist,maximproper,5);
return bytes;
}
diff --git a/src/output.cpp b/src/output.cpp
index de7ed5baa..50a7cc008 100644
--- a/src/output.cpp
+++ b/src/output.cpp
@@ -1,547 +1,547 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "output.h"
#include "style_dump.h"
#include "atom.h"
#include "neighbor.h"
#include "input.h"
#include "variable.h"
#include "comm.h"
#include "update.h"
#include "group.h"
#include "domain.h"
#include "thermo.h"
#include "modify.h"
#include "compute.h"
#include "force.h"
#include "dump.h"
#include "write_restart.h"
#include "accelerator_cuda.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define DELTA 1
#define MYMIN(a,b) ((a) < (b) ? (a) : (b))
#define MYMAX(a,b) ((a) > (b) ? (a) : (b))
/* ----------------------------------------------------------------------
initialize all output
------------------------------------------------------------------------- */
Output::Output(LAMMPS *lmp) : Pointers(lmp)
{
// create default computes for temp,pressure,pe
char **newarg = new char*[4];
newarg[0] = (char *) "thermo_temp";
newarg[1] = (char *) "all";
newarg[2] = (char *) "temp";
modify->add_compute(3,newarg,lmp->suffix);
newarg[0] = (char *) "thermo_press";
newarg[1] = (char *) "all";
newarg[2] = (char *) "pressure";
newarg[3] = (char *) "thermo_temp";
modify->add_compute(4,newarg,lmp->suffix);
newarg[0] = (char *) "thermo_pe";
newarg[1] = (char *) "all";
newarg[2] = (char *) "pe";
modify->add_compute(3,newarg,lmp->suffix);
delete [] newarg;
// create default Thermo class
newarg = new char*[1];
newarg[0] = (char *) "one";
thermo = new Thermo(lmp,1,newarg);
delete [] newarg;
thermo_every = 0;
var_thermo = NULL;
ndump = 0;
max_dump = 0;
every_dump = NULL;
next_dump = NULL;
last_dump = NULL;
var_dump = NULL;
ivar_dump = NULL;
dump = NULL;
restart = NULL;
restart1 = restart2 = NULL;
restart_every = 0;
last_restart = -1;
}
/* ----------------------------------------------------------------------
free all memory
------------------------------------------------------------------------- */
Output::~Output()
{
if (thermo) delete thermo;
delete [] var_thermo;
memory->destroy(every_dump);
memory->destroy(next_dump);
memory->destroy(last_dump);
for (int i = 0; i < ndump; i++) delete [] var_dump[i];
memory->sfree(var_dump);
memory->destroy(ivar_dump);
for (int i = 0; i < ndump; i++) delete dump[i];
memory->sfree(dump);
delete restart;
delete [] restart1;
delete [] restart2;
}
/* ---------------------------------------------------------------------- */
void Output::init()
{
thermo->init();
if (thermo_every) delete [] var_thermo;
else if (var_thermo) {
ivar_thermo = input->variable->find(var_thermo);
if (ivar_thermo < 0)
- error->all("Variable name for thermo every does not exist");
+ error->all(FLERR,"Variable name for thermo every does not exist");
if (!input->variable->equalstyle(ivar_thermo))
- error->all("Variable for thermo every is invalid style");
+ error->all(FLERR,"Variable for thermo every is invalid style");
}
for (int i = 0; i < ndump; i++) dump[i]->init();
for (int i = 0; i < ndump; i++)
if (every_dump[i] == 0) {
ivar_dump[i] = input->variable->find(var_dump[i]);
if (ivar_dump[i] < 0)
- error->all("Variable name for dump every does not exist");
+ error->all(FLERR,"Variable name for dump every does not exist");
if (!input->variable->equalstyle(ivar_dump[i]))
- error->all("Variable for dump every is invalid style");
+ error->all(FLERR,"Variable for dump every is invalid style");
}
}
/* ----------------------------------------------------------------------
perform output for setup of run/min
do dump first, so memory_usage will include dump allocation
do thermo last, so will print after memory_usage
------------------------------------------------------------------------- */
void Output::setup(int flag)
{
bigint ntimestep = update->ntimestep;
// perform dump at start of run if current timestep is multiple of every
// and last dump was not on this timestep
// set next_dump to multiple of every
// will not write on last step of run unless multiple of every
// set next_dump_any to smallest next_dump
// if no dumps, set next_dump_any to last+1 so will not influence next
// wrap dumps that invoke computes with clear/add
// if dump not written now, add_all on future step since clear/add is noop
int writeflag;
if (ndump && update->restrict_output == 0) {
for (int idump = 0; idump < ndump; idump++) {
if (dump[idump]->clearstep) modify->clearstep_compute();
writeflag = 0;
if (every_dump[idump] && ntimestep % every_dump[idump] == 0 &&
last_dump[idump] != ntimestep) writeflag = 1;
if (last_dump[idump] < 0 && dump[idump]->first_flag == 1) writeflag = 1;
if (writeflag) {
dump[idump]->write();
last_dump[idump] = ntimestep;
}
if (every_dump[idump])
next_dump[idump] =
(ntimestep/every_dump[idump])*every_dump[idump] + every_dump[idump];
else {
int nextdump = static_cast<int>
(input->variable->compute_equal(ivar_dump[idump]));
if (nextdump <= ntimestep)
- error->all("Dump every variable returned a bad timestep");
+ error->all(FLERR,"Dump every variable returned a bad timestep");
next_dump[idump] = nextdump;
}
if (dump[idump]->clearstep) {
if (writeflag) modify->addstep_compute(next_dump[idump]);
else modify->addstep_compute_all(next_dump[idump]);
}
if (idump) next_dump_any = MYMIN(next_dump_any,next_dump[idump]);
else next_dump_any = next_dump[0];
}
} else next_dump_any = update->laststep + 1;
// do not write a restart file at start of run
// set next_restart to multiple of every
// will not write on last step of run unless multiple of every
// if every = 0, set next_restart to last+1 so will not influence next
if (restart_every && update->restrict_output == 0)
next_restart = (ntimestep/restart_every)*restart_every + restart_every;
else next_restart = update->laststep + 1;
// print memory usage unless being called between multiple runs
if (flag) memory_usage();
// always do thermo with header at start of run
// set next_thermo to multiple of every or last step of run (if smaller)
// if every = 0, set next_thermo to last step of run
// thermo may invoke computes so wrap with clear/add
modify->clearstep_compute();
thermo->header();
thermo->compute(0);
last_thermo = ntimestep;
if (thermo_every) {
next_thermo = (ntimestep/thermo_every)*thermo_every + thermo_every;
next_thermo = MYMIN(next_thermo,update->laststep);
} else if (var_thermo) {
next_thermo = static_cast<int>
(input->variable->compute_equal(ivar_thermo));
if (next_thermo <= ntimestep)
- error->all("Thermo every variable returned a bad timestep");
+ error->all(FLERR,"Thermo every variable returned a bad timestep");
} else next_thermo = update->laststep;
modify->addstep_compute(next_thermo);
// next = next timestep any output will be done
next = MYMIN(next_dump_any,next_restart);
next = MYMIN(next,next_thermo);
}
/* ----------------------------------------------------------------------
perform all output for this timestep
only perform output if next matches current step and last doesn't
do dump/restart before thermo so thermo CPU time will include them
------------------------------------------------------------------------- */
void Output::write(bigint ntimestep)
{
// next_dump does not force output on last step of run
// wrap dumps that invoke computes with clear/add
// download data from GPU if necessary
if (next_dump_any == ntimestep) {
if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->downloadAll();
for (int idump = 0; idump < ndump; idump++) {
if (next_dump[idump] == ntimestep && last_dump[idump] != ntimestep) {
if (dump[idump]->clearstep) modify->clearstep_compute();
dump[idump]->write();
last_dump[idump] = ntimestep;
if (every_dump[idump]) next_dump[idump] += every_dump[idump];
else {
int nextdump = static_cast<int>
(input->variable->compute_equal(ivar_dump[idump]));
if (nextdump <= ntimestep)
- error->all("Dump every variable returned a bad timestep");
+ error->all(FLERR,"Dump every variable returned a bad timestep");
next_dump[idump] = nextdump;
}
if (dump[idump]->clearstep) modify->addstep_compute(next_dump[idump]);
}
if (idump) next_dump_any = MYMIN(next_dump_any,next_dump[idump]);
else next_dump_any = next_dump[0];
}
}
// next_restart does not force output on last step of run
// for toggle = 0, replace "*" with current timestep in restart filename
// download data from GPU if necessary
if (next_restart == ntimestep && last_restart != ntimestep) {
if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->downloadAll();
if (restart_toggle == 0) {
char *file = new char[strlen(restart1) + 16];
char *ptr = strchr(restart1,'*');
*ptr = '\0';
sprintf(file,"%s" BIGINT_FORMAT "%s",restart1,ntimestep,ptr+1);
*ptr = '*';
restart->write(file);
delete [] file;
} else if (restart_toggle == 1) {
restart->write(restart1);
restart_toggle = 2;
} else if (restart_toggle == 2) {
restart->write(restart2);
restart_toggle = 1;
}
last_restart = ntimestep;
next_restart += restart_every;
}
// insure next_thermo forces output on last step of run
// thermo may invoke computes so wrap with clear/add
if (next_thermo == ntimestep && last_thermo != ntimestep) {
modify->clearstep_compute();
thermo->compute(1);
last_thermo = ntimestep;
if (thermo_every) next_thermo += thermo_every;
else if (var_thermo) {
next_thermo = static_cast<int>
(input->variable->compute_equal(ivar_thermo));
if (next_thermo <= ntimestep)
- error->all("Thermo every variable returned a bad timestep");
+ error->all(FLERR,"Thermo every variable returned a bad timestep");
} else next_thermo = update->laststep;
next_thermo = MYMIN(next_thermo,update->laststep);
modify->addstep_compute(next_thermo);
}
// next = next timestep any output will be done
next = MYMIN(next_dump_any,next_restart);
next = MYMIN(next,next_thermo);
}
/* ----------------------------------------------------------------------
force a snapshot to be written for all dumps
------------------------------------------------------------------------- */
void Output::write_dump(bigint ntimestep)
{
for (int idump = 0; idump < ndump; idump++) {
dump[idump]->write();
last_dump[idump] = ntimestep;
}
}
/* ----------------------------------------------------------------------
force a restart file to be written
------------------------------------------------------------------------- */
void Output::write_restart(bigint ntimestep)
{
if (restart_toggle == 0) {
char *file = new char[strlen(restart1) + 16];
char *ptr = strchr(restart1,'*');
*ptr = '\0';
sprintf(file,"%s" BIGINT_FORMAT "%s",restart1,ntimestep,ptr+1);
*ptr = '*';
restart->write(file);
delete [] file;
} else if (restart_toggle == 1) {
restart->write(restart1);
restart_toggle = 2;
} else if (restart_toggle == 2) {
restart->write(restart2);
restart_toggle = 1;
}
last_restart = ntimestep;
}
/* ----------------------------------------------------------------------
add a Dump to list of Dumps
------------------------------------------------------------------------- */
void Output::add_dump(int narg, char **arg)
{
- if (narg < 5) error->all("Illegal dump command");
+ if (narg < 5) error->all(FLERR,"Illegal dump command");
// error checks
for (int idump = 0; idump < ndump; idump++)
- if (strcmp(arg[0],dump[idump]->id) == 0) error->all("Reuse of dump ID");
+ if (strcmp(arg[0],dump[idump]->id) == 0) error->all(FLERR,"Reuse of dump ID");
int igroup = group->find(arg[1]);
- if (igroup == -1) error->all("Could not find dump group ID");
- if (atoi(arg[3]) <= 0) error->all("Invalid dump frequency");
+ if (igroup == -1) error->all(FLERR,"Could not find dump group ID");
+ if (atoi(arg[3]) <= 0) error->all(FLERR,"Invalid dump frequency");
// extend Dump list if necessary
if (ndump == max_dump) {
max_dump += DELTA;
dump = (Dump **)
memory->srealloc(dump,max_dump*sizeof(Dump *),"output:dump");
memory->grow(every_dump,max_dump,"output:every_dump");
memory->grow(next_dump,max_dump,"output:next_dump");
memory->grow(last_dump,max_dump,"output:last_dump");
var_dump = (char **)
memory->srealloc(var_dump,max_dump*sizeof(char *),"output:var_dump");
memory->grow(ivar_dump,max_dump,"output:ivar_dump");
}
// create the Dump
if (0) return; // dummy line to enable else-if macro expansion
#define DUMP_CLASS
#define DumpStyle(key,Class) \
else if (strcmp(arg[2],#key) == 0) dump[ndump] = new Class(lmp,narg,arg);
#include "style_dump.h"
#undef DUMP_CLASS
- else error->all("Invalid dump style");
+ else error->all(FLERR,"Invalid dump style");
every_dump[ndump] = atoi(arg[3]);
- if (every_dump[ndump] <= 0) error->all("Illegal dump command");
+ if (every_dump[ndump] <= 0) error->all(FLERR,"Illegal dump command");
last_dump[ndump] = -1;
var_dump[ndump] = NULL;
ndump++;
}
/* ----------------------------------------------------------------------
modify parameters of a Dump
------------------------------------------------------------------------- */
void Output::modify_dump(int narg, char **arg)
{
- if (narg < 1) error->all("Illegal dump_modify command");
+ if (narg < 1) error->all(FLERR,"Illegal dump_modify command");
// find which dump it is
int idump;
for (idump = 0; idump < ndump; idump++)
if (strcmp(arg[0],dump[idump]->id) == 0) break;
- if (idump == ndump) error->all("Cound not find dump_modify ID");
+ if (idump == ndump) error->all(FLERR,"Cound not find dump_modify ID");
dump[idump]->modify_params(narg-1,&arg[1]);
}
/* ----------------------------------------------------------------------
delete a Dump from list of Dumps
------------------------------------------------------------------------- */
void Output::delete_dump(char *id)
{
// find which dump it is and delete it
int idump;
for (idump = 0; idump < ndump; idump++)
if (strcmp(id,dump[idump]->id) == 0) break;
- if (idump == ndump) error->all("Could not find undump ID");
+ if (idump == ndump) error->all(FLERR,"Could not find undump ID");
delete dump[idump];
delete [] var_dump[idump];
// move other dumps down in list one slot
for (int i = idump+1; i < ndump; i++) {
dump[i-1] = dump[i];
every_dump[i-1] = every_dump[i];
next_dump[i-1] = next_dump[i];
last_dump[i-1] = last_dump[i];
var_dump[i-1] = var_dump[i];
ivar_dump[i-1] = ivar_dump[i];
}
ndump--;
}
/* ----------------------------------------------------------------------
new Thermo style
------------------------------------------------------------------------- */
void Output::create_thermo(int narg, char **arg)
{
- if (narg < 1) error->all("Illegal thermo_style command");
+ if (narg < 1) error->all(FLERR,"Illegal thermo_style command");
// don't allow this so that dipole style can safely allocate inertia vector
if (domain->box_exist == 0)
- error->all("Thermo_style command before simulation box is defined");
+ error->all(FLERR,"Thermo_style command before simulation box is defined");
// warn if previous thermo had been modified via thermo_modify command
if (thermo->modified && comm->me == 0)
- error->warning("New thermo_style command, "
+ error->warning(FLERR,"New thermo_style command, "
"previous thermo_modify settings will be lost");
// set thermo = NULL in case new Thermo throws an error
delete thermo;
thermo = NULL;
thermo = new Thermo(lmp,narg,arg);
}
/* ----------------------------------------------------------------------
setup restart capability
if only one filename and it contains no "*", then append ".*"
------------------------------------------------------------------------- */
void Output::create_restart(int narg, char **arg)
{
- if (narg < 1) error->all("Illegal restart command");
+ if (narg < 1) error->all(FLERR,"Illegal restart command");
if (restart) delete restart;
delete [] restart1;
delete [] restart2;
restart = NULL;
restart1 = restart2 = NULL;
last_restart = -1;
restart_every = atoi(arg[0]);
if (restart_every == 0) {
- if (narg != 1) error->all("Illegal restart command");
+ if (narg != 1) error->all(FLERR,"Illegal restart command");
return;
}
restart = new WriteRestart(lmp);
int n = strlen(arg[1]) + 3;
restart1 = new char[n];
strcpy(restart1,arg[1]);
if (narg == 2) {
restart_toggle = 0;
restart2 = NULL;
if (strchr(restart1,'*') == NULL) strcat(restart1,".*");
} else if (narg == 3) {
restart_toggle = 1;
n = strlen(arg[2]) + 1;
restart2 = new char[n];
strcpy(restart2,arg[2]);
- } else error->all("Illegal restart command");
+ } else error->all(FLERR,"Illegal restart command");
}
/* ----------------------------------------------------------------------
sum and print memory usage
result is only memory on proc 0, not averaged across procs
------------------------------------------------------------------------- */
void Output::memory_usage()
{
bigint bytes = 0;
bytes += atom->memory_usage();
bytes += neighbor->memory_usage();
bytes += comm->memory_usage();
bytes += update->memory_usage();
bytes += force->memory_usage();
bytes += modify->memory_usage();
for (int i = 0; i < ndump; i++) dump[i]->memory_usage();
double mbytes = bytes/1024.0/1024.0;
if (comm->me == 0) {
if (screen)
fprintf(screen,"Memory usage per processor = %g Mbytes\n",mbytes);
if (logfile)
fprintf(logfile,"Memory usage per processor = %g Mbytes\n",mbytes);
}
}
diff --git a/src/pair.cpp b/src/pair.cpp
index 0357188ff..9374ac003 100644
--- a/src/pair.cpp
+++ b/src/pair.cpp
@@ -1,1138 +1,1135 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "float.h"
#include "limits.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair.h"
#include "atom.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "domain.h"
#include "comm.h"
#include "force.h"
#include "update.h"
#include "accelerator_cuda.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
enum{GEOMETRIC,ARITHMETIC,SIXTHPOWER};
enum{R,RSQ,BMP};
/* ---------------------------------------------------------------------- */
Pair::Pair(LAMMPS *lmp) : Pointers(lmp)
{
THIRD = 1.0/3.0;
eng_vdwl = eng_coul = 0.0;
comm_forward = comm_reverse = 0;
single_enable = 1;
respa_enable = 0;
one_coeff = 0;
no_virial_fdotr_compute = 0;
ghostneigh = 0;
nextra = 0;
pvector = NULL;
// pair_modify settings
offset_flag = 0;
mix_flag = GEOMETRIC;
tail_flag = 0;
etail = ptail = etail_ij = ptail_ij = 0.0;
ncoultablebits = 12;
tabinner = sqrt(2.0);
allocated = 0;
maxeatom = maxvatom = 0;
eatom = NULL;
vatom = NULL;
}
/* ---------------------------------------------------------------------- */
Pair::~Pair()
{
memory->destroy(eatom);
memory->destroy(vatom);
}
/* ----------------------------------------------------------------------
modify parameters of the pair style
pair_hybrid has its own version of this routine for its sub-styles
------------------------------------------------------------------------- */
void Pair::modify_params(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal pair_modify command");
+ if (narg == 0) error->all(FLERR,"Illegal pair_modify command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"mix") == 0) {
- if (iarg+2 > narg) error->all("Illegal pair_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command");
if (strcmp(arg[iarg+1],"geometric") == 0) mix_flag = GEOMETRIC;
else if (strcmp(arg[iarg+1],"arithmetic") == 0) mix_flag = ARITHMETIC;
else if (strcmp(arg[iarg+1],"sixthpower") == 0) mix_flag = SIXTHPOWER;
- else error->all("Illegal pair_modify command");
+ else error->all(FLERR,"Illegal pair_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"shift") == 0) {
- if (iarg+2 > narg) error->all("Illegal pair_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) offset_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) offset_flag = 0;
- else error->all("Illegal pair_modify command");
+ else error->all(FLERR,"Illegal pair_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"table") == 0) {
- if (iarg+2 > narg) error->all("Illegal pair_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command");
ncoultablebits = atoi(arg[iarg+1]);
if (ncoultablebits > sizeof(float)*CHAR_BIT)
- error->all("Too many total bits for bitmapped lookup table");
+ error->all(FLERR,"Too many total bits for bitmapped lookup table");
iarg += 2;
} else if (strcmp(arg[iarg],"tabinner") == 0) {
- if (iarg+2 > narg) error->all("Illegal pair_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command");
tabinner = atof(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"tail") == 0) {
- if (iarg+2 > narg) error->all("Illegal pair_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal pair_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) tail_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) tail_flag = 0;
- else error->all("Illegal pair_modify command");
+ else error->all(FLERR,"Illegal pair_modify command");
iarg += 2;
- } else error->all("Illegal pair_modify command");
+ } else error->all(FLERR,"Illegal pair_modify command");
}
}
/* ---------------------------------------------------------------------- */
void Pair::init()
{
int i,j;
if (offset_flag && tail_flag)
- error->all("Cannot have both pair_modify shift and tail set to yes");
+ error->all(FLERR,"Cannot have both pair_modify shift and tail set to yes");
if (tail_flag && domain->dimension == 2)
- error->all("Cannot use pair tail corrections with 2d simulations");
+ error->all(FLERR,"Cannot use pair tail corrections with 2d simulations");
if (tail_flag && domain->nonperiodic && comm->me == 0)
- error->warning("Using pair tail corrections with nonperiodic system");
+ error->warning(FLERR,"Using pair tail corrections with nonperiodic system");
- if (!allocated) error->all("All pair coeffs are not set");
+ if (!allocated) error->all(FLERR,"All pair coeffs are not set");
// I,I coeffs must be set
// init_one() will check if I,J is set explicitly or inferred by mixing
for (i = 1; i <= atom->ntypes; i++)
- if (setflag[i][i] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][i] == 0) error->all(FLERR,"All pair coeffs are not set");
// style-specific initialization
init_style();
// call init_one() for each I,J
// set cutsq for each I,J, used to neighbor
// cutforce = max of all I,J cutoffs
cutforce = 0.0;
etail = ptail = 0.0;
double cut;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
cut = init_one(i,j);
cutsq[i][j] = cutsq[j][i] = cut*cut;
cutforce = MAX(cutforce,cut);
if (tail_flag) {
etail += etail_ij;
ptail += ptail_ij;
if (i != j) {
etail += etail_ij;
ptail += ptail_ij;
}
}
}
}
/* ----------------------------------------------------------------------
reset all type-based params by invoking init_one() for each I,J
called by fix adapt after it changes one or more params
------------------------------------------------------------------------- */
void Pair::reinit()
{
int i,j;
double tmp;
etail = ptail = 0.0;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
tmp = init_one(i,j);
if (tail_flag) {
etail += etail_ij;
ptail += ptail_ij;
if (i != j) {
etail += etail_ij;
ptail += ptail_ij;
}
}
}
}
/* ----------------------------------------------------------------------
init specific to a pair style
specific pair style can override this function
if needs its own error checks
if needs another kind of neighbor list
request default neighbor list = half list
------------------------------------------------------------------------- */
void Pair::init_style()
{
neighbor->request(this);
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
specific pair style can override this function
------------------------------------------------------------------------- */
void Pair::init_list(int which, NeighList *ptr)
{
list = ptr;
}
/* ----------------------------------------------------------------------
mixing of pair potential prefactors (epsilon)
------------------------------------------------------------------------- */
double Pair::mix_energy(double eps1, double eps2, double sig1, double sig2)
{
double value;
if (mix_flag == GEOMETRIC)
value = sqrt(eps1*eps2);
else if (mix_flag == ARITHMETIC)
value = sqrt(eps1*eps2);
else if (mix_flag == SIXTHPOWER)
value = 2.0 * sqrt(eps1*eps2) *
pow(sig1,3.0) * pow(sig2,3.0) / (pow(sig1,6.0) + pow(sig2,6.0));
return value;
}
/* ----------------------------------------------------------------------
mixing of pair potential distances (sigma, cutoff)
------------------------------------------------------------------------- */
double Pair::mix_distance(double sig1, double sig2)
{
double value;
if (mix_flag == GEOMETRIC)
value = sqrt(sig1*sig2);
else if (mix_flag == ARITHMETIC)
value = 0.5 * (sig1+sig2);
else if (mix_flag == SIXTHPOWER)
value = pow((0.5 * (pow(sig1,6.0) + pow(sig2,6.0))),1.0/6.0);
return value;
}
/* ----------------------------------------------------------------------
setup for energy, virial computation
see integrate::ev_set() for values of eflag (0-3) and vflag (0-6)
------------------------------------------------------------------------- */
void Pair::ev_setup(int eflag, int vflag)
{
int i,n;
evflag = 1;
eflag_either = eflag;
eflag_global = eflag % 2;
eflag_atom = eflag / 2;
vflag_either = vflag;
vflag_global = vflag % 4;
vflag_atom = vflag / 4;
// reallocate per-atom arrays if necessary
if (eflag_atom && atom->nmax > maxeatom) {
maxeatom = atom->nmax;
memory->destroy(eatom);
memory->create(eatom,maxeatom,"pair:eatom");
}
if (vflag_atom && atom->nmax > maxvatom) {
maxvatom = atom->nmax;
memory->destroy(vatom);
memory->create(vatom,maxvatom,6,"pair:vatom");
}
// zero accumulators
// use force->newton instead of newton_pair
// b/c some bonds/dihedrals call pair::ev_tally with pairwise info
if (eflag_global) eng_vdwl = eng_coul = 0.0;
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
if (eflag_atom) {
n = atom->nlocal;
if (force->newton) n += atom->nghost;
for (i = 0; i < n; i++) eatom[i] = 0.0;
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton) n += atom->nghost;
for (i = 0; i < n; i++) {
vatom[i][0] = 0.0;
vatom[i][1] = 0.0;
vatom[i][2] = 0.0;
vatom[i][3] = 0.0;
vatom[i][4] = 0.0;
vatom[i][5] = 0.0;
}
}
// if vflag_global = 2 and pair::compute() calls virial_fdotr_compute()
// compute global virial via (F dot r) instead of via pairwise summation
// unset other flags as appropriate
if (vflag_global == 2 && no_virial_fdotr_compute == 0) {
vflag_fdotr = 1;
vflag_global = 0;
if (vflag_atom == 0) vflag_either = 0;
if (vflag_either == 0 && eflag_either == 0) evflag = 0;
} else vflag_fdotr = 0;
if (lmp->cuda) lmp->cuda->evsetup_eatom_vatom(eflag_atom,vflag_atom);
}
/* ----------------------------------------------------------------------
tally eng_vdwl and virial into global and per-atom accumulators
need i < nlocal test since called by bond_quartic and dihedral_charmm
------------------------------------------------------------------------- */
void Pair::ev_tally(int i, int j, int nlocal, int newton_pair,
double evdwl, double ecoul, double fpair,
double delx, double dely, double delz)
{
double evdwlhalf,ecoulhalf,epairhalf,v[6];
if (eflag_either) {
if (eflag_global) {
if (newton_pair) {
eng_vdwl += evdwl;
eng_coul += ecoul;
} else {
evdwlhalf = 0.5*evdwl;
ecoulhalf = 0.5*ecoul;
if (i < nlocal) {
eng_vdwl += evdwlhalf;
eng_coul += ecoulhalf;
}
if (j < nlocal) {
eng_vdwl += evdwlhalf;
eng_coul += ecoulhalf;
}
}
}
if (eflag_atom) {
epairhalf = 0.5 * (evdwl + ecoul);
if (newton_pair || i < nlocal) eatom[i] += epairhalf;
if (newton_pair || j < nlocal) eatom[j] += epairhalf;
}
}
if (vflag_either) {
v[0] = delx*delx*fpair;
v[1] = dely*dely*fpair;
v[2] = delz*delz*fpair;
v[3] = delx*dely*fpair;
v[4] = delx*delz*fpair;
v[5] = dely*delz*fpair;
if (vflag_global) {
if (newton_pair) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
if (j < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
}
}
if (vflag_atom) {
if (newton_pair || i < nlocal) {
vatom[i][0] += 0.5*v[0];
vatom[i][1] += 0.5*v[1];
vatom[i][2] += 0.5*v[2];
vatom[i][3] += 0.5*v[3];
vatom[i][4] += 0.5*v[4];
vatom[i][5] += 0.5*v[5];
}
if (newton_pair || j < nlocal) {
vatom[j][0] += 0.5*v[0];
vatom[j][1] += 0.5*v[1];
vatom[j][2] += 0.5*v[2];
vatom[j][3] += 0.5*v[3];
vatom[j][4] += 0.5*v[4];
vatom[j][5] += 0.5*v[5];
}
}
}
}
/* ----------------------------------------------------------------------
tally eng_vdwl and virial into global and per-atom accumulators
can use this version with full neighbor lists
------------------------------------------------------------------------- */
void Pair::ev_tally_full(int i, double evdwl, double ecoul, double fpair,
double delx, double dely, double delz)
{
double v[6];
if (eflag_either) {
if (eflag_global) {
eng_vdwl += 0.5*evdwl;
eng_coul += 0.5*ecoul;
}
if (eflag_atom) eatom[i] += 0.5 * (evdwl + ecoul);
}
if (vflag_either) {
v[0] = 0.5*delx*delx*fpair;
v[1] = 0.5*dely*dely*fpair;
v[2] = 0.5*delz*delz*fpair;
v[3] = 0.5*delx*dely*fpair;
v[4] = 0.5*delx*delz*fpair;
v[5] = 0.5*dely*delz*fpair;
if (vflag_global) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
}
if (vflag_atom) {
vatom[i][0] += v[0];
vatom[i][1] += v[1];
vatom[i][2] += v[2];
vatom[i][3] += v[3];
vatom[i][4] += v[4];
vatom[i][5] += v[5];
}
}
}
/* ----------------------------------------------------------------------
tally eng_vdwl and virial into global and per-atom accumulators
for virial, have delx,dely,delz and fx,fy,fz
------------------------------------------------------------------------- */
void Pair::ev_tally_xyz(int i, int j, int nlocal, int newton_pair,
double evdwl, double ecoul,
double fx, double fy, double fz,
double delx, double dely, double delz)
{
double evdwlhalf,ecoulhalf,epairhalf,v[6];
if (eflag_either) {
if (eflag_global) {
if (newton_pair) {
eng_vdwl += evdwl;
eng_coul += ecoul;
} else {
evdwlhalf = 0.5*evdwl;
ecoulhalf = 0.5*ecoul;
if (i < nlocal) {
eng_vdwl += evdwlhalf;
eng_coul += ecoulhalf;
}
if (j < nlocal) {
eng_vdwl += evdwlhalf;
eng_coul += ecoulhalf;
}
}
}
if (eflag_atom) {
epairhalf = 0.5 * (evdwl + ecoul);
if (newton_pair || i < nlocal) eatom[i] += epairhalf;
if (newton_pair || j < nlocal) eatom[j] += epairhalf;
}
}
if (vflag_either) {
v[0] = delx*fx;
v[1] = dely*fy;
v[2] = delz*fz;
v[3] = delx*fy;
v[4] = delx*fz;
v[5] = dely*fz;
if (vflag_global) {
if (newton_pair) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
if (j < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
}
}
if (vflag_atom) {
if (newton_pair || i < nlocal) {
vatom[i][0] += 0.5*v[0];
vatom[i][1] += 0.5*v[1];
vatom[i][2] += 0.5*v[2];
vatom[i][3] += 0.5*v[3];
vatom[i][4] += 0.5*v[4];
vatom[i][5] += 0.5*v[5];
}
if (newton_pair || j < nlocal) {
vatom[j][0] += 0.5*v[0];
vatom[j][1] += 0.5*v[1];
vatom[j][2] += 0.5*v[2];
vatom[j][3] += 0.5*v[3];
vatom[j][4] += 0.5*v[4];
vatom[j][5] += 0.5*v[5];
}
}
}
}
/* ----------------------------------------------------------------------
tally eng_vdwl and virial into global and per-atom accumulators
for virial, have delx,dely,delz and fx,fy,fz
called when using full neighbor lists
------------------------------------------------------------------------- */
void Pair::ev_tally_xyz_full(int i, double evdwl, double ecoul,
double fx, double fy, double fz,
double delx, double dely, double delz)
{
double evdwlhalf,ecoulhalf,epairhalf,v[6];
if (eflag_either) {
if (eflag_global) {
evdwlhalf = 0.5*evdwl;
ecoulhalf = 0.5*ecoul;
eng_vdwl += evdwlhalf;
eng_coul += ecoulhalf;
}
if (eflag_atom) {
epairhalf = 0.5 * (evdwl + ecoul);
eatom[i] += epairhalf;
}
}
if (vflag_either) {
v[0] = 0.5*delx*fx;
v[1] = 0.5*dely*fy;
v[2] = 0.5*delz*fz;
v[3] = 0.5*delx*fy;
v[4] = 0.5*delx*fz;
v[5] = 0.5*dely*fz;
if (vflag_global) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
}
if (vflag_atom) {
vatom[i][0] += v[0];
vatom[i][1] += v[1];
vatom[i][2] += v[2];
vatom[i][3] += v[3];
vatom[i][4] += v[4];
vatom[i][5] += v[5];
}
}
}
/* ----------------------------------------------------------------------
tally eng_vdwl and virial into global and per-atom accumulators
called by SW and hbond potentials, newton_pair is always on
virial = riFi + rjFj + rkFk = (rj-ri) Fj + (rk-ri) Fk = drji*fj + drki*fk
------------------------------------------------------------------------- */
void Pair::ev_tally3(int i, int j, int k, double evdwl, double ecoul,
double *fj, double *fk, double *drji, double *drki)
{
double epairthird,v[6];
if (eflag_either) {
if (eflag_global) {
eng_vdwl += evdwl;
eng_coul += ecoul;
}
if (eflag_atom) {
epairthird = THIRD * (evdwl + ecoul);
eatom[i] += epairthird;
eatom[j] += epairthird;
eatom[k] += epairthird;
}
}
if (vflag_either) {
v[0] = drji[0]*fj[0] + drki[0]*fk[0];
v[1] = drji[1]*fj[1] + drki[1]*fk[1];
v[2] = drji[2]*fj[2] + drki[2]*fk[2];
v[3] = drji[0]*fj[1] + drki[0]*fk[1];
v[4] = drji[0]*fj[2] + drki[0]*fk[2];
v[5] = drji[1]*fj[2] + drki[1]*fk[2];
if (vflag_global) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
}
if (vflag_atom) {
vatom[i][0] += THIRD*v[0]; vatom[i][1] += THIRD*v[1];
vatom[i][2] += THIRD*v[2]; vatom[i][3] += THIRD*v[3];
vatom[i][4] += THIRD*v[4]; vatom[i][5] += THIRD*v[5];
vatom[j][0] += THIRD*v[0]; vatom[j][1] += THIRD*v[1];
vatom[j][2] += THIRD*v[2]; vatom[j][3] += THIRD*v[3];
vatom[j][4] += THIRD*v[4]; vatom[j][5] += THIRD*v[5];
vatom[k][0] += THIRD*v[0]; vatom[k][1] += THIRD*v[1];
vatom[k][2] += THIRD*v[2]; vatom[k][3] += THIRD*v[3];
vatom[k][4] += THIRD*v[4]; vatom[k][5] += THIRD*v[5];
}
}
}
/* ----------------------------------------------------------------------
tally eng_vdwl and virial into global and per-atom accumulators
called by AIREBO potential, newton_pair is always on
------------------------------------------------------------------------- */
void Pair::ev_tally4(int i, int j, int k, int m, double evdwl,
double *fi, double *fj, double *fk,
double *drim, double *drjm, double *drkm)
{
double epairfourth,v[6];
if (eflag_either) {
if (eflag_global) eng_vdwl += evdwl;
if (eflag_atom) {
epairfourth = 0.25 * evdwl;
eatom[i] += epairfourth;
eatom[j] += epairfourth;
eatom[k] += epairfourth;
eatom[m] += epairfourth;
}
}
if (vflag_atom) {
v[0] = 0.25 * (drim[0]*fi[0] + drjm[0]*fj[0] + drkm[0]*fk[0]);
v[1] = 0.25 * (drim[1]*fi[1] + drjm[1]*fj[1] + drkm[1]*fk[1]);
v[2] = 0.25 * (drim[2]*fi[2] + drjm[2]*fj[2] + drkm[2]*fk[2]);
v[3] = 0.25 * (drim[0]*fi[1] + drjm[0]*fj[1] + drkm[0]*fk[1]);
v[4] = 0.25 * (drim[0]*fi[2] + drjm[0]*fj[2] + drkm[0]*fk[2]);
v[5] = 0.25 * (drim[1]*fi[2] + drjm[1]*fj[2] + drkm[1]*fk[2]);
vatom[i][0] += v[0]; vatom[i][1] += v[1]; vatom[i][2] += v[2];
vatom[i][3] += v[3]; vatom[i][4] += v[4]; vatom[i][5] += v[5];
vatom[j][0] += v[0]; vatom[j][1] += v[1]; vatom[j][2] += v[2];
vatom[j][3] += v[3]; vatom[j][4] += v[4]; vatom[j][5] += v[5];
vatom[k][0] += v[0]; vatom[k][1] += v[1]; vatom[k][2] += v[2];
vatom[k][3] += v[3]; vatom[k][4] += v[4]; vatom[k][5] += v[5];
vatom[m][0] += v[0]; vatom[m][1] += v[1]; vatom[m][2] += v[2];
vatom[m][3] += v[3]; vatom[m][4] += v[4]; vatom[m][5] += v[5];
}
}
/* ----------------------------------------------------------------------
tally ecoul and virial into each of n atoms in list
called by TIP4P potential, newton_pair is always on
changes v values by dividing by n
------------------------------------------------------------------------- */
void Pair::ev_tally_list(int n, int *list, double ecoul, double *v)
{
int i,j;
if (eflag_either) {
if (eflag_global) eng_coul += ecoul;
if (eflag_atom) {
double epairatom = ecoul/n;
for (i = 0; i < n; i++) eatom[list[i]] += epairatom;
}
}
if (vflag_either) {
if (vflag_global) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
}
if (vflag_atom) {
v[0] /= n;
v[1] /= n;
v[2] /= n;
v[3] /= n;
v[4] /= n;
v[5] /= n;
for (i = 0; i < n; i++) {
j = list[i];
vatom[j][0] += v[0];
vatom[j][1] += v[1];
vatom[j][2] += v[2];
vatom[j][3] += v[3];
vatom[j][4] += v[4];
vatom[j][5] += v[5];
}
}
}
}
/* ----------------------------------------------------------------------
tally virial into per-atom accumulators
called by AIREBO potential, newton_pair is always on
fpair is magnitude of force on atom I
------------------------------------------------------------------------- */
void Pair::v_tally2(int i, int j, double fpair, double *drij)
{
double v[6];
v[0] = 0.5 * drij[0]*drij[0]*fpair;
v[1] = 0.5 * drij[1]*drij[1]*fpair;
v[2] = 0.5 * drij[2]*drij[2]*fpair;
v[3] = 0.5 * drij[0]*drij[1]*fpair;
v[4] = 0.5 * drij[0]*drij[2]*fpair;
v[5] = 0.5 * drij[1]*drij[2]*fpair;
vatom[i][0] += v[0]; vatom[i][1] += v[1]; vatom[i][2] += v[2];
vatom[i][3] += v[3]; vatom[i][4] += v[4]; vatom[i][5] += v[5];
vatom[j][0] += v[0]; vatom[j][1] += v[1]; vatom[j][2] += v[2];
vatom[j][3] += v[3]; vatom[j][4] += v[4]; vatom[j][5] += v[5];
}
/* ----------------------------------------------------------------------
tally virial into per-atom accumulators
called by AIREBO and Tersoff potential, newton_pair is always on
------------------------------------------------------------------------- */
void Pair::v_tally3(int i, int j, int k,
double *fi, double *fj, double *drik, double *drjk)
{
double v[6];
v[0] = THIRD * (drik[0]*fi[0] + drjk[0]*fj[0]);
v[1] = THIRD * (drik[1]*fi[1] + drjk[1]*fj[1]);
v[2] = THIRD * (drik[2]*fi[2] + drjk[2]*fj[2]);
v[3] = THIRD * (drik[0]*fi[1] + drjk[0]*fj[1]);
v[4] = THIRD * (drik[0]*fi[2] + drjk[0]*fj[2]);
v[5] = THIRD * (drik[1]*fi[2] + drjk[1]*fj[2]);
vatom[i][0] += v[0]; vatom[i][1] += v[1]; vatom[i][2] += v[2];
vatom[i][3] += v[3]; vatom[i][4] += v[4]; vatom[i][5] += v[5];
vatom[j][0] += v[0]; vatom[j][1] += v[1]; vatom[j][2] += v[2];
vatom[j][3] += v[3]; vatom[j][4] += v[4]; vatom[j][5] += v[5];
vatom[k][0] += v[0]; vatom[k][1] += v[1]; vatom[k][2] += v[2];
vatom[k][3] += v[3]; vatom[k][4] += v[4]; vatom[k][5] += v[5];
}
/* ----------------------------------------------------------------------
tally virial into per-atom accumulators
called by AIREBO potential, newton_pair is always on
------------------------------------------------------------------------- */
void Pair::v_tally4(int i, int j, int k, int m,
double *fi, double *fj, double *fk,
double *drim, double *drjm, double *drkm)
{
double v[6];
v[0] = 0.25 * (drim[0]*fi[0] + drjm[0]*fj[0] + drkm[0]*fk[0]);
v[1] = 0.25 * (drim[1]*fi[1] + drjm[1]*fj[1] + drkm[1]*fk[1]);
v[2] = 0.25 * (drim[2]*fi[2] + drjm[2]*fj[2] + drkm[2]*fk[2]);
v[3] = 0.25 * (drim[0]*fi[1] + drjm[0]*fj[1] + drkm[0]*fk[1]);
v[4] = 0.25 * (drim[0]*fi[2] + drjm[0]*fj[2] + drkm[0]*fk[2]);
v[5] = 0.25 * (drim[1]*fi[2] + drjm[1]*fj[2] + drkm[1]*fk[2]);
vatom[i][0] += v[0]; vatom[i][1] += v[1]; vatom[i][2] += v[2];
vatom[i][3] += v[3]; vatom[i][4] += v[4]; vatom[i][5] += v[5];
vatom[j][0] += v[0]; vatom[j][1] += v[1]; vatom[j][2] += v[2];
vatom[j][3] += v[3]; vatom[j][4] += v[4]; vatom[j][5] += v[5];
vatom[k][0] += v[0]; vatom[k][1] += v[1]; vatom[k][2] += v[2];
vatom[k][3] += v[3]; vatom[k][4] += v[4]; vatom[k][5] += v[5];
vatom[m][0] += v[0]; vatom[m][1] += v[1]; vatom[m][2] += v[2];
vatom[m][3] += v[3]; vatom[m][4] += v[4]; vatom[m][5] += v[5];
}
/* ----------------------------------------------------------------------
tally virial into global and per-atom accumulators
called by pair lubricate potential with 6 tensor components
------------------------------------------------------------------------- */
void Pair::v_tally_tensor(int i, int j, int nlocal, int newton_pair,
double vxx, double vyy, double vzz,
double vxy, double vxz, double vyz)
{
double v[6];
v[0] = vxx;
v[1] = vyy;
v[2] = vzz;
v[3] = vxy;
v[4] = vxz;
v[5] = vyz;
if (vflag_global) {
if (newton_pair) {
virial[0] += v[0];
virial[1] += v[1];
virial[2] += v[2];
virial[3] += v[3];
virial[4] += v[4];
virial[5] += v[5];
} else {
if (i < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
if (j < nlocal) {
virial[0] += 0.5*v[0];
virial[1] += 0.5*v[1];
virial[2] += 0.5*v[2];
virial[3] += 0.5*v[3];
virial[4] += 0.5*v[4];
virial[5] += 0.5*v[5];
}
}
}
if (vflag_atom) {
if (newton_pair || i < nlocal) {
vatom[i][0] += 0.5*v[0];
vatom[i][1] += 0.5*v[1];
vatom[i][2] += 0.5*v[2];
vatom[i][3] += 0.5*v[3];
vatom[i][4] += 0.5*v[4];
vatom[i][5] += 0.5*v[5];
}
if (newton_pair || j < nlocal) {
vatom[j][0] += 0.5*v[0];
vatom[j][1] += 0.5*v[1];
vatom[j][2] += 0.5*v[2];
vatom[j][3] += 0.5*v[3];
vatom[j][4] += 0.5*v[4];
vatom[j][5] += 0.5*v[5];
}
}
}
/* ----------------------------------------------------------------------
compute global pair virial via summing F dot r over own & ghost atoms
at this point, only pairwise forces have been accumulated in atom->f
------------------------------------------------------------------------- */
void Pair::virial_fdotr_compute()
{
double **x = atom->x;
double **f = atom->f;
// sum over force on all particles including ghosts
if (neighbor->includegroup == 0) {
int nall = atom->nlocal + atom->nghost;
for (int i = 0; i < nall; i++) {
virial[0] += f[i][0]*x[i][0];
virial[1] += f[i][1]*x[i][1];
virial[2] += f[i][2]*x[i][2];
virial[3] += f[i][1]*x[i][0];
virial[4] += f[i][2]*x[i][0];
virial[5] += f[i][2]*x[i][1];
}
// neighbor includegroup flag is set
// sum over force on initial nfirst particles and ghosts
} else {
int nall = atom->nfirst;
for (int i = 0; i < nall; i++) {
virial[0] += f[i][0]*x[i][0];
virial[1] += f[i][1]*x[i][1];
virial[2] += f[i][2]*x[i][2];
virial[3] += f[i][1]*x[i][0];
virial[4] += f[i][2]*x[i][0];
virial[5] += f[i][2]*x[i][1];
}
nall = atom->nlocal + atom->nghost;
for (int i = atom->nlocal; i < nall; i++) {
virial[0] += f[i][0]*x[i][0];
virial[1] += f[i][1]*x[i][1];
virial[2] += f[i][2]*x[i][2];
virial[3] += f[i][1]*x[i][0];
virial[4] += f[i][2]*x[i][0];
virial[5] += f[i][2]*x[i][1];
}
}
}
/* ----------------------------------------------------------------------
write a table of pair potential energy/force vs distance to a file
------------------------------------------------------------------------- */
void Pair::write_file(int narg, char **arg)
{
- if (narg < 8) error->all("Illegal pair_write command");
- if (single_enable == 0) error->all("Pair style does not support pair_write");
+ if (narg < 8) error->all(FLERR,"Illegal pair_write command");
+ if (single_enable == 0) error->all(FLERR,"Pair style does not support pair_write");
// parse arguments
int itype = atoi(arg[0]);
int jtype = atoi(arg[1]);
if (itype < 1 || itype > atom->ntypes || jtype < 1 || jtype > atom->ntypes)
- error->all("Invalid atom types in pair_write command");
+ error->all(FLERR,"Invalid atom types in pair_write command");
int n = atoi(arg[2]);
int style;
if (strcmp(arg[3],"r") == 0) style = R;
else if (strcmp(arg[3],"rsq") == 0) style = RSQ;
else if (strcmp(arg[3],"bitmap") == 0) style = BMP;
- else error->all("Invalid style in pair_write command");
+ else error->all(FLERR,"Invalid style in pair_write command");
double inner = atof(arg[4]);
double outer = atof(arg[5]);
if (inner <= 0.0 || inner >= outer)
- error->all("Invalid cutoffs in pair_write command");
+ error->all(FLERR,"Invalid cutoffs in pair_write command");
// open file in append mode
// print header in format used by pair_style table
int me;
MPI_Comm_rank(world,&me);
FILE *fp;
if (me == 0) {
fp = fopen(arg[6],"a");
- if (fp == NULL) error->one("Cannot open pair_write file");
+ if (fp == NULL) error->one(FLERR,"Cannot open pair_write file");
fprintf(fp,"# Pair potential %s for atom types %d %d: i,r,energy,force\n",
force->pair_style,itype,jtype);
if (style == R)
fprintf(fp,"\n%s\nN %d R %g %g\n\n",arg[7],n,inner,outer);
if (style == RSQ)
fprintf(fp,"\n%s\nN %d RSQ %g %g\n\n",arg[7],n,inner,outer);
}
// initialize potentials before evaluating pair potential
// insures all pair coeffs are set and force constants
force->init();
// if pair style = any of EAM, swap in dummy fp vector
double eamfp[2];
eamfp[0] = eamfp[1] = 0.0;
double *eamfp_hold;
Pair *epair = force->pair_match("eam",0);
if (epair) epair->swap_eam(eamfp,&eamfp_hold);
// if atom style defines charge, swap in dummy q vec
double q[2];
q[0] = q[1] = 1.0;
if (narg == 10) {
q[0] = atof(arg[8]);
q[1] = atof(arg[9]);
}
double *q_hold;
if (atom->q) {
q_hold = atom->q;
atom->q = q;
}
// evaluate energy and force at each of N distances
int masklo,maskhi,nmask,nshiftbits;
if (style == BMP) {
init_bitmap(inner,outer,n,masklo,maskhi,nmask,nshiftbits);
int ntable = 1 << n;
if (me == 0)
fprintf(fp,"\n%s\nN %d BITMAP %g %g\n\n",arg[7],ntable,inner,outer);
n = ntable;
}
double r,e,f,rsq;
union_int_float_t rsq_lookup;
for (int i = 0; i < n; i++) {
if (style == R) {
r = inner + (outer-inner) * i/(n-1);
rsq = r*r;
} else if (style == RSQ) {
rsq = inner*inner + (outer*outer - inner*inner) * i/(n-1);
r = sqrt(rsq);
} else if (style == BMP) {
rsq_lookup.i = i << nshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < inner*inner) {
rsq_lookup.i = i << nshiftbits;
rsq_lookup.i |= maskhi;
}
rsq = rsq_lookup.f;
r = sqrt(rsq);
}
if (rsq < cutsq[itype][jtype]) {
e = single(0,1,itype,jtype,rsq,1.0,1.0,f);
f *= r;
} else e = f = 0.0;
if (me == 0) fprintf(fp,"%d %g %g %g\n",i+1,r,e,f);
}
// restore original vecs that were swapped in for
double *tmp;
if (epair) epair->swap_eam(eamfp_hold,&tmp);
if (atom->q) atom->q = q_hold;
if (me == 0) fclose(fp);
}
/* ----------------------------------------------------------------------
define bitmap parameters based on inner and outer cutoffs
------------------------------------------------------------------------- */
void Pair::init_bitmap(double inner, double outer, int ntablebits,
int &masklo, int &maskhi, int &nmask, int &nshiftbits)
{
if (sizeof(int) != sizeof(float))
- error->all("Bitmapped lookup tables require int/float be same size");
+ error->all(FLERR,"Bitmapped lookup tables require int/float be same size");
if (ntablebits > sizeof(float)*CHAR_BIT)
- error->all("Too many total bits for bitmapped lookup table");
+ error->all(FLERR,"Too many total bits for bitmapped lookup table");
- if (inner >= outer) error->warning("Table inner cutoff >= outer cutoff");
+ if (inner >= outer) error->warning(FLERR,"Table inner cutoff >= outer cutoff");
int nlowermin = 1;
while (!((pow(double(2),nlowermin) <= inner*inner) &&
(pow(double(2),nlowermin+1) > inner*inner))) {
if (pow(double(2),nlowermin) <= inner*inner) nlowermin++;
else nlowermin--;
}
int nexpbits = 0;
double required_range = outer*outer / pow(double(2),nlowermin);
double available_range = 2.0;
while (available_range < required_range) {
nexpbits++;
available_range = pow(double(2),pow(double(2),nexpbits));
}
int nmantbits = ntablebits - nexpbits;
if (nexpbits > sizeof(float)*CHAR_BIT - FLT_MANT_DIG)
- error->all("Too many exponent bits for lookup table");
+ error->all(FLERR,"Too many exponent bits for lookup table");
if (nmantbits+1 > FLT_MANT_DIG)
- error->all("Too many mantissa bits for lookup table");
- if (nmantbits < 3) error->all("Too few bits for lookup table");
+ error->all(FLERR,"Too many mantissa bits for lookup table");
+ if (nmantbits < 3) error->all(FLERR,"Too few bits for lookup table");
nshiftbits = FLT_MANT_DIG - (nmantbits+1);
nmask = 1;
for (int j = 0; j < ntablebits+nshiftbits; j++) nmask *= 2;
nmask -= 1;
union_int_float_t rsq_lookup;
rsq_lookup.f = outer*outer;
maskhi = rsq_lookup.i & ~(nmask);
rsq_lookup.f = inner*inner;
masklo = rsq_lookup.i & ~(nmask);
}
/* ---------------------------------------------------------------------- */
double Pair::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
return bytes;
}
diff --git a/src/pair_born.cpp b/src/pair_born.cpp
index 926a3194e..406b95a0c 100644
--- a/src/pair_born.cpp
+++ b/src/pair_born.cpp
@@ -1,411 +1,408 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing Author: Sai Jayaraman (Sandia)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_born.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairBorn::PairBorn(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairBorn::~PairBorn()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(a);
memory->destroy(rho);
memory->destroy(sigma);
memory->destroy(c);
memory->destroy(d);
memory->destroy(rhoinv);
memory->destroy(born1);
memory->destroy(born2);
memory->destroy(born3);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairBorn::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forceborn,factor_lj;
double r,rexp;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
rexp = exp((sigma[itype][jtype]-r)*rhoinv[itype][jtype]);
forceborn = born1[itype][jtype]*r*rexp - born2[itype][jtype]*r6inv
+ born3[itype][jtype]*r2inv*r6inv;
fpair = factor_lj*forceborn*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = a[itype][jtype]*rexp - c[itype][jtype]*r6inv
+ d[itype][jtype]*r6inv*r2inv - offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairBorn::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(a,n+1,n+1,"pair:a");
memory->create(rho,n+1,n+1,"pair:rho");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(c,n+1,n+1,"pair:c");
memory->create(d,n+1,n+1,"pair:d");
memory->create(rhoinv,n+1,n+1,"pair:rhoinv");
memory->create(born1,n+1,n+1,"pair:born1");
memory->create(born2,n+1,n+1,"pair:born2");
memory->create(born3,n+1,n+1,"pair:born3");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairBorn::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = atof(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairBorn::coeff(int narg, char **arg)
{
- if (narg < 7 || narg > 8) error->all("Incorrect args for pair coefficients");
+ if (narg < 7 || narg > 8) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a_one = force->numeric(arg[2]);
double rho_one = force->numeric(arg[3]);
double sigma_one = force->numeric(arg[4]);
- if (rho_one <= 0) error->all("Incorrect args for pair coefficients");
+ if (rho_one <= 0) error->all(FLERR,"Incorrect args for pair coefficients");
double c_one = force->numeric(arg[5]);
double d_one = force->numeric(arg[6]);
double cut_one = cut_global;
if (narg == 8) cut_one = force->numeric(arg[7]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a[i][j] = a_one;
rho[i][j] = rho_one;
sigma[i][j] = sigma_one;
c[i][j] = c_one;
d[i][j] = d_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairBorn::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
rhoinv[i][j] = 1.0/rho[i][j];
born1[i][j] = a[i][j]/rho[i][j];
born2[i][j] = 6.0*c[i][j];
born3[i][j] = 8.0*d[i][j];
if (offset_flag) {
double rexp = exp((sigma[i][j]-cut[i][j])*rhoinv[i][j]);
offset[i][j] = a[i][j]*rexp - c[i][j]/pow(cut[i][j],6.0) +
d[i][j]/pow(cut[i][j],8.0);
} else offset[i][j] = 0.0;
a[j][i] = a[i][j];
c[j][i] = c[i][j];
d[j][i] = d[i][j];
rhoinv[j][i] = rhoinv[i][j];
sigma[j][i] = sigma[i][j];
born1[j][i] = born1[i][j];
born2[j][i] = born2[i][j];
born3[j][i] = born3[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double rho1 = rho[i][j];
double rho2 = rho1*rho1;
double rho3 = rho2*rho1;
double rc = cut[i][j];
double rc2 = rc*rc;
double rc3 = rc2*rc;
double rc5 = rc3*rc2;
etail_ij = 2.0*PI*all[0]*all[1] *
(a[i][j]*exp((sigma[i][j]-rc)/rho1)*rho1*
(rc2 + 2.0*rho1*rc + 2.0*rho2) -
c[i][j]/(3.0*rc3) + d[i][j]/(5.0*rc5));
ptail_ij = (-1/3.0)*2.0*PI*all[0]*all[1] *
(-a[i][j]*exp((sigma[i][j]-rc)/rho1) *
(rc3 + 3.0*rho1*rc2 + 6.0*rho2*rc + 6.0*rho3) +
2.0*c[i][j]/rc3 - 8.0*d[i][j]/(5.0*rc5));
}
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBorn::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a[i][j],sizeof(double),1,fp);
fwrite(&rho[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&c[i][j],sizeof(double),1,fp);
fwrite(&d[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBorn::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a[i][j],sizeof(double),1,fp);
fread(&rho[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&c[i][j],sizeof(double),1,fp);
fread(&d[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&rho[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&c[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&d[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBorn::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBorn::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairBorn::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,rexp,forceborn,phiborn;
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
rexp = exp((sigma[itype][jtype]-r)*rhoinv[itype][jtype]);
forceborn = born1[itype][jtype]*r*rexp - born2[itype][jtype]*r6inv +
born3[itype][jtype]*r2inv*r6inv;
fforce = factor_lj*forceborn*r2inv;
phiborn = a[itype][jtype]*rexp - c[itype][jtype]*r6inv +
d[itype][jtype]*r2inv*r6inv - offset[itype][jtype];
return factor_lj*phiborn;
}
/* ---------------------------------------------------------------------- */
void *PairBorn::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"a") == 0) return (void *) a;
if (strcmp(str,"c") == 0) return (void *) c;
if (strcmp(str,"d") == 0) return (void *) d;
return NULL;
}
diff --git a/src/pair_buck.cpp b/src/pair_buck.cpp
index 02add6114..0490f80ee 100644
--- a/src/pair_buck.cpp
+++ b/src/pair_buck.cpp
@@ -1,380 +1,377 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_buck.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairBuck::PairBuck(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairBuck::~PairBuck()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(a);
memory->destroy(rho);
memory->destroy(c);
memory->destroy(rhoinv);
memory->destroy(buck1);
memory->destroy(buck2);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairBuck::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcebuck,factor_lj;
double r,rexp;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
rexp = exp(-r*rhoinv[itype][jtype]);
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
fpair = factor_lj*forcebuck*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairBuck::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut_lj");
memory->create(a,n+1,n+1,"pair:a");
memory->create(rho,n+1,n+1,"pair:rho");
memory->create(c,n+1,n+1,"pair:c");
memory->create(rhoinv,n+1,n+1,"pair:rhoinv");
memory->create(buck1,n+1,n+1,"pair:buck1");
memory->create(buck2,n+1,n+1,"pair:buck2");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairBuck::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairBuck::coeff(int narg, char **arg)
{
- if (narg < 5 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a_one = force->numeric(arg[2]);
double rho_one = force->numeric(arg[3]);
- if (rho_one <= 0) error->all("Incorrect args for pair coefficients");
+ if (rho_one <= 0) error->all(FLERR,"Incorrect args for pair coefficients");
double c_one = force->numeric(arg[4]);
double cut_one = cut_global;
if (narg == 6) cut_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a[i][j] = a_one;
rho[i][j] = rho_one;
c[i][j] = c_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairBuck::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
rhoinv[i][j] = 1.0/rho[i][j];
buck1[i][j] = a[i][j]/rho[i][j];
buck2[i][j] = 6.0*c[i][j];
if (offset_flag) {
double rexp = exp(-cut[i][j]/rho[i][j]);
offset[i][j] = a[i][j]*rexp - c[i][j]/pow(cut[i][j],6.0);
} else offset[i][j] = 0.0;
a[j][i] = a[i][j];
c[j][i] = c[i][j];
rhoinv[j][i] = rhoinv[i][j];
buck1[j][i] = buck1[i][j];
buck2[j][i] = buck2[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double rho1 = rho[i][j];
double rho2 = rho1*rho1;
double rho3 = rho2*rho1;
double rc = cut[i][j];
double rc2 = rc*rc;
double rc3 = rc2*rc;
etail_ij = 2.0*PI*all[0]*all[1]*
(a[i][j]*exp(-rc/rho1)*rho1*(rc2 + 2.0*rho1*rc + 2.0*rho2) -
c[i][j]/(3.0*rc3));
ptail_ij = (-1/3.0)*2.0*PI*all[0]*all[1]*
(-a[i][j]*exp(-rc/rho1)*
(rc3 + 3.0*rho1*rc2 + 6.0*rho2*rc + 6.0*rho3) + 2.0*c[i][j]/rc3);
}
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuck::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a[i][j],sizeof(double),1,fp);
fwrite(&rho[i][j],sizeof(double),1,fp);
fwrite(&c[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuck::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a[i][j],sizeof(double),1,fp);
fread(&rho[i][j],sizeof(double),1,fp);
fread(&c[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&rho[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&c[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuck::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuck::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairBuck::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,rexp,forcebuck,phibuck;
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
rexp = exp(-r*rhoinv[itype][jtype]);
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
fforce = factor_lj*forcebuck*r2inv;
phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
offset[itype][jtype];
return factor_lj*phibuck;
}
/* ---------------------------------------------------------------------- */
void *PairBuck::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"a") == 0) return (void *) a;
if (strcmp(str,"c") == 0) return (void *) c;
return NULL;
}
diff --git a/src/pair_buck_coul_cut.cpp b/src/pair_buck_coul_cut.cpp
index 841efaacd..51c179b88 100644
--- a/src/pair_buck_coul_cut.cpp
+++ b/src/pair_buck_coul_cut.cpp
@@ -1,445 +1,442 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Eduardo Bringa (LLNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_buck_coul_cut.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairBuckCoulCut::PairBuckCoulCut(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairBuckCoulCut::~PairBuckCoulCut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
memory->destroy(a);
memory->destroy(rho);
memory->destroy(c);
memory->destroy(rhoinv);
memory->destroy(buck1);
memory->destroy(buck2);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairBuckCoulCut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forcebuck,factor_coul,factor_lj;
double r,rexp;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r = sqrt(rsq);
if (rsq < cut_coulsq[itype][jtype])
forcecoul = qqrd2e * qtmp*q[j]/r;
else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
rexp = exp(-r*rhoinv[itype][jtype]);
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
} else forcebuck = 0.0;
fpair = (factor_coul*forcecoul + factor_lj*forcebuck) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq[itype][jtype])
ecoul = factor_coul * qqrd2e * qtmp*q[j]/r;
else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairBuckCoulCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"pair:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"pair:cut_coulsq");
memory->create(a,n+1,n+1,"pair:a");
memory->create(rho,n+1,n+1,"pair:rho");
memory->create(c,n+1,n+1,"pair:c");
memory->create(rhoinv,n+1,n+1,"pair:rhoinv");
memory->create(buck1,n+1,n+1,"pair:buck1");
memory->create(buck2,n+1,n+1,"pair:buck2");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairBuckCoulCut::settings(int narg, char **arg)
{
- if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul_global = cut_lj_global;
else cut_coul_global = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_lj[i][j] = cut_lj_global;
cut_coul[i][j] = cut_coul_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairBuckCoulCut::coeff(int narg, char **arg)
{
- if (narg < 5 || narg > 7) error->all("Incorrect args for pair coefficients");
+ if (narg < 5 || narg > 7) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a_one = force->numeric(arg[2]);
double rho_one = force->numeric(arg[3]);
- if (rho_one <= 0) error->all("Incorrect args for pair coefficients");
+ if (rho_one <= 0) error->all(FLERR,"Incorrect args for pair coefficients");
double c_one = force->numeric(arg[4]);
double cut_lj_one = cut_lj_global;
double cut_coul_one = cut_coul_global;
if (narg >= 6) cut_coul_one = cut_lj_one = force->numeric(arg[5]);
if (narg == 7) cut_coul_one = force->numeric(arg[6]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a[i][j] = a_one;
rho[i][j] = rho_one;
c[i][j] = c_one;
cut_lj[i][j] = cut_lj_one;
cut_coul[i][j] = cut_coul_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairBuckCoulCut::init_style()
{
if (!atom->q_flag)
- error->all("Pair style buck/coul/cut requires atom attribute q");
+ error->all(FLERR,"Pair style buck/coul/cut requires atom attribute q");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairBuckCoulCut::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
double cut = MAX(cut_lj[i][j],cut_coul[i][j]);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
cut_coulsq[i][j] = cut_coul[i][j] * cut_coul[i][j];
rhoinv[i][j] = 1.0/rho[i][j];
buck1[i][j] = a[i][j]/rho[i][j];
buck2[i][j] = 6.0*c[i][j];
if (offset_flag) {
double rexp = exp(-cut_lj[i][j]/rho[i][j]);
offset[i][j] = a[i][j]*rexp - c[i][j]/pow(cut_lj[i][j],6.0);
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
cut_coulsq[j][i] = cut_coulsq[i][j];
a[j][i] = a[i][j];
c[j][i] = c[i][j];
rhoinv[j][i] = rhoinv[i][j];
buck1[j][i] = buck1[i][j];
buck2[j][i] = buck2[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double rho1 = rho[i][j];
double rho2 = rho1*rho1;
double rho3 = rho2*rho1;
double rc = cut_lj[i][j];
double rc2 = rc*rc;
double rc3 = rc2*rc;
etail_ij = 2.0*PI*all[0]*all[1]*
(a[i][j]*exp(-rc/rho1)*rho1*(rc2 + 2.0*rho1*rc + 2.0*rho2) -
c[i][j]/(3.0*rc3));
ptail_ij = (-1/3.0)*2.0*PI*all[0]*all[1]*
(-a[i][j]*exp(-rc/rho1)*
(rc3 + 3.0*rho1*rc2 + 6.0*rho2*rc + 6.0*rho3) + 2.0*c[i][j]/rc3);
}
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuckCoulCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a[i][j],sizeof(double),1,fp);
fwrite(&rho[i][j],sizeof(double),1,fp);
fwrite(&c[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
fwrite(&cut_coul[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuckCoulCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a[i][j],sizeof(double),1,fp);
fread(&rho[i][j],sizeof(double),1,fp);
fread(&c[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
fread(&cut_coul[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&rho[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&c[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairBuckCoulCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairBuckCoulCut::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairBuckCoulCut::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,rexp,forcecoul,forcebuck,phicoul,phibuck;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype])
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
r = sqrt(rsq);
rexp = exp(-r*rhoinv[itype][jtype]);
forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv;
} else forcebuck = 0.0;
fforce = (factor_coul*forcecoul + factor_lj*forcebuck) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq[itype][jtype]) {
phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
eng += factor_coul*phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv -
offset[itype][jtype];
eng += factor_lj*phibuck;
}
return eng;
}
diff --git a/src/pair_coul_cut.cpp b/src/pair_coul_cut.cpp
index 16a522432..fbe2bfdfc 100644
--- a/src/pair_coul_cut.cpp
+++ b/src/pair_coul_cut.cpp
@@ -1,311 +1,308 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_coul_cut.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairCoulCut::PairCoulCut(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairCoulCut::~PairCoulCut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(scale);
}
}
/* ---------------------------------------------------------------------- */
void PairCoulCut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,ecoul,fpair;
double rsq,r2inv,rinv,forcecoul,factor_coul;
int *ilist,*jlist,*numneigh,**firstneigh;
ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
rinv = sqrt(r2inv);
forcecoul = qqrd2e * scale[itype][jtype] * qtmp*q[j]*rinv;
fpair = factor_coul*forcecoul * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag)
ecoul = factor_coul * qqrd2e * scale[itype][jtype] * qtmp*q[j]*rinv;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
0.0,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairCoulCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(scale,n+1,n+1,"pair:scale");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairCoulCut::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairCoulCut::coeff(int narg, char **arg)
{
- if (narg < 2 || narg > 3) error->all("Incorrect args for pair coefficients");
+ if (narg < 2 || narg > 3) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double cut_one = cut_global;
if (narg == 3) cut_one = force->numeric(arg[2]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
cut[i][j] = cut_one;
scale[i][j] = 1.0;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairCoulCut::init_style()
{
if (!atom->q_flag)
- error->all("Pair style coul/cut requires atom attribute q");
+ error->all(FLERR,"Pair style coul/cut requires atom attribute q");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairCoulCut::init_one(int i, int j)
{
if (setflag[i][j] == 0)
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
scale[j][i] = scale[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairCoulCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairCoulCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) fread(&cut[i][j],sizeof(double),1,fp);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairCoulCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairCoulCut::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairCoulCut::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,rinv,forcecoul,phicoul;
r2inv = 1.0/rsq;
rinv = sqrt(r2inv);
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*rinv;
fforce = factor_coul*forcecoul * r2inv;
phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*rinv;
return factor_coul*phicoul;
}
/* ---------------------------------------------------------------------- */
void *PairCoulCut::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"scale") == 0) return (void *) scale;
return NULL;
}
diff --git a/src/pair_coul_debye.cpp b/src/pair_coul_debye.cpp
index 4527919f8..2606a1f3c 100644
--- a/src/pair_coul_debye.cpp
+++ b/src/pair_coul_debye.cpp
@@ -1,183 +1,180 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_coul_debye.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairCoulDebye::PairCoulDebye(LAMMPS *lmp) : PairCoulCut(lmp) {}
/* ---------------------------------------------------------------------- */
void PairCoulDebye::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,ecoul,fpair;
double rsq,r2inv,r,rinv,forcecoul,factor_coul,screening;
int *ilist,*jlist,*numneigh,**firstneigh;
ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*r);
forcecoul = qqrd2e * qtmp*q[j] * screening * (kappa + rinv);
fpair = factor_coul*forcecoul * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) ecoul = factor_coul * qqrd2e * qtmp*q[j] * rinv * screening;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
0.0,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairCoulDebye::settings(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal pair_style command");
+ if (narg != 2) error->all(FLERR,"Illegal pair_style command");
kappa = force->numeric(arg[0]);
cut_global = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairCoulDebye::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&kappa,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairCoulDebye::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&kappa,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&kappa,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairCoulDebye::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r,rinv,forcecoul,phicoul,screening;
r2inv = 1.0/rsq;
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*r);
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j] *
screening * (kappa + rinv);
fforce = factor_coul*forcecoul * r2inv;
phicoul = force->qqrd2e * atom->q[i]*atom->q[j] * rinv * screening;
return factor_coul*phicoul;
}
diff --git a/src/pair_dpd.cpp b/src/pair_dpd.cpp
index 2ffb078bb..5c701a89e 100644
--- a/src/pair_dpd.cpp
+++ b/src/pair_dpd.cpp
@@ -1,386 +1,383 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Kurt Smith (U Pittsburgh)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_dpd.h"
#include "atom.h"
#include "atom_vec.h"
#include "comm.h"
#include "update.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EPSILON 1.0e-10
/* ---------------------------------------------------------------------- */
PairDPD::PairDPD(LAMMPS *lmp) : Pair(lmp)
{
random = NULL;
}
/* ---------------------------------------------------------------------- */
PairDPD::~PairDPD()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(a0);
memory->destroy(gamma);
memory->destroy(sigma);
}
if (random) delete random;
}
/* ---------------------------------------------------------------------- */
void PairDPD::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double vxtmp,vytmp,vztmp,delvx,delvy,delvz;
double rsq,r,rinv,dot,wd,randnum,factor_dpd;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double dtinvsqrt = 1.0/sqrt(update->dt);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
vxtmp = v[i][0];
vytmp = v[i][1];
vztmp = v[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_dpd = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
if (r < EPSILON) continue; // r can be 0.0 in DPD systems
rinv = 1.0/r;
delvx = vxtmp - v[j][0];
delvy = vytmp - v[j][1];
delvz = vztmp - v[j][2];
dot = delx*delvx + dely*delvy + delz*delvz;
wd = 1.0 - r/cut[itype][jtype];
randnum = random->gaussian();
// conservative force = a0 * wd
// drag force = -gamma * wd^2 * (delx dot delv) / r
// random force = sigma * wd * rnd * dtinvsqrt;
fpair = a0[itype][jtype]*wd;
fpair -= gamma[itype][jtype]*wd*wd*dot*rinv;
fpair += sigma[itype][jtype]*wd*randnum*dtinvsqrt;
fpair *= factor_dpd*rinv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
// unshifted eng of conservative term:
// evdwl = -a0[itype][jtype]*r * (1.0-0.5*r/cut[itype][jtype]);
// eng shifted to 0.0 at cutoff
evdwl = 0.5*a0[itype][jtype]*cut[itype][jtype] * wd*wd;
evdwl *= factor_dpd;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairDPD::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(a0,n+1,n+1,"pair:a0");
memory->create(gamma,n+1,n+1,"pair:gamma");
memory->create(sigma,n+1,n+1,"pair:sigma");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairDPD::settings(int narg, char **arg)
{
- if (narg != 3) error->all("Illegal pair_style command");
+ if (narg != 3) error->all(FLERR,"Illegal pair_style command");
temperature = force->numeric(arg[0]);
cut_global = force->numeric(arg[1]);
seed = force->inumeric(arg[2]);
// initialize Marsaglia RNG with processor-unique seed
- if (seed <= 0) error->all("Illegal pair_style command");
+ if (seed <= 0) error->all(FLERR,"Illegal pair_style command");
delete random;
random = new RanMars(lmp,seed + comm->me);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairDPD::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a0_one = force->numeric(arg[2]);
double gamma_one = force->numeric(arg[3]);
double cut_one = cut_global;
if (narg == 5) cut_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a0[i][j] = a0_one;
gamma[i][j] = gamma_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairDPD::init_style()
{
if (comm->ghost_velocity == 0)
- error->all("Pair dpd requires ghost atoms store velocity");
+ error->all(FLERR,"Pair dpd requires ghost atoms store velocity");
// if newton off, forces between atoms ij will be double computed
// using different random numbers
- if (force->newton_pair == 0 && comm->me == 0) error->warning(
+ if (force->newton_pair == 0 && comm->me == 0) error->warning(FLERR,
"Pair dpd needs newton pair on for momentum conservation");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairDPD::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
sigma[i][j] = sqrt(2.0*force->boltz*temperature*gamma[i][j]);
cut[j][i] = cut[i][j];
a0[j][i] = a0[i][j];
gamma[j][i] = gamma[i][j];
sigma[j][i] = sigma[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDPD::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a0[i][j],sizeof(double),1,fp);
fwrite(&gamma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDPD::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a0[i][j],sizeof(double),1,fp);
fread(&gamma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a0[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&gamma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDPD::write_restart_settings(FILE *fp)
{
fwrite(&temperature,sizeof(double),1,fp);
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&seed,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDPD::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&temperature,sizeof(double),1,fp);
fread(&cut_global,sizeof(double),1,fp);
fread(&seed,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&temperature,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&seed,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
// initialize Marsaglia RNG with processor-unique seed
// same seed that pair_style command initially specified
if (random) delete random;
random = new RanMars(lmp,seed + comm->me);
}
/* ---------------------------------------------------------------------- */
double PairDPD::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_dpd, double &fforce)
{
double r,rinv,wd,phi;
r = sqrt(rsq);
if (r < EPSILON) {
fforce = 0.0;
return 0.0;
}
rinv = 1.0/r;
wd = 1.0 - r/cut[itype][jtype];
fforce = a0[itype][jtype]*wd * factor_dpd*rinv;
phi = 0.5*a0[itype][jtype]*cut[itype][jtype] * wd*wd;
return factor_dpd*phi;
}
diff --git a/src/pair_dpd_tstat.cpp b/src/pair_dpd_tstat.cpp
index cab7a99fa..4151ecc5b 100644
--- a/src/pair_dpd_tstat.cpp
+++ b/src/pair_dpd_tstat.cpp
@@ -1,240 +1,237 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "pair_dpd_tstat.h"
#include "atom.h"
#include "update.h"
#include "force.h"
#include "neigh_list.h"
#include "comm.h"
#include "random_mars.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EPSILON 1.0e-10
/* ---------------------------------------------------------------------- */
PairDPDTstat::PairDPDTstat(LAMMPS *lmp) : PairDPD(lmp)
{
single_enable = 0;
}
/* ---------------------------------------------------------------------- */
void PairDPDTstat::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double vxtmp,vytmp,vztmp,delvx,delvy,delvz;
double rsq,r,rinv,dot,wd,randnum,factor_dpd;
int *ilist,*jlist,*numneigh,**firstneigh;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
// adjust sigma if target T is changing
if (t_start != t_stop) {
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
temperature = t_start + delta * (t_stop-t_start);
double boltz = force->boltz;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++)
sigma[i][j] = sigma[j][i] = sqrt(2.0*boltz*temperature*gamma[i][j]);
}
double **x = atom->x;
double **v = atom->v;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double dtinvsqrt = 1.0/sqrt(update->dt);
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
vxtmp = v[i][0];
vytmp = v[i][1];
vztmp = v[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_dpd = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
if (r < EPSILON) continue; // r can be 0.0 in DPD systems
rinv = 1.0/r;
delvx = vxtmp - v[j][0];
delvy = vytmp - v[j][1];
delvz = vztmp - v[j][2];
dot = delx*delvx + dely*delvy + delz*delvz;
wd = 1.0 - r/cut[itype][jtype];
randnum = random->gaussian();
// drag force = -gamma * wd^2 * (delx dot delv) / r
// random force = sigma * wd * rnd * dtinvsqrt;
fpair = -gamma[itype][jtype]*wd*wd*dot*rinv;
fpair += sigma[itype][jtype]*wd*randnum*dtinvsqrt;
fpair *= factor_dpd*rinv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
0.0,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairDPDTstat::settings(int narg, char **arg)
{
- if (narg != 4) error->all("Illegal pair_style command");
+ if (narg != 4) error->all(FLERR,"Illegal pair_style command");
t_start = force->numeric(arg[0]);
t_stop = force->numeric(arg[1]);
cut_global = force->numeric(arg[2]);
seed = force->inumeric(arg[3]);
temperature = t_start;
// initialize Marsaglia RNG with processor-unique seed
- if (seed <= 0) error->all("Illegal pair_style command");
+ if (seed <= 0) error->all(FLERR,"Illegal pair_style command");
delete random;
random = new RanMars(lmp,seed + comm->me);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairDPDTstat::coeff(int narg, char **arg)
{
- if (narg < 3 || narg > 4) error->all("Incorrect args for pair coefficients");
+ if (narg < 3 || narg > 4) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a0_one = 0.0;
double gamma_one = force->numeric(arg[2]);
double cut_one = cut_global;
if (narg == 4) cut_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a0[i][j] = a0_one;
gamma[i][j] = gamma_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairDPDTstat::write_restart_settings(FILE *fp)
{
fwrite(&t_start,sizeof(double),1,fp);
fwrite(&t_stop,sizeof(double),1,fp);
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&seed,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairDPDTstat::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&t_start,sizeof(double),1,fp);
fread(&t_stop,sizeof(double),1,fp);
fread(&cut_global,sizeof(double),1,fp);
fread(&seed,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&t_start,1,MPI_DOUBLE,0,world);
MPI_Bcast(&t_stop,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&seed,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
// initialize Marsaglia RNG with processor-unique seed
// same seed that pair_style command initially specified
if (random) delete random;
random = new RanMars(lmp,seed + comm->me);
}
diff --git a/src/pair_gauss.cpp b/src/pair_gauss.cpp
index 646a29cdb..4649cdb0e 100644
--- a/src/pair_gauss.cpp
+++ b/src/pair_gauss.cpp
@@ -1,338 +1,335 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Sai Jayaraman (Sandia)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_gauss.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define EPSILON 1.0e-10
/* ---------------------------------------------------------------------- */
PairGauss::PairGauss(LAMMPS *lmp) :Pair(lmp)
{
nextra = 1;
pvector = new double[1];
}
/* ---------------------------------------------------------------------- */
PairGauss::~PairGauss()
{
delete [] pvector;
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(a);
memory->destroy(b);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairGauss::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double r,rsq,r2inv,forcelj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
int occ = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
// define a Gaussian well to be occupied if
// the site it interacts with is within the force maximum
if (eflag_global && rsq < 0.5/b[itype][jtype]) occ++;
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r = sqrt(rsq);
forcelj = - 2.0*a[itype][jtype]*b[itype][jtype] * rsq *
exp(-b[itype][jtype]*rsq);
fpair = forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag)
evdwl = -(a[itype][jtype]*exp(-b[itype][jtype]*rsq) -
offset[itype][jtype]);
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (eflag_global) pvector[0] = occ;
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairGauss::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut_gauss");
memory->create(a,n+1,n+1,"pair:a");
memory->create(b,n+1,n+1,"pair:b");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairGauss::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = atof(arg[0]);
// reset cutoffs that have been explicity set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairGauss::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo, ihi, jlo, jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a_one = atof(arg[2]);
double b_one = atof(arg[3]);
double cut_one = cut_global;
if (narg == 5) cut_one = atof(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j<=jhi; j++) {
a[i][j] = a_one;
b[i][j] = b_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++ ;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairGauss::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
if (offset_flag) offset[i][j] = a[i][j]*exp(-b[i][j]*cut[i][j]*cut[i][j]);
else offset[i][j] = 0.0;
a[j][i] = a[i][j];
b[j][i] = b[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairGauss::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a[i][j],sizeof(double),1,fp);
fwrite(&b[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairGauss::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a[i][j],sizeof(double),1,fp);
fread(&b[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&b[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairGauss::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairGauss::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairGauss::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,forcelj,philj,r;
r = sqrt(rsq);
r2inv = 1.0/rsq;
philj = -(a[itype][jtype]*exp(-b[itype][jtype]*rsq) - offset[itype][jtype]);
forcelj = -2.0*a[itype][jtype]*b[itype][jtype]*rsq*exp(-b[itype][jtype]*rsq);
fforce = forcelj*r2inv;
return philj;
}
/* ---------------------------------------------------------------------- */
void *PairGauss::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"a") == 0) return (void *) a;
return NULL;
}
diff --git a/src/pair_hybrid.cpp b/src/pair_hybrid.cpp
index a57bf3372..97939fef3 100644
--- a/src/pair_hybrid.cpp
+++ b/src/pair_hybrid.cpp
@@ -1,692 +1,689 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "string.h"
#include "ctype.h"
#include "pair_hybrid.h"
#include "atom.h"
#include "force.h"
#include "pair.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "update.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairHybrid::PairHybrid(LAMMPS *lmp) : Pair(lmp)
{
nstyles = 0;
}
/* ---------------------------------------------------------------------- */
PairHybrid::~PairHybrid()
{
if (nstyles) {
for (int m = 0; m < nstyles; m++) delete styles[m];
delete [] styles;
for (int m = 0; m < nstyles; m++) delete [] keywords[m];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cutghost);
memory->destroy(nmap);
memory->destroy(map);
}
}
/* ----------------------------------------------------------------------
call each sub-style's compute function
accumulate sub-style global/peratom energy/virial in hybrid
for global vflag = 1:
each sub-style computes own virial[6]
sum sub-style virial[6] to hybrid's virial[6]
for global vflag = 2:
call sub-style with adjusted vflag to prevent it calling
virial_fdotr_compute()
hybrid calls virial_fdotr_compute() on final accumulated f
------------------------------------------------------------------------- */
void PairHybrid::compute(int eflag, int vflag)
{
int i,j,m,n;
// if no_virial_fdotr_compute is set and global component of
// incoming vflag = 2, then
// reset vflag as if global component were 1
// necessary since one or more sub-styles cannot compute virial as F dot r
if (no_virial_fdotr_compute && vflag % 4 == 2) vflag = 1 + vflag/4 * 4;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = eflag_global = vflag_global =
eflag_atom = vflag_atom = 0;
// check if global component of incoming vflag = 2
// if so, reset vflag passed to substyle as if it were 0
// necessary so substyle will not invoke virial_fdotr_compute()
int vflag_substyle;
if (vflag % 4 == 2) vflag_substyle = vflag/4 * 4;
else vflag_substyle = vflag;
for (m = 0; m < nstyles; m++) {
styles[m]->compute(eflag,vflag_substyle);
if (eflag_global) {
eng_vdwl += styles[m]->eng_vdwl;
eng_coul += styles[m]->eng_coul;
}
if (vflag_global) {
for (n = 0; n < 6; n++) virial[n] += styles[m]->virial[n];
}
if (eflag_atom) {
n = atom->nlocal;
if (force->newton_pair) n += atom->nghost;
double *eatom_substyle = styles[m]->eatom;
for (i = 0; i < n; i++) eatom[i] += eatom_substyle[i];
}
if (vflag_atom) {
n = atom->nlocal;
if (force->newton_pair) n += atom->nghost;
double **vatom_substyle = styles[m]->vatom;
for (i = 0; i < n; i++)
for (j = 0; j < 6; j++)
vatom[i][j] += vatom_substyle[i][j];
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairHybrid::compute_inner()
{
for (int m = 0; m < nstyles; m++)
if (styles[m]->respa_enable) styles[m]->compute_inner();
}
/* ---------------------------------------------------------------------- */
void PairHybrid::compute_middle()
{
for (int m = 0; m < nstyles; m++)
if (styles[m]->respa_enable) styles[m]->compute_middle();
}
/* ---------------------------------------------------------------------- */
void PairHybrid::compute_outer(int eflag, int vflag)
{
for (int m = 0; m < nstyles; m++)
if (styles[m]->respa_enable) styles[m]->compute_outer(eflag,vflag);
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairHybrid::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cutghost,n+1,n+1,"pair:cutghost");
memory->create(nmap,n+1,n+1,"pair:nmap");
memory->create(map,n+1,n+1,nstyles,"pair:map");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
nmap[i][j] = 0;
}
/* ----------------------------------------------------------------------
create one pair style for each arg in list
------------------------------------------------------------------------- */
void PairHybrid::settings(int narg, char **arg)
{
int i,m,istyle;
- if (narg < 1) error->all("Illegal pair_style command");
+ if (narg < 1) error->all(FLERR,"Illegal pair_style command");
// delete old lists, since cannot just change settings
if (nstyles) {
for (m = 0; m < nstyles; m++) delete styles[m];
delete [] styles;
for (m = 0; m < nstyles; m++) delete [] keywords[m];
delete [] keywords;
}
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cutghost);
memory->destroy(nmap);
memory->destroy(map);
}
allocated = 0;
// count sub-styles by skipping numeric args
// exception is 1st arg of style "table", which is non-numeric word
// exception is 1st two args of style "lj/coul", which are non-numeric
// exception is 1st two args of style "buck/coul", which are non-numeric
// exception is 1st arg of reax/c style, which is non-numeric
// need a better way to skip these exceptions
nstyles = 0;
i = 0;
while (i < narg) {
if (strcmp(arg[i],"table") == 0) i++;
if (strcmp(arg[i],"lj/coul") == 0) i += 2;
if (strcmp(arg[i],"buck/coul") == 0) i += 2;
if (strcmp(arg[i],"reax/c") == 0) i++;
i++;
while (i < narg && !isalpha(arg[i][0])) i++;
nstyles++;
}
// allocate list of sub-styles
styles = new Pair*[nstyles];
keywords = new char*[nstyles];
// allocate each sub-style and call its settings() with subset of args
// define subset of args for a sub-style by skipping numeric args
// exception is 1st arg of style "table", which is non-numeric
// exception is 1st two args of style "lj/coul", which are non-numeric
// exception is 1st two args of style "buck/coul", which are non-numeric
// exception is 1st arg of reax/c style, which is non-numeric
// need a better way to skip these exceptions
int dummy;
nstyles = 0;
i = 0;
while (i < narg) {
for (m = 0; m < nstyles; m++)
if (strcmp(arg[i],keywords[m]) == 0)
- error->all("Pair style hybrid cannot use same pair style twice");
+ error->all(FLERR,"Pair style hybrid cannot use same pair style twice");
if (strcmp(arg[i],"hybrid") == 0)
- error->all("Pair style hybrid cannot have hybrid as an argument");
+ error->all(FLERR,"Pair style hybrid cannot have hybrid as an argument");
if (strcmp(arg[i],"none") == 0)
- error->all("Pair style hybrid cannot have none as an argument");
+ error->all(FLERR,"Pair style hybrid cannot have none as an argument");
styles[nstyles] = force->new_pair(arg[i],NULL,dummy);
keywords[nstyles] = new char[strlen(arg[i])+1];
strcpy(keywords[nstyles],arg[i]);
istyle = i;
if (strcmp(arg[i],"table") == 0) i++;
if (strcmp(arg[i],"lj/coul") == 0) i += 2;
if (strcmp(arg[i],"buck/coul") == 0) i += 2;
if (strcmp(arg[i],"reax/c") == 0) i++;
i++;
while (i < narg && !isalpha(arg[i][0])) i++;
styles[nstyles]->settings(i-istyle-1,&arg[istyle+1]);
nstyles++;
}
// set comm_forward, comm_reverse to max of any sub-style
for (m = 0; m < nstyles; m++) {
if (styles[m]) comm_forward = MAX(comm_forward,styles[m]->comm_forward);
if (styles[m]) comm_reverse = MAX(comm_reverse,styles[m]->comm_reverse);
}
// single_enable = 0 if any sub-style = 0
// respa_enable = 1 if any sub-style is set
// no_virial_fdotr_compute = 1 if any sub-style is set
// ghostneigh = 1 if any sub-style is set
for (m = 0; m < nstyles; m++)
if (styles[m]->single_enable == 0) single_enable = 0;
for (m = 0; m < nstyles; m++)
if (styles[m]->respa_enable) respa_enable = 1;
for (m = 0; m < nstyles; m++)
if (styles[m]->no_virial_fdotr_compute) no_virial_fdotr_compute = 1;
for (m = 0; m < nstyles; m++)
if (styles[m]->ghostneigh) ghostneigh = 1;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairHybrid::coeff(int narg, char **arg)
{
- if (narg < 3) error->all("Incorrect args for pair coefficients");
+ if (narg < 3) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
// 3rd arg = pair sub-style name
// allow for "none" as valid sub-style name
int m;
for (m = 0; m < nstyles; m++)
if (strcmp(arg[2],keywords[m]) == 0) break;
int none = 0;
if (m == nstyles) {
if (strcmp(arg[2],"none") == 0) none = 1;
- else error->all("Pair coeff for hybrid has invalid style");
+ else error->all(FLERR,"Pair coeff for hybrid has invalid style");
}
// move 1st/2nd args to 2nd/3rd args
// just copy ptrs, since arg[] points into original input line
arg[2] = arg[1];
arg[1] = arg[0];
// invoke sub-style coeff() starting with 1st arg
if (!none) styles[m]->coeff(narg-1,&arg[1]);
// if sub-style only allows one pair coeff call (with * * and type mapping)
// then unset setflag/map assigned to that style before setting it below
// in case pair coeff for this sub-style is being called for 2nd time
if (!none && styles[m]->one_coeff)
for (int i = 1; i <= atom->ntypes; i++)
for (int j = i; j <= atom->ntypes; j++)
if (nmap[i][j] && map[i][j][0] == m) {
setflag[i][j] = 0;
nmap[i][j] = 0;
}
// set setflag and which type pairs map to which sub-style
// if sub-style is none: set hybrid setflag, wipe out map
// else: set hybrid setflag & map only if substyle setflag is set
// previous mappings are wiped out
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
if (none) {
setflag[i][j] = 1;
nmap[i][j] = 0;
count++;
} else if (styles[m]->setflag[i][j]) {
setflag[i][j] = 1;
nmap[i][j] = 1;
map[i][j][0] = m;
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairHybrid::init_style()
{
int i,m,itype,jtype,used,istyle,skip;
// error if a sub-style is not used
int ntypes = atom->ntypes;
for (istyle = 0; istyle < nstyles; istyle++) {
used = 0;
for (itype = 1; itype <= ntypes; itype++)
for (jtype = itype; jtype <= ntypes; jtype++)
for (m = 0; m < nmap[itype][jtype]; m++)
if (map[itype][jtype][m] == istyle) used = 1;
- if (used == 0) error->all("Pair hybrid sub-style is not used");
+ if (used == 0) error->all(FLERR,"Pair hybrid sub-style is not used");
}
// each sub-style makes its neighbor list request(s)
for (istyle = 0; istyle < nstyles; istyle++) styles[istyle]->init_style();
// create skip lists for each pair neigh request
// any kind of list can have its skip flag set at this stage
for (i = 0; i < neighbor->nrequest; i++) {
if (!neighbor->requests[i]->pair) continue;
// istyle = associated sub-style
for (istyle = 0; istyle < nstyles; istyle++)
if (styles[istyle] == neighbor->requests[i]->requestor) break;
// allocate iskip and ijskip
// initialize so as to skip all pair types
// set ijskip = 0 if type pair matches any entry in sub-style map
// set ijskip = 0 if mixing will assign type pair to this sub-style
// will occur if type pair is currently unassigned
// and both I,I and J,J are assigned to single sub-style
// and sub-style for both I,I and J,J match istyle
// set iskip = 1 only if all ijskip for itype are 1
int *iskip = new int[ntypes+1];
int **ijskip;
memory->create(ijskip,ntypes+1,ntypes+1,"pair_hybrid:ijskip");
for (itype = 1; itype <= ntypes; itype++)
for (jtype = 1; jtype <= ntypes; jtype++)
ijskip[itype][jtype] = 1;
for (itype = 1; itype <= ntypes; itype++)
for (jtype = itype; jtype <= ntypes; jtype++) {
for (m = 0; m < nmap[itype][jtype]; m++)
if (map[itype][jtype][m] == istyle)
ijskip[itype][jtype] = ijskip[jtype][itype] = 0;
if (nmap[itype][jtype] == 0 &&
nmap[itype][itype] == 1 && map[itype][itype][0] == istyle &&
nmap[jtype][jtype] == 1 && map[jtype][jtype][0] == istyle)
ijskip[itype][jtype] = ijskip[jtype][itype] = 0;
}
for (itype = 1; itype <= ntypes; itype++) {
iskip[itype] = 1;
for (jtype = 1; jtype <= ntypes; jtype++)
if (ijskip[itype][jtype] == 0) iskip[itype] = 0;
}
// if any skipping occurs
// set request->skip and copy iskip and ijskip into request
// else delete iskip and ijskip
skip = 0;
for (itype = 1; itype <= ntypes; itype++)
for (jtype = 1; jtype <= ntypes; jtype++)
if (ijskip[itype][jtype] == 1) skip = 1;
if (skip) {
neighbor->requests[i]->skip = 1;
neighbor->requests[i]->iskip = iskip;
neighbor->requests[i]->ijskip = ijskip;
} else {
delete [] iskip;
memory->destroy(ijskip);
}
}
// combine sub-style neigh list requests and create new ones if needed
modify_requests();
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairHybrid::init_one(int i, int j)
{
// if I,J is not set explicitly:
// perform mixing only if I,I sub-style = J,J sub-style
// also require I,I and J,J are both assigned to single sub-style
if (setflag[i][j] == 0) {
if (nmap[i][i] != 1 || nmap[j][j] != 1 || map[i][i][0] != map[j][j][0])
- error->one("All pair coeffs are not set");
+ error->one(FLERR,"All pair coeffs are not set");
nmap[i][j] = 1;
map[i][j][0] = map[i][i][0];
}
// call init/mixing for all sub-styles of I,J
// set cutsq in sub-style just as Pair::init() does via call to init_one()
// set cutghost for I,J and J,I just as sub-style does
// sum tail corrections for I,J
// return max cutoff of all sub-styles assigned to I,J
// if no sub-styles assigned to I,J (pair_coeff none), cutmax = 0.0 returned
double cutmax = 0.0;
cutghost[i][j] = cutghost[j][i] = 0.0;
if (tail_flag) etail_ij = ptail_ij = 0.0;
nmap[j][i] = nmap[i][j];
for (int k = 0; k < nmap[i][j]; k++) {
map[j][i][k] = map[i][j][k];
double cut = styles[map[i][j][k]]->init_one(i,j);
styles[map[i][j][k]]->cutsq[i][j] =
styles[map[i][j][k]]->cutsq[j][i] = cut*cut;
if (styles[map[i][j][k]]->ghostneigh)
cutghost[i][j] = cutghost[j][i] =
MAX(cutghost[i][j],styles[map[i][j][k]]->cutghost[i][j]);
if (tail_flag) {
etail_ij += styles[map[i][j][k]]->etail_ij;
ptail_ij += styles[map[i][j][k]]->ptail_ij;
}
cutmax = MAX(cutmax,cut);
}
return cutmax;
}
/* ----------------------------------------------------------------------
combine sub-style neigh list requests and create new ones if needed
------------------------------------------------------------------------- */
void PairHybrid::modify_requests()
{
int i,j;
NeighRequest *irq,*jrq;
// loop over pair requests only
// if list is skip list and not copy, look for non-skip list of same kind
// if one exists, point at that one via otherlist
// else make new non-skip request of same kind and point at that one
// don't bother to set ID for new request, since pair hybrid ignores list
// only exception is half_from_full:
// ignore it, turn off skip, since it will derive from its skip parent
// after possible new request creation, unset skip flag and otherlist
// for these derived lists: granhistory, rRESPA inner/middle
// this prevents neighbor from treating them as skip lists
// copy list check is for pair style = hybrid/overlay
// which invokes this routine
for (i = 0; i < neighbor->nrequest; i++) {
if (!neighbor->requests[i]->pair) continue;
irq = neighbor->requests[i];
if (irq->skip == 0 || irq->copy) continue;
if (irq->half_from_full) {
irq->skip = 0;
continue;
}
for (j = 0; j < neighbor->nrequest; j++) {
if (!neighbor->requests[j]->pair) continue;
jrq = neighbor->requests[j];
if (irq->same_kind(jrq) && jrq->skip == 0) break;
}
if (j < neighbor->nrequest) irq->otherlist = j;
else {
int newrequest = neighbor->request(this);
neighbor->requests[newrequest]->copy_request(irq);
irq->otherlist = newrequest;
}
if (irq->granhistory || irq->respainner || irq->respamiddle) {
irq->skip = 0;
irq->otherlist = -1;
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairHybrid::write_restart(FILE *fp)
{
fwrite(&nstyles,sizeof(int),1,fp);
// each sub-style writes its settings, but no coeff info
int n;
for (int m = 0; m < nstyles; m++) {
n = strlen(keywords[m]) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(keywords[m],sizeof(char),n,fp);
styles[m]->write_restart_settings(fp);
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairHybrid::read_restart(FILE *fp)
{
int me = comm->me;
if (me == 0) fread(&nstyles,sizeof(int),1,fp);
MPI_Bcast(&nstyles,1,MPI_INT,0,world);
styles = new Pair*[nstyles];
keywords = new char*[nstyles];
// each sub-style is created via new_pair()
// each reads its settings, but no coeff info
int n,dummy;
for (int m = 0; m < nstyles; m++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
keywords[m] = new char[n];
if (me == 0) fread(keywords[m],sizeof(char),n,fp);
MPI_Bcast(keywords[m],n,MPI_CHAR,0,world);
styles[m] = force->new_pair(keywords[m],NULL,dummy);
styles[m]->read_restart_settings(fp);
}
}
/* ----------------------------------------------------------------------
call sub-style to compute single interaction
error if sub-style does not support single() call
since overlay could have multiple sub-styles, sum results explicitly
------------------------------------------------------------------------- */
double PairHybrid::single(int i, int j, int itype, int jtype,
double rsq, double factor_coul, double factor_lj,
double &fforce)
{
if (nmap[itype][jtype] == 0)
- error->one("Invoked pair single on pair style none");
+ error->one(FLERR,"Invoked pair single on pair style none");
double fone;
fforce = 0.0;
double esum = 0.0;
for (int m = 0; m < nmap[itype][jtype]; m++) {
if (rsq < styles[map[itype][jtype][m]]->cutsq[itype][jtype]) {
if (styles[map[itype][jtype][m]]->single_enable == 0)
- error->all("Pair hybrid sub-style does not support single call");
+ error->all(FLERR,"Pair hybrid sub-style does not support single call");
esum += styles[map[itype][jtype][m]]->
single(i,j,itype,jtype,rsq,factor_coul,factor_lj,fone);
fforce += fone;
}
}
return esum;
}
/* ----------------------------------------------------------------------
modify parameters of the pair style
call modify_params of PairHybrid
also pass command args to each sub-style of hybrid
------------------------------------------------------------------------- */
void PairHybrid::modify_params(int narg, char **arg)
{
Pair::modify_params(narg,arg);
for (int m = 0; m < nstyles; m++) styles[m]->modify_params(narg,arg);
}
/* ----------------------------------------------------------------------
memory usage of each sub-style
------------------------------------------------------------------------- */
double PairHybrid::memory_usage()
{
double bytes = maxeatom * sizeof(double);
bytes += maxvatom*6 * sizeof(double);
for (int m = 0; m < nstyles; m++) bytes += styles[m]->memory_usage();
return bytes;
}
/* ----------------------------------------------------------------------
extract a ptr to a particular quantity stored by pair
pass request thru to sub-styles
return first non-NULL result except for cut_coul request
for cut_coul, insure all non-NULL results are equal since required by Kspace
------------------------------------------------------------------------- */
void *PairHybrid::extract(char *str, int &dim)
{
void *cutptr = NULL;
void *ptr;
double cutvalue;
for (int m = 0; m < nstyles; m++) {
ptr = styles[m]->extract(str,dim);
if (ptr && strcmp(str,"cut_coul") == 0) {
double *p_newvalue = (double *) ptr;
double newvalue = *p_newvalue;
if (cutptr && newvalue != cutvalue)
- error->all("Coulomb cutoffs of pair hybrid sub-styles do not match");
+ error->all(FLERR,"Coulomb cutoffs of pair hybrid sub-styles do not match");
cutptr = ptr;
cutvalue = newvalue;
} else if (ptr) return ptr;
}
if (strcmp(str,"cut_coul") == 0) return cutptr;
return NULL;
}
/* ---------------------------------------------------------------------- */
void PairHybrid::reset_dt()
{
for (int m = 0; m < nstyles; m++) styles[m]->reset_dt();
}
/* ----------------------------------------------------------------------
check if itype,jtype maps to sub-style
------------------------------------------------------------------------- */
int PairHybrid::check_ijtype(int itype, int jtype, char *substyle)
{
for (int m = 0; m < nmap[itype][jtype]; m++)
if (strcmp(keywords[map[itype][jtype][m]],substyle) == 0) return 1;
return 0;
}
diff --git a/src/pair_hybrid_overlay.cpp b/src/pair_hybrid_overlay.cpp
index f6b73bffb..4d3e14af3 100644
--- a/src/pair_hybrid_overlay.cpp
+++ b/src/pair_hybrid_overlay.cpp
@@ -1,127 +1,124 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "pair_hybrid_overlay.h"
#include "atom.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairHybridOverlay::PairHybridOverlay(LAMMPS *lmp) : PairHybrid(lmp) {}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairHybridOverlay::coeff(int narg, char **arg)
{
- if (narg < 3) error->all("Incorrect args for pair coefficients");
+ if (narg < 3) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
// 3rd arg = pair sub-style name
// allow for "none" as valid sub-style name
int m;
for (m = 0; m < nstyles; m++)
if (strcmp(arg[2],keywords[m]) == 0) break;
int none = 0;
if (m == nstyles) {
if (strcmp(arg[2],"none") == 0) none = 1;
- else error->all("Pair coeff for hybrid has invalid style");
+ else error->all(FLERR,"Pair coeff for hybrid has invalid style");
}
// move 1st/2nd args to 2nd/3rd args
// just copy ptrs, since arg[] points into original input line
arg[2] = arg[1];
arg[1] = arg[0];
// invoke sub-style coeff() starting with 1st arg
if (!none) styles[m]->coeff(narg-1,&arg[1]);
// set setflag and which type pairs map to which sub-style
// if sub-style is none: set hybrid subflag, wipe out map
// else: set hybrid setflag & map only if substyle setflag is set
// if sub-style is new for type pair, add as multiple mapping
// if sub-style exists for type pair, don't add, just update coeffs
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
if (none) {
setflag[i][j] = 1;
nmap[i][j] = 0;
count++;
} else if (styles[m]->setflag[i][j]) {
int k;
for (k = 0; k < nmap[i][j]; k++)
if (map[i][j][k] == m) break;
if (k == nmap[i][j]) map[i][j][nmap[i][j]++] = m;
setflag[i][j] = 1;
count++;
}
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
combine sub-style neigh list requests and create new ones if needed
------------------------------------------------------------------------- */
void PairHybridOverlay::modify_requests()
{
int i,j;
NeighRequest *irq,*jrq;
// loop over pair requests only
// if a previous list is same kind with same skip attributes
// then make this one a copy list of that one
// works whether both lists are no-skip or yes-skip
// will not point a list at a copy list, but at copy list's parent
for (i = 0; i < neighbor->nrequest; i++) {
if (!neighbor->requests[i]->pair) continue;
irq = neighbor->requests[i];
for (j = 0; j < i; j++) {
if (!neighbor->requests[j]->pair) continue;
jrq = neighbor->requests[j];
if (irq->same_kind(jrq) && irq->same_skip(jrq)) {
irq->copy = 1;
irq->otherlist = j;
break;
}
}
}
// perform same operations on skip lists as pair style = hybrid
PairHybrid::modify_requests();
}
diff --git a/src/pair_lj96_cut.cpp b/src/pair_lj96_cut.cpp
index 758ef0ab5..76f808dd0 100644
--- a/src/pair_lj96_cut.cpp
+++ b/src/pair_lj96_cut.cpp
@@ -1,703 +1,700 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Chuanfu Luo (luochuanfu@gmail.com)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj96_cut.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJ96Cut::PairLJ96Cut(LAMMPS *lmp) : Pair(lmp)
{
respa_enable = 1;
}
/* ---------------------------------------------------------------------- */
PairLJ96Cut::~PairLJ96Cut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJ96Cut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairLJ96Cut::compute_inner()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj,rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = listinner->inum;
ilist = listinner->ilist;
numneigh = listinner->numneigh;
firstneigh = listinner->firstneigh;
double cut_out_on = cut_respa[0];
double cut_out_off = cut_respa[1];
double cut_out_diff = cut_out_off - cut_out_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 - rsw*rsw*(3.0 - 2.0*rsw);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJ96Cut::compute_middle()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj,rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = listmiddle->inum;
ilist = listmiddle->ilist;
numneigh = listmiddle->numneigh;
firstneigh = listmiddle->firstneigh;
double cut_in_off = cut_respa[0];
double cut_in_on = cut_respa[1];
double cut_out_on = cut_respa[2];
double cut_out_off = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_out_diff = cut_out_off - cut_out_on;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJ96Cut::compute_outer(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r3inv,r6inv,forcelj,factor_lj,rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = listouter->inum;
ilist = listouter->ilist;
numneigh = listouter->numneigh;
firstneigh = listouter->firstneigh;
double cut_in_off = cut_respa[2];
double cut_in_on = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
if (rsq > cut_in_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
if (eflag) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
evdwl = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (vflag) {
if (rsq <= cut_in_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
} else if (rsq < cut_in_on_sq)
fpair = factor_lj*forcelj*r2inv;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJ96Cut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJ96Cut::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJ96Cut::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = atof(arg[2]);
double sigma_one = atof(arg[3]);
double cut_one = cut_global;
if (narg == 5) cut_one = atof(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJ96Cut::init_style()
{
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
} else irequest = neighbor->request(this);
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
regular or rRESPA
------------------------------------------------------------------------- */
void PairLJ96Cut::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listinner = ptr;
else if (id == 2) listmiddle = ptr;
else if (id == 3) listouter = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJ96Cut::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
lj1[i][j] = 36.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],9.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,9.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
// check interior rRESPA cutoff
if (cut_respa && cut[i][j] < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig3 = sigma[i][j]*sigma[i][j]*sigma[i][j];
double sig6 = sig3*sig3;
double rc3 = cut[i][j]*cut[i][j]*cut[i][j];
double rc6 = rc3*rc3;
etail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig3 - 2.0*rc3) / (6.0*rc6);
ptail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (3.0*sig3 - 4.0*rc3) / (6.0*rc6);
}
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJ96Cut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJ96Cut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJ96Cut::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJ96Cut::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJ96Cut::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r3inv,r6inv,forcelj,philj;
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
r3inv = sqrt(r6inv);
forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]);
fforce = factor_lj*forcelj*r2inv;
philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) -
offset[itype][jtype];
return factor_lj*philj;
}
diff --git a/src/pair_lj_cubic.cpp b/src/pair_lj_cubic.cpp
index 545e0ab29..df06f7ded 100644
--- a/src/pair_lj_cubic.cpp
+++ b/src/pair_lj_cubic.cpp
@@ -1,361 +1,358 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Aidan Thompson (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_cubic.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
using namespace PairLJCubicConstants;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCubic::PairLJCubic(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJCubic::~PairLJCubic()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(cut_inner);
memory->destroy(cut_inner_sq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
}
}
/* ---------------------------------------------------------------------- */
void PairLJCubic::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
double r,t,rmin;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq <= cut_inner_sq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else {
r = sqrt(rsq);
rmin = sigma[itype][jtype]*RT6TWO;
t = (r - cut_inner[itype][jtype])/rmin;
forcelj = epsilon[itype][jtype]*(-DPHIDS + A3*t*t/2.0)*r/rmin;
}
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq <= cut_inner_sq[itype][jtype])
evdwl = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
else
evdwl = epsilon[itype][jtype]*
(PHIS + DPHIDS*t - A3*t*t*t/6.0);
evdwl *= factor_lj;
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJCubic::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(cut_inner,n+1,n+1,"pair:cut_inner");
memory->create(cut_inner_sq,n+1,n+1,"pair:cut_inner_sq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJCubic::settings(int narg, char **arg)
{
- if (narg != 0) error->all("Illegal pair_style command");
+ if (narg != 0) error->all(FLERR,"Illegal pair_style command");
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = 0.0;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJCubic::coeff(int narg, char **arg)
{
if (narg != 4)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double rmin = sigma_one*RT6TWO;
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_inner[i][j] = rmin*SS;
cut[i][j] = rmin*SM;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJCubic::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut_inner[i][j] = mix_distance(cut_inner[i][i],cut_inner[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
cut_inner_sq[i][j] = cut_inner[i][j]*cut_inner[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
cut_inner[j][i] = cut_inner[i][j];
cut_inner_sq[j][i] = cut_inner_sq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCubic::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_inner[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCubic::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_inner[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_inner[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCubic::write_restart_settings(FILE *fp)
{
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCubic::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJCubic::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcelj,philj;
double r,t;
double rmin;
r2inv = 1.0/rsq;
if (rsq <= cut_inner_sq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else {
r = sqrt(rsq);
rmin = sigma[itype][jtype]*RT6TWO;
t = (r - cut_inner[itype][jtype])/rmin;
forcelj = epsilon[itype][jtype]*(-DPHIDS + A3*t*t/2.0)*r/rmin;
}
fforce = factor_lj*forcelj*r2inv;
if (rsq <= cut_inner_sq[itype][jtype])
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
else
philj = epsilon[itype][jtype]*
(PHIS + DPHIDS*t - A3*t*t*t/6.0);
return factor_lj*philj;
}
diff --git a/src/pair_lj_cut.cpp b/src/pair_lj_cut.cpp
index 5af7e1c89..671d6420c 100644
--- a/src/pair_lj_cut.cpp
+++ b/src/pair_lj_cut.cpp
@@ -1,705 +1,702 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_cut.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "neigh_request.h"
#include "update.h"
#include "integrate.h"
#include "respa.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCut::PairLJCut(LAMMPS *lmp) : Pair(lmp)
{
respa_enable = 1;
}
/* ---------------------------------------------------------------------- */
PairLJCut::~PairLJCut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJCut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ---------------------------------------------------------------------- */
void PairLJCut::compute_inner()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj,rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = listinner->inum;
ilist = listinner->ilist;
numneigh = listinner->numneigh;
firstneigh = listinner->firstneigh;
double cut_out_on = cut_respa[0];
double cut_out_off = cut_respa[1];
double cut_out_diff = cut_out_off - cut_out_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 - rsw*rsw*(3.0 - 2.0*rsw);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCut::compute_middle()
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj,rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = listmiddle->inum;
ilist = listmiddle->ilist;
numneigh = listmiddle->numneigh;
firstneigh = listmiddle->firstneigh;
double cut_in_off = cut_respa[0];
double cut_in_on = cut_respa[1];
double cut_out_on = cut_respa[2];
double cut_out_off = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_out_diff = cut_out_off - cut_out_on;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
double cut_out_on_sq = cut_out_on*cut_out_on;
double cut_out_off_sq = cut_out_off*cut_out_off;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_out_off_sq && rsq > cut_in_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
if (rsq > cut_out_on_sq) {
rsw = (sqrt(rsq) - cut_out_on)/cut_out_diff;
fpair *= 1.0 + rsw*rsw*(2.0*rsw - 3.0);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
}
}
}
/* ---------------------------------------------------------------------- */
void PairLJCut::compute_outer(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj,rsw;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = listouter->inum;
ilist = listouter->ilist;
numneigh = listouter->numneigh;
firstneigh = listouter->firstneigh;
double cut_in_off = cut_respa[2];
double cut_in_on = cut_respa[3];
double cut_in_diff = cut_in_on - cut_in_off;
double cut_in_off_sq = cut_in_off*cut_in_off;
double cut_in_on_sq = cut_in_on*cut_in_on;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
if (rsq > cut_in_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
if (rsq < cut_in_on_sq) {
rsw = (sqrt(rsq) - cut_in_off)/cut_in_diff;
fpair *= rsw*rsw*(3.0 - 2.0*rsw);
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
}
if (eflag) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (vflag) {
if (rsq <= cut_in_off_sq) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj*r2inv;
} else if (rsq < cut_in_on_sq)
fpair = factor_lj*forcelj*r2inv;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJCut::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJCut::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 5) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 5) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_one = cut_global;
if (narg == 5) cut_one = force->numeric(arg[4]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCut::init_style()
{
// request regular or rRESPA neighbor lists
int irequest;
if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) {
int respa = 0;
if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
if (respa == 0) irequest = neighbor->request(this);
else if (respa == 1) {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
} else {
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respainner = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 2;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respamiddle = 1;
irequest = neighbor->request(this);
neighbor->requests[irequest]->id = 3;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->respaouter = 1;
}
} else irequest = neighbor->request(this);
// set rRESPA cutoffs
if (strstr(update->integrate_style,"respa") &&
((Respa *) update->integrate)->level_inner >= 0)
cut_respa = ((Respa *) update->integrate)->cutoff;
else cut_respa = NULL;
}
/* ----------------------------------------------------------------------
neighbor callback to inform pair style of neighbor list to use
regular or rRESPA
------------------------------------------------------------------------- */
void PairLJCut::init_list(int id, NeighList *ptr)
{
if (id == 0) list = ptr;
else if (id == 1) listinner = ptr;
else if (id == 2) listmiddle = ptr;
else if (id == 3) listouter = ptr;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJCut::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
// check interior rRESPA cutoff
if (cut_respa && cut[i][j] < cut_respa[3])
- error->all("Pair cutoff < Respa interior cutoff");
+ error->all(FLERR,"Pair cutoff < Respa interior cutoff");
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig2 = sigma[i][j]*sigma[i][j];
double sig6 = sig2*sig2*sig2;
double rc3 = cut[i][j]*cut[i][j]*cut[i][j];
double rc6 = rc3*rc3;
double rc9 = rc3*rc6;
etail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig6 - 3.0*rc6) / (9.0*rc9);
ptail_ij = 16.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9);
}
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCut::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJCut::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcelj,philj;
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fforce = factor_lj*forcelj*r2inv;
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
return factor_lj*philj;
}
/* ---------------------------------------------------------------------- */
void *PairLJCut::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"epsilon") == 0) return (void *) epsilon;
return NULL;
}
diff --git a/src/pair_lj_cut_coul_cut.cpp b/src/pair_lj_cut_coul_cut.cpp
index efd034482..1d311d4b7 100644
--- a/src/pair_lj_cut_coul_cut.cpp
+++ b/src/pair_lj_cut_coul_cut.cpp
@@ -1,433 +1,430 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_cut_coul_cut.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJCutCoulCut::PairLJCutCoulCut(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJCutCoulCut::~PairLJCutCoulCut()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut_lj);
memory->destroy(cut_ljsq);
memory->destroy(cut_coul);
memory->destroy(cut_coulsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulCut::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype])
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq[itype][jtype])
ecoul = factor_coul * qqrd2e * qtmp*q[j]*sqrt(r2inv);
else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJCutCoulCut::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
memory->create(cut_coul,n+1,n+1,"pair:cut_coul");
memory->create(cut_coulsq,n+1,n+1,"pair:cut_coulsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJCutCoulCut::settings(int narg, char **arg)
{
- if (narg < 1 || narg > 2) error->all("Illegal pair_style command");
+ if (narg < 1 || narg > 2) error->all(FLERR,"Illegal pair_style command");
cut_lj_global = force->numeric(arg[0]);
if (narg == 1) cut_coul_global = cut_lj_global;
else cut_coul_global = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_lj[i][j] = cut_lj_global;
cut_coul[i][j] = cut_coul_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJCutCoulCut::coeff(int narg, char **arg)
{
- if (narg < 4 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 4 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_lj_one = cut_lj_global;
double cut_coul_one = cut_coul_global;
if (narg >= 5) cut_coul_one = cut_lj_one = force->numeric(arg[4]);
if (narg == 6) cut_coul_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_lj[i][j] = cut_lj_one;
cut_coul[i][j] = cut_coul_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJCutCoulCut::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/cut/coul/cut requires atom attribute q");
+ error->all(FLERR,"Pair style lj/cut/coul/cut requires atom attribute q");
neighbor->request(this);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJCutCoulCut::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]);
cut_coul[i][j] = mix_distance(cut_coul[i][i],cut_coul[j][j]);
}
double cut = MAX(cut_lj[i][j],cut_coul[i][j]);
cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
cut_coulsq[i][j] = cut_coul[i][j] * cut_coul[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut_lj[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
cut_ljsq[j][i] = cut_ljsq[i][j];
cut_coulsq[j][i] = cut_coulsq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig2 = sigma[i][j]*sigma[i][j];
double sig6 = sig2*sig2*sig2;
double rc3 = cut_lj[i][j]*cut_lj[i][j]*cut_lj[i][j];
double rc6 = rc3*rc3;
double rc9 = rc3*rc6;
etail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (sig6 - 3.0*rc6) / (9.0*rc9);
ptail_ij = 16.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9);
}
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCutCoulCut::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_lj[i][j],sizeof(double),1,fp);
fwrite(&cut_coul[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCutCoulCut::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_lj[i][j],sizeof(double),1,fp);
fread(&cut_coul[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCutCoulCut::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCutCoulCut::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJCutCoulCut::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcecoul,forcelj,phicoul,philj;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype])
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq[itype][jtype]) {
phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
eng += factor_coul*phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
eng += factor_lj*philj;
}
return eng;
}
diff --git a/src/pair_lj_cut_coul_debye.cpp b/src/pair_lj_cut_coul_debye.cpp
index 1954d0d1f..023d86654 100644
--- a/src/pair_lj_cut_coul_debye.cpp
+++ b/src/pair_lj_cut_coul_debye.cpp
@@ -1,222 +1,222 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_lj_cut_coul_debye.h"
#include "atom.h"
#include "neigh_list.h"
#include "force.h"
#include "comm.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
PairLJCutCoulDebye::PairLJCutCoulDebye(LAMMPS *lmp) : PairLJCutCoulCut(lmp) {}
/* ---------------------------------------------------------------------- */
void PairLJCutCoulDebye::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double r,rinv,screening;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype]) {
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*r);
forcecoul = qqrd2e * qtmp*q[j] * screening * (kappa + rinv);
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fpair = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq[itype][jtype])
ecoul = factor_coul * qqrd2e * qtmp*q[j] * rinv * screening;
else ecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJCutCoulDebye::settings(int narg, char **arg)
{
- if (narg < 2 || narg > 3) error->all("Illegal pair_style command");
+ if (narg < 2 || narg > 3) error->all(FLERR,"Illegal pair_style command");
kappa = force->numeric(arg[0]);
cut_lj_global = force->numeric(arg[1]);
if (narg == 2) cut_coul_global = cut_lj_global;
else cut_coul_global = force->numeric(arg[2]);
// reset cutoffs that were previously set from data file
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j] == 1) {
cut_lj[i][j] = cut_lj_global;
cut_coul[i][j] = cut_coul_global;
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJCutCoulDebye::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_global,sizeof(double),1,fp);
fwrite(&cut_coul_global,sizeof(double),1,fp);
fwrite(&kappa,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJCutCoulDebye::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_global,sizeof(double),1,fp);
fread(&cut_coul_global,sizeof(double),1,fp);
fread(&kappa,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&kappa,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJCutCoulDebye::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,r,rinv,screening,forcecoul,forcelj,phicoul,philj;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq[itype][jtype]) {
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*r);
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j] *
screening * (kappa + rinv);
} else forcecoul = 0.0;
if (rsq < cut_ljsq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
} else forcelj = 0.0;
fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq[itype][jtype]) {
phicoul = force->qqrd2e * atom->q[i]*atom->q[j] * rinv * screening;
eng += factor_coul*phicoul;
}
if (rsq < cut_ljsq[itype][jtype]) {
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
eng += factor_lj*philj;
}
return eng;
}
diff --git a/src/pair_lj_expand.cpp b/src/pair_lj_expand.cpp
index 1f5e659da..57110ac81 100644
--- a/src/pair_lj_expand.cpp
+++ b/src/pair_lj_expand.cpp
@@ -1,391 +1,388 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_expand.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJExpand::PairLJExpand(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJExpand::~PairLJExpand()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(shift);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJExpand::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
double r,rshift,rshiftsq;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
rshift = r - shift[itype][jtype];
rshiftsq = rshift*rshift;
r2inv = 1.0/rshiftsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fpair = factor_lj*forcelj/rshift/r;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJExpand::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(shift,n+1,n+1,"pair:shift");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJExpand::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJExpand::coeff(int narg, char **arg)
{
- if (narg < 5 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double shift_one = force->numeric(arg[4]);
double cut_one = cut_global;
if (narg == 6) cut_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
shift[i][j] = shift_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJExpand::init_one(int i, int j)
{
// always mix shift arithmetically
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
shift[i][j] = 0.5 * (shift[i][i] + shift[j][j]);
}
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (offset_flag) {
double ratio = sigma[i][j] / cut[i][j];
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
} else offset[i][j] = 0.0;
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
shift[j][i] = shift[i][j];
offset[j][i] = offset[i][j];
// compute I,J contribution to long-range tail correction
// count total # of atoms of type I and J via Allreduce
if (tail_flag) {
int *type = atom->type;
int nlocal = atom->nlocal;
double count[2],all[2];
count[0] = count[1] = 0.0;
for (int k = 0; k < nlocal; k++) {
if (type[k] == i) count[0] += 1.0;
if (type[k] == j) count[1] += 1.0;
}
MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
double PI = 4.0*atan(1.0);
double sig2 = sigma[i][j]*sigma[i][j];
double sig6 = sig2*sig2*sig2;
double shiftcut = shift[i][j] - cut[i][j];
double rc3 = shiftcut*shiftcut*shiftcut;
double rc4 = rc3*shiftcut;
double rc5 = rc4*shiftcut;
double rc6 = rc5*shiftcut;
double rc9 = rc6*rc3;
double rc10 = rc9*shiftcut;
double rc11 = rc10*shiftcut;
double rc12 = rc11*shiftcut;
double shift2 = shift[i][j]*shift[i][j];
double shift3 = shift2*shift[i][j];
etail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6*((-1.0/(9.0*rc9) + shift[i][j]/(5.0*rc10) -
shift2/(11.0*rc11))*sig6 +
1.0/(3.0*rc3) - shift[i][j]/(2.0*rc4) + shift2/(5.0*rc5));
ptail_ij = 8.0*PI*all[0]*all[1]*epsilon[i][j] *
sig6* ((-4.0/(3.0*rc9) + 18.0*shift[i][j]/(5.0*rc10) -
36.0*shift2/(11.0*rc11) + shift3/rc12)*sig6 +
2.0/rc3 - 9.0*shift[i][j]/(2.0*rc4) +
18.0*shift2/(5.0*rc5) - shift3/rc6)/3.0;
}
return cut[i][j] + shift[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJExpand::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&shift[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJExpand::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&shift[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&shift[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJExpand::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJExpand::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJExpand::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r,rshift,rshiftsq,r2inv,r6inv,forcelj,philj;
r = sqrt(rsq);
rshift = r - shift[itype][jtype];
rshiftsq = rshift*rshift;
r2inv = 1.0/rshiftsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
fforce = factor_lj*forcelj/rshift/r;
philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
offset[itype][jtype];
return factor_lj*philj;
}
diff --git a/src/pair_lj_gromacs.cpp b/src/pair_lj_gromacs.cpp
index 462c1f2f2..5b43ff2ac 100644
--- a/src/pair_lj_gromacs.cpp
+++ b/src/pair_lj_gromacs.cpp
@@ -1,420 +1,417 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mark Stevens (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_gromacs.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJGromacs::PairLJGromacs(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJGromacs::~PairLJGromacs()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(cut_inner);
memory->destroy(cut_inner_sq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(ljsw1);
memory->destroy(ljsw2);
memory->destroy(ljsw3);
memory->destroy(ljsw4);
memory->destroy(ljsw5);
}
}
/* ---------------------------------------------------------------------- */
void PairLJGromacs::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
double r,t,fswitch,eswitch;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_inner_sq[itype][jtype]) {
r = sqrt(rsq);
t = r - cut_inner[itype][jtype];
fswitch = r*t*t*(ljsw1[itype][jtype] + ljsw2[itype][jtype]*t);
forcelj += fswitch;
}
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
evdwl += ljsw5[itype][jtype];
if (rsq > cut_inner_sq[itype][jtype]) {
eswitch = t*t*t*(ljsw3[itype][jtype] + ljsw4[itype][jtype]*t);
evdwl += eswitch;
}
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJGromacs::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(cut_inner,n+1,n+1,"pair:cut_inner");
memory->create(cut_inner_sq,n+1,n+1,"pair:cut_inner_sq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(ljsw1,n+1,n+1,"pair:ljsw1");
memory->create(ljsw2,n+1,n+1,"pair:ljsw2");
memory->create(ljsw3,n+1,n+1,"pair:ljsw3");
memory->create(ljsw4,n+1,n+1,"pair:ljsw4");
memory->create(ljsw5,n+1,n+1,"pair:ljsw5");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJGromacs::settings(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal pair_style command");
+ if (narg != 2) error->all(FLERR,"Illegal pair_style command");
cut_inner_global = force->numeric(arg[0]);
cut_global = force->numeric(arg[1]);
if (cut_inner_global <= 0.0 || cut_inner_global > cut_global)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_inner[i][j] = cut_inner_global;
cut[i][j] = cut_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJGromacs::coeff(int narg, char **arg)
{
if (narg != 4 && narg != 6)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_inner_one = cut_inner_global;
double cut_one = cut_global;
if (narg == 6) {
cut_inner_one = force->numeric(arg[4]);
cut_one = force->numeric(arg[5]);
}
if (cut_inner_one <= 0.0 || cut_inner_one > cut_one)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_inner[i][j] = cut_inner_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJGromacs::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut_inner[i][j] = mix_distance(cut_inner[i][i],cut_inner[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
cut_inner_sq[i][j] = cut_inner[i][j]*cut_inner[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
double r6inv = 1.0/pow(cut[i][j],6.0);
double r8inv = 1.0/pow(cut[i][j],8.0);
double t = cut[i][j] - cut_inner[i][j];
double t2inv = 1.0/(t*t);
double t3inv = t2inv/t;
double t3 = 1.0/t3inv;
double a6 = (7.0*cut_inner[i][j] - 10.0*cut[i][j])*r8inv*t2inv;
double b6 = (9.0*cut[i][j] - 7.0*cut_inner[i][j])*r8inv*t3inv;
double a12 = (13.0*cut_inner[i][j] - 16.0*cut[i][j])*r6inv*r8inv*t2inv;
double b12 = (15.0*cut[i][j] - 13.0*cut_inner[i][j])*r6inv*r8inv*t3inv;
double c6 = r6inv - t3*(6.0*a6/3.0 + 6.0*b6*t/4.0);
double c12 = r6inv*r6inv - t3*(12.0*a12/3.0 + 12.0*b12*t/4.0);
ljsw1[i][j] = lj1[i][j]*a12 - lj2[i][j]*a6;
ljsw2[i][j] = lj1[i][j]*b12 - lj2[i][j]*b6;
ljsw3[i][j] = -lj3[i][j]*12.0*a12/3.0 + lj4[i][j]*6.0*a6/3.0;
ljsw4[i][j] = -lj3[i][j]*12.0*b12/4.0 + lj4[i][j]*6.0*b6/4.0;
ljsw5[i][j] = -lj3[i][j]*c12 + lj4[i][j]*c6;
cut_inner[j][i] = cut_inner[i][j];
cut_inner_sq[j][i] = cut_inner_sq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
ljsw1[j][i] = ljsw1[i][j];
ljsw2[j][i] = ljsw2[i][j];
ljsw3[j][i] = ljsw3[i][j];
ljsw4[j][i] = ljsw4[i][j];
ljsw5[j][i] = ljsw5[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJGromacs::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_inner[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJGromacs::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_inner[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_inner[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJGromacs::write_restart_settings(FILE *fp)
{
fwrite(&cut_inner_global,sizeof(double),1,fp);
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJGromacs::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_inner_global,sizeof(double),1,fp);
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_inner_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJGromacs::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcelj,philj;
double r,t,fswitch,phiswitch;
r2inv = 1.0/rsq;
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_inner_sq[itype][jtype]) {
r = sqrt(rsq);
t = r - cut_inner[itype][jtype];
fswitch = r*t*t*(ljsw1[itype][jtype] + ljsw2[itype][jtype]*t);
forcelj += fswitch;
}
fforce = factor_lj*forcelj*r2inv;
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
philj += ljsw5[itype][jtype];
if (rsq > cut_inner_sq[itype][jtype]) {
phiswitch = t*t*t*(ljsw3[itype][jtype] + ljsw4[itype][jtype]*t);
philj += phiswitch;
}
return factor_lj*philj;
}
diff --git a/src/pair_lj_gromacs_coul_gromacs.cpp b/src/pair_lj_gromacs_coul_gromacs.cpp
index e60cf8229..af681aeab 100644
--- a/src/pair_lj_gromacs_coul_gromacs.cpp
+++ b/src/pair_lj_gromacs_coul_gromacs.cpp
@@ -1,487 +1,484 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Mark Stevens (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_lj_gromacs_coul_gromacs.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neighbor.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJGromacsCoulGromacs::PairLJGromacsCoulGromacs(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJGromacsCoulGromacs::~PairLJGromacsCoulGromacs()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(ljsw1);
memory->destroy(ljsw2);
memory->destroy(ljsw3);
memory->destroy(ljsw4);
memory->destroy(ljsw5);
}
}
/* ---------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
double rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj;
double r,tlj,tc,fswitch,fswitchcoul,eswitch,ecoulswitch;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = ecoul = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
double *q = atom->q;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_coul = force->special_coul;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
double qqrd2e = force->qqrd2e;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
qtmp = q[i];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
factor_coul = special_coul[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
if (rsq < cut_bothsq) {
r2inv = 1.0/rsq;
// skip if qi or qj = 0.0 since this potential may be used as
// coarse-grain model with many uncharged atoms
if (rsq < cut_coulsq && qtmp != 0.0 && q[j] != 0.0) {
forcecoul = qqrd2e * qtmp*q[j]*sqrt(r2inv);
if (rsq > cut_coul_innersq) {
r = sqrt(rsq);
tc = r - cut_coul_inner;
fswitchcoul = qqrd2e * qtmp*q[j]*r*tc*tc*(coulsw1 + coulsw2*tc);
forcecoul += fswitchcoul;
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
jtype = type[j];
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
r = sqrt(rsq);
tlj = r - cut_lj_inner;
fswitch = r*tlj*tlj*(ljsw1[itype][jtype] +
ljsw2[itype][jtype]*tlj);
forcelj += fswitch;
}
} else forcelj = 0.0;
fpair = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_coulsq) {
ecoul = qqrd2e * qtmp*q[j] * (sqrt(r2inv) - coulsw5);
if (rsq > cut_coul_innersq) {
ecoulswitch = tc*tc*tc * (coulsw3 + coulsw4*tc);
ecoul += qqrd2e*qtmp*q[j]*ecoulswitch;
}
ecoul *= factor_coul;
} else ecoul = 0.0;
if (rsq < cut_ljsq) {
evdwl = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
evdwl += ljsw5[itype][jtype];
if (rsq > cut_lj_innersq) {
eswitch = tlj*tlj*tlj *
(ljsw3[itype][jtype] + ljsw4[itype][jtype]*tlj);
evdwl += eswitch;
}
evdwl *= factor_lj;
} else evdwl = 0.0;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,ecoul,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(ljsw1,n+1,n+1,"pair:ljsw1");
memory->create(ljsw2,n+1,n+1,"pair:ljsw2");
memory->create(ljsw3,n+1,n+1,"pair:ljsw3");
memory->create(ljsw4,n+1,n+1,"pair:ljsw4");
memory->create(ljsw5,n+1,n+1,"pair:ljsw5");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::settings(int narg, char **arg)
{
if (narg != 2 && narg != 4)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
cut_lj_inner = force->numeric(arg[0]);
cut_lj = force->numeric(arg[1]);
if (narg == 2) {
cut_coul_inner = cut_lj_inner;
cut_coul = cut_lj;
} else {
cut_coul_inner = force->numeric(arg[2]);
cut_coul = force->numeric(arg[3]);
}
if (cut_lj_inner <= 0.0 || cut_coul_inner < 0.0)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
if (cut_lj_inner > cut_lj || cut_coul_inner > cut_coul)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::coeff(int narg, char **arg)
{
- if (narg != 4) error->all("Incorrect args for pair coefficients");
+ if (narg != 4) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init specific to this pair style
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::init_style()
{
if (!atom->q_flag)
- error->all("Pair style lj/gromacs/coul/gromacs requires atom attribute q");
+ error->all(FLERR,"Pair style lj/gromacs/coul/gromacs requires atom attribute q");
neighbor->request(this);
cut_lj_innersq = cut_lj_inner * cut_lj_inner;
cut_ljsq = cut_lj * cut_lj;
cut_coul_innersq = cut_coul_inner * cut_coul_inner;
cut_coulsq = cut_coul * cut_coul;
cut_bothsq = MAX(cut_ljsq,cut_coulsq);
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJGromacsCoulGromacs::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
}
double cut = MAX(cut_lj,cut_coul);
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
double r6inv = 1.0/pow(cut_lj,6.0);
double r8inv = 1.0/pow(cut_lj,8.0);
double t = cut_lj - cut_lj_inner;
double t2inv = 1.0/(t*t);
double t3inv = t2inv/t;
double t3 = 1.0/t3inv;
double a6 = (7.0*cut_lj_inner - 10.0*cut_lj)*r8inv*t2inv;
double b6 = (9.0*cut_lj - 7.0*cut_lj_inner)*r8inv*t3inv;
double a12 = (13.0*cut_lj_inner - 16.0*cut_lj)*r6inv*r8inv*t2inv;
double b12 = (15.0*cut_lj - 13.0*cut_lj_inner)*r6inv*r8inv*t3inv;
double c6 = r6inv - t3*(6.0*a6/3.0 + 6.0*b6*t/4.0);
double c12 = r6inv*r6inv - t3*(12.0*a12/3.0 + 12.0*b12*t/4.0);
ljsw1[i][j] = lj1[i][j]*a12 - lj2[i][j]*a6;
ljsw2[i][j] = lj1[i][j]*b12 - lj2[i][j]*b6;
ljsw3[i][j] = -lj3[i][j]*12.0*a12/3.0 + lj4[i][j]*6.0*a6/3.0;
ljsw4[i][j] = -lj3[i][j]*12.0*b12/4.0 + lj4[i][j]*6.0*b6/4.0;
ljsw5[i][j] = -lj3[i][j]*c12 + lj4[i][j]*c6;
double r3inv = 1.0/pow(cut_coul,3.0);
t = cut_coul - cut_coul_inner;
t2inv = 1.0/(t*t);
t3inv = t2inv/t;
double a1 = (2.0*cut_coul_inner - 5.0*cut_coul) * r3inv*t2inv;
double b1 = (4.0*cut_coul - 2.0*cut_coul_inner) * r3inv*t3inv;
coulsw1 = a1;
coulsw2 = b1;
coulsw3 = -a1/3.0;
coulsw4 = -b1/4.0;
coulsw5 = 1.0/cut_coul - t*t*t*(a1/3.0 + b1*t/4.0);
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
ljsw1[j][i] = ljsw1[i][j];
ljsw2[j][i] = ljsw2[i][j];
ljsw3[j][i] = ljsw3[i][j];
ljsw4[j][i] = ljsw4[i][j];
ljsw5[j][i] = ljsw5[i][j];
return cut;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::write_restart_settings(FILE *fp)
{
fwrite(&cut_lj_inner,sizeof(double),1,fp);
fwrite(&cut_lj,sizeof(double),1,fp);
fwrite(&cut_coul_inner,sizeof(double),1,fp);
fwrite(&cut_coul,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJGromacsCoulGromacs::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_lj_inner,sizeof(double),1,fp);
fread(&cut_lj,sizeof(double),1,fp);
fread(&cut_coul_inner,sizeof(double),1,fp);
fread(&cut_coul,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_lj_inner,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_lj,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul_inner,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJGromacsCoulGromacs::single(int i, int j, int itype, int jtype,
double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcecoul,forcelj,phicoul,philj;
double r,tlj,tc,fswitch,phiswitch,fswitchcoul,phiswitchcoul;
r2inv = 1.0/rsq;
if (rsq < cut_coulsq) {
forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv);
if (rsq > cut_coul_innersq) {
r = sqrt(rsq);
tc = r - cut_coul_inner;
fswitchcoul = force->qqrd2e *
atom->q[i]*atom->q[j] * r*tc*tc * (coulsw1 + coulsw2*tc);
forcecoul += fswitchcoul;
}
} else forcecoul = 0.0;
if (rsq < cut_ljsq) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
if (rsq > cut_lj_innersq) {
r = sqrt(rsq);
tlj = r - cut_lj_inner;
fswitch = r*tlj*tlj*(ljsw1[itype][jtype] + ljsw2[itype][jtype]*tlj);
forcelj += fswitch;
}
} else forcelj = 0.0;
fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv;
double eng = 0.0;
if (rsq < cut_coulsq) {
phicoul = force->qqrd2e * atom->q[i]*atom->q[j] * (sqrt(r2inv)-coulsw5);
if (rsq > cut_coul_innersq) {
phiswitchcoul = force->qqrd2e * atom->q[i]*atom->q[j] *
tc*tc*tc * (coulsw3 + coulsw4*tc);
phicoul += phiswitchcoul;
}
eng += factor_coul*phicoul;
}
if (rsq < cut_ljsq) {
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]);
philj += ljsw5[itype][jtype];
if (rsq > cut_lj_innersq) {
phiswitch = tlj*tlj*tlj *
(ljsw3[itype][jtype] + ljsw4[itype][jtype]*tlj);
philj += phiswitch;
}
eng += factor_lj*philj;
}
return eng;
}
diff --git a/src/pair_lj_smooth.cpp b/src/pair_lj_smooth.cpp
index af85406da..de1276991 100644
--- a/src/pair_lj_smooth.cpp
+++ b/src/pair_lj_smooth.cpp
@@ -1,434 +1,431 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Craig Maloney (UCSB)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_lj_smooth.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairLJSmooth::PairLJSmooth(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairLJSmooth::~PairLJSmooth()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(cut_inner);
memory->destroy(cut_inner_sq);
memory->destroy(epsilon);
memory->destroy(sigma);
memory->destroy(lj1);
memory->destroy(lj2);
memory->destroy(lj3);
memory->destroy(lj4);
memory->destroy(ljsw0);
memory->destroy(ljsw1);
memory->destroy(ljsw2);
memory->destroy(ljsw3);
memory->destroy(ljsw4);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairLJSmooth::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r6inv,forcelj,factor_lj;
double r,t,tsq,fskin;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
if (rsq < cut_inner_sq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv-lj2[itype][jtype]);
} else {
r = sqrt(rsq);
t = r - cut_inner[itype][jtype];
tsq = t*t;
fskin = ljsw1[itype][jtype] + ljsw2[itype][jtype]*t +
ljsw3[itype][jtype]*tsq + ljsw4[itype][jtype]*tsq*t;
forcelj = fskin*r;
}
fpair = factor_lj*forcelj*r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (rsq < cut_inner_sq[itype][jtype])
evdwl = r6inv * (lj3[itype][jtype]*r6inv -
lj4[itype][jtype]) - offset[itype][jtype];
else
evdwl = ljsw0[itype][jtype] - ljsw1[itype][jtype]*t -
ljsw2[itype][jtype]*tsq/2.0 - ljsw3[itype][jtype]*tsq*t/3.0 -
ljsw4[itype][jtype]*tsq*tsq/4.0 - offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairLJSmooth::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(cut_inner,n+1,n+1,"pair:cut_inner");
memory->create(cut_inner_sq,n+1,n+1,"pair:cut_inner_sq");
memory->create(epsilon,n+1,n+1,"pair:epsilon");
memory->create(sigma,n+1,n+1,"pair:sigma");
memory->create(lj1,n+1,n+1,"pair:lj1");
memory->create(lj2,n+1,n+1,"pair:lj2");
memory->create(lj3,n+1,n+1,"pair:lj3");
memory->create(lj4,n+1,n+1,"pair:lj4");
memory->create(ljsw0,n+1,n+1,"pair:ljsw0");
memory->create(ljsw1,n+1,n+1,"pair:ljsw1");
memory->create(ljsw2,n+1,n+1,"pair:ljsw2");
memory->create(ljsw3,n+1,n+1,"pair:ljsw3");
memory->create(ljsw4,n+1,n+1,"pair:ljsw4");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairLJSmooth::settings(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal pair_style command");
+ if (narg != 2) error->all(FLERR,"Illegal pair_style command");
cut_inner_global = force->numeric(arg[0]);
cut_global = force->numeric(arg[1]);
if (cut_inner_global <= 0.0 || cut_inner_global > cut_global)
- error->all("Illegal pair_style command");
+ error->all(FLERR,"Illegal pair_style command");
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) {
cut_inner[i][j] = cut_inner_global;
cut[i][j] = cut_global;
}
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairLJSmooth::coeff(int narg, char **arg)
{
if (narg != 4 && narg != 6)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double epsilon_one = force->numeric(arg[2]);
double sigma_one = force->numeric(arg[3]);
double cut_inner_one = cut_inner_global;
double cut_one = cut_global;
if (narg == 6) {
cut_inner_one = force->numeric(arg[4]);
cut_one = force->numeric(arg[5]);
}
if (cut_inner_one <= 0.0 || cut_inner_one > cut_one)
- error->all("Incorrect args for pair coefficients");
+ error->all(FLERR,"Incorrect args for pair coefficients");
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
epsilon[i][j] = epsilon_one;
sigma[i][j] = sigma_one;
cut_inner[i][j] = cut_inner_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairLJSmooth::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
sigma[i][i],sigma[j][j]);
sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
cut_inner[i][j] = mix_distance(cut_inner[i][i],cut_inner[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
cut_inner_sq[i][j] = cut_inner[i][j]*cut_inner[i][j];
lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
if (cut_inner[i][j] != cut[i][j]) {
double r6inv = 1.0/pow(cut_inner[i][j],6.0);
double t = cut[i][j] - cut_inner[i][j];
double tsq = t*t;
double ratio = sigma[i][j] / cut_inner[i][j];
ljsw0[i][j] = 4.0*epsilon[i][j]*(pow(ratio,12.0) - pow(ratio,6.0));
ljsw1[i][j] = r6inv*(lj1[i][j]*r6inv-lj2[i][j]) / cut_inner[i][j];
ljsw2[i][j] = -r6inv * (13.0*lj1[i][j]*r6inv - 7.0*lj2[i][j]) /
cut_inner_sq[i][j];
ljsw3[i][j] = -(3.0/tsq) * (ljsw1[i][j] + 2.0/3.0*ljsw2[i][j]*t);
ljsw4[i][j] = -1.0/(3.0*tsq) * (ljsw2[i][j] + 2.0*ljsw3[i][j]*t);
if (offset_flag)
offset[i][j] = ljsw0[i][j] - ljsw1[i][j]*t - ljsw2[i][j]*tsq/2.0 -
ljsw3[i][j]*tsq*t/3.0 - ljsw4[i][j]*tsq*tsq/4.0;
else offset[i][j] = 0.0;
} else {
ljsw0[i][j] = 0.0;
ljsw1[i][j] = 0.0;
ljsw2[i][j] = 0.0;
ljsw3[i][j] = 0.0;
ljsw4[i][j] = 0.0;
double ratio = sigma[i][j] / cut_inner[i][j];
if (offset_flag)
offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
else offset[i][j] = 0.0;
}
cut_inner[j][i] = cut_inner[i][j];
cut_inner_sq[j][i] = cut_inner_sq[i][j];
lj1[j][i] = lj1[i][j];
lj2[j][i] = lj2[i][j];
lj3[j][i] = lj3[i][j];
lj4[j][i] = lj4[i][j];
ljsw0[j][i] = ljsw0[i][j];
ljsw1[j][i] = ljsw1[i][j];
ljsw2[j][i] = ljsw2[i][j];
ljsw3[j][i] = ljsw3[i][j];
ljsw4[j][i] = ljsw4[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJSmooth::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&epsilon[i][j],sizeof(double),1,fp);
fwrite(&sigma[i][j],sizeof(double),1,fp);
fwrite(&cut_inner[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJSmooth::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&epsilon[i][j],sizeof(double),1,fp);
fread(&sigma[i][j],sizeof(double),1,fp);
fread(&cut_inner[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_inner[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairLJSmooth::write_restart_settings(FILE *fp)
{
fwrite(&cut_inner_global,sizeof(double),1,fp);
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairLJSmooth::read_restart_settings(FILE *fp)
{
int me = comm->me;
if (me == 0) {
fread(&cut_inner_global,sizeof(double),1,fp);
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_inner_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairLJSmooth::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r6inv,forcelj,philj,r,t,tsq,fskin;
r2inv = 1.0/rsq;
if (rsq < cut_inner_sq[itype][jtype]) {
r6inv = r2inv*r2inv*r2inv;
forcelj = r6inv * (lj1[itype][jtype]*r6inv-lj2[itype][jtype]);
} else {
r = sqrt(rsq);
t = r - cut_inner[itype][jtype];
tsq = t*t;
fskin = ljsw1[itype][jtype] + ljsw2[itype][jtype]*t +
ljsw3[itype][jtype]*tsq + ljsw4[itype][jtype]*tsq*t;
forcelj = fskin*r;
}
fforce = factor_lj*forcelj*r2inv;
if (rsq < cut_inner_sq[itype][jtype])
philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]) -
offset[itype][jtype];
else
philj = ljsw0[itype][jtype] - ljsw1[itype][jtype]*t -
ljsw2[itype][jtype]*tsq/2.0 - ljsw3[itype][jtype]*tsq*t/3.0 -
ljsw4[itype][jtype]*tsq*tsq/4.0 - offset[itype][jtype];
return factor_lj*philj;
}
diff --git a/src/pair_morse.cpp b/src/pair_morse.cpp
index 0817fd3fb..d05235a97 100644
--- a/src/pair_morse.cpp
+++ b/src/pair_morse.cpp
@@ -1,326 +1,323 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "pair_morse.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairMorse::PairMorse(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairMorse::~PairMorse()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(cut);
memory->destroy(d0);
memory->destroy(alpha);
memory->destroy(r0);
memory->destroy(morse1);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairMorse::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r,dr,dexp,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
dr = r - r0[itype][jtype];
dexp = exp(-alpha[itype][jtype] * dr);
fpair = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) -
offset[itype][jtype];
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairMorse::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(d0,n+1,n+1,"pair:d0");
memory->create(alpha,n+1,n+1,"pair:alpha");
memory->create(r0,n+1,n+1,"pair:r0");
memory->create(morse1,n+1,n+1,"pair:morse1");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairMorse::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairMorse::coeff(int narg, char **arg)
{
- if (narg < 5 || narg > 6) error->all("Incorrect args for pair coefficients");
+ if (narg < 5 || narg > 6) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double d0_one = force->numeric(arg[2]);
double alpha_one = force->numeric(arg[3]);
double r0_one = force->numeric(arg[4]);
double cut_one = cut_global;
if (narg == 6) cut_one = force->numeric(arg[5]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
d0[i][j] = d0_one;
alpha[i][j] = alpha_one;
r0[i][j] = r0_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairMorse::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
morse1[i][j] = 2.0*d0[i][j]*alpha[i][j];
if (offset_flag) {
double alpha_dr = -alpha[i][j] * (cut[i][j] - r0[i][j]);
offset[i][j] = d0[i][j] * (exp(2.0*alpha_dr) - 2.0*exp(alpha_dr));
} else offset[i][j] = 0.0;
d0[j][i] = d0[i][j];
alpha[j][i] = alpha[i][j];
r0[j][i] = r0[i][j];
morse1[j][i] = morse1[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairMorse::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&d0[i][j],sizeof(double),1,fp);
fwrite(&alpha[i][j],sizeof(double),1,fp);
fwrite(&r0[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairMorse::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&d0[i][j],sizeof(double),1,fp);
fread(&alpha[i][j],sizeof(double),1,fp);
fread(&r0[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&d0[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&alpha[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&r0[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairMorse::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairMorse::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairMorse::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r,dr,dexp,phi;
r = sqrt(rsq);
dr = r - r0[itype][jtype];
dexp = exp(-alpha[itype][jtype] * dr);
fforce = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r;
phi = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) - offset[itype][jtype];
return factor_lj*phi;
}
diff --git a/src/pair_soft.cpp b/src/pair_soft.cpp
index 758a3f041..ce25f4a78 100644
--- a/src/pair_soft.cpp
+++ b/src/pair_soft.cpp
@@ -1,311 +1,308 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pair_soft.h"
#include "atom.h"
#include "comm.h"
#include "force.h"
#include "update.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairSoft::PairSoft(LAMMPS *lmp) : Pair(lmp)
{
PI = 4.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
PairSoft::~PairSoft()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(prefactor);
memory->destroy(cut);
}
}
/* ---------------------------------------------------------------------- */
void PairSoft::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double r,rsq,arg,factor_lj;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r = sqrt(rsq);
arg = PI*r/cut[itype][jtype];
if (r > 0.0) fpair = factor_lj * prefactor[itype][jtype] *
sin(arg) * PI/cut[itype][jtype]/r;
else fpair = 0.0;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag)
evdwl = factor_lj * prefactor[itype][jtype] * (1.0+cos(arg));
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairSoft::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(prefactor,n+1,n+1,"pair:prefactor");
memory->create(cut,n+1,n+1,"pair:cut");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairSoft::settings(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal pair_style command");
+ if (narg != 1) error->all(FLERR,"Illegal pair_style command");
cut_global = force->numeric(arg[0]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairSoft::coeff(int narg, char **arg)
{
- if (narg < 3 || narg > 4) error->all("Incorrect args for pair coefficients");
+ if (narg < 3 || narg > 4) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double prefactor_one = force->numeric(arg[2]);
double cut_one = cut_global;
if (narg == 4) cut_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
prefactor[i][j] = prefactor_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairSoft::init_one(int i, int j)
{
// always mix prefactors geometrically
if (setflag[i][j] == 0) {
prefactor[i][j] = sqrt(prefactor[i][i]*prefactor[j][j]);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
prefactor[j][i] = prefactor[i][j];
cut[j][i] = cut[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairSoft::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&prefactor[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairSoft::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&prefactor[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&prefactor[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairSoft::write_restart_settings(FILE *fp)
{
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairSoft::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&cut_global,sizeof(double),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairSoft::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r,arg,philj;
r = sqrt(rsq);
arg = PI*r/cut[itype][jtype];
fforce = factor_lj * prefactor[itype][jtype] *
sin(arg) * PI/cut[itype][jtype]/r;
philj = prefactor[itype][jtype] * (1.0+cos(arg));
return factor_lj*philj;
}
/* ---------------------------------------------------------------------- */
void *PairSoft::extract(char *str, int &dim)
{
dim = 2;
if (strcmp(str,"a") == 0) return (void *) prefactor;
return NULL;
}
diff --git a/src/pair_table.cpp b/src/pair_table.cpp
index 64e737933..40530b163 100644
--- a/src/pair_table.cpp
+++ b/src/pair_table.cpp
@@ -1,963 +1,960 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "pair_table.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define LOOKUP 0
#define LINEAR 1
#define SPLINE 2
#define BITMAP 3
#define R 1
#define RSQ 2
#define BMP 3
#define MAXLINE 1024
/* ---------------------------------------------------------------------- */
PairTable::PairTable(LAMMPS *lmp) : Pair(lmp)
{
ntables = 0;
tables = NULL;
}
/* ---------------------------------------------------------------------- */
PairTable::~PairTable()
{
for (int m = 0; m < ntables; m++) free_table(&tables[m]);
memory->sfree(tables);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(tabindex);
}
}
/* ---------------------------------------------------------------------- */
void PairTable::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype,itable;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,factor_lj,fraction,value,a,b;
int *ilist,*jlist,*numneigh,**firstneigh;
Table *tb;
union_int_float_t rsq_lookup;
int tlm1 = tablength - 1;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor_lj = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
tb = &tables[tabindex[itype][jtype]];
if (rsq < tb->innersq)
- error->one("Pair distance < table inner cutoff");
+ error->one(FLERR,"Pair distance < table inner cutoff");
if (tabstyle == LOOKUP) {
itable = static_cast<int> ((rsq - tb->innersq) * tb->invdelta);
if (itable >= tlm1)
- error->one("Pair distance > table outer cutoff");
+ error->one(FLERR,"Pair distance > table outer cutoff");
fpair = factor_lj * tb->f[itable];
} else if (tabstyle == LINEAR) {
itable = static_cast<int> ((rsq - tb->innersq) * tb->invdelta);
if (itable >= tlm1)
- error->one("Pair distance > table outer cutoff");
+ error->one(FLERR,"Pair distance > table outer cutoff");
fraction = (rsq - tb->rsq[itable]) * tb->invdelta;
value = tb->f[itable] + fraction*tb->df[itable];
fpair = factor_lj * value;
} else if (tabstyle == SPLINE) {
itable = static_cast<int> ((rsq - tb->innersq) * tb->invdelta);
if (itable >= tlm1)
- error->one("Pair distance > table outer cutoff");
+ error->one(FLERR,"Pair distance > table outer cutoff");
b = (rsq - tb->rsq[itable]) * tb->invdelta;
a = 1.0 - b;
value = a * tb->f[itable] + b * tb->f[itable+1] +
((a*a*a-a)*tb->f2[itable] + (b*b*b-b)*tb->f2[itable+1]) *
tb->deltasq6;
fpair = factor_lj * value;
} else {
rsq_lookup.f = rsq;
itable = rsq_lookup.i & tb->nmask;
itable >>= tb->nshiftbits;
fraction = (rsq_lookup.f - tb->rsq[itable]) * tb->drsq[itable];
value = tb->f[itable] + fraction*tb->df[itable];
fpair = factor_lj * value;
}
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
if (tabstyle == LOOKUP)
evdwl = tb->e[itable];
else if (tabstyle == LINEAR || tabstyle == BITMAP)
evdwl = tb->e[itable] + fraction*tb->de[itable];
else
evdwl = a * tb->e[itable] + b * tb->e[itable+1] +
((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) *
tb->deltasq6;
evdwl *= factor_lj;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairTable::allocate()
{
allocated = 1;
int nt = atom->ntypes;
memory->create(setflag,nt+1,nt+1,"pair:setflag");
for (int i = 1; i <= nt; i++)
for (int j = i; j <= nt; j++)
setflag[i][j] = 0;
memory->create(cutsq,nt+1,nt+1,"pair:cutsq");
memory->create(tabindex,nt+1,nt+1,"pair:tabindex");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairTable::settings(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal pair_style command");
+ if (narg != 2) error->all(FLERR,"Illegal pair_style command");
// new settings
if (strcmp(arg[0],"lookup") == 0) tabstyle = LOOKUP;
else if (strcmp(arg[0],"linear") == 0) tabstyle = LINEAR;
else if (strcmp(arg[0],"spline") == 0) tabstyle = SPLINE;
else if (strcmp(arg[0],"bitmap") == 0) tabstyle = BITMAP;
- else error->all("Unknown table style in pair_style command");
+ else error->all(FLERR,"Unknown table style in pair_style command");
tablength = force->inumeric(arg[1]);
- if (tablength < 2) error->all("Illegal number of pair table entries");
+ if (tablength < 2) error->all(FLERR,"Illegal number of pair table entries");
// delete old tables, since cannot just change settings
for (int m = 0; m < ntables; m++) free_table(&tables[m]);
memory->sfree(tables);
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(tabindex);
}
allocated = 0;
ntables = 0;
tables = NULL;
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairTable::coeff(int narg, char **arg)
{
- if (narg != 4 && narg != 5) error->all("Illegal pair_coeff command");
+ if (narg != 4 && narg != 5) error->all(FLERR,"Illegal pair_coeff command");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
int me;
MPI_Comm_rank(world,&me);
tables = (Table *)
memory->srealloc(tables,(ntables+1)*sizeof(Table),"pair:tables");
Table *tb = &tables[ntables];
null_table(tb);
if (me == 0) read_table(tb,arg[2],arg[3]);
bcast_table(tb);
// set table cutoff
if (narg == 5) tb->cut = force->numeric(arg[4]);
else if (tb->rflag) tb->cut = tb->rhi;
else tb->cut = tb->rfile[tb->ninput-1];
// error check on table parameters
// insure cutoff is within table
// for BITMAP tables, file values can be in non-ascending order
- if (tb->ninput <= 1) error->one("Invalid pair table length");
+ if (tb->ninput <= 1) error->one(FLERR,"Invalid pair table length");
double rlo,rhi;
if (tb->rflag == 0) {
rlo = tb->rfile[0];
rhi = tb->rfile[tb->ninput-1];
} else {
rlo = tb->rlo;
rhi = tb->rhi;
}
- if (tb->cut <= rlo || tb->cut > rhi) error->all("Invalid pair table cutoff");
- if (rlo <= 0.0) error->all("Invalid pair table cutoff");
+ if (tb->cut <= rlo || tb->cut > rhi) error->all(FLERR,"Invalid pair table cutoff");
+ if (rlo <= 0.0) error->all(FLERR,"Invalid pair table cutoff");
// match = 1 if don't need to spline read-in tables
// this is only the case if r values needed by final tables
// exactly match r values read from file
// for tabstyle SPLINE, always need to build spline tables
tb->match = 0;
if (tabstyle == LINEAR && tb->ninput == tablength &&
tb->rflag == RSQ && tb->rhi == tb->cut) tb->match = 1;
if (tabstyle == BITMAP && tb->ninput == 1 << tablength &&
tb->rflag == BMP && tb->rhi == tb->cut) tb->match = 1;
if (tb->rflag == BMP && tb->match == 0)
- error->all("Bitmapped table in file does not match requested table");
+ error->all(FLERR,"Bitmapped table in file does not match requested table");
// spline read-in values and compute r,e,f vectors within table
if (tb->match == 0) spline_table(tb);
compute_table(tb);
// store ptr to table in tabindex
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
tabindex[i][j] = ntables;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Illegal pair_coeff command");
+ if (count == 0) error->all(FLERR,"Illegal pair_coeff command");
ntables++;
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairTable::init_one(int i, int j)
{
- if (setflag[i][j] == 0) error->all("All pair coeffs are not set");
+ if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
tabindex[j][i] = tabindex[i][j];
return tables[tabindex[i][j]].cut;
}
/* ----------------------------------------------------------------------
read a table section from a tabulated potential file
only called by proc 0
this function sets these values in Table:
ninput,rfile,efile,ffile,rflag,rlo,rhi,fpflag,fplo,fphi,ntablebits
------------------------------------------------------------------------- */
void PairTable::read_table(Table *tb, char *file, char *keyword)
{
char line[MAXLINE];
// open file
FILE *fp = fopen(file,"r");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
// loop until section found with matching keyword
while (1) {
if (fgets(line,MAXLINE,fp) == NULL)
- error->one("Did not find keyword in table file");
+ error->one(FLERR,"Did not find keyword in table file");
if (strspn(line," \t\n\r") == strlen(line)) continue; // blank line
if (line[0] == '#') continue; // comment
if (strstr(line,keyword) == line) break; // matching keyword
fgets(line,MAXLINE,fp); // no match, skip section
param_extract(tb,line);
fgets(line,MAXLINE,fp);
for (int i = 0; i < tb->ninput; i++) fgets(line,MAXLINE,fp);
}
// read args on 2nd line of section
// allocate table arrays for file values
fgets(line,MAXLINE,fp);
param_extract(tb,line);
memory->create(tb->rfile,tb->ninput,"pair:rfile");
memory->create(tb->efile,tb->ninput,"pair:efile");
memory->create(tb->ffile,tb->ninput,"pair:ffile");
// setup bitmap parameters for table to read in
tb->ntablebits = 0;
int masklo,maskhi,nmask,nshiftbits;
if (tb->rflag == BMP) {
while (1 << tb->ntablebits < tb->ninput) tb->ntablebits++;
if (1 << tb->ntablebits != tb->ninput)
- error->one("Bitmapped table is incorrect length in table file");
+ error->one(FLERR,"Bitmapped table is incorrect length in table file");
init_bitmap(tb->rlo,tb->rhi,tb->ntablebits,masklo,maskhi,nmask,nshiftbits);
}
// read r,e,f table values from file
// if rflag set, compute r
// if rflag not set, use r from file
int itmp;
double rtmp;
union_int_float_t rsq_lookup;
fgets(line,MAXLINE,fp);
for (int i = 0; i < tb->ninput; i++) {
fgets(line,MAXLINE,fp);
sscanf(line,"%d %lg %lg %lg",&itmp,&rtmp,&tb->efile[i],&tb->ffile[i]);
if (tb->rflag == R)
rtmp = tb->rlo + (tb->rhi - tb->rlo)*i/(tb->ninput-1);
else if (tb->rflag == RSQ) {
rtmp = tb->rlo*tb->rlo +
(tb->rhi*tb->rhi - tb->rlo*tb->rlo)*i/(tb->ninput-1);
rtmp = sqrt(rtmp);
} else if (tb->rflag == BMP) {
rsq_lookup.i = i << nshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tb->rlo*tb->rlo) {
rsq_lookup.i = i << nshiftbits;
rsq_lookup.i |= maskhi;
}
rtmp = sqrtf(rsq_lookup.f);
}
tb->rfile[i] = rtmp;
}
// close file
fclose(fp);
}
/* ----------------------------------------------------------------------
broadcast read-in table info from proc 0 to other procs
this function communicates these values in Table:
ninput,rfile,efile,ffile,rflag,rlo,rhi,fpflag,fplo,fphi
------------------------------------------------------------------------- */
void PairTable::bcast_table(Table *tb)
{
MPI_Bcast(&tb->ninput,1,MPI_INT,0,world);
int me;
MPI_Comm_rank(world,&me);
if (me > 0) {
memory->create(tb->rfile,tb->ninput,"pair:rfile");
memory->create(tb->efile,tb->ninput,"pair:efile");
memory->create(tb->ffile,tb->ninput,"pair:ffile");
}
MPI_Bcast(tb->rfile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(tb->efile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(tb->ffile,tb->ninput,MPI_DOUBLE,0,world);
MPI_Bcast(&tb->rflag,1,MPI_INT,0,world);
if (tb->rflag) {
MPI_Bcast(&tb->rlo,1,MPI_DOUBLE,0,world);
MPI_Bcast(&tb->rhi,1,MPI_DOUBLE,0,world);
}
MPI_Bcast(&tb->fpflag,1,MPI_INT,0,world);
if (tb->fpflag) {
MPI_Bcast(&tb->fplo,1,MPI_DOUBLE,0,world);
MPI_Bcast(&tb->fphi,1,MPI_DOUBLE,0,world);
}
}
/* ----------------------------------------------------------------------
build spline representation of e,f over entire range of read-in table
this function sets these values in Table: e2file,f2file
------------------------------------------------------------------------- */
void PairTable::spline_table(Table *tb)
{
memory->create(tb->e2file,tb->ninput,"pair:e2file");
memory->create(tb->f2file,tb->ninput,"pair:f2file");
double ep0 = - tb->ffile[0];
double epn = - tb->ffile[tb->ninput-1];
spline(tb->rfile,tb->efile,tb->ninput,ep0,epn,tb->e2file);
if (tb->fpflag == 0) {
tb->fplo = (tb->ffile[1] - tb->ffile[0]) / (tb->rfile[1] - tb->rfile[0]);
tb->fphi = (tb->ffile[tb->ninput-1] - tb->ffile[tb->ninput-2]) /
(tb->rfile[tb->ninput-1] - tb->rfile[tb->ninput-2]);
}
double fp0 = tb->fplo;
double fpn = tb->fphi;
spline(tb->rfile,tb->ffile,tb->ninput,fp0,fpn,tb->f2file);
}
/* ----------------------------------------------------------------------
extract attributes from parameter line in table section
format of line: N value R/RSQ/BITMAP lo hi FP fplo fphi
N is required, other params are optional
------------------------------------------------------------------------- */
void PairTable::param_extract(Table *tb, char *line)
{
tb->ninput = 0;
tb->rflag = 0;
tb->fpflag = 0;
char *word = strtok(line," \t\n\r\f");
while (word) {
if (strcmp(word,"N") == 0) {
word = strtok(NULL," \t\n\r\f");
tb->ninput = atoi(word);
} else if (strcmp(word,"R") == 0 || strcmp(word,"RSQ") == 0 ||
strcmp(word,"BITMAP") == 0) {
if (strcmp(word,"R") == 0) tb->rflag = R;
else if (strcmp(word,"RSQ") == 0) tb->rflag = RSQ;
else if (strcmp(word,"BITMAP") == 0) tb->rflag = BMP;
word = strtok(NULL," \t\n\r\f");
tb->rlo = atof(word);
word = strtok(NULL," \t\n\r\f");
tb->rhi = atof(word);
} else if (strcmp(word,"FP") == 0) {
tb->fpflag = 1;
word = strtok(NULL," \t\n\r\f");
tb->fplo = atof(word);
word = strtok(NULL," \t\n\r\f");
tb->fphi = atof(word);
} else {
printf("WORD: %s\n",word);
- error->one("Invalid keyword in pair table parameters");
+ error->one(FLERR,"Invalid keyword in pair table parameters");
}
word = strtok(NULL," \t\n\r\f");
}
- if (tb->ninput == 0) error->one("Pair table parameters did not set N");
+ if (tb->ninput == 0) error->one(FLERR,"Pair table parameters did not set N");
}
/* ----------------------------------------------------------------------
compute r,e,f vectors from splined values
------------------------------------------------------------------------- */
void PairTable::compute_table(Table *tb)
{
int tlm1 = tablength-1;
// inner = inner table bound
// cut = outer table bound
// delta = table spacing in rsq for N-1 bins
double inner;
if (tb->rflag) inner = tb->rlo;
else inner = tb->rfile[0];
tb->innersq = inner*inner;
tb->delta = (tb->cut*tb->cut - tb->innersq) / tlm1;
tb->invdelta = 1.0/tb->delta;
// direct lookup tables
// N-1 evenly spaced bins in rsq from inner to cut
// e,f = value at midpt of bin
// e,f are N-1 in length since store 1 value at bin midpt
// f is converted to f/r when stored in f[i]
// e,f are never a match to read-in values, always computed via spline interp
if (tabstyle == LOOKUP) {
memory->create(tb->e,tlm1,"pair:e");
memory->create(tb->f,tlm1,"pair:f");
double r,rsq;
for (int i = 0; i < tlm1; i++) {
rsq = tb->innersq + (i+0.5)*tb->delta;
r = sqrt(rsq);
tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r);
tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r;
}
}
// linear tables
// N-1 evenly spaced bins in rsq from inner to cut
// rsq,e,f = value at lower edge of bin
// de,df values = delta from lower edge to upper edge of bin
// rsq,e,f are N in length so de,df arrays can compute difference
// f is converted to f/r when stored in f[i]
// e,f can match read-in values, else compute via spline interp
if (tabstyle == LINEAR) {
memory->create(tb->rsq,tablength,"pair:rsq");
memory->create(tb->e,tablength,"pair:e");
memory->create(tb->f,tablength,"pair:f");
memory->create(tb->de,tlm1,"pair:de");
memory->create(tb->df,tlm1,"pair:df");
double r,rsq;
for (int i = 0; i < tablength; i++) {
rsq = tb->innersq + i*tb->delta;
r = sqrt(rsq);
tb->rsq[i] = rsq;
if (tb->match) {
tb->e[i] = tb->efile[i];
tb->f[i] = tb->ffile[i]/r;
} else {
tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r);
tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r;
}
}
for (int i = 0; i < tlm1; i++) {
tb->de[i] = tb->e[i+1] - tb->e[i];
tb->df[i] = tb->f[i+1] - tb->f[i];
}
}
// cubic spline tables
// N-1 evenly spaced bins in rsq from inner to cut
// rsq,e,f = value at lower edge of bin
// e2,f2 = spline coefficient for each bin
// rsq,e,f,e2,f2 are N in length so have N-1 spline bins
// f is converted to f/r after e is splined
// e,f can match read-in values, else compute via spline interp
if (tabstyle == SPLINE) {
memory->create(tb->rsq,tablength,"pair:rsq");
memory->create(tb->e,tablength,"pair:e");
memory->create(tb->f,tablength,"pair:f");
memory->create(tb->e2,tablength,"pair:e2");
memory->create(tb->f2,tablength,"pair:f2");
tb->deltasq6 = tb->delta*tb->delta / 6.0;
double r,rsq;
for (int i = 0; i < tablength; i++) {
rsq = tb->innersq + i*tb->delta;
r = sqrt(rsq);
tb->rsq[i] = rsq;
if (tb->match) {
tb->e[i] = tb->efile[i];
tb->f[i] = tb->ffile[i]/r;
} else {
tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r);
tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r);
}
}
// ep0,epn = dE/dr at inner and at cut
double ep0 = - tb->f[0];
double epn = - tb->f[tlm1];
spline(tb->rsq,tb->e,tablength,ep0,epn,tb->e2);
// fp0,fpn = dh/dg at inner and at cut
// h(r) = f(r)/r and g(r) = r^2
// dh/dg = (1/r df/dr - f/r^2) / 2r
// dh/dg in secant approx = (f(r2)/r2 - f(r1)/r1) / (g(r2) - g(r1))
double fp0,fpn;
double secant_factor = 0.1;
if (tb->fpflag) fp0 = (tb->fplo/sqrt(tb->innersq) - tb->f[0]/tb->innersq) /
(2.0 * sqrt(tb->innersq));
else {
double rsq1 = tb->innersq;
double rsq2 = rsq1 + secant_factor*tb->delta;
fp0 = (splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,sqrt(rsq2)) /
sqrt(rsq2) - tb->f[0] / sqrt(rsq1)) / (secant_factor*tb->delta);
}
if (tb->fpflag && tb->cut == tb->rfile[tb->ninput-1]) fpn =
(tb->fphi/tb->cut - tb->f[tlm1]/(tb->cut*tb->cut)) / (2.0 * tb->cut);
else {
double rsq2 = tb->cut * tb->cut;
double rsq1 = rsq2 - secant_factor*tb->delta;
fpn = (tb->f[tlm1] / sqrt(rsq2) -
splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,sqrt(rsq1)) /
sqrt(rsq1)) / (secant_factor*tb->delta);
}
for (int i = 0; i < tablength; i++) tb->f[i] /= sqrt(tb->rsq[i]);
spline(tb->rsq,tb->f,tablength,fp0,fpn,tb->f2);
}
// bitmapped linear tables
// 2^N bins from inner to cut, spaced in bitmapped manner
// f is converted to f/r when stored in f[i]
// e,f can match read-in values, else compute via spline interp
if (tabstyle == BITMAP) {
double r;
union_int_float_t rsq_lookup;
int masklo,maskhi;
// linear lookup tables of length ntable = 2^n
// stored value = value at lower edge of bin
init_bitmap(inner,tb->cut,tablength,masklo,maskhi,tb->nmask,tb->nshiftbits);
int ntable = 1 << tablength;
int ntablem1 = ntable - 1;
memory->create(tb->rsq,ntable,"pair:rsq");
memory->create(tb->e,ntable,"pair:e");
memory->create(tb->f,ntable,"pair:f");
memory->create(tb->de,ntable,"pair:de");
memory->create(tb->df,ntable,"pair:df");
memory->create(tb->drsq,ntable,"pair:drsq");
union_int_float_t minrsq_lookup;
minrsq_lookup.i = 0 << tb->nshiftbits;
minrsq_lookup.i |= maskhi;
for (int i = 0; i < ntable; i++) {
rsq_lookup.i = i << tb->nshiftbits;
rsq_lookup.i |= masklo;
if (rsq_lookup.f < tb->innersq) {
rsq_lookup.i = i << tb->nshiftbits;
rsq_lookup.i |= maskhi;
}
r = sqrtf(rsq_lookup.f);
tb->rsq[i] = rsq_lookup.f;
if (tb->match) {
tb->e[i] = tb->efile[i];
tb->f[i] = tb->ffile[i]/r;
} else {
tb->e[i] = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r);
tb->f[i] = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r;
}
minrsq_lookup.f = MIN(minrsq_lookup.f,rsq_lookup.f);
}
tb->innersq = minrsq_lookup.f;
for (int i = 0; i < ntablem1; i++) {
tb->de[i] = tb->e[i+1] - tb->e[i];
tb->df[i] = tb->f[i+1] - tb->f[i];
tb->drsq[i] = 1.0/(tb->rsq[i+1] - tb->rsq[i]);
}
// get the delta values for the last table entries
// tables are connected periodically between 0 and ntablem1
tb->de[ntablem1] = tb->e[0] - tb->e[ntablem1];
tb->df[ntablem1] = tb->f[0] - tb->f[ntablem1];
tb->drsq[ntablem1] = 1.0/(tb->rsq[0] - tb->rsq[ntablem1]);
// get the correct delta values at itablemax
// smallest r is in bin itablemin
// largest r is in bin itablemax, which is itablemin-1,
// or ntablem1 if itablemin=0
// deltas at itablemax only needed if corresponding rsq < cut*cut
// if so, compute deltas between rsq and cut*cut
// if tb->match, data at cut*cut is unavailable, so we'll take
// deltas at itablemax-1 as a good approximation
double e_tmp,f_tmp;
int itablemin = minrsq_lookup.i & tb->nmask;
itablemin >>= tb->nshiftbits;
int itablemax = itablemin - 1;
if (itablemin == 0) itablemax = ntablem1;
int itablemaxm1 = itablemax - 1;
if (itablemax == 0) itablemaxm1 = ntablem1;
rsq_lookup.i = itablemax << tb->nshiftbits;
rsq_lookup.i |= maskhi;
if (rsq_lookup.f < tb->cut*tb->cut) {
if (tb->match) {
tb->de[itablemax] = tb->de[itablemaxm1];
tb->df[itablemax] = tb->df[itablemaxm1];
tb->drsq[itablemax] = tb->drsq[itablemaxm1];
} else {
rsq_lookup.f = tb->cut*tb->cut;
r = sqrtf(rsq_lookup.f);
e_tmp = splint(tb->rfile,tb->efile,tb->e2file,tb->ninput,r);
f_tmp = splint(tb->rfile,tb->ffile,tb->f2file,tb->ninput,r)/r;
tb->de[itablemax] = e_tmp - tb->e[itablemax];
tb->df[itablemax] = f_tmp - tb->f[itablemax];
tb->drsq[itablemax] = 1.0/(rsq_lookup.f - tb->rsq[itablemax]);
}
}
}
}
/* ----------------------------------------------------------------------
set all ptrs in a table to NULL, so can be freed safely
------------------------------------------------------------------------- */
void PairTable::null_table(Table *tb)
{
tb->rfile = tb->efile = tb->ffile = NULL;
tb->e2file = tb->f2file = NULL;
tb->rsq = tb->drsq = tb->e = tb->de = NULL;
tb->f = tb->df = tb->e2 = tb->f2 = NULL;
}
/* ----------------------------------------------------------------------
free all arrays in a table
------------------------------------------------------------------------- */
void PairTable::free_table(Table *tb)
{
memory->destroy(tb->rfile);
memory->destroy(tb->efile);
memory->destroy(tb->ffile);
memory->destroy(tb->e2file);
memory->destroy(tb->f2file);
memory->destroy(tb->rsq);
memory->destroy(tb->drsq);
memory->destroy(tb->e);
memory->destroy(tb->de);
memory->destroy(tb->f);
memory->destroy(tb->df);
memory->destroy(tb->e2);
memory->destroy(tb->f2);
}
/* ----------------------------------------------------------------------
spline and splint routines modified from Numerical Recipes
------------------------------------------------------------------------- */
void PairTable::spline(double *x, double *y, int n,
double yp1, double ypn, double *y2)
{
int i,k;
double p,qn,sig,un;
double *u = new double[n];
if (yp1 > 0.99e30) y2[0] = u[0] = 0.0;
else {
y2[0] = -0.5;
u[0] = (3.0/(x[1]-x[0])) * ((y[1]-y[0]) / (x[1]-x[0]) - yp1);
}
for (i = 1; i < n-1; i++) {
sig = (x[i]-x[i-1]) / (x[i+1]-x[i-1]);
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 (ypn > 0.99e30) qn = un = 0.0;
else {
qn = 0.5;
un = (3.0/(x[n-1]-x[n-2])) * (ypn - (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 (k = n-2; k >= 0; k--) y2[k] = y2[k]*y2[k+1] + u[k];
delete [] u;
}
/* ---------------------------------------------------------------------- */
double PairTable::splint(double *xa, double *ya, double *y2a, int n, double x)
{
int klo,khi,k;
double h,b,a,y;
klo = 0;
khi = n-1;
while (khi-klo > 1) {
k = (khi+klo) >> 1;
if (xa[k] > x) khi = k;
else klo = k;
}
h = xa[khi]-xa[klo];
a = (xa[khi]-x) / h;
b = (x-xa[klo]) / h;
y = a*ya[klo] + b*ya[khi] +
((a*a*a-a)*y2a[klo] + (b*b*b-b)*y2a[khi]) * (h*h)/6.0;
return y;
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairTable::write_restart(FILE *fp)
{
write_restart_settings(fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairTable::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairTable::write_restart_settings(FILE *fp)
{
fwrite(&tabstyle,sizeof(int),1,fp);
fwrite(&tablength,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairTable::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&tabstyle,sizeof(int),1,fp);
fread(&tablength,sizeof(int),1,fp);
}
MPI_Bcast(&tabstyle,1,MPI_DOUBLE,0,world);
MPI_Bcast(&tablength,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairTable::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
int itable;
double fraction,value,a,b,phi;
int tlm1 = tablength - 1;
Table *tb = &tables[tabindex[itype][jtype]];
- if (rsq < tb->innersq) error->one("Pair distance < table inner cutoff");
+ if (rsq < tb->innersq) error->one(FLERR,"Pair distance < table inner cutoff");
if (tabstyle == LOOKUP) {
itable = static_cast<int> ((rsq-tb->innersq) * tb->invdelta);
- if (itable >= tlm1) error->one("Pair distance > table outer cutoff");
+ if (itable >= tlm1) error->one(FLERR,"Pair distance > table outer cutoff");
fforce = factor_lj * tb->f[itable];
} else if (tabstyle == LINEAR) {
itable = static_cast<int> ((rsq-tb->innersq) * tb->invdelta);
- if (itable >= tlm1) error->one("Pair distance > table outer cutoff");
+ if (itable >= tlm1) error->one(FLERR,"Pair distance > table outer cutoff");
fraction = (rsq - tb->rsq[itable]) * tb->invdelta;
value = tb->f[itable] + fraction*tb->df[itable];
fforce = factor_lj * value;
} else if (tabstyle == SPLINE) {
itable = static_cast<int> ((rsq-tb->innersq) * tb->invdelta);
- if (itable >= tlm1) error->one("Pair distance > table outer cutoff");
+ if (itable >= tlm1) error->one(FLERR,"Pair distance > table outer cutoff");
b = (rsq - tb->rsq[itable]) * tb->invdelta;
a = 1.0 - b;
value = a * tb->f[itable] + b * tb->f[itable+1] +
((a*a*a-a)*tb->f2[itable] + (b*b*b-b)*tb->f2[itable+1]) *
tb->deltasq6;
fforce = factor_lj * value;
} else {
union_int_float_t rsq_lookup;
rsq_lookup.f = rsq;
itable = rsq_lookup.i & tb->nmask;
itable >>= tb->nshiftbits;
fraction = (rsq_lookup.f - tb->rsq[itable]) * tb->drsq[itable];
value = tb->f[itable] + fraction*tb->df[itable];
fforce = factor_lj * value;
}
if (tabstyle == LOOKUP)
phi = tb->e[itable];
else if (tabstyle == LINEAR || tabstyle == BITMAP)
phi = tb->e[itable] + fraction*tb->de[itable];
else
phi = a * tb->e[itable] + b * tb->e[itable+1] +
((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) * tb->deltasq6;
return factor_lj*phi;
}
/* ----------------------------------------------------------------------
return the Coulomb cutoff for tabled potentials
called by KSpace solvers which require that all pairwise cutoffs be the same
loop over all tables not just those indexed by tabindex[i][j] since
no way to know which tables are active since pair::init() not yet called
------------------------------------------------------------------------- */
void *PairTable::extract(char *str, int &dim)
{
if (strcmp(str,"cut_coul") != 0) return NULL;
- if (ntables == 0) error->all("All pair coeffs are not set");
+ if (ntables == 0) error->all(FLERR,"All pair coeffs are not set");
double cut_coul = tables[0].cut;
for (int m = 1; m < ntables; m++)
if (tables[m].cut != cut_coul)
- error->all("Pair table cutoffs must all be equal to use with KSpace");
+ error->all(FLERR,"Pair table cutoffs must all be equal to use with KSpace");
dim = 0;
return &tables[0].cut;
}
diff --git a/src/pair_yukawa.cpp b/src/pair_yukawa.cpp
index 85359921d..0e544c116 100644
--- a/src/pair_yukawa.cpp
+++ b/src/pair_yukawa.cpp
@@ -1,316 +1,313 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "pair_yukawa.h"
#include "atom.h"
#include "force.h"
#include "comm.h"
#include "neigh_list.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
PairYukawa::PairYukawa(LAMMPS *lmp) : Pair(lmp) {}
/* ---------------------------------------------------------------------- */
PairYukawa::~PairYukawa()
{
if (allocated) {
memory->destroy(setflag);
memory->destroy(cutsq);
memory->destroy(rad);
memory->destroy(cut);
memory->destroy(a);
memory->destroy(offset);
}
}
/* ---------------------------------------------------------------------- */
void PairYukawa::compute(int eflag, int vflag)
{
int i,j,ii,jj,inum,jnum,itype,jtype;
double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
double rsq,r2inv,r,rinv,screening,forceyukawa,factor;
int *ilist,*jlist,*numneigh,**firstneigh;
evdwl = 0.0;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = vflag_fdotr = 0;
double **x = atom->x;
double **f = atom->f;
int *type = atom->type;
int nlocal = atom->nlocal;
double *special_lj = force->special_lj;
int newton_pair = force->newton_pair;
inum = list->inum;
ilist = list->ilist;
numneigh = list->numneigh;
firstneigh = list->firstneigh;
// loop over neighbors of my atoms
for (ii = 0; ii < inum; ii++) {
i = ilist[ii];
xtmp = x[i][0];
ytmp = x[i][1];
ztmp = x[i][2];
itype = type[i];
jlist = firstneigh[i];
jnum = numneigh[i];
for (jj = 0; jj < jnum; jj++) {
j = jlist[jj];
factor = special_lj[sbmask(j)];
j &= NEIGHMASK;
delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
jtype = type[j];
if (rsq < cutsq[itype][jtype]) {
r2inv = 1.0/rsq;
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*r);
forceyukawa = a[itype][jtype] * screening * (kappa + rinv);
fpair = factor*forceyukawa * r2inv;
f[i][0] += delx*fpair;
f[i][1] += dely*fpair;
f[i][2] += delz*fpair;
if (newton_pair || j < nlocal) {
f[j][0] -= delx*fpair;
f[j][1] -= dely*fpair;
f[j][2] -= delz*fpair;
}
if (eflag) {
evdwl = a[itype][jtype] * screening * rinv - offset[itype][jtype];
evdwl *= factor;
}
if (evflag) ev_tally(i,j,nlocal,newton_pair,
evdwl,0.0,fpair,delx,dely,delz);
}
}
}
if (vflag_fdotr) virial_fdotr_compute();
}
/* ----------------------------------------------------------------------
allocate all arrays
------------------------------------------------------------------------- */
void PairYukawa::allocate()
{
allocated = 1;
int n = atom->ntypes;
memory->create(setflag,n+1,n+1,"pair:setflag");
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
setflag[i][j] = 0;
memory->create(cutsq,n+1,n+1,"pair:cutsq");
memory->create(rad,n+1,"pair:rad");
memory->create(cut,n+1,n+1,"pair:cut");
memory->create(a,n+1,n+1,"pair:a");
memory->create(offset,n+1,n+1,"pair:offset");
}
/* ----------------------------------------------------------------------
global settings
------------------------------------------------------------------------- */
void PairYukawa::settings(int narg, char **arg)
{
- if (narg != 2) error->all("Illegal pair_style command");
+ if (narg != 2) error->all(FLERR,"Illegal pair_style command");
kappa = force->numeric(arg[0]);
cut_global = force->numeric(arg[1]);
// reset cutoffs that have been explicitly set
if (allocated) {
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i+1; j <= atom->ntypes; j++)
if (setflag[i][j]) cut[i][j] = cut_global;
}
}
/* ----------------------------------------------------------------------
set coeffs for one or more type pairs
------------------------------------------------------------------------- */
void PairYukawa::coeff(int narg, char **arg)
{
- if (narg < 3 || narg > 4) error->all("Incorrect args for pair coefficients");
+ if (narg < 3 || narg > 4) error->all(FLERR,"Incorrect args for pair coefficients");
if (!allocated) allocate();
int ilo,ihi,jlo,jhi;
force->bounds(arg[0],atom->ntypes,ilo,ihi);
force->bounds(arg[1],atom->ntypes,jlo,jhi);
double a_one = force->numeric(arg[2]);
double cut_one = cut_global;
if (narg == 4) cut_one = force->numeric(arg[3]);
int count = 0;
for (int i = ilo; i <= ihi; i++) {
for (int j = MAX(jlo,i); j <= jhi; j++) {
a[i][j] = a_one;
cut[i][j] = cut_one;
setflag[i][j] = 1;
count++;
}
}
- if (count == 0) error->all("Incorrect args for pair coefficients");
+ if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
}
/* ----------------------------------------------------------------------
init for one type pair i,j and corresponding j,i
------------------------------------------------------------------------- */
double PairYukawa::init_one(int i, int j)
{
if (setflag[i][j] == 0) {
a[i][j] = mix_energy(a[i][i],a[j][j],1.0,1.0);
cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
}
if (offset_flag) {
double screening = exp(-kappa * cut[i][j]);
offset[i][j] = a[i][j] * screening / cut[i][j];
} else offset[i][j] = 0.0;
a[j][i] = a[i][j];
offset[j][i] = offset[i][j];
return cut[i][j];
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairYukawa::write_restart(FILE *fp)
{
write_restart_settings(fp);
int i,j;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
fwrite(&setflag[i][j],sizeof(int),1,fp);
if (setflag[i][j]) {
fwrite(&a[i][j],sizeof(double),1,fp);
fwrite(&cut[i][j],sizeof(double),1,fp);
}
}
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairYukawa::read_restart(FILE *fp)
{
read_restart_settings(fp);
allocate();
int i,j;
int me = comm->me;
for (i = 1; i <= atom->ntypes; i++)
for (j = i; j <= atom->ntypes; j++) {
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
if (setflag[i][j]) {
if (me == 0) {
fread(&a[i][j],sizeof(double),1,fp);
fread(&cut[i][j],sizeof(double),1,fp);
}
MPI_Bcast(&a[i][j],1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
}
}
}
/* ----------------------------------------------------------------------
proc 0 writes to restart file
------------------------------------------------------------------------- */
void PairYukawa::write_restart_settings(FILE *fp)
{
fwrite(&kappa,sizeof(double),1,fp);
fwrite(&cut_global,sizeof(double),1,fp);
fwrite(&offset_flag,sizeof(int),1,fp);
fwrite(&mix_flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 reads from restart file, bcasts
------------------------------------------------------------------------- */
void PairYukawa::read_restart_settings(FILE *fp)
{
if (comm->me == 0) {
fread(&kappa,sizeof(double),1,fp);
fread(&cut_global,sizeof(double),1,fp);
fread(&offset_flag,sizeof(int),1,fp);
fread(&mix_flag,sizeof(int),1,fp);
}
MPI_Bcast(&kappa,1,MPI_DOUBLE,0,world);
MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
}
/* ---------------------------------------------------------------------- */
double PairYukawa::single(int i, int j, int itype, int jtype, double rsq,
double factor_coul, double factor_lj,
double &fforce)
{
double r2inv,r,rinv,screening,forceyukawa,phi;
r2inv = 1.0/rsq;
r = sqrt(rsq);
rinv = 1.0/r;
screening = exp(-kappa*r);
forceyukawa = a[itype][jtype] * screening * (kappa + rinv);
fforce = factor_lj*forceyukawa * r2inv;
phi = a[itype][jtype] * screening * rinv - offset[itype][jtype];
return factor_lj*phi;
}
diff --git a/src/pointers.h b/src/pointers.h
index f2f2215b8..d00665c97 100644
--- a/src/pointers.h
+++ b/src/pointers.h
@@ -1,80 +1,87 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
// Pointers class contains ptrs to master copy of
// fundamental LAMMPS class ptrs stored in lammps.h
// every LAMMPS class inherits from Pointers to access lammps.h ptrs
// these variables are auto-initialized by Pointer class constructor
// *& variables are really pointers to the pointers in lammps.h
// & enables them to be accessed directly in any class, e.g. atom->x
#ifndef LMP_POINTERS_H
#define LMP_POINTERS_H
#include "lmptype.h"
#include "mpi.h"
#include "lammps.h"
namespace LAMMPS_NS {
+// universal defines inside namespace
+
+#define FLERR __FILE__,__LINE__
+
+#define MIN(A,B) ((A) < (B)) ? (A) : (B)
+#define MAX(A,B) ((A) > (B)) ? (A) : (B)
+
class Pointers {
public:
Pointers(LAMMPS *ptr) :
lmp(ptr),
memory(ptr->memory),
error(ptr->error),
universe(ptr->universe),
input(ptr->input),
atom(ptr->atom),
update(ptr->update),
neighbor(ptr->neighbor),
comm(ptr->comm),
domain(ptr->domain),
force(ptr->force),
modify(ptr->modify),
group(ptr->group),
output(ptr->output),
timer(ptr->timer),
world(ptr->world),
infile(ptr->infile),
screen(ptr->screen),
logfile(ptr->logfile) {}
virtual ~Pointers() {}
protected:
LAMMPS *lmp;
Memory *&memory;
Error *&error;
Universe *&universe;
Input *&input;
Atom *&atom;
Update *&update;
Neighbor *&neighbor;
Comm *&comm;
Domain *&domain;
Force *&force;
Modify *&modify;
Group *&group;
Output *&output;
Timer *&timer;
MPI_Comm &world;
FILE *&infile;
FILE *&screen;
FILE *&logfile;
};
}
#endif
diff --git a/src/random_mars.cpp b/src/random_mars.cpp
index 966f3a671..2430eabd5 100644
--- a/src/random_mars.cpp
+++ b/src/random_mars.cpp
@@ -1,115 +1,115 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
// Marsaglia random number generator
#include "math.h"
#include "random_mars.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
RanMars::RanMars(LAMMPS *lmp, int seed) : Pointers(lmp)
{
int ij,kl,i,j,k,l,ii,jj,m;
double s,t;
if (seed <= 0 || seed > 900000000)
- error->all("Invalid seed for Marsaglia random # generator");
+ error->all(FLERR,"Invalid seed for Marsaglia random # generator");
save = 0;
u = new double[97+1];
ij = (seed-1)/30082;
kl = (seed-1) - 30082*ij;
i = (ij/177) % 177 + 2;
j = ij %177 + 2;
k = (kl/169) % 178 + 1;
l = kl % 169;
for (ii = 1; ii <= 97; ii++) {
s = 0.0;
t = 0.5;
for (jj = 1; jj <= 24; jj++) {
m = ((i*j) % 179)*k % 179;
i = j;
j = k;
k = m;
l = (53*l+1) % 169;
if ((l*m) % 64 >= 32) s = s + t;
t = 0.5*t;
}
u[ii] = s;
}
c = 362436.0 / 16777216.0;
cd = 7654321.0 / 16777216.0;
cm = 16777213.0 / 16777216.0;
i97 = 97;
j97 = 33;
uniform();
}
/* ---------------------------------------------------------------------- */
RanMars::~RanMars()
{
delete [] u;
}
/* ----------------------------------------------------------------------
uniform RN
------------------------------------------------------------------------- */
double RanMars::uniform()
{
double uni = u[i97] - u[j97];
if (uni < 0.0) uni += 1.0;
u[i97] = uni;
i97--;
if (i97 == 0) i97 = 97;
j97--;
if (j97 == 0) j97 = 97;
c -= cd;
if (c < 0.0) c += cm;
uni -= c;
if (uni < 0.0) uni += 1.0;
return uni;
}
/* ----------------------------------------------------------------------
gaussian RN
------------------------------------------------------------------------- */
double RanMars::gaussian()
{
double first,v1,v2,rsq,fac;
if (!save) {
int again = 1;
while (again) {
v1 = 2.0*uniform()-1.0;
v2 = 2.0*uniform()-1.0;
rsq = v1*v1 + v2*v2;
if (rsq < 1.0 && rsq != 0.0) again = 0;
}
fac = sqrt(-2.0*log(rsq)/rsq);
second = v1*fac;
first = v2*fac;
save = 1;
} else {
first = second;
save = 0;
}
return first;
}
diff --git a/src/random_park.cpp b/src/random_park.cpp
index cbfa0d109..6867a61a5 100644
--- a/src/random_park.cpp
+++ b/src/random_park.cpp
@@ -1,144 +1,145 @@
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
// Park/Miller RNG
#include "math.h"
#include "random_park.h"
-#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define IA1 1366
#define IC1 150889
#define IM1 714025
#define IA2 8121
#define IC2 28411
#define IM2 134456
#define IA3 7141
#define IC3 54773
#define IM3 259200
/* ---------------------------------------------------------------------- */
RanPark::RanPark(LAMMPS *lmp, int seed_init) : Pointers(lmp)
{
- if (seed_init <= 0) error->all("Invalid seed for Park random # generator");
+ if (seed_init <= 0)
+ error->all(FLERR,"Invalid seed for Park random # generator");
seed = seed_init;
save = 0;
}
/* ----------------------------------------------------------------------
uniform RN
------------------------------------------------------------------------- */
double RanPark::uniform()
{
int k = seed/IQ;
seed = IA*(seed-k*IQ) - IR*k;
if (seed < 0) seed += IM;
double ans = AM*seed;
return ans;
}
/* ----------------------------------------------------------------------
gaussian RN
------------------------------------------------------------------------- */
double RanPark::gaussian()
{
double first,v1,v2,rsq,fac;
if (!save) {
int again = 1;
while (again) {
v1 = 2.0*uniform()-1.0;
v2 = 2.0*uniform()-1.0;
rsq = v1*v1 + v2*v2;
if (rsq < 1.0 && rsq != 0.0) again = 0;
}
fac = sqrt(-2.0*log(rsq)/rsq);
second = v1*fac;
first = v2*fac;
save = 1;
} else {
first = second;
save = 0;
}
return first;
}
/* ---------------------------------------------------------------------- */
void RanPark::reset(int seed_init)
{
- if (seed_init <= 0) error->all("Invalid seed for Park random # generator");
+ if (seed_init <= 0)
+ error->all(FLERR,"Invalid seed for Park random # generator");
seed = seed_init;
save = 0;
}
/* ----------------------------------------------------------------------
reset the seed based on atom coords and ibase = caller seed
use hash function, treating user seed and coords as sequence of input ints
this is Jenkins One-at-a-time hash, see Wikipedia entry on hash tables
------------------------------------------------------------------------- */
void RanPark::reset(int ibase, double *coord)
{
int i;
char *str = (char *) &ibase;
int n = sizeof(int);
unsigned int hash = 0;
for (i = 0; i < n; i++) {
hash += str[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
str = (char *) coord;
n = 3 * sizeof(double);
for (i = 0; i < n; i++) {
hash += str[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
// keep 31 bits of unsigned int as new seed
seed = hash & 0x7ffffff;
// warm up the RNG
for (i = 0; i < 5; i++) uniform();
save = 0;
}
/* ---------------------------------------------------------------------- */
int RanPark::state()
{
return seed;
}
diff --git a/src/read_data.cpp b/src/read_data.cpp
index 40a5d06a5..91d684ec0 100644
--- a/src/read_data.cpp
+++ b/src/read_data.cpp
@@ -1,1397 +1,1394 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "math.h"
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
#include "ctype.h"
#include "read_data.h"
#include "atom.h"
#include "atom_vec.h"
#include "atom_vec_ellipsoid.h"
#include "comm.h"
#include "update.h"
#include "force.h"
#include "pair.h"
#include "domain.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "error.h"
#include "memory.h"
#include "special.h"
using namespace LAMMPS_NS;
#define MAXLINE 256
#define LB_FACTOR 1.1
#define CHUNK 1024
#define DELTA 4 // must be 2 or larger
// customize for new sections
#define NSECTIONS 21 // change when add to header::section_keywords
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
ReadData::ReadData(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
line = new char[MAXLINE];
keyword = new char[MAXLINE];
buffer = new char[CHUNK*MAXLINE];
narg = maxarg = 0;
arg = NULL;
// customize for new sections
// pointers to atom styles that store extra info
nellipsoids = 0;
avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
}
/* ---------------------------------------------------------------------- */
ReadData::~ReadData()
{
delete [] line;
delete [] keyword;
delete [] buffer;
memory->sfree(arg);
}
/* ---------------------------------------------------------------------- */
void ReadData::command(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal read_data command");
+ if (narg != 1) error->all(FLERR,"Illegal read_data command");
if (domain->box_exist)
- error->all("Cannot read_data after simulation box is defined");
+ error->all(FLERR,"Cannot read_data after simulation box is defined");
if (domain->dimension == 2 && domain->zperiodic == 0)
- error->all("Cannot run 2d simulation with nonperiodic Z dimension");
+ error->all(FLERR,"Cannot run 2d simulation with nonperiodic Z dimension");
// scan data file to determine max topology needed per atom
// allocate initial topology arrays
if (atom->molecular) {
if (me == 0) {
if (screen) fprintf(screen,"Scanning data file ...\n");
open(arg[0]);
header(0);
scan(atom->bond_per_atom,atom->angle_per_atom,
atom->dihedral_per_atom,atom->improper_per_atom);
if (compressed) pclose(fp);
else fclose(fp);
atom->bond_per_atom += atom->extra_bond_per_atom;
}
MPI_Bcast(&atom->bond_per_atom,1,MPI_INT,0,world);
MPI_Bcast(&atom->angle_per_atom,1,MPI_INT,0,world);
MPI_Bcast(&atom->dihedral_per_atom,1,MPI_INT,0,world);
MPI_Bcast(&atom->improper_per_atom,1,MPI_INT,0,world);
} else
atom->bond_per_atom = atom->angle_per_atom =
atom->dihedral_per_atom = atom->improper_per_atom = 0;
// read header info
if (me == 0) {
if (screen) fprintf(screen,"Reading data file ...\n");
open(arg[0]);
}
header(1);
domain->box_exist = 1;
// problem setup using info from header
update->ntimestep = 0;
int n;
if (comm->nprocs == 1) n = static_cast<int> (atom->natoms);
else n = static_cast<int> (LB_FACTOR * atom->natoms / comm->nprocs);
atom->allocate_type_arrays();
atom->avec->grow(n);
n = atom->nmax;
domain->print_box(" ");
domain->set_initial_box();
domain->set_global_box();
comm->set_procs();
domain->set_local_box();
// customize for new sections
// read rest of file in free format
int atomflag = 0;
while (strlen(keyword)) {
if (strcmp(keyword,"Atoms") == 0) {
atoms();
atomflag = 1;
} else if (strcmp(keyword,"Velocities") == 0) {
- if (atomflag == 0) error->one("Must read Atoms before Velocities");
+ if (atomflag == 0) error->one(FLERR,"Must read Atoms before Velocities");
velocities();
} else if (strcmp(keyword,"Ellipsoids") == 0) {
if (!avec_ellipsoid)
- error->one("Invalid data file section: Ellipsoids");
- if (atomflag == 0) error->one("Must read Atoms before Ellipsoids");
+ error->one(FLERR,"Invalid data file section: Ellipsoids");
+ if (atomflag == 0) error->one(FLERR,"Must read Atoms before Ellipsoids");
ellipsoids();
} else if (strcmp(keyword,"Bonds") == 0) {
if (atom->avec->bonds_allow == 0)
- error->one("Invalid data file section: Bonds");
- if (atomflag == 0) error->one("Must read Atoms before Bonds");
+ error->one(FLERR,"Invalid data file section: Bonds");
+ if (atomflag == 0) error->one(FLERR,"Must read Atoms before Bonds");
bonds();
} else if (strcmp(keyword,"Angles") == 0) {
if (atom->avec->angles_allow == 0)
- error->one("Invalid data file section: Angles");
- if (atomflag == 0) error->one("Must read Atoms before Angles");
+ error->one(FLERR,"Invalid data file section: Angles");
+ if (atomflag == 0) error->all(FLERR,"Must read Atoms before Angles");
angles();
} else if (strcmp(keyword,"Dihedrals") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: Dihedrals");
- if (atomflag == 0) error->one("Must read Atoms before Dihedrals");
+ error->all(FLERR,"Invalid data file section: Dihedrals");
+ if (atomflag == 0) error->one(FLERR,"Must read Atoms before Dihedrals");
dihedrals();
} else if (strcmp(keyword,"Impropers") == 0) {
if (atom->avec->impropers_allow == 0)
- error->one("Invalid data file section: Impropers");
- if (atomflag == 0) error->one("Must read Atoms before Impropers");
+ error->one(FLERR,"Invalid data file section: Impropers");
+ if (atomflag == 0) error->one(FLERR,"Must read Atoms before Impropers");
impropers();
} else if (strcmp(keyword,"Masses") == 0) {
mass();
} else if (strcmp(keyword,"Pair Coeffs") == 0) {
if (force->pair == NULL)
- error->one("Must define pair_style before Pair Coeffs");
+ error->one(FLERR,"Must define pair_style before Pair Coeffs");
paircoeffs();
} else if (strcmp(keyword,"Bond Coeffs") == 0) {
if (atom->avec->bonds_allow == 0)
- error->one("Invalid data file section: Bond Coeffs");
+ error->one(FLERR,"Invalid data file section: Bond Coeffs");
if (force->bond == NULL)
- error->one("Must define bond_style before Bond Coeffs");
+ error->one(FLERR,"Must define bond_style before Bond Coeffs");
bondcoeffs();
} else if (strcmp(keyword,"Angle Coeffs") == 0) {
if (atom->avec->angles_allow == 0)
- error->one("Invalid data file section: Angle Coeffs");
+ error->one(FLERR,"Invalid data file section: Angle Coeffs");
if (force->angle == NULL)
- error->one("Must define angle_style before Angle Coeffs");
+ error->one(FLERR,"Must define angle_style before Angle Coeffs");
anglecoeffs(0);
} else if (strcmp(keyword,"Dihedral Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: Dihedral Coeffs");
+ error->one(FLERR,"Invalid data file section: Dihedral Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before Dihedral Coeffs");
+ error->one(FLERR,"Must define dihedral_style before Dihedral Coeffs");
dihedralcoeffs(0);
} else if (strcmp(keyword,"Improper Coeffs") == 0) {
if (atom->avec->impropers_allow == 0)
- error->one("Invalid data file section: Improper Coeffs");
+ error->one(FLERR,"Invalid data file section: Improper Coeffs");
if (force->improper == NULL)
- error->one("Must define improper_style before Improper Coeffs");
+ error->one(FLERR,"Must define improper_style before Improper Coeffs");
impropercoeffs(0);
} else if (strcmp(keyword,"BondBond Coeffs") == 0) {
if (atom->avec->angles_allow == 0)
- error->one("Invalid data file section: BondBond Coeffs");
+ error->one(FLERR,"Invalid data file section: BondBond Coeffs");
if (force->angle == NULL)
- error->one("Must define angle_style before BondBond Coeffs");
+ error->one(FLERR,"Must define angle_style before BondBond Coeffs");
anglecoeffs(1);
} else if (strcmp(keyword,"BondAngle Coeffs") == 0) {
if (atom->avec->angles_allow == 0)
- error->one("Invalid data file section: BondAngle Coeffs");
+ error->one(FLERR,"Invalid data file section: BondAngle Coeffs");
if (force->angle == NULL)
- error->one("Must define angle_style before BondAngle Coeffs");
+ error->one(FLERR,"Must define angle_style before BondAngle Coeffs");
anglecoeffs(2);
} else if (strcmp(keyword,"MiddleBondTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: MiddleBondTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: MiddleBondTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before MiddleBondTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before MiddleBondTorsion Coeffs");
dihedralcoeffs(1);
} else if (strcmp(keyword,"EndBondTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: EndBondTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: EndBondTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before EndBondTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before EndBondTorsion Coeffs");
dihedralcoeffs(2);
} else if (strcmp(keyword,"AngleTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: AngleTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: AngleTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before AngleTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before AngleTorsion Coeffs");
dihedralcoeffs(3);
} else if (strcmp(keyword,"AngleAngleTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: AngleAngleTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: AngleAngleTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before AngleAngleTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before AngleAngleTorsion Coeffs");
dihedralcoeffs(4);
} else if (strcmp(keyword,"BondBond13 Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: BondBond13 Coeffs");
+ error->one(FLERR,"Invalid data file section: BondBond13 Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before BondBond13 Coeffs");
+ error->one(FLERR,"Must define dihedral_style before BondBond13 Coeffs");
dihedralcoeffs(5);
} else if (strcmp(keyword,"AngleAngle Coeffs") == 0) {
if (atom->avec->impropers_allow == 0)
- error->one("Invalid data file section: AngleAngle Coeffs");
+ error->one(FLERR,"Invalid data file section: AngleAngle Coeffs");
if (force->improper == NULL)
- error->one("Must define improper_style before AngleAngle Coeffs");
+ error->one(FLERR,"Must define improper_style before AngleAngle Coeffs");
impropercoeffs(1);
} else {
char str[128];
sprintf(str,"Unknown identifier in data file: %s",keyword);
- error->one(str);
+ error->one(FLERR,str);
}
parse_keyword(0,1);
}
// close file
if (me == 0) {
if (compressed) pclose(fp);
else fclose(fp);
}
// error if natoms > 0 yet no atoms were read
- if (atom->natoms > 0 && atomflag == 0) error->one("No atoms in data file");
+ if (atom->natoms > 0 && atomflag == 0) error->one(FLERR,"No atoms in data file");
// create bond topology now that system is defined
if (atom->molecular) {
Special special(lmp);
special.build();
}
}
/* ----------------------------------------------------------------------
read free-format header of data file
if flag = 0, only called by proc 0
if flag = 1, called by all procs so bcast lines as read them
1st line and blank lines are skipped
non-blank lines are checked for header keywords and leading value is read
header ends with EOF or non-blank line containing no header keyword
if EOF, line is set to blank line
else line has first keyword line for rest of file
------------------------------------------------------------------------- */
void ReadData::header(int flag)
{
int n;
char *ptr;
// customize for new sections
char *section_keywords[NSECTIONS] =
{"Atoms","Velocities","Ellipsoids",
"Bonds","Angles","Dihedrals","Impropers",
"Masses","Pair Coeffs","Bond Coeffs","Angle Coeffs",
"Dihedral Coeffs","Improper Coeffs",
"BondBond Coeffs","BondAngle Coeffs","MiddleBondTorsion Coeffs",
"EndBondTorsion Coeffs","AngleTorsion Coeffs",
"AngleAngleTorsion Coeffs","BondBond13 Coeffs","AngleAngle Coeffs"};
// skip 1st line of file
if (me == 0) {
char *eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
}
// customize for new header lines
while (1) {
// read a line and bcast length if flag is set
if (me == 0) {
if (fgets(line,MAXLINE,fp) == NULL) n = 0;
else n = strlen(line) + 1;
}
if (flag) MPI_Bcast(&n,1,MPI_INT,0,world);
// if n = 0 then end-of-file so return with blank line
if (n == 0) {
line[0] = '\0';
return;
}
// bcast line if flag is set
if (flag) MPI_Bcast(line,n,MPI_CHAR,0,world);
// trim anything from '#' onward
// if line is blank, continue
if (ptr = strchr(line,'#')) *ptr = '\0';
if (strspn(line," \t\n\r") == strlen(line)) continue;
// search line for header keyword and set corresponding variable
if (strstr(line,"atoms")) sscanf(line,BIGINT_FORMAT,&atom->natoms);
else if (strstr(line,"bonds")) sscanf(line,BIGINT_FORMAT,&atom->nbonds);
else if (strstr(line,"angles")) sscanf(line,BIGINT_FORMAT,&atom->nangles);
else if (strstr(line,"dihedrals")) sscanf(line,BIGINT_FORMAT,
&atom->ndihedrals);
else if (strstr(line,"impropers")) sscanf(line,BIGINT_FORMAT,
&atom->nimpropers);
else if (strstr(line,"atom types")) sscanf(line,"%d",&atom->ntypes);
else if (strstr(line,"bond types")) sscanf(line,"%d",&atom->nbondtypes);
else if (strstr(line,"angle types")) sscanf(line,"%d",&atom->nangletypes);
else if (strstr(line,"dihedral types"))
sscanf(line,"%d",&atom->ndihedraltypes);
else if (strstr(line,"improper types"))
sscanf(line,"%d",&atom->nimpropertypes);
else if (strstr(line,"extra bond per atom"))
sscanf(line,"%d",&atom->extra_bond_per_atom);
else if (strstr(line,"ellipsoids")) {
if (!avec_ellipsoid)
- error->one("No ellipsoids allowed with this atom style");
+ error->one(FLERR,"No ellipsoids allowed with this atom style");
sscanf(line,BIGINT_FORMAT,&nellipsoids);
}
else if (strstr(line,"xlo xhi"))
sscanf(line,"%lg %lg",&domain->boxlo[0],&domain->boxhi[0]);
else if (strstr(line,"ylo yhi"))
sscanf(line,"%lg %lg",&domain->boxlo[1],&domain->boxhi[1]);
else if (strstr(line,"zlo zhi"))
sscanf(line,"%lg %lg",&domain->boxlo[2],&domain->boxhi[2]);
else if (strstr(line,"xy xz yz")) {
domain->triclinic = 1;
sscanf(line,"%lg %lg %lg",&domain->xy,&domain->xz,&domain->yz);
} else break;
}
// error check on total system size
if (atom->natoms < 0 || atom->natoms > MAXBIGINT ||
atom->nbonds < 0 || atom->nbonds > MAXBIGINT ||
atom->nangles < 0 || atom->nangles > MAXBIGINT ||
atom->ndihedrals < 0 || atom->ndihedrals > MAXBIGINT ||
atom->nimpropers < 0 || atom->nimpropers > MAXBIGINT) {
- if (flag == 0) error->one("System in data file is too big");
- else error->one("System in data file is too big");
+ if (flag == 0) error->one(FLERR,"System in data file is too big");
+ else error->one(FLERR,"System in data file is too big");
}
// check that exiting string is a valid section keyword
parse_keyword(1,flag);
for (n = 0; n < NSECTIONS; n++)
if (strcmp(keyword,section_keywords[n]) == 0) break;
if (n == NSECTIONS) {
char str[128];
sprintf(str,"Unknown identifier in data file: %s",keyword);
- error->one(str);
+ error->one(FLERR,str);
}
// error check on consistency of header values
if ((atom->nbonds || atom->nbondtypes) &&
atom->avec->bonds_allow == 0)
- error->one("No bonds allowed with this atom style");
+ error->one(FLERR,"No bonds allowed with this atom style");
if ((atom->nangles || atom->nangletypes) &&
atom->avec->angles_allow == 0)
- error->one("No angles allowed with this atom style");
+ error->one(FLERR,"No angles allowed with this atom style");
if ((atom->ndihedrals || atom->ndihedraltypes) &&
atom->avec->dihedrals_allow == 0)
- error->one("No dihedrals allowed with this atom style");
+ error->one(FLERR,"No dihedrals allowed with this atom style");
if ((atom->nimpropers || atom->nimpropertypes) &&
atom->avec->impropers_allow == 0)
- error->one("No impropers allowed with this atom style");
+ error->one(FLERR,"No impropers allowed with this atom style");
if (atom->nbonds > 0 && atom->nbondtypes <= 0)
- error->one("Bonds defined but no bond types");
+ error->one(FLERR,"Bonds defined but no bond types");
if (atom->nangles > 0 && atom->nangletypes <= 0)
- error->one("Angles defined but no angle types");
+ error->one(FLERR,"Angles defined but no angle types");
if (atom->ndihedrals > 0 && atom->ndihedraltypes <= 0)
- error->one("Dihedrals defined but no dihedral types");
+ error->one(FLERR,"Dihedrals defined but no dihedral types");
if (atom->nimpropers > 0 && atom->nimpropertypes <= 0)
- error->one("Impropers defined but no improper types");
+ error->one(FLERR,"Impropers defined but no improper types");
}
/* ----------------------------------------------------------------------
read all atoms
------------------------------------------------------------------------- */
void ReadData::atoms()
{
int i,m,nchunk;
bigint nread = 0;
bigint natoms = atom->natoms;
while (nread < natoms) {
if (natoms-nread > CHUNK) nchunk = CHUNK;
else nchunk = natoms-nread;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < nchunk; i++) {
eof = fgets(&buffer[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buffer[m]);
}
m++;
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
atom->data_atoms(nchunk,buffer);
nread += nchunk;
}
// check that all atoms were assigned correctly
bigint tmp = atom->nlocal;
MPI_Allreduce(&tmp,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " atoms\n",natoms);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " atoms\n",natoms);
}
- if (natoms != atom->natoms) error->all("Did not assign all atoms correctly");
+ if (natoms != atom->natoms) error->all(FLERR,"Did not assign all atoms correctly");
// if any atom ID < 0, error
// if all atom IDs = 0, tag_enable = 0
// if any atom ID > 0, error if any atom ID == 0
// not checking if atom IDs > natoms or are unique
int nlocal = atom->nlocal;
int *tag = atom->tag;
int flag = 0;
for (int i = 0; i < nlocal; i++)
if (tag[i] < 0) flag = 1;
int flag_all;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
if (flag_all)
- error->all("Invalid atom ID in Atoms section of data file");
+ error->all(FLERR,"Invalid atom ID in Atoms section of data file");
flag = 0;
for (int i = 0; i < nlocal; i++)
if (tag[i] > 0) flag = 1;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_MAX,world);
if (flag_all == 0) atom->tag_enable = 0;
if (atom->tag_enable) {
flag = 0;
for (int i = 0; i < nlocal; i++)
if (tag[i] == 0) flag = 1;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_SUM,world);
if (flag_all)
- error->all("Invalid atom ID in Atoms section of data file");
+ error->all(FLERR,"Invalid atom ID in Atoms section of data file");
}
// create global mapping
if (atom->map_style) {
atom->map_init();
atom->map_set();
}
}
/* ----------------------------------------------------------------------
read all velocities
to find atoms, must build atom map if not a molecular system
------------------------------------------------------------------------- */
void ReadData::velocities()
{
int i,m,nchunk;
int mapflag = 0;
if (atom->map_style == 0) {
mapflag = 1;
atom->map_style = 1;
atom->map_init();
atom->map_set();
}
bigint nread = 0;
bigint natoms = atom->natoms;
while (nread < natoms) {
if (natoms-nread > CHUNK) nchunk = CHUNK;
else nchunk = natoms-nread;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < nchunk; i++) {
eof = fgets(&buffer[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buffer[m]);
}
m++;
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
atom->data_vels(nchunk,buffer);
nread += nchunk;
}
if (mapflag) {
atom->map_delete();
atom->map_style = 0;
}
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " velocities\n",natoms);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " velocities\n",natoms);
}
}
/* ----------------------------------------------------------------------
read all ellipsoids
to find atoms, must build atom map if not a molecular system
------------------------------------------------------------------------- */
void ReadData::ellipsoids()
{
int i,m,nchunk;
int mapflag = 0;
if (atom->map_style == 0) {
mapflag = 1;
atom->map_style = 1;
atom->map_init();
atom->map_set();
}
bigint nread = 0;
bigint natoms = nellipsoids;
while (nread < natoms) {
if (natoms-nread > CHUNK) nchunk = CHUNK;
else nchunk = natoms-nread;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < nchunk; i++) {
eof = fgets(&buffer[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buffer[m]);
}
m++;
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
atom->data_bonus(nchunk,buffer,avec_ellipsoid);
nread += nchunk;
}
if (mapflag) {
atom->map_delete();
atom->map_style = 0;
}
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " ellipsoids\n",natoms);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " ellipsoids\n",natoms);
}
}
/* ---------------------------------------------------------------------- */
void ReadData::bonds()
{
int i,m,nchunk;
bigint nread = 0;
bigint nbonds = atom->nbonds;
while (nread < nbonds) {
nchunk = MIN(nbonds-nread,CHUNK);
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < nchunk; i++) {
eof = fgets(&buffer[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buffer[m]);
}
m++;
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
atom->data_bonds(nchunk,buffer);
nread += nchunk;
}
// check that bonds were assigned correctly
int nlocal = atom->nlocal;
bigint sum;
bigint n = 0;
for (i = 0; i < nlocal; i++) n += atom->num_bond[i];
MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
int factor = 1;
if (!force->newton_bond) factor = 2;
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " bonds\n",sum/factor);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " bonds\n",sum/factor);
}
- if (sum != factor*atom->nbonds) error->all("Bonds assigned incorrectly");
+ if (sum != factor*atom->nbonds) error->all(FLERR,"Bonds assigned incorrectly");
}
/* ---------------------------------------------------------------------- */
void ReadData::angles()
{
int i,m,nchunk;
bigint nread = 0;
bigint nangles = atom->nangles;
while (nread < nangles) {
nchunk = MIN(nangles-nread,CHUNK);
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < nchunk; i++) {
eof = fgets(&buffer[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buffer[m]);
}
m++;
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
atom->data_angles(nchunk,buffer);
nread += nchunk;
}
// check that ang
int nlocal = atom->nlocal;
bigint sum;
bigint n = 0;
for (i = 0; i < nlocal; i++) n += atom->num_angle[i];
MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
int factor = 1;
if (!force->newton_bond) factor = 3;
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " angles\n",sum/factor);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " angles\n",sum/factor);
}
- if (sum != factor*atom->nangles) error->all("Angles assigned incorrectly");
+ if (sum != factor*atom->nangles) error->all(FLERR,"Angles assigned incorrectly");
}
/* ---------------------------------------------------------------------- */
void ReadData::dihedrals()
{
int i,m,nchunk;
bigint nread = 0;
bigint ndihedrals = atom->ndihedrals;
while (nread < ndihedrals) {
nchunk = MIN(ndihedrals-nread,CHUNK);
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < nchunk; i++) {
eof = fgets(&buffer[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buffer[m]);
}
m++;
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
atom->data_dihedrals(nchunk,buffer);
nread += nchunk;
}
// check that dihedrals were assigned correctly
int nlocal = atom->nlocal;
bigint sum;
bigint n = 0;
for (i = 0; i < nlocal; i++) n += atom->num_dihedral[i];
MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
int factor = 1;
if (!force->newton_bond) factor = 4;
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " dihedrals\n",sum/factor);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " dihedrals\n",sum/factor);
}
if (sum != factor*atom->ndihedrals)
- error->all("Dihedrals assigned incorrectly");
+ error->all(FLERR,"Dihedrals assigned incorrectly");
}
/* ---------------------------------------------------------------------- */
void ReadData::impropers()
{
int i,m,nchunk;
bigint nread = 0;
bigint nimpropers = atom->nimpropers;
while (nread < nimpropers) {
nchunk = MIN(nimpropers-nread,CHUNK);
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < nchunk; i++) {
eof = fgets(&buffer[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buffer[m]);
}
m++;
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buffer,m,MPI_CHAR,0,world);
atom->data_impropers(nchunk,buffer);
nread += nchunk;
}
// check that impropers were assigned correctly
int nlocal = atom->nlocal;
bigint sum;
bigint n = 0;
for (i = 0; i < nlocal; i++) n += atom->num_improper[i];
MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
int factor = 1;
if (!force->newton_bond) factor = 4;
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " impropers\n",sum/factor);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " impropers\n",sum/factor);
}
if (sum != factor*atom->nimpropers)
- error->all("Impropers assigned incorrectly");
+ error->all(FLERR,"Impropers assigned incorrectly");
}
/* ---------------------------------------------------------------------- */
void ReadData::mass()
{
int i,m;
char *buf = new char[atom->ntypes*MAXLINE];
char *original = buf;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < atom->ntypes; i++) {
eof = fgets(&buf[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buf[m]);
buf[m-1] = '\0';
}
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buf,m,MPI_CHAR,0,world);
for (i = 0; i < atom->ntypes; i++) {
atom->set_mass(buf);
buf += strlen(buf) + 1;
}
delete [] original;
}
/* ---------------------------------------------------------------------- */
void ReadData::paircoeffs()
{
int i,m;
char *buf = new char[atom->ntypes*MAXLINE];
char *original = buf;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < atom->ntypes; i++) {
eof = fgets(&buf[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buf[m]);
buf[m-1] = '\0';
}
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buf,m,MPI_CHAR,0,world);
for (i = 0; i < atom->ntypes; i++) {
m = strlen(buf) + 1;
parse_coeffs(buf,NULL,1);
force->pair->coeff(narg,arg);
buf += m;
}
delete [] original;
}
/* ---------------------------------------------------------------------- */
void ReadData::bondcoeffs()
{
int i,m;
char *buf = new char[atom->nbondtypes*MAXLINE];
char *original = buf;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < atom->nbondtypes; i++) {
eof = fgets(&buf[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buf[m]);
buf[m-1] = '\0';
}
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buf,m,MPI_CHAR,0,world);
for (i = 0; i < atom->nbondtypes; i++) {
m = strlen(buf) + 1;
parse_coeffs(buf,NULL,0);
force->bond->coeff(narg,arg);
buf += m;
}
delete [] original;
}
/* ---------------------------------------------------------------------- */
void ReadData::anglecoeffs(int which)
{
int i,m;
char *buf = new char[atom->nangletypes*MAXLINE];
char *original = buf;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < atom->nangletypes; i++) {
eof = fgets(&buf[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buf[m]);
buf[m-1] = '\0';
}
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buf,m,MPI_CHAR,0,world);
for (i = 0; i < atom->nangletypes; i++) {
m = strlen(buf) + 1;
if (which == 0) parse_coeffs(buf,NULL,0);
else if (which == 1) parse_coeffs(buf,"bb",0);
else if (which == 2) parse_coeffs(buf,"ba",0);
force->angle->coeff(narg,arg);
buf += m;
}
delete [] original;
}
/* ---------------------------------------------------------------------- */
void ReadData::dihedralcoeffs(int which)
{
int i,m;
char *buf = new char[atom->ndihedraltypes*MAXLINE];
char *original = buf;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < atom->ndihedraltypes; i++) {
eof = fgets(&buf[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buf[m]);
buf[m-1] = '\0';
}
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buf,m,MPI_CHAR,0,world);
for (i = 0; i < atom->ndihedraltypes; i++) {
m = strlen(buf) + 1;
if (which == 0) parse_coeffs(buf,NULL,0);
else if (which == 1) parse_coeffs(buf,"mbt",0);
else if (which == 2) parse_coeffs(buf,"ebt",0);
else if (which == 3) parse_coeffs(buf,"at",0);
else if (which == 4) parse_coeffs(buf,"aat",0);
else if (which == 5) parse_coeffs(buf,"bb13",0);
force->dihedral->coeff(narg,arg);
buf += m;
}
delete [] original;
}
/* ---------------------------------------------------------------------- */
void ReadData::impropercoeffs(int which)
{
int i,m;
char *buf = new char[atom->nimpropertypes*MAXLINE];
char *original = buf;
if (me == 0) {
char *eof;
m = 0;
for (i = 0; i < atom->nimpropertypes; i++) {
eof = fgets(&buf[m],MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
m += strlen(&buf[m]);
buf[m-1] = '\0';
}
}
MPI_Bcast(&m,1,MPI_INT,0,world);
MPI_Bcast(buf,m,MPI_CHAR,0,world);
for (i = 0; i < atom->nimpropertypes; i++) {
m = strlen(buf) + 1;
if (which == 0) parse_coeffs(buf,NULL,0);
else if (which == 1) parse_coeffs(buf,"aa",0);
force->improper->coeff(narg,arg);
buf += m;
}
delete [] original;
}
/* ----------------------------------------------------------------------
proc 0 scans the data file for topology maximums
------------------------------------------------------------------------- */
void ReadData::scan(int &bond_per_atom, int &angle_per_atom,
int &dihedral_per_atom, int &improper_per_atom)
{
int i,tmp1,tmp2,atom1,atom2,atom3,atom4;
char *eof;
if (atom->natoms > MAXSMALLINT)
- error->all("Molecular data file has too many atoms");
+ error->all(FLERR,"Molecular data file has too many atoms");
// customize for new sections
int natoms = static_cast<int> (atom->natoms);
bond_per_atom = angle_per_atom = dihedral_per_atom = improper_per_atom = 0;
int ellipsoid_flag = 0;
// customize for new sections
// allocate topology counting vector
// initially, array length = 1 to natoms
// will grow via reallocate() if atom IDs > natoms
int cmax = natoms + 1;
int *count;
memory->create(count,cmax,"read_data:count");
while (strlen(keyword)) {
if (strcmp(keyword,"Masses") == 0) skip_lines(atom->ntypes);
else if (strcmp(keyword,"Atoms") == 0) skip_lines(natoms);
else if (strcmp(keyword,"Velocities") == 0) skip_lines(natoms);
else if (strcmp(keyword,"Ellipsoids") == 0) {
if (!avec_ellipsoid)
- error->one("Invalid data file section: Ellipsoids");
+ error->one(FLERR,"Invalid data file section: Ellipsoids");
ellipsoid_flag = 1;
skip_lines(nellipsoids);
} else if (strcmp(keyword,"Pair Coeffs") == 0) {
if (force->pair == NULL)
- error->one("Must define pair_style before Pair Coeffs");
+ error->one(FLERR,"Must define pair_style before Pair Coeffs");
skip_lines(atom->ntypes);
} else if (strcmp(keyword,"Bond Coeffs") == 0) {
if (atom->avec->bonds_allow == 0)
- error->one("Invalid data file section: Bond Coeffs");
+ error->one(FLERR,"Invalid data file section: Bond Coeffs");
if (force->bond == NULL)
- error->one("Must define bond_style before Bond Coeffs");
+ error->one(FLERR,"Must define bond_style before Bond Coeffs");
skip_lines(atom->nbondtypes);
} else if (strcmp(keyword,"Angle Coeffs") == 0) {
if (atom->avec->angles_allow == 0)
- error->one("Invalid data file section: Angle Coeffs");
+ error->one(FLERR,"Invalid data file section: Angle Coeffs");
if (force->angle == NULL)
- error->one("Must define angle_style before Angle Coeffs");
+ error->one(FLERR,"Must define angle_style before Angle Coeffs");
skip_lines(atom->nangletypes);
} else if (strcmp(keyword,"Dihedral Coeffs") == 0) {
skip_lines(atom->ndihedraltypes);
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: Dihedral Coeffs");
+ error->one(FLERR,"Invalid data file section: Dihedral Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before Dihedral Coeffs");
+ error->one(FLERR,"Must define dihedral_style before Dihedral Coeffs");
} else if (strcmp(keyword,"Improper Coeffs") == 0) {
if (atom->avec->impropers_allow == 0)
- error->one("Invalid data file section: Improper Coeffs");
+ error->one(FLERR,"Invalid data file section: Improper Coeffs");
if (force->improper == NULL)
- error->one("Must define improper_style before Improper Coeffs");
+ error->one(FLERR,"Must define improper_style before Improper Coeffs");
skip_lines(atom->nimpropertypes);
} else if (strcmp(keyword,"BondBond Coeffs") == 0) {
if (atom->avec->angles_allow == 0)
- error->one("Invalid data file section: BondBond Coeffs");
+ error->one(FLERR,"Invalid data file section: BondBond Coeffs");
if (force->angle == NULL)
- error->one("Must define angle_style before BondBond Coeffs");
+ error->one(FLERR,"Must define angle_style before BondBond Coeffs");
skip_lines(atom->nangletypes);
} else if (strcmp(keyword,"BondAngle Coeffs") == 0) {
if (atom->avec->angles_allow == 0)
- error->one("Invalid data file section: BondAngle Coeffs");
+ error->one(FLERR,"Invalid data file section: BondAngle Coeffs");
if (force->angle == NULL)
- error->one("Must define angle_style before BondAngle Coeffs");
+ error->one(FLERR,"Must define angle_style before BondAngle Coeffs");
skip_lines(atom->nangletypes);
} else if (strcmp(keyword,"MiddleBondTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: MiddleBondTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: MiddleBondTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before MiddleBondTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before MiddleBondTorsion Coeffs");
skip_lines(atom->ndihedraltypes);
} else if (strcmp(keyword,"EndBondTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: EndBondTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: EndBondTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before EndBondTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before EndBondTorsion Coeffs");
skip_lines(atom->ndihedraltypes);
} else if (strcmp(keyword,"AngleTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: AngleTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: AngleTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before AngleTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before AngleTorsion Coeffs");
skip_lines(atom->ndihedraltypes);
} else if (strcmp(keyword,"AngleAngleTorsion Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: AngleAngleTorsion Coeffs");
+ error->one(FLERR,"Invalid data file section: AngleAngleTorsion Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before AngleAngleTorsion Coeffs");
+ error->one(FLERR,"Must define dihedral_style before AngleAngleTorsion Coeffs");
skip_lines(atom->ndihedraltypes);
} else if (strcmp(keyword,"BondBond13 Coeffs") == 0) {
if (atom->avec->dihedrals_allow == 0)
- error->one("Invalid data file section: BondBond13 Coeffs");
+ error->one(FLERR,"Invalid data file section: BondBond13 Coeffs");
if (force->dihedral == NULL)
- error->one("Must define dihedral_style before BondBond13 Coeffs");
+ error->one(FLERR,"Must define dihedral_style before BondBond13 Coeffs");
skip_lines(atom->ndihedraltypes);
} else if (strcmp(keyword,"AngleAngle Coeffs") == 0) {
if (atom->avec->impropers_allow == 0)
- error->one("Invalid data file section: AngleAngle Coeffs");
+ error->one(FLERR,"Invalid data file section: AngleAngle Coeffs");
if (force->improper == NULL)
- error->one("Must define improper_style before AngleAngle Coeffs");
+ error->one(FLERR,"Must define improper_style before AngleAngle Coeffs");
skip_lines(atom->nimpropertypes);
} else if (strcmp(keyword,"Bonds") == 0) {
for (i = 1; i < cmax; i++) count[i] = 0;
if (force->newton_bond)
for (i = 0; i < atom->nbonds; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d",&tmp1,&tmp2,&atom1,&atom2);
if (atom1 >= cmax) cmax = reallocate(&count,cmax,atom1);
count[atom1]++;
}
else
for (i = 0; i < atom->nbonds; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d",&tmp1,&tmp2,&atom1,&atom2);
int amax = MAX(atom1,atom2);
if (amax >= cmax) cmax = reallocate(&count,cmax,amax);
count[atom1]++;
count[atom2]++;
}
for (i = 1; i < cmax; i++) bond_per_atom = MAX(bond_per_atom,count[i]);
if (screen) fprintf(screen," %d = max bonds/atom\n",bond_per_atom);
if (logfile) fprintf(logfile," %d = max bonds/atom\n",bond_per_atom);
} else if (strcmp(keyword,"Angles") == 0) {
for (i = 1; i < cmax; i++) count[i] = 0;
if (force->newton_bond)
for (i = 0; i < atom->nangles; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d %d",&tmp1,&tmp2,&atom1,&atom2,&atom3);
if (atom2 >= cmax) cmax = reallocate(&count,cmax,atom2);
count[atom2]++;
}
else
for (i = 0; i < atom->nangles; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d %d",&tmp1,&tmp2,&atom1,&atom2,&atom3);
int amax = MAX(atom1,atom2);
amax = MAX(amax,atom3);
if (amax >= cmax) cmax = reallocate(&count,cmax,amax);
count[atom1]++;
count[atom2]++;
count[atom3]++;
}
for (i = 1; i < cmax; i++) angle_per_atom = MAX(angle_per_atom,count[i]);
if (screen) fprintf(screen," %d = max angles/atom\n",angle_per_atom);
if (logfile) fprintf(logfile," %d = max angles/atom\n",angle_per_atom);
} else if (strcmp(keyword,"Dihedrals") == 0) {
for (i = 1; i < cmax; i++) count[i] = 0;
if (force->newton_bond)
for (i = 0; i < atom->ndihedrals; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d %d %d",
&tmp1,&tmp2,&atom1,&atom2,&atom3,&atom4);
if (atom2 >= cmax) cmax = reallocate(&count,cmax,atom2);
count[atom2]++;
}
else
for (i = 0; i < atom->ndihedrals; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d %d %d",
&tmp1,&tmp2,&atom1,&atom2,&atom3,&atom4);
int amax = MAX(atom1,atom2);
amax = MAX(amax,atom3);
amax = MAX(amax,atom4);
if (amax >= cmax) cmax = reallocate(&count,cmax,amax);
count[atom1]++;
count[atom2]++;
count[atom3]++;
count[atom4]++;
}
for (i = 1; i < cmax; i++)
dihedral_per_atom = MAX(dihedral_per_atom,count[i]);
if (screen)
fprintf(screen," %d = max dihedrals/atom\n",dihedral_per_atom);
if (logfile)
fprintf(logfile," %d = max dihedrals/atom\n",dihedral_per_atom);
} else if (strcmp(keyword,"Impropers") == 0) {
for (i = 1; i < cmax; i++) count[i] = 0;
if (force->newton_bond)
for (i = 0; i < atom->nimpropers; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d %d %d",
&tmp1,&tmp2,&atom1,&atom2,&atom3,&atom4);
if (atom2 >= cmax) cmax = reallocate(&count,cmax,atom2);
count[atom2]++;
}
else
for (i = 0; i < atom->nimpropers; i++) {
eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
sscanf(line,"%d %d %d %d %d %d",
&tmp1,&tmp2,&atom1,&atom2,&atom3,&atom4);
int amax = MAX(atom1,atom2);
amax = MAX(amax,atom3);
amax = MAX(amax,atom4);
if (amax >= cmax) cmax = reallocate(&count,cmax,amax);
count[atom1]++;
count[atom2]++;
count[atom3]++;
count[atom4]++;
}
for (i = 1; i < cmax; i++)
improper_per_atom = MAX(improper_per_atom,count[i]);
if (screen)
fprintf(screen," %d = max impropers/atom\n",improper_per_atom);
if (logfile)
fprintf(logfile," %d = max impropers/atom\n",improper_per_atom);
} else {
char str[128];
sprintf(str,"Unknown identifier in data file: %s",keyword);
- error->one(str);
+ error->one(FLERR,str);
}
parse_keyword(0,0);
}
// free topology counting vector
memory->destroy(count);
// error check that topology was specified in file
if ((atom->nbonds && !bond_per_atom) ||
(atom->nangles && !angle_per_atom) ||
(atom->ndihedrals && !dihedral_per_atom) ||
(atom->nimpropers && !improper_per_atom))
- error->one("Needed topology not in data file");
+ error->one(FLERR,"Needed topology not in data file");
// customize for new sections
// error check that Bonus sections were speficied in file
if (nellipsoids && !ellipsoid_flag)
- error->one("Needed bonus data not in data file");
+ error->one(FLERR,"Needed bonus data not in data file");
}
/* ----------------------------------------------------------------------
reallocate the count vector from cmax to amax+1 and return new length
zero new locations
------------------------------------------------------------------------- */
int ReadData::reallocate(int **pcount, int cmax, int amax)
{
int *count = *pcount;
memory->grow(count,amax+1,"read_data:count");
for (int i = cmax; i <= amax; i++) count[i] = 0;
*pcount = count;
return amax+1;
}
/* ----------------------------------------------------------------------
proc 0 opens data file
test if gzipped
------------------------------------------------------------------------- */
void ReadData::open(char *file)
{
compressed = 0;
char *suffix = file + strlen(file) - 3;
if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1;
if (!compressed) fp = fopen(file,"r");
else {
#ifdef LAMMPS_GZIP
char gunzip[128];
sprintf(gunzip,"gunzip -c %s",file);
fp = popen(gunzip,"r");
#else
- error->one("Cannot open gzipped file");
+ error->one(FLERR,"Cannot open gzipped file");
#endif
}
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open file %s",file);
- error->one(str);
+ error->one(FLERR,str);
}
}
/* ----------------------------------------------------------------------
grab next keyword
read lines until one is non-blank
keyword is all text on line w/out leading & trailing white space
read one additional line (assumed blank)
if any read hits EOF, set keyword to empty
if first = 1, line variable holds non-blank line that ended header
if flag = 0, only proc 0 is calling so no bcast
else flag = 1, bcast keyword line to all procs
------------------------------------------------------------------------- */
void ReadData::parse_keyword(int first, int flag)
{
int eof = 0;
// proc 0 reads upto non-blank line plus 1 following line
// eof is set to 1 if any read hits end-of-file
if (me == 0) {
if (!first) {
if (fgets(line,MAXLINE,fp) == NULL) eof = 1;
}
while (eof == 0 && strspn(line," \t\n\r") == strlen(line)) {
if (fgets(line,MAXLINE,fp) == NULL) eof = 1;
}
if (fgets(buffer,MAXLINE,fp) == NULL) eof = 1;
}
// if eof, set keyword empty and return
if (flag) MPI_Bcast(&eof,1,MPI_INT,0,world);
if (eof) {
keyword[0] = '\0';
return;
}
// bcast keyword line to all procs
if (flag) {
int n;
if (me == 0) n = strlen(line) + 1;
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(line,n,MPI_CHAR,0,world);
}
// copy non-whitespace portion of line into keyword
int start = strspn(line," \t\n\r");
int stop = strlen(line) - 1;
while (line[stop] == ' ' || line[stop] == '\t'
|| line[stop] == '\n' || line[stop] == '\r') stop--;
line[stop+1] = '\0';
strcpy(keyword,&line[start]);
}
/* ----------------------------------------------------------------------
proc 0 reads N lines from file
------------------------------------------------------------------------- */
void ReadData::skip_lines(int n)
{
char *eof;
for (int i = 0; i < n; i++) eof = fgets(line,MAXLINE,fp);
- if (eof == NULL) error->one("Unexpected end of data file");
+ if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
}
/* ----------------------------------------------------------------------
parse a line of coeffs into words, storing them in narg,arg
trim anything from '#' onward
word strings remain in line, are not copied
if addstr != NULL, add addstr as extra arg for class2 angle/dihedral/improper
if 2nd word starts with letter, then is hybrid style, add addstr after it
else add addstr before 2nd word
if dupflag, duplicate 1st word, so pair_coeff "2" becomes "2 2"
------------------------------------------------------------------------- */
void ReadData::parse_coeffs(char *line, char *addstr, int dupflag)
{
char *ptr;
if (ptr = strchr(line,'#')) *ptr = '\0';
narg = 0;
char *word = strtok(line," \t\n\r\f");
while (word) {
if (narg == maxarg) {
maxarg += DELTA;
arg = (char **)
memory->srealloc(arg,maxarg*sizeof(char *),"read_data:arg");
}
if (addstr && narg == 1 && !islower(word[0])) arg[narg++] = addstr;
arg[narg++] = word;
if (addstr && narg == 2 && islower(word[0])) arg[narg++] = addstr;
if (dupflag && narg == 1) arg[narg++] = word;
word = strtok(NULL," \t\n\r\f");
}
}
diff --git a/src/read_restart.cpp b/src/read_restart.cpp
index d815b7ff8..0514cea31 100644
--- a/src/read_restart.cpp
+++ b/src/read_restart.cpp
@@ -1,837 +1,837 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "string.h"
#include "stdlib.h"
//#include "sys/types.h"
#include "dirent.h"
#include "read_restart.h"
#include "atom.h"
#include "atom_vec.h"
#include "domain.h"
#include "comm.h"
#include "irregular.h"
#include "update.h"
#include "modify.h"
#include "fix.h"
#include "fix_read_restart.h"
#include "group.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "special.h"
#include "universe.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
// same as write_restart.cpp
enum{VERSION,SMALLINT,TAGINT,BIGINT,
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID_0,PROCGRID_1,PROCGRID_2,
NEWTON_PAIR,NEWTON_BOND,XPERIODIC,YPERIODIC,ZPERIODIC,
BOUNDARY_00,BOUNDARY_01,BOUNDARY_10,BOUNDARY_11,BOUNDARY_20,BOUNDARY_21,
ATOM_STYLE,NATOMS,NTYPES,
NBONDS,NBONDTYPES,BOND_PER_ATOM,
NANGLES,NANGLETYPES,ANGLE_PER_ATOM,
NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM,
NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM,
BOXLO_0,BOXHI_0,BOXLO_1,BOXHI_1,BOXLO_2,BOXHI_2,
SPECIAL_LJ_1,SPECIAL_LJ_2,SPECIAL_LJ_3,
SPECIAL_COUL_1,SPECIAL_COUL_2,SPECIAL_COUL_3,
XY,XZ,YZ};
enum{MASS};
enum{PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER};
#define LB_FACTOR 1.1
/* ---------------------------------------------------------------------- */
ReadRestart::ReadRestart(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void ReadRestart::command(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal read_restart command");
+ if (narg != 1) error->all(FLERR,"Illegal read_restart command");
if (domain->box_exist)
- error->all("Cannot read_restart after simulation box is defined");
+ error->all(FLERR,"Cannot read_restart after simulation box is defined");
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
// if filename contains "*", search dir for latest restart file
char *file = new char[strlen(arg[0]) + 16];
if (strchr(arg[0],'*')) {
int n;
if (me == 0) {
file_search(arg[0],file);
n = strlen(file) + 1;
}
MPI_Bcast(&n,1,MPI_INT,0,world);
MPI_Bcast(file,n,MPI_CHAR,0,world);
} else strcpy(file,arg[0]);
// check if filename contains "%"
int multiproc;
if (strchr(file,'%')) multiproc = 1;
else multiproc = 0;
// open single restart file or base file for multiproc case
if (me == 0) {
if (screen) fprintf(screen,"Reading restart file ...\n");
char *hfile;
if (multiproc) {
hfile = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(hfile,"%s%s%s",file,"base",ptr+1);
*ptr = '%';
} else hfile = file;
fp = fopen(hfile,"rb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",hfile);
- error->one(str);
+ error->one(FLERR,str);
}
if (multiproc) delete [] hfile;
}
// read header info and create atom style and simulation box
header();
domain->box_exist = 1;
// problem setup using info from header
int n;
if (nprocs == 1) n = static_cast<int> (atom->natoms);
else n = static_cast<int> (LB_FACTOR * atom->natoms / nprocs);
atom->allocate_type_arrays();
atom->avec->grow(n);
n = atom->nmax;
domain->print_box(" ");
domain->set_initial_box();
domain->set_global_box();
comm->set_procs();
domain->set_local_box();
// read groups, ntype-length arrays, force field, fix info from file
// nextra = max # of extra quantities stored with each atom
group->read_restart(fp);
type_arrays();
force_fields();
int nextra = modify->read_restart(fp);
atom->nextra_store = nextra;
memory->create(atom->extra,n,nextra,"atom:extra");
// single file:
// nprocs_file = # of chunks in file
// proc 0 reads chunks one at a time and bcasts it to other procs
// each proc unpacks the atoms, saving ones in it's sub-domain
// check for atom in sub-domain differs for orthogonal vs triclinic box
// close restart file when done
AtomVec *avec = atom->avec;
int maxbuf = 0;
double *buf = NULL;
int m;
if (multiproc == 0) {
int triclinic = domain->triclinic;
double *x,lamda[3];
double *coord,*sublo,*subhi;
if (triclinic == 0) {
sublo = domain->sublo;
subhi = domain->subhi;
} else {
sublo = domain->sublo_lamda;
subhi = domain->subhi_lamda;
}
for (int iproc = 0; iproc < nprocs_file; iproc++) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
if (n > maxbuf) {
maxbuf = n;
memory->destroy(buf);
memory->create(buf,maxbuf,"read_restart:buf");
}
if (n > 0) {
if (me == 0) fread(buf,sizeof(double),n,fp);
MPI_Bcast(buf,n,MPI_DOUBLE,0,world);
}
m = 0;
while (m < n) {
x = &buf[m+1];
if (triclinic) {
domain->x2lamda(x,lamda);
coord = lamda;
} else coord = x;
if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1] &&
coord[2] >= sublo[2] && coord[2] < subhi[2]) {
m += avec->unpack_restart(&buf[m]);
}
else m += static_cast<int> (buf[m]);
}
}
if (me == 0) fclose(fp);
// one file per proc:
// nprocs_file = # of files
// each proc reads 1/P fraction of files, keeping all atoms in the files
// perform irregular comm to migrate atoms to correct procs
// close restart file when done
} else {
if (me == 0) fclose(fp);
char *perproc = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
for (int iproc = me; iproc < nprocs_file; iproc += nprocs) {
*ptr = '\0';
sprintf(perproc,"%s%d%s",file,iproc,ptr+1);
*ptr = '%';
fp = fopen(perproc,"rb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",perproc);
- error->one(str);
+ error->one(FLERR,str);
}
fread(&n,sizeof(int),1,fp);
if (n > maxbuf) {
maxbuf = n;
memory->destroy(buf);
memory->create(buf,maxbuf,"read_restart:buf");
}
if (n > 0) fread(buf,sizeof(double),n,fp);
m = 0;
while (m < n) m += avec->unpack_restart(&buf[m]);
fclose(fp);
}
delete [] perproc;
// create a temporary fix to hold and migrate extra atom info
// necessary b/c irregular will migrate atoms
if (nextra) {
char cextra[8],fixextra[8];
sprintf(cextra,"%d",nextra);
sprintf(fixextra,"%d",modify->nfix_restart_peratom);
char **newarg = new char*[5];
newarg[0] = (char *) "_read_restart";
newarg[1] = (char *) "all";
newarg[2] = (char *) "READ_RESTART";
newarg[3] = cextra;
newarg[4] = fixextra;
modify->add_fix(5,newarg);
delete [] newarg;
}
// move atoms to new processors via irregular()
// in case read by different proc than wrote restart file
// first do map_init() since irregular->migrate_atoms() will do map_clear()
if (atom->map_style) atom->map_init();
if (domain->triclinic) domain->x2lamda(atom->nlocal);
Irregular *irregular = new Irregular(lmp);
irregular->migrate_atoms();
delete irregular;
if (domain->triclinic) domain->lamda2x(atom->nlocal);
// put extra atom info held by fix back into atom->extra
// destroy temporary fix
if (nextra) {
memory->destroy(atom->extra);
memory->create(atom->extra,atom->nmax,nextra,"atom:extra");
int ifix = modify->find_fix("_read_restart");
FixReadRestart *fix = (FixReadRestart *) modify->fix[ifix];
int *count = fix->count;
double **extra = fix->extra;
double **atom_extra = atom->extra;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
for (int j = 0; j < count[i]; j++)
atom_extra[i][j] = extra[i][j];
modify->delete_fix("_read_restart");
}
}
// clean-up memory
delete [] file;
memory->destroy(buf);
// check that all atoms were assigned to procs
bigint natoms;
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " atoms\n",natoms);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " atoms\n",natoms);
}
- if (natoms != atom->natoms) error->all("Did not assign all atoms correctly");
+ if (natoms != atom->natoms) error->all(FLERR,"Did not assign all atoms correctly");
if (me == 0) {
if (atom->nbonds) {
if (screen) fprintf(screen," " BIGINT_FORMAT " bonds\n",atom->nbonds);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " bonds\n",atom->nbonds);
}
if (atom->nangles) {
if (screen) fprintf(screen," " BIGINT_FORMAT " angles\n",
atom->nangles);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " angles\n",
atom->nangles);
}
if (atom->ndihedrals) {
if (screen) fprintf(screen," " BIGINT_FORMAT " dihedrals\n",
atom->ndihedrals);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " dihedrals\n",
atom->ndihedrals);
}
if (atom->nimpropers) {
if (screen) fprintf(screen," " BIGINT_FORMAT " impropers\n",
atom->nimpropers);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " impropers\n",
atom->nimpropers);
}
}
// check if tags are being used
// create global mapping and bond topology now that system is defined
int flag = 0;
for (int i = 0; i < atom->nlocal; i++)
if (atom->tag[i] > 0) flag = 1;
int flag_all;
MPI_Allreduce(&flag,&flag_all,1,MPI_INT,MPI_MAX,world);
if (flag_all == 0) atom->tag_enable = 0;
if (atom->map_style) {
atom->map_init();
atom->map_set();
}
if (atom->molecular) {
Special special(lmp);
special.build();
}
}
/* ----------------------------------------------------------------------
infile contains a "*"
search for all files which match the infile pattern
replace "*" with latest timestep value to create outfile name
search dir referenced by initial pathname of file
if infile also contains "%", use "base" when searching directory
only called by proc 0
------------------------------------------------------------------------- */
void ReadRestart::file_search(char *infile, char *outfile)
{
char *ptr;
// separate infile into dir + filename
char *dirname = new char[strlen(infile) + 1];
char *filename = new char[strlen(infile) + 1];
if (strchr(infile,'/')) {
ptr = strrchr(infile,'/');
*ptr = '\0';
strcpy(dirname,infile);
strcpy(filename,ptr+1);
*ptr = '/';
} else {
strcpy(dirname,"./");
strcpy(filename,infile);
}
// if filename contains "%" replace "%" with "base"
char *pattern = new char[strlen(filename) + 16];
if (ptr = strchr(filename,'%')) {
*ptr = '\0';
sprintf(pattern,"%s%s%s",filename,"base",ptr+1);
*ptr = '%';
} else strcpy(pattern,filename);
// scan all files in directory, searching for files that match pattern
// maxnum = largest int that matches "*"
int n = strlen(pattern) + 16;
char *begin = new char[n];
char *middle = new char[n];
char *end = new char[n];
ptr = strchr(pattern,'*');
*ptr = '\0';
strcpy(begin,pattern);
strcpy(end,ptr+1);
int nbegin = strlen(begin);
bigint maxnum = -1;
struct dirent *ep;
DIR *dp = opendir(dirname);
if (dp == NULL)
- error->one("Cannot open dir to search for restart file");
+ error->one(FLERR,"Cannot open dir to search for restart file");
while (ep = readdir(dp)) {
if (strstr(ep->d_name,begin) != ep->d_name) continue;
if ((ptr = strstr(&ep->d_name[nbegin],end)) == NULL) continue;
if (strlen(end) == 0) ptr = ep->d_name + strlen(ep->d_name);
*ptr = '\0';
if (strlen(&ep->d_name[nbegin]) < n) {
strcpy(middle,&ep->d_name[nbegin]);
if (ATOBIGINT(middle) > maxnum) maxnum = ATOBIGINT(middle);
}
}
closedir(dp);
- if (maxnum < 0) error->one("Found no restart file matching pattern");
+ if (maxnum < 0) error->one(FLERR,"Found no restart file matching pattern");
// create outfile with maxint substituted for "*"
// use original infile, not pattern, since need to retain "%" in filename
ptr = strchr(infile,'*');
*ptr = '\0';
sprintf(outfile,"%s" BIGINT_FORMAT "%s",infile,maxnum,ptr+1);
*ptr = '*';
// clean up
delete [] dirname;
delete [] filename;
delete [] pattern;
delete [] begin;
delete [] middle;
delete [] end;
}
/* ----------------------------------------------------------------------
read header of restart file
------------------------------------------------------------------------- */
void ReadRestart::header()
{
int px,py,pz;
int xperiodic,yperiodic,zperiodic;
int boundary[3][2];
// read flags and values until flag = -1
int flag = read_int();
while (flag >= 0) {
// check restart file version, warn if different
if (flag == VERSION) {
char *version = read_char();
if (strcmp(version,universe->version) != 0 && me == 0) {
- error->warning("Restart file version does not match LAMMPS version");
+ error->warning(FLERR,"Restart file version does not match LAMMPS version");
if (screen) fprintf(screen," restart file = %s, LAMMPS = %s\n",
version,universe->version);
}
delete [] version;
// check lmptype.h sizes, error if different
} else if (flag == SMALLINT) {
int size = read_int();
if (size != sizeof(smallint))
- error->all("Smallint setting in lmptype.h is not compatible");
+ error->all(FLERR,"Smallint setting in lmptype.h is not compatible");
} else if (flag == TAGINT) {
int size = read_int();
if (size != sizeof(tagint))
- error->all("Tagint setting in lmptype.h is not compatible");
+ error->all(FLERR,"Tagint setting in lmptype.h is not compatible");
} else if (flag == BIGINT) {
int size = read_int();
if (size != sizeof(bigint))
- error->all("Bigint setting in lmptype.h is not compatible");
+ error->all(FLERR,"Bigint setting in lmptype.h is not compatible");
// reset unit_style only if different
// so that timestep,neighbor-skin are not changed
} else if (flag == UNITS) {
char *style = read_char();
if (strcmp(style,update->unit_style) != 0) update->set_units(style);
delete [] style;
} else if (flag == NTIMESTEP) {
update->ntimestep = read_bigint();
// set dimension from restart file
} else if (flag == DIMENSION) {
int dimension = read_int();
domain->dimension = dimension;
if (domain->dimension == 2 && domain->zperiodic == 0)
- error->all("Cannot run 2d simulation with nonperiodic Z dimension");
+ error->all(FLERR,"Cannot run 2d simulation with nonperiodic Z dimension");
// read nprocs from restart file, warn if different
} else if (flag == NPROCS) {
nprocs_file = read_int();
if (nprocs_file != comm->nprocs && me == 0)
- error->warning("Restart file used different # of processors");
+ error->warning(FLERR,"Restart file used different # of processors");
// don't set procgrid, warn if different
} else if (flag == PROCGRID_0) {
px = read_int();
} else if (flag == PROCGRID_1) {
py = read_int();
} else if (flag == PROCGRID_2) {
pz = read_int();
if (comm->user_procgrid[0] != 0 &&
(px != comm->user_procgrid[0] || py != comm->user_procgrid[1] ||
pz != comm->user_procgrid[2]) && me == 0)
- error->warning("Restart file used different 3d processor grid");
+ error->warning(FLERR,"Restart file used different 3d processor grid");
// don't set newton_pair, leave input script value unchanged
// set newton_bond from restart file
// warn if different and input script settings are not default
} else if (flag == NEWTON_PAIR) {
int newton_pair_file = read_int();
if (force->newton_pair != 1) {
if (newton_pair_file != force->newton_pair && me == 0)
- error->warning("Restart file used different newton pair setting, "
+ error->warning(FLERR,"Restart file used different newton pair setting, "
"using input script value");
}
} else if (flag == NEWTON_BOND) {
int newton_bond_file = read_int();
if (force->newton_bond != 1) {
if (newton_bond_file != force->newton_bond && me == 0)
- error->warning("Restart file used different newton bond setting, "
+ error->warning(FLERR,"Restart file used different newton bond setting, "
"using restart file value");
}
force->newton_bond = newton_bond_file;
if (force->newton_pair || force->newton_bond) force->newton = 1;
else force->newton = 0;
// set boundary settings from restart file
// warn if different and input script settings are not default
} else if (flag == XPERIODIC) {
xperiodic = read_int();
} else if (flag == YPERIODIC) {
yperiodic = read_int();
} else if (flag == ZPERIODIC) {
zperiodic = read_int();
} else if (flag == BOUNDARY_00) {
boundary[0][0] = read_int();
} else if (flag == BOUNDARY_01) {
boundary[0][1] = read_int();
} else if (flag == BOUNDARY_10) {
boundary[1][0] = read_int();
} else if (flag == BOUNDARY_11) {
boundary[1][1] = read_int();
} else if (flag == BOUNDARY_20) {
boundary[2][0] = read_int();
} else if (flag == BOUNDARY_21) {
boundary[2][1] = read_int();
if (domain->boundary[0][0] || domain->boundary[0][1] ||
domain->boundary[1][0] || domain->boundary[1][1] ||
domain->boundary[2][0] || domain->boundary[2][1]) {
if (boundary[0][0] != domain->boundary[0][0] ||
boundary[0][1] != domain->boundary[0][1] ||
boundary[1][0] != domain->boundary[1][0] ||
boundary[1][1] != domain->boundary[1][1] ||
boundary[2][0] != domain->boundary[2][0] ||
boundary[2][1] != domain->boundary[2][1]) {
if (me == 0)
- error->warning("Restart file used different boundary settings, "
+ error->warning(FLERR,"Restart file used different boundary settings, "
"using restart file values");
}
}
domain->boundary[0][0] = boundary[0][0];
domain->boundary[0][1] = boundary[0][1];
domain->boundary[1][0] = boundary[1][0];
domain->boundary[1][1] = boundary[1][1];
domain->boundary[2][0] = boundary[2][0];
domain->boundary[2][1] = boundary[2][1];
domain->periodicity[0] = domain->xperiodic = xperiodic;
domain->periodicity[1] = domain->yperiodic = yperiodic;
domain->periodicity[2] = domain->zperiodic = zperiodic;
domain->nonperiodic = 0;
if (xperiodic == 0 || yperiodic == 0 || zperiodic == 0) {
domain->nonperiodic = 1;
if (boundary[0][0] >= 2 || boundary[0][1] >= 2 ||
boundary[1][0] >= 2 || boundary[1][1] >= 2 ||
boundary[2][0] >= 2 || boundary[2][1] >= 2)
domain->nonperiodic = 2;
}
// create new AtomVec class
// if style = hybrid, read additional sub-class arguments
} else if (flag == ATOM_STYLE) {
char *style = read_char();
int nwords = 0;
char **words = NULL;
if (strcmp(style,"hybrid") == 0) {
nwords = read_int();
words = new char*[nwords];
for (int i = 0; i < nwords; i++) words[i] = read_char();
}
atom->create_avec(style,nwords,words);
for (int i = 0; i < nwords; i++) delete [] words[i];
delete [] words;
delete [] style;
} else if (flag == NATOMS) {
atom->natoms = read_bigint();
} else if (flag == NTYPES) {
atom->ntypes = read_int();
} else if (flag == NBONDS) {
atom->nbonds = read_bigint();
} else if (flag == NBONDTYPES) {
atom->nbondtypes = read_int();
} else if (flag == BOND_PER_ATOM) {
atom->bond_per_atom = read_int();
} else if (flag == NANGLES) {
atom->nangles = read_bigint();
} else if (flag == NANGLETYPES) {
atom->nangletypes = read_int();
} else if (flag == ANGLE_PER_ATOM) {
atom->angle_per_atom = read_int();
} else if (flag == NDIHEDRALS) {
atom->ndihedrals = read_bigint();
} else if (flag == NDIHEDRALTYPES) {
atom->ndihedraltypes = read_int();
} else if (flag == DIHEDRAL_PER_ATOM) {
atom->dihedral_per_atom = read_int();
} else if (flag == NIMPROPERS) {
atom->nimpropers = read_bigint();
} else if (flag == NIMPROPERTYPES) {
atom->nimpropertypes = read_int();
} else if (flag == IMPROPER_PER_ATOM) {
atom->improper_per_atom = read_int();
} else if (flag == BOXLO_0) {
domain->boxlo[0] = read_double();
} else if (flag == BOXHI_0) {
domain->boxhi[0] = read_double();
} else if (flag == BOXLO_1) {
domain->boxlo[1] = read_double();
} else if (flag == BOXHI_1) {
domain->boxhi[1] = read_double();
} else if (flag == BOXLO_2) {
domain->boxlo[2] = read_double();
} else if (flag == BOXHI_2) {
domain->boxhi[2] = read_double();
} else if (flag == SPECIAL_LJ_1) {
force->special_lj[1] = read_double();
} else if (flag == SPECIAL_LJ_2) {
force->special_lj[2] = read_double();
} else if (flag == SPECIAL_LJ_3) {
force->special_lj[3] = read_double();
} else if (flag == SPECIAL_COUL_1) {
force->special_coul[1] = read_double();
} else if (flag == SPECIAL_COUL_2) {
force->special_coul[2] = read_double();
} else if (flag == SPECIAL_COUL_3) {
force->special_coul[3] = read_double();
} else if (flag == XY) {
domain->triclinic = 1;
domain->xy = read_double();
} else if (flag == XZ) {
domain->triclinic = 1;
domain->xz = read_double();
} else if (flag == YZ) {
domain->triclinic = 1;
domain->yz = read_double();
- } else error->all("Invalid flag in header section of restart file");
+ } else error->all(FLERR,"Invalid flag in header section of restart file");
flag = read_int();
}
}
/* ---------------------------------------------------------------------- */
void ReadRestart::type_arrays()
{
int flag = read_int();
while (flag >= 0) {
if (flag == MASS) {
double *mass = new double[atom->ntypes+1];
if (me == 0) fread(&mass[1],sizeof(double),atom->ntypes,fp);
MPI_Bcast(&mass[1],atom->ntypes,MPI_DOUBLE,0,world);
atom->set_mass(mass);
delete [] mass;
- } else error->all("Invalid flag in type arrays section of restart file");
+ } else error->all(FLERR,"Invalid flag in type arrays section of restart file");
flag = read_int();
}
}
/* ---------------------------------------------------------------------- */
void ReadRestart::force_fields()
{
int n;
char *style;
int flag = read_int();
while (flag >= 0) {
if (flag == PAIR) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
style = new char[n];
if (me == 0) fread(style,sizeof(char),n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_pair(style);
delete [] style;
force->pair->read_restart(fp);
} else if (flag == BOND) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
style = new char[n];
if (me == 0) fread(style,sizeof(char),n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_bond(style);
delete [] style;
force->bond->read_restart(fp);
} else if (flag == ANGLE) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
style = new char[n];
if (me == 0) fread(style,sizeof(char),n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_angle(style);
delete [] style;
force->angle->read_restart(fp);
} else if (flag == DIHEDRAL) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
style = new char[n];
if (me == 0) fread(style,sizeof(char),n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_dihedral(style);
delete [] style;
force->dihedral->read_restart(fp);
} else if (flag == IMPROPER) {
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
style = new char[n];
if (me == 0) fread(style,sizeof(char),n,fp);
MPI_Bcast(style,n,MPI_CHAR,0,world);
force->create_improper(style);
delete [] style;
force->improper->read_restart(fp);
- } else error->all("Invalid flag in force field section of restart file");
+ } else error->all(FLERR,"Invalid flag in force field section of restart file");
flag = read_int();
}
}
/* ----------------------------------------------------------------------
read an int from restart file and bcast it
------------------------------------------------------------------------- */
int ReadRestart::read_int()
{
int value;
if (me == 0) fread(&value,sizeof(int),1,fp);
MPI_Bcast(&value,1,MPI_INT,0,world);
return value;
}
/* ----------------------------------------------------------------------
read a double from restart file and bcast it
------------------------------------------------------------------------- */
double ReadRestart::read_double()
{
double value;
if (me == 0) fread(&value,sizeof(double),1,fp);
MPI_Bcast(&value,1,MPI_DOUBLE,0,world);
return value;
}
/* ----------------------------------------------------------------------
read a char str from restart file and bcast it
str is allocated here, ptr is returned, caller must deallocate
------------------------------------------------------------------------- */
char *ReadRestart::read_char()
{
int n;
if (me == 0) fread(&n,sizeof(int),1,fp);
MPI_Bcast(&n,1,MPI_INT,0,world);
char *value = new char[n];
if (me == 0) fread(value,sizeof(char),n,fp);
MPI_Bcast(value,n,MPI_CHAR,0,world);
return value;
}
/* ----------------------------------------------------------------------
read a bigint from restart file and bcast it
------------------------------------------------------------------------- */
bigint ReadRestart::read_bigint()
{
bigint value;
if (me == 0) fread(&value,sizeof(bigint),1,fp);
MPI_Bcast(&value,1,MPI_LMP_BIGINT,0,world);
return value;
}
diff --git a/src/region.cpp b/src/region.cpp
index 412fcdeff..d73ebd368 100644
--- a/src/region.cpp
+++ b/src/region.cpp
@@ -1,382 +1,382 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "region.h"
#include "update.h"
#include "domain.h"
#include "lattice.h"
#include "input.h"
#include "variable.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Region::Region(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
int n = strlen(arg[0]) + 1;
id = new char[n];
strcpy(id,arg[0]);
n = strlen(arg[1]) + 1;
style = new char[n];
strcpy(style,arg[1]);
xstr = ystr = zstr = tstr = NULL;
dx = dy = dz = 0.0;
laststep = -1;
}
/* ---------------------------------------------------------------------- */
Region::~Region()
{
delete [] id;
delete [] style;
delete [] xstr;
delete [] ystr;
delete [] zstr;
delete [] tstr;
}
/* ---------------------------------------------------------------------- */
void Region::init()
{
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for region does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for region does not exist");
if (!input->variable->equalstyle(xvar))
- error->all("Variable for region is invalid style");
+ error->all(FLERR,"Variable for region is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for region does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for region does not exist");
if (!input->variable->equalstyle(yvar))
- error->all("Variable for region is not equal style");
+ error->all(FLERR,"Variable for region is not equal style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for region does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for region does not exist");
if (!input->variable->equalstyle(zvar))
- error->all("Variable for region is not equal style");
+ error->all(FLERR,"Variable for region is not equal style");
}
if (tstr) {
tvar = input->variable->find(tstr);
- if (tvar < 0) error->all("Variable name for region does not exist");
+ if (tvar < 0) error->all(FLERR,"Variable name for region does not exist");
if (!input->variable->equalstyle(tvar))
- error->all("Variable for region is not equal style");
+ error->all(FLERR,"Variable for region is not equal style");
}
}
/* ----------------------------------------------------------------------
return 1 if region is dynamic, 0 if static
only primitive regions define it here
union/intersect regions have their own dynamic_check()
------------------------------------------------------------------------- */
int Region::dynamic_check()
{
return dynamic;
}
/* ----------------------------------------------------------------------
determine if point x,y,z is a match to region volume
XOR computes 0 if 2 args are the same, 1 if different
note that inside() returns 1 for points on surface of region
thus point on surface of exterior region will not match
if region is dynamic, apply inverse transform to x,y,z
unmove first, then unrotate, so don't have to change rotation point
------------------------------------------------------------------------- */
int Region::match(double x, double y, double z)
{
if (dynamic) inverse_transform(x,y,z);
return !(inside(x,y,z) ^ interior);
}
/* ----------------------------------------------------------------------
generate list of contact points for interior or exterior regions
if region is dynamic:
before: inverse transform x,y,z (unmove, then unrotate)
after: forward transform contact point xs,yx,zs (rotate, then move),
then reset contact delx,dely,delz based on new contact point
no need to do this if no rotation since delxyz doesn't change
------------------------------------------------------------------------- */
int Region::surface(double x, double y, double z, double cutoff)
{
int ncontact;
double xs,ys,zs;
double xnear[3],xorig[3];
if (dynamic) {
xorig[0] = x;
xorig[1] = y;
xorig[2] = z;
inverse_transform(x,y,z);
}
xnear[0] = x;
xnear[1] = y;
xnear[2] = z;
if (interior) ncontact = surface_interior(xnear,cutoff);
else ncontact = surface_exterior(xnear,cutoff);
if (rotateflag && ncontact) {
for (int i = 0; i < ncontact; i++) {
xs = xnear[0] - contact[i].delx;
ys = xnear[1] - contact[i].dely;
zs = xnear[2] - contact[i].delz;
forward_transform(xs,ys,zs);
contact[i].delx = xorig[0] - xs;
contact[i].dely = xorig[1] - ys;
contact[i].delz = xorig[2] - zs;
}
}
return ncontact;
}
/* ----------------------------------------------------------------------
add a single contact at Nth location in contact array
x = particle position
xp,yp,zp = region surface point
------------------------------------------------------------------------- */
void Region::add_contact(int n, double *x, double xp, double yp, double zp)
{
double delx = x[0] - xp;
double dely = x[1] - yp;
double delz = x[2] - zp;
contact[n].r = sqrt(delx*delx + dely*dely + delz*delz);
contact[n].delx = delx;
contact[n].dely = dely;
contact[n].delz = delz;
}
/* ----------------------------------------------------------------------
transform a point x,y,z in region space to moved space
rotate first (around original P), then displace
------------------------------------------------------------------------- */
void Region::forward_transform(double &x, double &y, double &z)
{
if (rotateflag) {
if (update->ntimestep != laststep)
theta = input->variable->compute_equal(tvar);
rotate(x,y,z,theta);
}
if (moveflag) {
if (update->ntimestep != laststep) {
if (xstr) dx = input->variable->compute_equal(xvar);
if (ystr) dy = input->variable->compute_equal(yvar);
if (zstr) dz = input->variable->compute_equal(zvar);
}
x += dx;
y += dy;
z += dz;
}
laststep = update->ntimestep;
}
/* ----------------------------------------------------------------------
transform a point x,y,z in moved space back to region space
undisplace first, then unrotate (around original P)
------------------------------------------------------------------------- */
void Region::inverse_transform(double &x, double &y, double &z)
{
if (moveflag) {
if (update->ntimestep != laststep) {
if (xstr) dx = input->variable->compute_equal(xvar);
if (ystr) dy = input->variable->compute_equal(yvar);
if (zstr) dz = input->variable->compute_equal(zvar);
}
x -= dx;
y -= dy;
z -= dz;
}
if (rotateflag) {
if (update->ntimestep != laststep)
theta = input->variable->compute_equal(tvar);
rotate(x,y,z,-theta);
}
laststep = update->ntimestep;
}
/* ----------------------------------------------------------------------
rotate x,y,z by angle via right-hand rule around point and runit normal
sign of angle determines whether rotating forward/backward in time
return updated x,y,z
P = point = vector = point of rotation
R = vector = axis of rotation
w = omega of rotation (from period)
X0 = x,y,z = initial coord of atom
R0 = runit = unit vector for R
C = (X0 dot R0) R0 = projection of atom coord onto R
D = X0 - P = vector from P to X0
A = D - C = vector from R line to X0
B = R0 cross A = vector perp to A in plane of rotation
A,B define plane of circular rotation around R line
x,y,z = P + C + A cos(w*dt) + B sin(w*dt)
------------------------------------------------------------------------- */
void Region::rotate(double &x, double &y, double &z, double angle)
{
double a[3],b[3],c[3],d[3],disp[3];
double sine = sin(angle);
double cosine = cos(angle);
double x0dotr = x*runit[0] + y*runit[1] + z*runit[2];
c[0] = x0dotr * runit[0];
c[1] = x0dotr * runit[1];
c[2] = x0dotr * runit[2];
d[0] = x - point[0];
d[1] = y - point[1];
d[2] = z - point[2];
a[0] = d[0] - c[0];
a[1] = d[1] - c[1];
a[2] = d[2] - c[2];
b[0] = runit[1]*a[2] - runit[2]*a[1];
b[1] = runit[2]*a[0] - runit[0]*a[2];
b[2] = runit[0]*a[1] - runit[1]*a[0];
disp[0] = a[0]*cosine + b[0]*sine;
disp[1] = a[1]*cosine + b[1]*sine;
disp[2] = a[2]*cosine + b[2]*sine;
x = point[0] + c[0] + disp[0];
y = point[1] + c[1] + disp[1];
z = point[2] + c[2] + disp[2];
}
/* ----------------------------------------------------------------------
parse optional parameters at end of region input line
------------------------------------------------------------------------- */
void Region::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal region command");
+ if (narg < 0) error->all(FLERR,"Illegal region command");
// option defaults
interior = 1;
scaleflag = 1;
moveflag = rotateflag = 0;
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal region command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal region command");
if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
- else error->all("Illegal region command");
+ else error->all(FLERR,"Illegal region command");
iarg += 2;
} else if (strcmp(arg[iarg],"side") == 0) {
- if (iarg+2 > narg) error->all("Illegal region command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal region command");
if (strcmp(arg[iarg+1],"in") == 0) interior = 1;
else if (strcmp(arg[iarg+1],"out") == 0) interior = 0;
- else error->all("Illegal region command");
+ else error->all(FLERR,"Illegal region command");
iarg += 2;
} else if (strcmp(arg[iarg],"move") == 0) {
- if (iarg+4 > narg) error->all("Illegal region command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal region command");
if (strcmp(arg[iarg+1],"NULL") != 0) {
if (strstr(arg[iarg+1],"v_") != arg[iarg+1])
- error->all("Illegal region command");
+ error->all(FLERR,"Illegal region command");
int n = strlen(&arg[iarg+1][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[iarg+1][2]);
}
if (strcmp(arg[iarg+2],"NULL") != 0) {
if (strstr(arg[iarg+2],"v_") != arg[iarg+2])
- error->all("Illegal region command");
+ error->all(FLERR,"Illegal region command");
int n = strlen(&arg[iarg+2][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[iarg+2][2]);
}
if (strcmp(arg[iarg+3],"NULL") != 0) {
if (strstr(arg[iarg+3],"v_") != arg[iarg+3])
- error->all("Illegal region command");
+ error->all(FLERR,"Illegal region command");
int n = strlen(&arg[iarg+3][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[iarg+3][2]);
}
moveflag = 1;
iarg += 4;
} else if (strcmp(arg[iarg],"rotate") == 0) {
- if (iarg+8 > narg) error->all("Illegal region command");
+ if (iarg+8 > narg) error->all(FLERR,"Illegal region command");
if (strstr(arg[iarg+1],"v_") != arg[iarg+1])
- error->all("Illegal region command");
+ error->all(FLERR,"Illegal region command");
int n = strlen(&arg[iarg+1][2]) + 1;
tstr = new char[n];
strcpy(tstr,&arg[iarg+1][2]);
point[0] = atof(arg[iarg+2]);
point[1] = atof(arg[iarg+3]);
point[2] = atof(arg[iarg+4]);
axis[0] = atof(arg[iarg+5]);
axis[1] = atof(arg[iarg+6]);
axis[2] = atof(arg[iarg+7]);
rotateflag = 1;
iarg += 8;
- } else error->all("Illegal region command");
+ } else error->all(FLERR,"Illegal region command");
}
// error check
if ((moveflag || rotateflag) &&
(strcmp(style,"union") == 0 || strcmp(style,"intersect") == 0))
- error->all("Region union or intersect cannot be dynamic");
+ error->all(FLERR,"Region union or intersect cannot be dynamic");
// setup scaling
if (scaleflag && domain->lattice == NULL)
- error->all("Use of region with undefined lattice");
+ error->all(FLERR,"Use of region with undefined lattice");
if (scaleflag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
if (rotateflag) {
point[0] *= xscale;
point[1] *= yscale;
point[2] *= zscale;
}
// runit = unit vector along rotation axis
if (rotateflag) {
double len = sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
if (len == 0.0)
- error->all("Region cannot have 0 length rotation vector");
+ error->all(FLERR,"Region cannot have 0 length rotation vector");
runit[0] = axis[0]/len;
runit[1] = axis[1]/len;
runit[2] = axis[2]/len;
}
if (moveflag || rotateflag) dynamic = 1;
else dynamic = 0;
}
diff --git a/src/region_block.cpp b/src/region_block.cpp
index ff01e7f6a..cf5eb9920 100644
--- a/src/region_block.cpp
+++ b/src/region_block.cpp
@@ -1,228 +1,225 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "region_block.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
RegBlock::RegBlock(LAMMPS *lmp, int narg, char **arg) : Region(lmp, narg, arg)
{
options(narg-8,&arg[8]);
if (strcmp(arg[2],"INF") == 0 || strcmp(arg[2],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[2],"INF") == 0) xlo = -BIG;
else if (domain->triclinic == 0) xlo = domain->boxlo[0];
else xlo = domain->boxlo_bound[0];
} else xlo = xscale*atof(arg[2]);
if (strcmp(arg[3],"INF") == 0 || strcmp(arg[3],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[3],"INF") == 0) xhi = BIG;
else if (domain->triclinic == 0) xhi = domain->boxhi[0];
else xhi = domain->boxhi_bound[0];
} else xhi = xscale*atof(arg[3]);
if (strcmp(arg[4],"INF") == 0 || strcmp(arg[4],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[4],"INF") == 0) ylo = -BIG;
else if (domain->triclinic == 0) ylo = domain->boxlo[1];
else ylo = domain->boxlo_bound[1];
} else ylo = yscale*atof(arg[4]);
if (strcmp(arg[5],"INF") == 0 || strcmp(arg[5],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[5],"INF") == 0) yhi = BIG;
else if (domain->triclinic == 0) yhi = domain->boxhi[1];
else yhi = domain->boxhi_bound[1];
} else yhi = yscale*atof(arg[5]);
if (strcmp(arg[6],"INF") == 0 || strcmp(arg[6],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[6],"INF") == 0) zlo = -BIG;
else if (domain->triclinic == 0) zlo = domain->boxlo[2];
else zlo = domain->boxlo_bound[2];
} else zlo = zscale*atof(arg[6]);
if (strcmp(arg[7],"INF") == 0 || strcmp(arg[7],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[7],"INF") == 0) zhi = BIG;
else if (domain->triclinic == 0) zhi = domain->boxhi[2];
else zhi = domain->boxhi_bound[2];
} else zhi = zscale*atof(arg[7]);
// error check
if (xlo > xhi || ylo > yhi || zlo > zhi)
- error->all("Illegal region block command");
+ error->all(FLERR,"Illegal region block command");
// extent of block
if (interior) {
bboxflag = 1;
extent_xlo = xlo;
extent_xhi = xhi;
extent_ylo = ylo;
extent_yhi = yhi;
extent_zlo = zlo;
extent_zhi = zhi;
} else bboxflag = 0;
// particle could be close to all 6 planes
cmax = 6;
contact = new Contact[cmax];
}
/* ---------------------------------------------------------------------- */
RegBlock::~RegBlock()
{
delete [] contact;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is inside or on surface
inside = 0 if x,y,z is outside and not on surface
------------------------------------------------------------------------- */
int RegBlock::inside(double x, double y, double z)
{
if (x >= xlo && x <= xhi && y >= ylo && y <= yhi && z >= zlo && z <= zhi)
return 1;
return 0;
}
/* ----------------------------------------------------------------------
contact if 0 <= x < cutoff from one or more inner surfaces of block
can be one contact for each of 6 faces
no contact if outside (possible if called from union/intersect)
delxyz = vector from nearest point on block to x
------------------------------------------------------------------------- */
int RegBlock::surface_interior(double *x, double cutoff)
{
double delta;
// x is exterior to block
if (x[0] < xlo || x[0] > xhi || x[1] < ylo || x[1] > yhi ||
x[2] < ylo || x[2] > zhi) return 0;
// x is interior to block or on its surface
int n = 0;
delta = x[0] - xlo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delx = delta;
contact[n].dely = contact[n].delz = 0.0;
n++;
}
delta = xhi - x[0];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delx = -delta;
contact[n].dely = contact[n].delz = 0.0;
n++;
}
delta = x[1] - ylo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].dely = delta;
contact[n].delx = contact[n].delz = 0.0;
n++;
}
delta = yhi - x[1];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].dely = -delta;
contact[n].delx = contact[n].delz = 0.0;
n++;
}
delta = x[2] - zlo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
delta = zhi - x[2];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = -delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
return n;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from outer surface of block
no contact if inside (possible if called from union/intersect)
delxyz = vector from nearest point on block to x
------------------------------------------------------------------------- */
int RegBlock::surface_exterior(double *x, double cutoff)
{
double xp,yp,zp;
// x is far enough from block that there is no contact
// x is interior to block
if (x[0] <= xlo-cutoff || x[0] >= xhi+cutoff ||
x[1] <= ylo-cutoff || x[1] >= yhi+cutoff ||
x[2] <= zlo-cutoff || x[2] >= zhi+cutoff) return 0;
if (x[0] > xlo && x[0] < xhi && x[1] > ylo && x[1] < yhi &&
x[2] > zlo && x[2] < zhi) return 0;
// x is exterior to block or on its surface
// xp,yp,zp = point on surface of block that x is closest to
// could be edge or corner pt of block
// do not add contact point if r >= cutoff
if (x[0] < xlo) xp = xlo;
else if (x[0] > xhi) xp = xhi;
else xp = x[0];
if (x[1] < ylo) yp = ylo;
else if (x[1] > yhi) yp = yhi;
else yp = x[1];
if (x[2] < zlo) zp = zlo;
else if (x[2] > zhi) zp = zhi;
else zp = x[2];
add_contact(0,x,xp,yp,zp);
if (contact[0].r < cutoff) return 1;
return 0;
}
diff --git a/src/region_cone.cpp b/src/region_cone.cpp
index c6b94c295..bfa4e7971 100644
--- a/src/region_cone.cpp
+++ b/src/region_cone.cpp
@@ -1,583 +1,583 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pim Schravendijk
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "region_cone.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
RegCone::RegCone(LAMMPS *lmp, int narg, char **arg) :
Region(lmp, narg, arg)
{
options(narg-9,&arg[9]);
if (strcmp(arg[2],"x") && strcmp(arg[2],"y") && strcmp(arg[2],"z"))
- error->all("Illegal region cylinder command");
+ error->all(FLERR,"Illegal region cylinder command");
axis = arg[2][0];
if (axis == 'x') {
c1 = yscale*atof(arg[3]);
c2 = zscale*atof(arg[4]);
radiuslo = yscale*atof(arg[5]);
radiushi = yscale*atof(arg[6]);
} else if (axis == 'y') {
c1 = xscale*atof(arg[3]);
c2 = zscale*atof(arg[4]);
radiuslo = xscale*atof(arg[5]);
radiushi = xscale*atof(arg[6]);
} else if (axis == 'z') {
c1 = xscale*atof(arg[3]);
c2 = yscale*atof(arg[4]);
radiuslo = xscale*atof(arg[5]);
radiushi = xscale*atof(arg[6]);
}
if (strcmp(arg[7],"INF") == 0 || strcmp(arg[7],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (axis == 'x') {
if (strcmp(arg[7],"INF") == 0) lo = -BIG;
else if (domain->triclinic == 0) lo = domain->boxlo[0];
else lo = domain->boxlo_bound[0];
}
if (axis == 'y') {
if (strcmp(arg[7],"INF") == 0) lo = -BIG;
else if (domain->triclinic == 0) lo = domain->boxlo[1];
else lo = domain->boxlo_bound[1];
}
if (axis == 'z') {
if (strcmp(arg[7],"INF") == 0) lo = -BIG;
else if (domain->triclinic == 0) lo = domain->boxlo[2];
else lo = domain->boxlo_bound[2];
}
} else {
if (axis == 'x') lo = xscale*atof(arg[7]);
if (axis == 'y') lo = yscale*atof(arg[7]);
if (axis == 'z') lo = zscale*atof(arg[7]);
}
if (strcmp(arg[8],"INF") == 0 || strcmp(arg[7],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (axis == 'x') {
if (strcmp(arg[8],"INF") == 0) hi = BIG;
else if (domain->triclinic == 0) hi = domain->boxhi[0];
else hi = domain->boxhi_bound[0];
}
if (axis == 'y') {
if (strcmp(arg[8],"INF") == 0) hi = BIG;
if (domain->triclinic == 0) hi = domain->boxhi[1];
else hi = domain->boxhi_bound[1];
}
if (axis == 'z') {
if (strcmp(arg[8],"INF") == 0) hi = BIG;
else if (domain->triclinic == 0) hi = domain->boxhi[2];
else hi = domain->boxhi_bound[2];
}
} else {
if (axis == 'x') hi = xscale*atof(arg[8]);
if (axis == 'y') hi = yscale*atof(arg[8]);
if (axis == 'z') hi = zscale*atof(arg[8]);
}
// error check
- if (radiuslo < 0.0) error->all("Illegal radius in region cone command");
- if (radiushi < 0.0) error->all("Illegal radius in region cone command");
+ if (radiuslo < 0.0) error->all(FLERR,"Illegal radius in region cone command");
+ if (radiushi < 0.0) error->all(FLERR,"Illegal radius in region cone command");
if (radiuslo == 0.0 && radiushi == 0.0)
- error->all("Illegal radius in region cone command");
- if (hi == lo) error->all("Illegal cone length in region cone command");
+ error->all(FLERR,"Illegal radius in region cone command");
+ if (hi == lo) error->all(FLERR,"Illegal cone length in region cone command");
// extent of cone
if (radiuslo > radiushi) maxradius = radiuslo;
else maxradius = radiushi;
if (interior) {
bboxflag = 1;
if (axis == 'x') {
extent_xlo = lo;
extent_xhi = hi;
extent_ylo = c1 - maxradius;
extent_yhi = c1 + maxradius;
extent_zlo = c2 - maxradius;
extent_zhi = c2 + maxradius;
}
if (axis == 'y') {
extent_xlo = c1 - maxradius;
extent_xhi = c1 + maxradius;
extent_ylo = lo;
extent_yhi = hi;
extent_zlo = c2 - maxradius;
extent_zhi = c2 + maxradius;
}
if (axis == 'z') {
extent_xlo = c1 - maxradius;
extent_xhi = c1 + maxradius;
extent_ylo = c2 - maxradius;
extent_yhi = c2 + maxradius;
extent_zlo = lo;
extent_zhi = hi;
}
} else bboxflag = 0;
// particle could be contact cone surface and 2 ends
cmax = 3;
contact = new Contact[cmax];
}
/* ---------------------------------------------------------------------- */
RegCone::~RegCone()
{
delete [] contact;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is inside or on surface
inside = 0 if x,y,z is outside and not on surface
------------------------------------------------------------------------- */
int RegCone::inside(double x, double y, double z)
{
double del1,del2,dist;
double currentradius;
int inside;
if (axis == 'x') {
del1 = y - c1;
del2 = z - c2;
dist = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (x-lo)*(radiushi-radiuslo)/(hi-lo);
if (dist <= currentradius && x >= lo && x <= hi) inside = 1;
else inside = 0;
}
if (axis == 'y') {
del1 = x - c1;
del2 = z - c2;
dist = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (y-lo)*(radiushi-radiuslo)/(hi-lo);
if (dist <= currentradius && y >= lo && y <= hi) inside = 1;
else inside = 0;
}
if (axis == 'z') {
del1 = x - c1;
del2 = y - c2;
dist = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (z-lo)*(radiushi-radiuslo)/(hi-lo);
if (dist <= currentradius && z >= lo && z <= hi) inside = 1;
else inside = 0;
}
return inside;
}
/* ----------------------------------------------------------------------
contact if 0 <= x < cutoff from one or more inner surfaces of cone
can be one contact for each of 3 cone surfaces
no contact if outside (possible if called from union/intersect)
delxyz = vector from nearest point on cone to x
special case: no contact with curved surf if x is on center axis
------------------------------------------------------------------------- */
int RegCone::surface_interior(double *x, double cutoff)
{
double del1,del2,r,currentradius,delx,dely,delz,dist,delta;
double surflo[3],surfhi[3],xs[3];
int n = 0;
if (axis == 'x') {
del1 = x[1] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (x[0]-lo)*(radiushi-radiuslo)/(hi-lo);
// x is exterior to cone
if (r > currentradius || x[0] < lo || x[0] > hi) return 0;
// x is interior to cone or on its surface
// surflo = pt on outer circle of bottom end plane, same dir as x vs axis
// surfhi = pt on outer circle of top end plane, same dir as x vs axis
if (r > 0.0) {
surflo[0] = lo;
surflo[1] = c1 + del1*radiuslo/r;
surflo[2] = c2 + del2*radiuslo/r;
surfhi[0] = hi;
surfhi[1] = c1 + del1*radiushi/r;
surfhi[2] = c2 + del2*radiushi/r;
point_on_line_segment(surflo,surfhi,x,xs);
delx = x[0] - xs[0];
dely = x[1] - xs[1];
delz = x[2] - xs[2];
dist = sqrt(delx*delx + dely*dely + delz*delz);
if (dist < cutoff) {
contact[n].r = dist;
contact[n].delx = delx;
contact[n].dely = dely;
contact[n].delz = delz;
n++;
}
}
delta = x[0] - lo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delx = delta;
contact[n].dely = contact[n].delz = 0.0;
n++;
}
delta = hi - x[0];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delx = -delta;
contact[n].dely = contact[n].delz = 0.0;
n++;
}
} else if (axis == 'y') {
del1 = x[0] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (x[1]-lo)*(radiushi-radiuslo)/(hi-lo);
// y is exterior to cone
if (r > currentradius || x[1] < lo || x[1] > hi) return 0;
// y is interior to cone or on its surface
// surflo = pt on outer circle of bottom end plane, same dir as y vs axis
// surfhi = pt on outer circle of top end plane, same dir as y vs axis
if (r > 0.0) {
surflo[0] = c1 + del1*radiuslo/r;
surflo[1] = lo;
surflo[2] = c2 + del2*radiuslo/r;
surfhi[0] = c1 + del1*radiushi/r;
surfhi[1] = hi;
surfhi[2] = c2 + del2*radiushi/r;
point_on_line_segment(surflo,surfhi,x,xs);
delx = x[0] - xs[0];
dely = x[1] - xs[1];
delz = x[2] - xs[2];
dist = sqrt(delx*delx + dely*dely + delz*delz);
if (dist < cutoff) {
contact[n].r = dist;
contact[n].delx = delx;
contact[n].dely = dely;
contact[n].delz = delz;
n++;
}
}
delta = x[1] - lo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
delta = hi - x[1];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = -delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
} else {
del1 = x[0] - c1;
del2 = x[1] - c2;
r = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (x[2]-lo)*(radiushi-radiuslo)/(hi-lo);
// x is exterior to cone
if (r > currentradius || x[2] < lo || x[2] > hi) return 0;
// z is interior to cone or on its surface
// surflo = pt on outer circle of bottom end plane, same dir as z vs axis
// surfhi = pt on outer circle of top end plane, same dir as z vs axis
if (r > 0.0) {
surflo[0] = c1 + del1*radiuslo/r;
surflo[1] = c2 + del2*radiuslo/r;
surflo[2] = lo;
surfhi[0] = c1 + del1*radiushi/r;
surfhi[1] = c2 + del2*radiushi/r;
surfhi[2] = hi;
point_on_line_segment(surflo,surfhi,x,xs);
delx = x[0] - xs[0];
dely = x[1] - xs[1];
delz = x[2] - xs[2];
dist = sqrt(delx*delx + dely*dely + delz*delz);
if (dist < cutoff) {
contact[n].r = dist;
contact[n].delx = delx;
contact[n].dely = dely;
contact[n].delz = delz;
n++;
}
}
delta = x[2] - lo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
delta = hi - x[2];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = -delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
}
return n;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from outer surface of cone
no contact if inside (possible if called from union/intersect)
delxyz = vector from nearest point on cone to x
------------------------------------------------------------------------- */
int RegCone::surface_exterior(double *x, double cutoff)
{
double del1,del2,r,currentradius,distsq;
double corner1[3],corner2[3],corner3[3],corner4[3],xp[3],nearest[3];
if (axis == 'x') {
del1 = x[1] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (x[0]-lo)*(radiushi-radiuslo)/(hi-lo);
// x is far enough from cone that there is no contact
// x is interior to cone
if (r >= maxradius+cutoff ||
x[0] <= lo-cutoff || x[0] >= hi+cutoff) return 0;
if (r < currentradius && x[0] > lo && x[0] < hi) return 0;
// x is exterior to cone or on its surface
// corner1234 = 4 corner pts of half trapezoid = cone surf in plane of x
// project x to 3 line segments in half trapezoid (4th is axis of cone)
// nearest = point on surface of cone that x is closest to
// could be edge of cone
// do not add contact point if r >= cutoff
corner1[0] = lo;
corner1[1] = c1 + del1*radiuslo/r;
corner1[2] = c2 + del2*radiuslo/r;
corner2[0] = hi;
corner2[1] = c1 + del1*radiushi/r;
corner2[2] = c2 + del2*radiushi/r;
corner3[0] = lo;
corner3[1] = c1;
corner3[2] = c2;
corner4[0] = hi;
corner4[1] = c1;
corner4[2] = c2;
distsq = BIG;
point_on_line_segment(corner1,corner2,x,xp);
distsq = closest(x,xp,nearest,distsq);
point_on_line_segment(corner1,corner3,x,xp);
distsq = closest(x,xp,nearest,distsq);
point_on_line_segment(corner2,corner4,x,xp);
distsq = closest(x,xp,nearest,distsq);
add_contact(0,x,nearest[0],nearest[1],nearest[2]);
if (contact[0].r < cutoff) return 1;
return 0;
} else if (axis == 'y') {
del1 = x[0] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (x[1]-lo)*(radiushi-radiuslo)/(hi-lo);
// y is far enough from cone that there is no contact
// y is interior to cone
if (r >= maxradius+cutoff ||
x[1] <= lo-cutoff || x[1] >= hi+cutoff) return 0;
if (r < currentradius && x[1] > lo && x[1] < hi) return 0;
// y is exterior to cone or on its surface
// corner1234 = 4 corner pts of half trapezoid = cone surf in plane of y
// project x to 3 line segments in half trapezoid (4th is axis of cone)
// nearest = point on surface of cone that y is closest to
// could be edge of cone
// do not add contact point if r >= cutoff
corner1[0] = c1 + del1*radiuslo/r;
corner1[1] = lo;
corner1[2] = c2 + del2*radiuslo/r;
corner2[0] = c1 + del1*radiushi/r;
corner2[1] = hi;
corner2[2] = c2 + del2*radiushi/r;
corner3[0] = c1;
corner3[1] = lo;
corner3[2] = c2;
corner4[0] = c1;
corner4[1] = hi;
corner4[2] = c2;
distsq = BIG;
point_on_line_segment(corner1,corner2,x,xp);
distsq = closest(x,xp,nearest,distsq);
point_on_line_segment(corner1,corner3,x,xp);
distsq = closest(x,xp,nearest,distsq);
point_on_line_segment(corner2,corner4,x,xp);
distsq = closest(x,xp,nearest,distsq);
add_contact(0,x,nearest[0],nearest[1],nearest[2]);
if (contact[0].r < cutoff) return 1;
return 0;
} else {
del1 = x[0] - c1;
del2 = x[1] - c2;
r = sqrt(del1*del1 + del2*del2);
currentradius = radiuslo + (x[2]-lo)*(radiushi-radiuslo)/(hi-lo);
// z is far enough from cone that there is no contact
// z is interior to cone
if (r >= maxradius+cutoff ||
x[2] <= lo-cutoff || x[2] >= hi+cutoff) return 0;
if (r < currentradius && x[2] > lo && x[2] < hi) return 0;
// z is exterior to cone or on its surface
// corner1234 = 4 corner pts of half trapezoid = cone surf in plane of z
// project x to 3 line segments in half trapezoid (4th is axis of cone)
// nearest = point on surface of cone that z is closest to
// could be edge of cone
// do not add contact point if r >= cutoff
corner1[0] = c1 + del1*radiuslo/r;
corner1[1] = c2 + del2*radiuslo/r;
corner1[2] = lo;
corner2[0] = c1 + del1*radiushi/r;
corner2[1] = c2 + del2*radiushi/r;
corner2[2] = hi;
corner3[0] = c1;
corner3[1] = c2;
corner3[2] = lo;
corner4[0] = c1;
corner4[1] = c2;
corner4[2] = hi;
distsq = BIG;
point_on_line_segment(corner1,corner2,x,xp);
distsq = closest(x,xp,nearest,distsq);
point_on_line_segment(corner1,corner3,x,xp);
distsq = closest(x,xp,nearest,distsq);
point_on_line_segment(corner2,corner4,x,xp);
distsq = closest(x,xp,nearest,distsq);
add_contact(0,x,nearest[0],nearest[1],nearest[2]);
if (contact[0].r < cutoff) return 1;
return 0;
}
}
/* ----------------------------------------------------------------------
find nearest point to C on line segment A,B and return it as D
project (C-A) onto (B-A)
t = length of that projection, normalized by length of (B-A)
t <= 0, C is closest to A
t >= 1, C is closest to B
else closest point is between A and B
------------------------------------------------------------------------- */
void RegCone::point_on_line_segment(double *a, double *b,
double *c, double *d)
{
double ba[3],ca[3];
subtract(a,b,ba);
subtract(a,c,ca);
double t = dotproduct(ca,ba) / dotproduct(ba,ba);
if (t <= 0.0) {
d[0] = a[0];
d[1] = a[1];
d[2] = a[2];
} else if (t >= 1.0) {
d[0] = b[0];
d[1] = b[1];
d[2] = b[2];
} else {
d[0] = a[0] + t*ba[0];
d[1] = a[1] + t*ba[1];
d[2] = a[2] + t*ba[2];
}
}
/* ---------------------------------------------------------------------- */
double RegCone::closest(double *x, double *near, double *nearest, double dsq)
{
double delx = x[0] - near[0];
double dely = x[1] - near[1];
double delz = x[2] - near[2];
double rsq = delx*delx + dely*dely + delz*delz;
if (rsq >= dsq) return dsq;
nearest[0] = near[0];
nearest[1] = near[1];
nearest[2] = near[2];
return rsq;
}
/* ----------------------------------------------------------------------
v3 = v2 - v1
------------------------------------------------------------------------- */
void RegCone::subtract(double *v1, double *v2, double *v3)
{
v3[0] = v2[0] - v1[0];
v3[1] = v2[1] - v1[1];
v3[2] = v2[2] - v1[2];
}
/* ----------------------------------------------------------------------
return dotproduct = v1 dot v2
------------------------------------------------------------------------- */
double RegCone::dotproduct(double *v1, double *v2)
{
return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]);
}
diff --git a/src/region_cylinder.cpp b/src/region_cylinder.cpp
index 58bb51f21..9aafb9ca8 100644
--- a/src/region_cylinder.cpp
+++ b/src/region_cylinder.cpp
@@ -1,405 +1,402 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "region_cylinder.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
RegCylinder::RegCylinder(LAMMPS *lmp, int narg, char **arg) :
Region(lmp, narg, arg)
{
options(narg-8,&arg[8]);
if (strcmp(arg[2],"x") && strcmp(arg[2],"y") && strcmp(arg[2],"z"))
- error->all("Illegal region cylinder command");
+ error->all(FLERR,"Illegal region cylinder command");
axis = arg[2][0];
if (axis == 'x') {
c1 = yscale*atof(arg[3]);
c2 = zscale*atof(arg[4]);
radius = yscale*atof(arg[5]);
} else if (axis == 'y') {
c1 = xscale*atof(arg[3]);
c2 = zscale*atof(arg[4]);
radius = xscale*atof(arg[5]);
} else if (axis == 'z') {
c1 = xscale*atof(arg[3]);
c2 = yscale*atof(arg[4]);
radius = xscale*atof(arg[5]);
}
if (strcmp(arg[6],"INF") == 0 || strcmp(arg[6],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (axis == 'x') {
if (strcmp(arg[6],"INF") == 0) lo = -BIG;
else if (domain->triclinic == 0) lo = domain->boxlo[0];
else lo = domain->boxlo_bound[0];
}
if (axis == 'y') {
if (strcmp(arg[6],"INF") == 0) lo = -BIG;
else if (domain->triclinic == 0) lo = domain->boxlo[1];
else lo = domain->boxlo_bound[1];
}
if (axis == 'z') {
if (strcmp(arg[6],"INF") == 0) lo = -BIG;
else if (domain->triclinic == 0) lo = domain->boxlo[2];
else lo = domain->boxlo_bound[2];
}
} else {
if (axis == 'x') lo = xscale*atof(arg[6]);
if (axis == 'y') lo = yscale*atof(arg[6]);
if (axis == 'z') lo = zscale*atof(arg[6]);
}
if (strcmp(arg[7],"INF") == 0 || strcmp(arg[6],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (axis == 'x') {
if (strcmp(arg[7],"INF") == 0) hi = BIG;
else if (domain->triclinic == 0) hi = domain->boxhi[0];
else hi = domain->boxhi_bound[0];
}
if (axis == 'y') {
if (strcmp(arg[7],"INF") == 0) hi = BIG;
else if (domain->triclinic == 0) hi = domain->boxhi[1];
else hi = domain->boxhi_bound[1];
}
if (axis == 'z') {
if (strcmp(arg[7],"INF") == 0) hi = BIG;
else if (domain->triclinic == 0) hi = domain->boxhi[2];
else hi = domain->boxhi_bound[2];
}
} else {
if (axis == 'x') hi = xscale*atof(arg[7]);
if (axis == 'y') hi = yscale*atof(arg[7]);
if (axis == 'z') hi = zscale*atof(arg[7]);
}
// error check
- if (radius <= 0.0) error->all("Illegal region cylinder command");
+ if (radius <= 0.0) error->all(FLERR,"Illegal region cylinder command");
// extent of cylinder
if (interior) {
bboxflag = 1;
if (axis == 'x') {
extent_xlo = lo;
extent_xhi = hi;
extent_ylo = c1 - radius;
extent_yhi = c1 + radius;
extent_zlo = c2 - radius;
extent_zhi = c2 + radius;
}
if (axis == 'y') {
extent_xlo = c1 - radius;
extent_xhi = c1 + radius;
extent_ylo = lo;
extent_yhi = hi;
extent_zlo = c2 - radius;
extent_zhi = c2 + radius;
}
if (axis == 'z') {
extent_xlo = c1 - radius;
extent_xhi = c1 + radius;
extent_ylo = c2 - radius;
extent_yhi = c2 + radius;
extent_zlo = lo;
extent_zhi = hi;
}
} else bboxflag = 0;
// particle could be contact cylinder surface and 2 ends
cmax = 3;
contact = new Contact[cmax];
}
/* ---------------------------------------------------------------------- */
RegCylinder::~RegCylinder()
{
delete [] contact;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is inside or on surface
inside = 0 if x,y,z is outside and not on surface
------------------------------------------------------------------------- */
int RegCylinder::inside(double x, double y, double z)
{
double del1,del2,dist;
int inside;
if (axis == 'x') {
del1 = y - c1;
del2 = z - c2;
dist = sqrt(del1*del1 + del2*del2);
if (dist <= radius && x >= lo && x <= hi) inside = 1;
else inside = 0;
} else if (axis == 'y') {
del1 = x - c1;
del2 = z - c2;
dist = sqrt(del1*del1 + del2*del2);
if (dist <= radius && y >= lo && y <= hi) inside = 1;
else inside = 0;
} else {
del1 = x - c1;
del2 = y - c2;
dist = sqrt(del1*del1 + del2*del2);
if (dist <= radius && z >= lo && z <= hi) inside = 1;
else inside = 0;
}
return inside;
}
/* ----------------------------------------------------------------------
contact if 0 <= x < cutoff from one or more inner surfaces of cylinder
can be one contact for each of 3 cylinder surfaces
no contact if outside (possible if called from union/intersect)
delxyz = vector from nearest point on cylinder to x
special case: no contact with curved surf if x is on center axis
------------------------------------------------------------------------- */
int RegCylinder::surface_interior(double *x, double cutoff)
{
double del1,del2,r,delta;
int n = 0;
if (axis == 'x') {
del1 = x[1] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
// x is exterior to cylinder
if (r > radius || x[0] < lo || x[0] > hi) return 0;
// x is interior to cylinder or on its surface
delta = radius - r;
if (delta < cutoff && r > 0.0) {
contact[n].r = delta;
contact[n].delx = 0.0;
contact[n].dely = del1*(1.0-radius/r);
contact[n].delz = del2*(1.0-radius/r);
n++;
}
delta = x[0] - lo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delx = delta;
contact[n].dely = contact[n].delz = 0.0;
n++;
}
delta = hi - x[0];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delx = -delta;
contact[n].dely = contact[n].delz = 0.0;
n++;
}
} else if (axis == 'y') {
del1 = x[0] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
// y is exterior to cylinder
if (r > radius || x[1] < lo || x[1] > hi) return 0;
// y is interior to cylinder or on its surface
delta = radius - r;
if (delta < cutoff && r > 0.0) {
contact[n].r = delta;
contact[n].delx = del1*(1.0-radius/r);
contact[n].dely = 0.0;
contact[n].delz = del2*(1.0-radius/r);
n++;
}
delta = x[1] - lo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].dely = delta;
contact[n].delx = contact[n].delz = 0.0;
n++;
}
delta = hi - x[1];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].dely = -delta;
contact[n].delx = contact[n].delz = 0.0;
n++;
}
} else {
del1 = x[0] - c1;
del2 = x[1] - c2;
r = sqrt(del1*del1 + del2*del2);
// z is exterior to cylinder
if (r > radius || x[2] < lo || x[2] > hi) return 0;
// z is interior to cylinder or on its surface
delta = radius - r;
if (delta < cutoff && r > 0.0) {
contact[n].r = delta;
contact[n].delx = del1*(1.0-radius/r);
contact[n].dely = del2*(1.0-radius/r);
contact[n].delz = 0.0;
n++;
}
delta = x[2] - lo;
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
delta = hi - x[2];
if (delta < cutoff) {
contact[n].r = delta;
contact[n].delz = -delta;
contact[n].delx = contact[n].dely = 0.0;
n++;
}
}
return n;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from outer surface of cylinder
no contact if inside (possible if called from union/intersect)
delxyz = vector from nearest point on cylinder to x
------------------------------------------------------------------------- */
int RegCylinder::surface_exterior(double *x, double cutoff)
{
double del1,del2,r;
double xp,yp,zp;
if (axis == 'x') {
del1 = x[1] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
// x is far enough from cylinder that there is no contact
// x is interior to cylinder
if (r >= radius+cutoff || x[0] <= lo-cutoff || x[0] >= hi+cutoff) return 0;
if (r < radius && x[0] > lo && x[0] < hi) return 0;
// x is exterior to cylinder or on its surface
// xp,yp,zp = point on surface of cylinder that x is closest to
// could be edge of cylinder
// do not add contact point if r >= cutoff
if (r > radius) {
yp = c1 + del1*radius/r;
zp = c2 + del2*radius/r;
} else {
yp = x[1];
zp = x[2];
}
if (x[0] < lo) xp = lo;
else if (x[0] > hi) xp = hi;
else xp = x[0];
add_contact(0,x,xp,yp,zp);
if (contact[0].r < cutoff) return 1;
return 0;
} else if (axis == 'y') {
del1 = x[0] - c1;
del2 = x[2] - c2;
r = sqrt(del1*del1 + del2*del2);
// y is far enough from cylinder that there is no contact
// y is interior to cylinder
if (r >= radius+cutoff || x[1] <= lo-cutoff || x[1] >= hi+cutoff) return 0;
if (r < radius && x[1] > lo && x[1] < hi) return 0;
// y is exterior to cylinder or on its surface
// xp,yp,zp = point on surface of cylinder that x is closest to
// could be edge of cylinder
// do not add contact point if r >= cutoff
if (r > radius) {
xp = c1 + del1*radius/r;
zp = c2 + del2*radius/r;
} else {
xp = x[0];
zp = x[2];
}
if (x[1] < lo) yp = lo;
else if (x[1] > hi) yp = hi;
else yp = x[1];
add_contact(0,x,xp,yp,zp);
if (contact[0].r < cutoff) return 1;
return 0;
} else {
del1 = x[0] - c1;
del2 = x[1] - c2;
r = sqrt(del1*del1 + del2*del2);
// z is far enough from cylinder that there is no contact
// z is interior to cylinder
if (r >= radius+cutoff || x[2] <= lo-cutoff || x[2] >= hi+cutoff) return 0;
if (r < radius && x[2] > lo && x[2] < hi) return 0;
// z is exterior to cylinder or on its surface
// xp,yp,zp = point on surface of cylinder that x is closest to
// could be edge of cylinder
// do not add contact point if r >= cutoff
if (r > radius) {
xp = c1 + del1*radius/r;
yp = c2 + del2*radius/r;
} else {
xp = x[0];
yp = x[1];
}
if (x[2] < lo) zp = lo;
else if (x[2] > hi) zp = hi;
else zp = x[2];
add_contact(0,x,xp,yp,zp);
if (contact[0].r < cutoff) return 1;
return 0;
}
}
diff --git a/src/region_intersect.cpp b/src/region_intersect.cpp
index abb959dea..5618b46b2 100644
--- a/src/region_intersect.cpp
+++ b/src/region_intersect.cpp
@@ -1,210 +1,207 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "region_intersect.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
RegIntersect::RegIntersect(LAMMPS *lmp, int narg, char **arg) :
Region(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal region command");
+ if (narg < 5) error->all(FLERR,"Illegal region command");
int n = atoi(arg[2]);
- if (n < 2) error->all("Illegal region command");
+ if (n < 2) error->all(FLERR,"Illegal region command");
options(narg-(n+3),&arg[n+3]);
// build list of regions to intersect
list = new int[n];
nregion = 0;
int iregion;
for (int iarg = 0; iarg < n; iarg++) {
iregion = domain->find_region(arg[iarg+3]);
- if (iregion == -1) error->all("Region intersect region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Region intersect region ID does not exist");
list[nregion++] = iregion;
}
// extent of intersection of regions
// has bounding box if interior and any sub-region has bounding box
Region **regions = domain->regions;
bboxflag = 0;
for (int ilist = 0; ilist < nregion; ilist++)
if (regions[list[ilist]]->bboxflag == 1) bboxflag = 1;
if (!interior) bboxflag = 0;
if (bboxflag) {
int first = 1;
for (int ilist = 0; ilist < nregion; ilist++) {
if (regions[list[ilist]]->bboxflag == 0) continue;
if (first) {
extent_xlo = regions[list[ilist]]->extent_xlo;
extent_ylo = regions[list[ilist]]->extent_ylo;
extent_zlo = regions[list[ilist]]->extent_zlo;
extent_xhi = regions[list[ilist]]->extent_xhi;
extent_yhi = regions[list[ilist]]->extent_yhi;
extent_zhi = regions[list[ilist]]->extent_zhi;
first = 0;
}
extent_xlo = MAX(extent_xlo,regions[list[ilist]]->extent_xlo);
extent_ylo = MAX(extent_ylo,regions[list[ilist]]->extent_ylo);
extent_zlo = MAX(extent_zlo,regions[list[ilist]]->extent_zlo);
extent_xhi = MIN(extent_xhi,regions[list[ilist]]->extent_xhi);
extent_yhi = MIN(extent_yhi,regions[list[ilist]]->extent_yhi);
extent_zhi = MIN(extent_zhi,regions[list[ilist]]->extent_zhi);
}
}
// possible contacts = sum of possible contacts in all sub-regions
cmax = 0;
for (int ilist = 0; ilist < nregion; ilist++)
cmax += regions[list[ilist]]->cmax;
contact = new Contact[cmax];
}
/* ---------------------------------------------------------------------- */
RegIntersect::~RegIntersect()
{
delete [] list;
delete [] contact;
}
/* ----------------------------------------------------------------------
return 1 if region is dynamic, 0 if static
dynamic if any sub-region is dynamic, else static
------------------------------------------------------------------------- */
int RegIntersect::dynamic_check()
{
Region **regions = domain->regions;
for (int ilist = 0; ilist < nregion; ilist++)
if (regions[list[ilist]]->dynamic_check()) return 1;
return 0;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is match() with all sub-regions
else inside = 0
------------------------------------------------------------------------- */
int RegIntersect::inside(double x, double y, double z)
{
int ilist;
Region **regions = domain->regions;
for (ilist = 0; ilist < nregion; ilist++)
if (!regions[list[ilist]]->match(x,y,z)) break;
if (ilist == nregion) return 1;
return 0;
}
/* ----------------------------------------------------------------------
compute contacts with interior of intersection of sub-regions
(1) compute contacts in each sub-region
(2) only keep a contact if surface point is match() to all other regions
------------------------------------------------------------------------- */
int RegIntersect::surface_interior(double *x, double cutoff)
{
int m,ilist,jlist,iregion,jregion,ncontacts;
double xs,ys,zs;
Region **regions = domain->regions;
int n = 0;
for (ilist = 0; ilist < nregion; ilist++) {
iregion = list[ilist];
ncontacts = regions[iregion]->surface(x[0],x[1],x[2],cutoff);
for (m = 0; m < ncontacts; m++) {
xs = x[0] - regions[iregion]->contact[m].delx;
ys = x[1] - regions[iregion]->contact[m].dely;
zs = x[2] - regions[iregion]->contact[m].delz;
for (jlist = 0; jlist < nregion; jlist++) {
if (jlist == ilist) continue;
jregion = list[jlist];
if (!regions[jregion]->match(xs,ys,zs)) break;
}
if (jlist == nregion) {
contact[n].r = regions[iregion]->contact[m].r;
contact[n].delx = regions[iregion]->contact[m].delx;
contact[n].dely = regions[iregion]->contact[m].dely;
contact[n].delz = regions[iregion]->contact[m].delz;
n++;
}
}
}
return n;
}
/* ----------------------------------------------------------------------
compute contacts with interior of intersection of sub-regions
(1) flip interior/exterior flag of each sub-region
(2) compute contacts in each sub-region
(3) only keep a contact if surface point is not match() to all other regions
(4) flip interior/exterior flags back to original settings
this is effectively same algorithm as surface_interior() for RegUnion
------------------------------------------------------------------------- */
int RegIntersect::surface_exterior(double *x, double cutoff)
{
int m,ilist,jlist,iregion,jregion,ncontacts;
double xs,ys,zs;
Region **regions = domain->regions;
int n = 0;
for (ilist = 0; ilist < nregion; ilist++)
regions[list[ilist]]->interior ^= 1;
for (ilist = 0; ilist < nregion; ilist++) {
iregion = list[ilist];
ncontacts = regions[iregion]->surface(x[0],x[1],x[2],cutoff);
for (m = 0; m < ncontacts; m++) {
xs = x[0] - regions[iregion]->contact[m].delx;
ys = x[1] - regions[iregion]->contact[m].dely;
zs = x[2] - regions[iregion]->contact[m].delz;
for (jlist = 0; jlist < nregion; jlist++) {
if (jlist == ilist) continue;
jregion = list[jlist];
if (regions[jregion]->match(xs,ys,zs)) break;
}
if (jlist == nregion) {
contact[n].r = regions[iregion]->contact[m].r;
contact[n].delx = regions[iregion]->contact[m].delx;
contact[n].dely = regions[iregion]->contact[m].dely;
contact[n].delz = regions[iregion]->contact[m].delz;
n++;
}
}
}
for (ilist = 0; ilist < nregion; ilist++)
regions[list[ilist]]->interior ^= 1;
return n;
}
diff --git a/src/region_plane.cpp b/src/region_plane.cpp
index 45b6f103a..aa2827422 100644
--- a/src/region_plane.cpp
+++ b/src/region_plane.cpp
@@ -1,110 +1,110 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "region_plane.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
RegPlane::RegPlane(LAMMPS *lmp, int narg, char **arg) :
Region(lmp, narg, arg)
{
options(narg-8,&arg[8]);
xp = xscale*atof(arg[2]);
yp = yscale*atof(arg[3]);
zp = zscale*atof(arg[4]);
normal[0] = xscale*atof(arg[5]);
normal[1] = yscale*atof(arg[6]);
normal[2] = zscale*atof(arg[7]);
// enforce unit normal
double rsq = normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2];
- if (rsq == 0.0) error->all("Illegal region plane command");
+ if (rsq == 0.0) error->all(FLERR,"Illegal region plane command");
normal[0] /= sqrt(rsq);
normal[1] /= sqrt(rsq);
normal[2] /= sqrt(rsq);
// plane has no bounding box
bboxflag = 0;
cmax = 1;
contact = new Contact[cmax];
}
/* ---------------------------------------------------------------------- */
RegPlane::~RegPlane()
{
delete [] contact;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is on normal side of plane or on plane
inside = 0 if x,y,z is on non-normal side of plane and not on plane
x,y,z is inside if (x-xp) dot normal >= 0
------------------------------------------------------------------------- */
int RegPlane::inside(double x, double y, double z)
{
double dot = (x-xp)*normal[0] + (y-yp)*normal[1] + (z-zp)*normal[2];
if (dot >= 0.0) return 1;
return 0;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from normal side of plane
no contact if on other side (possible if called from union/intersect)
delxyz = vector from nearest projected point on plane to x
------------------------------------------------------------------------- */
int RegPlane::surface_interior(double *x, double cutoff)
{
double dot = (x[0]-xp)*normal[0] + (x[1]-yp)*normal[1] + (x[2]-zp)*normal[2];
if (dot < cutoff && dot >= 0.0) {
contact[0].r = dot;
contact[0].delx = dot*normal[0];
contact[0].dely = dot*normal[1];
contact[0].delz = dot*normal[2];
return 1;
}
return 0;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from non-normal side of plane
no contact if on other side (possible if called from union/intersect)
delxyz = vector from nearest projected point on plane to x
------------------------------------------------------------------------- */
int RegPlane::surface_exterior(double *x, double cutoff)
{
double dot = (x[0]-xp)*normal[0] + (x[1]-yp)*normal[1] + (x[2]-zp)*normal[2];
dot = -dot;
if (dot < cutoff && dot >= 0.0) {
contact[0].r = dot;
contact[0].delx = dot*normal[0];
contact[0].dely = dot*normal[1];
contact[0].delz = dot*normal[2];
return 1;
}
return 0;
}
diff --git a/src/region_prism.cpp b/src/region_prism.cpp
index 26d65ab4f..72f40987c 100644
--- a/src/region_prism.cpp
+++ b/src/region_prism.cpp
@@ -1,513 +1,510 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Pieter in 't Veld (SNL)
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "region_prism.h"
#include "domain.h"
#include "force.h"
#include "error.h"
using namespace LAMMPS_NS;
#define BIG 1.0e20
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
RegPrism::RegPrism(LAMMPS *lmp, int narg, char **arg) : Region(lmp, narg, arg)
{
options(narg-11,&arg[11]);
if (strcmp(arg[2],"INF") == 0 || strcmp(arg[2],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[2],"INF") == 0) xlo = -BIG;
else xlo = domain->boxlo[0];
} else xlo = xscale*atof(arg[2]);
if (strcmp(arg[3],"INF") == 0 || strcmp(arg[3],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[3],"INF") == 0) xhi = BIG;
else xhi = domain->boxhi[0];
} else xhi = xscale*atof(arg[3]);
if (strcmp(arg[4],"INF") == 0 || strcmp(arg[4],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[4],"INF") == 0) ylo = -BIG;
else ylo = domain->boxlo[1];
} else ylo = yscale*atof(arg[4]);
if (strcmp(arg[5],"INF") == 0 || strcmp(arg[5],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[5],"INF") == 0) yhi = BIG;
else yhi = domain->boxhi[1];
} else yhi = yscale*atof(arg[5]);
if (strcmp(arg[6],"INF") == 0 || strcmp(arg[6],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[6],"INF") == 0) zlo = -BIG;
else zlo = domain->boxlo[2];
} else zlo = zscale*atof(arg[6]);
if (strcmp(arg[7],"INF") == 0 || strcmp(arg[7],"EDGE") == 0) {
if (domain->box_exist == 0)
- error->all("Cannot use region INF or EDGE when box does not exist");
+ error->all(FLERR,"Cannot use region INF or EDGE when box does not exist");
if (strcmp(arg[7],"INF") == 0) zhi = BIG;
else zhi = domain->boxhi[2];
} else zhi = zscale*atof(arg[7]);
xy = xscale*atof(arg[8]);
xz = xscale*atof(arg[9]);
yz = yscale*atof(arg[10]);
// error check
// prism cannot be 0 thickness in any dim, else inverse blows up
// non-zero tilt values cannot be used if either dim is INF on both ends
if (xlo >= xhi || ylo >= yhi || zlo >= zhi)
- error->all("Illegal region prism command");
+ error->all(FLERR,"Illegal region prism command");
if (xy != 0.0 && xlo == -BIG && xhi == BIG)
- error->all("Illegal region prism command");
+ error->all(FLERR,"Illegal region prism command");
if (xy != 0.0 && ylo == -BIG && yhi == BIG)
- error->all("Illegal region prism command");
+ error->all(FLERR,"Illegal region prism command");
if (xz != 0.0 && xlo == -BIG && xhi == BIG)
- error->all("Illegal region prism command");
+ error->all(FLERR,"Illegal region prism command");
if (xz != 0.0 && zlo == -BIG && zhi == BIG)
- error->all("Illegal region prism command");
+ error->all(FLERR,"Illegal region prism command");
if (yz != 0.0 && ylo == -BIG && yhi == BIG)
- error->all("Illegal region prism command");
+ error->all(FLERR,"Illegal region prism command");
if (yz != 0.0 && zlo == -BIG && zhi == BIG)
- error->all("Illegal region prism command");
+ error->all(FLERR,"Illegal region prism command");
// extent of prism
if (interior) {
bboxflag = 1;
extent_xlo = MIN(xlo,xlo+xy);
extent_xlo = MIN(extent_xlo,extent_xlo+xz);
extent_ylo = MIN(ylo,ylo+yz);
extent_zlo = zlo;
extent_xhi = MAX(xhi,xhi+xy);
extent_xhi = MAX(extent_xhi,extent_xhi+xz);
extent_yhi = MAX(yhi,yhi+yz);
extent_zhi = zhi;
} else bboxflag = 0;
// particle could contact all 6 planes
cmax = 6;
contact = new Contact[cmax];
// h = transformation matrix from tilt coords (0-1) to box coords (xyz)
// columns of h are edge vectors of tilted box
// hinv = transformation matrix from box coords to tilt coords
// both h and hinv are upper triangular
// since 1st edge of prism is along x-axis
// and bottom face of prism is in xy plane
h[0][0] = xhi - xlo;
h[0][1] = xy;
h[0][2] = xz;
h[1][1] = yhi - ylo;
h[1][2] = yz;
h[2][2] = zhi - zlo;
hinv[0][0] = 1.0/h[0][0];
hinv[0][1] = -h[0][1] / (h[0][0]*h[1][1]);
hinv[0][2] = (h[0][1]*h[1][2] - h[0][2]*h[1][1]) / (h[0][0]*h[1][1]*h[2][2]);
hinv[1][1] = 1.0/h[1][1];
hinv[1][2] = -h[1][2] / (h[1][1]*h[2][2]);
hinv[2][2] = 1.0/h[2][2];
// corners = 8 corner points of prism
// order = x varies fastest, then y, finally z
// clo/chi = lo and hi corner pts of prism
a[0] = xhi-xlo;
a[1] = 0.0;
a[2] = 0.0;
b[0] = xy;
b[1] = yhi-ylo;
b[2] = 0.0;
c[0] = xz;
c[1] = yz;
c[2] = zhi-zlo;
clo[0] = corners[0][0] = xlo;
clo[1] = corners[0][1] = ylo;
clo[2] = corners[0][2] = zlo;
corners[1][0] = xlo + a[0];
corners[1][1] = ylo + a[1];
corners[1][2] = zlo + a[2];
corners[2][0] = xlo + b[0];
corners[2][1] = ylo + b[1];
corners[2][2] = zlo + b[2];
corners[3][0] = xlo + a[0] + b[0];
corners[3][1] = ylo + a[1] + b[1];
corners[3][2] = zlo + a[2] + b[2];
corners[4][0] = xlo + c[0];
corners[4][1] = ylo + c[1];
corners[4][2] = zlo + c[2];
corners[5][0] = xlo + a[0] + c[0];
corners[5][1] = ylo + a[1] + c[1];
corners[5][2] = zlo + a[2] + c[2];
corners[6][0] = xlo + b[0] + c[0];
corners[6][1] = ylo + b[1] + c[1];
corners[6][2] = zlo + b[2] + c[2];
chi[0] = corners[7][0] = xlo + a[0] + b[0] + c[0];
chi[1] = corners[7][1] = ylo + a[1] + b[1] + c[1];
chi[2] = corners[7][2] = zlo + a[2] + b[2] + c[2];
// face = 6 inward-facing unit normals to prism faces
// order = xy plane, xz plane, yz plane
cross(a,b,face[0]);
cross(b,a,face[1]);
cross(c,a,face[2]);
cross(a,c,face[3]);
cross(b,c,face[4]);
cross(c,b,face[5]);
for (int i = 0; i < 6; i++) normalize(face[i]);
// tri = 3 vertices (0-7) in each of 12 triangles on 6 faces
// verts in each tri are ordered so that right-hand rule gives inward norm
// order = xy plane, xz plane, yz plane
tri[0][0] = 0; tri[0][1] = 1; tri[0][2] = 3;
tri[1][0] = 0; tri[1][1] = 3; tri[1][2] = 2;
tri[2][0] = 4; tri[2][1] = 7; tri[2][2] = 5;
tri[3][0] = 4; tri[3][1] = 6; tri[3][2] = 7;
tri[4][0] = 0; tri[4][1] = 4; tri[4][2] = 5;
tri[5][0] = 0; tri[5][1] = 5; tri[5][2] = 1;
tri[6][0] = 2; tri[6][1] = 7; tri[6][2] = 6;
tri[7][0] = 2; tri[7][1] = 3; tri[7][2] = 7;
tri[8][0] = 2; tri[8][1] = 6; tri[8][2] = 4;
tri[9][0] = 2; tri[9][1] = 4; tri[9][2] = 0;
tri[10][0] = 1; tri[10][1] = 5; tri[10][2] = 7;
tri[11][0] = 1; tri[11][1] = 7; tri[11][2] = 3;
}
/* ---------------------------------------------------------------------- */
RegPrism::~RegPrism()
{
delete [] contact;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is inside or on surface
inside = 0 if x,y,z is outside and not on surface
abc = Hinv * (xyz - xyz/lo)
abc = tilt coords (0-1)
Hinv = transformation matrix from box coords to tilt coords
xyz = box coords
xyz/lo = lower-left corner of prism
------------------------------------------------------------------------- */
int RegPrism::inside(double x, double y, double z)
{
double a = hinv[0][0]*(x-xlo) + hinv[0][1]*(y-ylo) + hinv[0][2]*(z-zlo);
double b = hinv[1][1]*(y-ylo) + hinv[1][2]*(z-zlo);
double c = hinv[2][2]*(z-zlo);
if (a >= 0.0 && a <= 1.0 && b >= 0.0 && b <= 1.0 && c >= 0.0 && c <= 1.0)
return 1;
return 0;
}
/* ----------------------------------------------------------------------
contact if 0 <= x < cutoff from one or more inner surfaces of prism
can be one contact for each of 6 faces
no contact if outside (possible if called from union/intersect)
delxyz = vector from nearest point on prism to x
------------------------------------------------------------------------- */
int RegPrism::surface_interior(double *x, double cutoff)
{
int i;
double dot;
double *corner;
// x is exterior to prism
for (i = 0; i < 6; i++) {
if (i % 2) corner = chi;
else corner = clo;
dot = (x[0]-corner[0])*face[i][0] + (x[1]-corner[1])*face[i][1] +
(x[2]-corner[2])*face[i][2];
if (dot < 0.0) return 0;
}
// x is interior to prism or on its surface
int n = 0;
for (int i = 0; i < 6; i++) {
if (i % 2) corner = chi;
else corner = clo;
dot = (x[0]-corner[0])*face[i][0] + (x[1]-corner[1])*face[i][1] +
(x[2]-corner[2])*face[i][2];
if (dot < cutoff) {
contact[n].r = dot;
contact[n].delx = dot*face[i][0];
contact[n].dely = dot*face[i][1];
contact[n].delz = dot*face[i][2];
n++;
}
}
return n;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from outer surface of prism
no contact if inside (possible if called from union/intersect)
delxyz = vector from nearest point on prism to x
------------------------------------------------------------------------- */
int RegPrism::surface_exterior(double *x, double cutoff)
{
int i;
double dot;
double *corner;
double xp,yp,zp;
// x is far enough from prism that there is no contact
for (i = 0; i < 6; i++) {
if (i % 2) corner = chi;
else corner = clo;
dot = (x[0]-corner[0])*face[i][0] + (x[1]-corner[1])*face[i][1] +
(x[2]-corner[2])*face[i][2];
if (dot <= -cutoff) return 0;
}
// x is interior to prism
for (i = 0; i < 6; i++) {
if (i % 2) corner = chi;
else corner = clo;
dot = (x[0]-corner[0])*face[i][0] + (x[1]-corner[1])*face[i][1] +
(x[2]-corner[2])*face[i][2];
if (dot <= 0.0) break;
}
if (i == 6) return 0;
// x is exterior to prism or on its surface
// xp,yp,zp = point on surface of prism that x is closest to
// could be edge or corner pt of prism
// do not add contact point if r >= cutoff
find_nearest(x,xp,yp,zp);
add_contact(0,x,xp,yp,zp);
if (contact[0].r < cutoff) return 1;
return 0;
}
/* ----------------------------------------------------------------------
x is exterior to prism or on its surface
return (xp,yp,zp) = nearest pt to x that is on surface of prism
------------------------------------------------------------------------- */
void RegPrism::find_nearest(double *x, double &xp, double &yp, double &zp)
{
int i,j,k,iface;
double xproj[3],xline[3],nearest[3];
double dot;
// generate successive xnear points, one nearest to x is (xp,yp,zp)
// loop over 6 faces and 2 triangles in each face
// xproj = x projected to plane of triangle
// if xproj is inside or on triangle boundary, that is xnear
// else: loop over 3 edges of triangle
// compute distance to edge line
// xnear = nearest point on line to xproj, bounded by segment end pts
double distsq = BIG;
for (int itri = 0; itri < 12; itri++) {
iface = itri/2;
i = tri[itri][0];
j = tri[itri][1];
k = tri[itri][2];
dot = (x[0]-corners[i][0])*face[iface][0] +
(x[1]-corners[i][1])*face[iface][1] +
(x[2]-corners[i][2])*face[iface][2];
xproj[0] = x[0] - dot*face[iface][0];
xproj[1] = x[1] - dot*face[iface][1];
xproj[2] = x[2] - dot*face[iface][2];
if (inside_tri(xproj,corners[i],corners[j],corners[k],face[iface]))
distsq = closest(x,xproj,nearest,distsq);
else {
point_on_line_segment(corners[i],corners[j],xproj,xline);
distsq = closest(x,xline,nearest,distsq);
point_on_line_segment(corners[j],corners[k],xproj,xline);
distsq = closest(x,xline,nearest,distsq);
point_on_line_segment(corners[i],corners[k],xproj,xline);
distsq = closest(x,xline,nearest,distsq);
}
}
xp = nearest[0];
yp = nearest[1];
zp = nearest[2];
}
/* ----------------------------------------------------------------------
test if x is inside triangle with vertices v1,v2,v3
norm = normal to triangle, defined by right-hand rule for v1,v2,v3 ordering
edge = edge vector of triangle
pvec = vector from vertex to x
xproduct = cross product of edge with pvec
if xproduct dot norm < 0.0 for any of 3 edges, then x is outside triangle
------------------------------------------------------------------------- */
int RegPrism::inside_tri(double *x, double *v1, double *v2, double *v3,
double *norm)
{
double edge[3],pvec[3],xproduct[3];
subtract(v1,v2,edge);
subtract(v1,x,pvec);
cross(edge,pvec,xproduct);
if (dotproduct(xproduct,norm) < 0.0) return 0;
subtract(v2,v3,edge);
subtract(v2,x,pvec);
cross(edge,pvec,xproduct);
if (dotproduct(xproduct,norm) < 0.0) return 0;
subtract(v3,v1,edge);
subtract(v3,x,pvec);
cross(edge,pvec,xproduct);
if (dotproduct(xproduct,norm) < 0.0) return 0;
return 1;
}
/* ----------------------------------------------------------------------
find nearest point to C on line segment A,B and return it as D
project (C-A) onto (B-A)
t = length of that projection, normalized by length of (B-A)
t <= 0, C is closest to A
t >= 1, C is closest to B
else closest point is between A and B
------------------------------------------------------------------------- */
void RegPrism::point_on_line_segment(double *a, double *b,
double *c, double *d)
{
double ba[3],ca[3];
subtract(a,b,ba);
subtract(a,c,ca);
double t = dotproduct(ca,ba) / dotproduct(ba,ba);
if (t <= 0.0) {
d[0] = a[0];
d[1] = a[1];
d[2] = a[2];
} else if (t >= 1.0) {
d[0] = b[0];
d[1] = b[1];
d[2] = b[2];
} else {
d[0] = a[0] + t*ba[0];
d[1] = a[1] + t*ba[1];
d[2] = a[2] + t*ba[2];
}
}
/* ---------------------------------------------------------------------- */
double RegPrism::closest(double *x, double *near, double *nearest, double dsq)
{
double delx = x[0] - near[0];
double dely = x[1] - near[1];
double delz = x[2] - near[2];
double rsq = delx*delx + dely*dely + delz*delz;
if (rsq >= dsq) return dsq;
nearest[0] = near[0];
nearest[1] = near[1];
nearest[2] = near[2];
return rsq;
}
/* ----------------------------------------------------------------------
v3 = v2 - v1
------------------------------------------------------------------------- */
void RegPrism::subtract(double *v1, double *v2, double *v3)
{
v3[0] = v2[0] - v1[0];
v3[1] = v2[1] - v1[1];
v3[2] = v2[2] - v1[2];
}
/* ----------------------------------------------------------------------
v3 = v1 x v2
------------------------------------------------------------------------- */
void RegPrism::cross(double *v1, double *v2, double *v3)
{
v3[0] = v1[1]*v2[2] - v1[2]*v2[1];
v3[1] = v1[2]*v2[0] - v1[0]*v2[2];
v3[2] = v1[0]*v2[1] - v1[1]*v2[0];
}
/* ----------------------------------------------------------------------
return dotproduct = v1 dot v2
------------------------------------------------------------------------- */
double RegPrism::dotproduct(double *v1, double *v2)
{
return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]);
}
/* ---------------------------------------------------------------------- */
void RegPrism::normalize(double *x)
{
double invlen = 1.0/sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
x[0] *= invlen;
x[1] *= invlen;
x[2] *= invlen;
}
diff --git a/src/region_sphere.cpp b/src/region_sphere.cpp
index b03ad6bc2..80446b55a 100644
--- a/src/region_sphere.cpp
+++ b/src/region_sphere.cpp
@@ -1,126 +1,126 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "region_sphere.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
RegSphere::RegSphere(LAMMPS *lmp, int narg, char **arg) :
Region(lmp, narg, arg)
{
options(narg-6,&arg[6]);
xc = xscale*atof(arg[2]);
yc = yscale*atof(arg[3]);
zc = zscale*atof(arg[4]);
radius = xscale*atof(arg[5]);
// error check
- if (radius < 0.0) error->all("Illegal region sphere command");
+ if (radius < 0.0) error->all(FLERR,"Illegal region sphere command");
// extent of sphere
if (interior) {
bboxflag = 1;
extent_xlo = xc - radius;
extent_xhi = xc + radius;
extent_ylo = yc - radius;
extent_yhi = yc + radius;
extent_zlo = zc - radius;
extent_zhi = zc + radius;
} else bboxflag = 0;
cmax = 1;
contact = new Contact[cmax];
}
/* ---------------------------------------------------------------------- */
RegSphere::~RegSphere()
{
delete [] contact;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is inside or on surface
inside = 0 if x,y,z is outside and not on surface
------------------------------------------------------------------------- */
int RegSphere::inside(double x, double y, double z)
{
double delx = x - xc;
double dely = y - yc;
double delz = z - zc;
double r = sqrt(delx*delx + dely*dely + delz*delz);
if (r <= radius) return 1;
return 0;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from inner surface of sphere
no contact if outside (possible if called from union/intersect)
delxyz = vector from nearest point on sphere to x
special case: no contact if x is at center of sphere
------------------------------------------------------------------------- */
int RegSphere::surface_interior(double *x, double cutoff)
{
double delx = x[0] - xc;
double dely = x[1] - yc;
double delz = x[2] - zc;
double r = sqrt(delx*delx + dely*dely + delz*delz);
if (r > radius || r == 0.0) return 0;
double delta = radius - r;
if (delta < cutoff) {
contact[0].r = delta;
contact[0].delx = delx*(1.0-radius/r);
contact[0].dely = dely*(1.0-radius/r);
contact[0].delz = delz*(1.0-radius/r);
return 1;
}
return 0;
}
/* ----------------------------------------------------------------------
one contact if 0 <= x < cutoff from outer surface of sphere
no contact if inside (possible if called from union/intersect)
delxyz = vector from nearest point on sphere to x
------------------------------------------------------------------------- */
int RegSphere::surface_exterior(double *x, double cutoff)
{
double delx = x[0] - xc;
double dely = x[1] - yc;
double delz = x[2] - zc;
double r = sqrt(delx*delx + dely*dely + delz*delz);
if (r < radius) return 0;
double delta = r - radius;
if (delta < cutoff) {
contact[0].r = delta;
contact[0].delx = delx*(1.0-radius/r);
contact[0].dely = dely*(1.0-radius/r);
contact[0].delz = delz*(1.0-radius/r);
return 1;
}
return 0;
}
diff --git a/src/region_union.cpp b/src/region_union.cpp
index 90a6815cb..ff566087e 100644
--- a/src/region_union.cpp
+++ b/src/region_union.cpp
@@ -1,202 +1,199 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "region_union.h"
#include "domain.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
RegUnion::RegUnion(LAMMPS *lmp, int narg, char **arg) : Region(lmp, narg, arg)
{
- if (narg < 5) error->all("Illegal region command");
+ if (narg < 5) error->all(FLERR,"Illegal region command");
int n = atoi(arg[2]);
- if (n < 2) error->all("Illegal region command");
+ if (n < 2) error->all(FLERR,"Illegal region command");
options(narg-(n+3),&arg[n+3]);
// build list of regions to union
list = new int[n];
nregion = 0;
int iregion;
for (int iarg = 0; iarg < n; iarg++) {
iregion = domain->find_region(arg[iarg+3]);
- if (iregion == -1) error->all("Region union region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Region union region ID does not exist");
list[nregion++] = iregion;
}
// extent of union of regions
// has bounding box if interior and all sub-regions have bounding box
Region **regions = domain->regions;
bboxflag = 1;
for (int ilist = 0; ilist < nregion; ilist++)
if (regions[list[ilist]]->bboxflag == 0) bboxflag = 0;
if (!interior) bboxflag = 0;
if (bboxflag) {
extent_xlo = extent_ylo = extent_zlo = BIG;
extent_xhi = extent_yhi = extent_zhi = -BIG;
for (int ilist = 0; ilist < nregion; ilist++) {
extent_xlo = MIN(extent_xlo,regions[list[ilist]]->extent_xlo);
extent_ylo = MIN(extent_ylo,regions[list[ilist]]->extent_ylo);
extent_zlo = MIN(extent_zlo,regions[list[ilist]]->extent_zlo);
extent_xhi = MAX(extent_xhi,regions[list[ilist]]->extent_xhi);
extent_yhi = MAX(extent_yhi,regions[list[ilist]]->extent_yhi);
extent_zhi = MAX(extent_zhi,regions[list[ilist]]->extent_zhi);
}
}
// possible contacts = sum of possible contacts in all sub-regions
cmax = 0;
for (int ilist = 0; ilist < nregion; ilist++)
cmax += regions[list[ilist]]->cmax;
contact = new Contact[cmax];
}
/* ---------------------------------------------------------------------- */
RegUnion::~RegUnion()
{
delete [] list;
delete [] contact;
}
/* ----------------------------------------------------------------------
return 1 if region is dynamic, 0 if static
dynamic if any sub-region is dynamic, else static
------------------------------------------------------------------------- */
int RegUnion::dynamic_check()
{
Region **regions = domain->regions;
for (int ilist = 0; ilist < nregion; ilist++)
if (regions[list[ilist]]->dynamic_check()) return 1;
return 0;
}
/* ----------------------------------------------------------------------
inside = 1 if x,y,z is match() with any sub-region
else inside = 0
------------------------------------------------------------------------- */
int RegUnion::inside(double x, double y, double z)
{
int ilist;
Region **regions = domain->regions;
for (ilist = 0; ilist < nregion; ilist++)
if (regions[list[ilist]]->match(x,y,z)) break;
if (ilist == nregion) return 0;
return 1;
}
/* ----------------------------------------------------------------------
compute contacts with interior of union of sub-regions
(1) compute contacts in each sub-region
(2) only keep a contact if surface point is not match() to all other regions
------------------------------------------------------------------------- */
int RegUnion::surface_interior(double *x, double cutoff)
{
int m,ilist,jlist,iregion,jregion,ncontacts;
double xs,ys,zs;
Region **regions = domain->regions;
int n = 0;
for (ilist = 0; ilist < nregion; ilist++) {
iregion = list[ilist];
ncontacts = regions[iregion]->surface(x[0],x[1],x[2],cutoff);
for (m = 0; m < ncontacts; m++) {
xs = x[0] - regions[iregion]->contact[m].delx;
ys = x[1] - regions[iregion]->contact[m].dely;
zs = x[2] - regions[iregion]->contact[m].delz;
for (jlist = 0; jlist < nregion; jlist++) {
if (jlist == ilist) continue;
jregion = list[jlist];
if (regions[jregion]->match(xs,ys,zs)) break;
}
if (jlist == nregion) {
contact[n].r = regions[iregion]->contact[m].r;
contact[n].delx = regions[iregion]->contact[m].delx;
contact[n].dely = regions[iregion]->contact[m].dely;
contact[n].delz = regions[iregion]->contact[m].delz;
n++;
}
}
}
return n;
}
/* ----------------------------------------------------------------------
compute contacts with exterior of union of sub-regions
(1) flip interior/exterior flag of each sub-region
(2) compute contacts in each sub-region
(3) only keep a contact if surface point is match() to all other regions
(4) flip interior/exterior flags back to original settings
this is effectively same algorithm as surface_interior() for RegIntersect
------------------------------------------------------------------------- */
int RegUnion::surface_exterior(double *x, double cutoff)
{
int m,ilist,jlist,iregion,jregion,ncontacts;
double xs,ys,zs;
Region **regions = domain->regions;
int n = 0;
for (ilist = 0; ilist < nregion; ilist++)
regions[list[ilist]]->interior ^= 1;
for (ilist = 0; ilist < nregion; ilist++) {
iregion = list[ilist];
ncontacts = regions[iregion]->surface(x[0],x[1],x[2],cutoff);
for (m = 0; m < ncontacts; m++) {
xs = x[0] - regions[iregion]->contact[m].delx;
ys = x[1] - regions[iregion]->contact[m].dely;
zs = x[2] - regions[iregion]->contact[m].delz;
for (jlist = 0; jlist < nregion; jlist++) {
if (jlist == ilist) continue;
jregion = list[jlist];
if (!regions[jregion]->match(xs,ys,zs)) break;
}
if (jlist == nregion) {
contact[n].r = regions[iregion]->contact[m].r;
contact[n].delx = regions[iregion]->contact[m].delx;
contact[n].dely = regions[iregion]->contact[m].dely;
contact[n].delz = regions[iregion]->contact[m].delz;
n++;
}
}
}
for (ilist = 0; ilist < nregion; ilist++)
regions[list[ilist]]->interior ^= 1;
return n;
}
diff --git a/src/replicate.cpp b/src/replicate.cpp
index b9767e424..da6a66206 100644
--- a/src/replicate.cpp
+++ b/src/replicate.cpp
@@ -1,397 +1,394 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "replicate.h"
#include "atom.h"
#include "atom_vec.h"
#include "atom_vec_hybrid.h"
#include "force.h"
#include "domain.h"
#include "comm.h"
#include "special.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define LB_FACTOR 1.1
#define EPSILON 1.0e-6
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
Replicate::Replicate(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void Replicate::command(int narg, char **arg)
{
int i,j,m,n;
if (domain->box_exist == 0)
- error->all("Replicate command before simulation box is defined");
- if (narg != 3) error->all("Illegal replicate command");
+ error->all(FLERR,"Replicate command before simulation box is defined");
+ if (narg != 3) error->all(FLERR,"Illegal replicate command");
int me = comm->me;
int nprocs = comm->nprocs;
if (me == 0 && screen) fprintf(screen,"Replicating atoms ...\n");
// nrep = total # of replications
int nx = atoi(arg[0]);
int ny = atoi(arg[1]);
int nz = atoi(arg[2]);
int nrep = nx*ny*nz;
// error and warning checks
- if (nx <= 0 || ny <= 0 || nz <= 0) error->all("Illegal replicate command");
+ if (nx <= 0 || ny <= 0 || nz <= 0) error->all(FLERR,"Illegal replicate command");
if (domain->dimension == 2 && nz != 1)
- error->all("Cannot replicate 2d simulation in z dimension");
+ error->all(FLERR,"Cannot replicate 2d simulation in z dimension");
if ((nx > 1 && domain->xperiodic == 0) ||
(ny > 1 && domain->yperiodic == 0) ||
(nz > 1 && domain->zperiodic == 0))
- error->warning("Replicating in a non-periodic dimension");
+ error->warning(FLERR,"Replicating in a non-periodic dimension");
if (atom->nextra_grow || atom->nextra_restart || atom->nextra_store)
- error->all("Cannot replicate with fixes that store atom quantities");
+ error->all(FLERR,"Cannot replicate with fixes that store atom quantities");
// maxtag = largest atom tag across all existing atoms
int maxtag = 0;
for (i = 0; i < atom->nlocal; i++) maxtag = MAX(atom->tag[i],maxtag);
int maxtag_all;
MPI_Allreduce(&maxtag,&maxtag_all,1,MPI_INT,MPI_MAX,world);
maxtag = maxtag_all;
// maxmol = largest molecule tag across all existing atoms
int maxmol = 0;
if (atom->molecular) {
for (i = 0; i < atom->nlocal; i++) maxmol = MAX(atom->molecule[i],maxmol);
int maxmol_all;
MPI_Allreduce(&maxmol,&maxmol_all,1,MPI_INT,MPI_MAX,world);
maxmol = maxmol_all;
}
// unmap existing atoms via image flags
for (i = 0; i < atom->nlocal; i++)
domain->unmap(atom->x[i],atom->image[i]);
// communication buffer for all my atom's info
// max_size = largest buffer needed by any proc
// must do before new Atom class created,
// since size_restart() uses atom->nlocal
int max_size;
int send_size = atom->avec->size_restart();
MPI_Allreduce(&send_size,&max_size,1,MPI_INT,MPI_MAX,world);
double *buf;
memory->create(buf,max_size,"replicate:buf");
// old = original atom class
// atom = new replicated atom class
// if old atom style was hybrid, pass sub-style names to create_avec
Atom *old = atom;
atom = new Atom(lmp);
atom->settings(old);
int nstyles = 0;
char **keywords = NULL;
if (strcmp(old->atom_style,"hybrid") == 0) {
AtomVecHybrid *avec_hybrid = (AtomVecHybrid *) old->avec;
nstyles = avec_hybrid->nstyles;
keywords = avec_hybrid->keywords;
}
atom->create_avec(old->atom_style,nstyles,keywords);
// check that new system will not be too large
// if molecular and N > MAXTAGINT, error
// if atomic and new N > MAXTAGINT, turn off tags for existing and new atoms
// new system cannot exceed MAXBIGINT
if (atom->molecular && (nrep*old->natoms < 0 || nrep*old->natoms > MAXTAGINT))
- error->all("Replicated molecular system atom IDs are too big");
+ error->all(FLERR,"Replicated molecular system atom IDs are too big");
if (nrep*old->natoms < 0 || nrep*old->natoms > MAXTAGINT)
atom->tag_enable = 0;
if (atom->tag_enable == 0)
for (int i = 0; i < atom->nlocal; i++)
atom->tag[i] = 0;
if (nrep*old->natoms < 0 || nrep*old->natoms > MAXBIGINT ||
nrep*old->nbonds < 0 || nrep*old->nbonds > MAXBIGINT ||
nrep*old->nangles < 0 || nrep*old->nangles > MAXBIGINT ||
nrep*old->ndihedrals < 0 || nrep*old->ndihedrals > MAXBIGINT ||
nrep*old->nimpropers < 0 || nrep*old->nimpropers > MAXBIGINT)
- error->all("Replicated system is too big");
+ error->all(FLERR,"Replicated system is too big");
// assign atom and topology counts in new class from old one
atom->natoms = old->natoms * nrep;
atom->nbonds = old->nbonds * nrep;
atom->nangles = old->nangles * nrep;
atom->ndihedrals = old->ndihedrals * nrep;
atom->nimpropers = old->nimpropers * nrep;
atom->ntypes = old->ntypes;
atom->nbondtypes = old->nbondtypes;
atom->nangletypes = old->nangletypes;
atom->ndihedraltypes = old->ndihedraltypes;
atom->nimpropertypes = old->nimpropertypes;
atom->bond_per_atom = old->bond_per_atom;
atom->angle_per_atom = old->angle_per_atom;
atom->dihedral_per_atom = old->dihedral_per_atom;
atom->improper_per_atom = old->improper_per_atom;
// store old simulation box
int triclinic = domain->triclinic;
double old_xprd = domain->xprd;
double old_yprd = domain->yprd;
double old_zprd = domain->zprd;
double old_xy = domain->xy;
double old_xz = domain->xz;
double old_yz = domain->yz;
// setup new simulation box
domain->boxhi[0] = domain->boxlo[0] + nx*old_xprd;
domain->boxhi[1] = domain->boxlo[1] + ny*old_yprd;
domain->boxhi[2] = domain->boxlo[2] + nz*old_zprd;
if (triclinic) {
domain->xy *= ny;
domain->xz *= nz;
domain->yz *= nz;
}
// new problem setup using new box boundaries
if (nprocs == 1) n = static_cast<int> (atom->natoms);
else n = static_cast<int> (LB_FACTOR * atom->natoms / nprocs);
atom->allocate_type_arrays();
atom->avec->grow(n);
n = atom->nmax;
domain->print_box(" ");
domain->set_initial_box();
domain->set_global_box();
comm->set_procs();
domain->set_local_box();
// copy type arrays to new atom class
if (atom->mass) {
for (int itype = 1; itype <= atom->ntypes; itype++) {
atom->mass_setflag[itype] = old->mass_setflag[itype];
if (atom->mass_setflag[itype]) atom->mass[itype] = old->mass[itype];
}
}
// set bounds for my proc
// if periodic and I am lo/hi proc, adjust bounds by EPSILON
// insures all replicated atoms will be owned even with round-off
double sublo[3],subhi[3];
if (triclinic == 0) {
sublo[0] = domain->sublo[0]; subhi[0] = domain->subhi[0];
sublo[1] = domain->sublo[1]; subhi[1] = domain->subhi[1];
sublo[2] = domain->sublo[2]; subhi[2] = domain->subhi[2];
} else {
sublo[0] = domain->sublo_lamda[0]; subhi[0] = domain->subhi_lamda[0];
sublo[1] = domain->sublo_lamda[1]; subhi[1] = domain->subhi_lamda[1];
sublo[2] = domain->sublo_lamda[2]; subhi[2] = domain->subhi_lamda[2];
}
if (domain->xperiodic) {
if (comm->myloc[0] == 0) sublo[0] -= EPSILON;
if (comm->myloc[0] == comm->procgrid[0]-1) subhi[0] += EPSILON;
}
if (domain->yperiodic) {
if (comm->myloc[1] == 0) sublo[1] -= EPSILON;
if (comm->myloc[1] == comm->procgrid[1]-1) subhi[1] += EPSILON;
}
if (domain->zperiodic) {
if (comm->myloc[2] == 0) sublo[2] -= EPSILON;
if (comm->myloc[2] == comm->procgrid[2]-1) subhi[2] += EPSILON;
}
// loop over all procs
// if this iteration of loop is me:
// pack my unmapped atom data into buf
// bcast it to all other procs
// performs 3d replicate loop with while loop over atoms in buf
// x = new replicated position, remapped into simulation box
// unpack atom into new atom class from buf if I own it
// adjust tag, mol #, coord, topology info as needed
AtomVec *old_avec = old->avec;
AtomVec *avec = atom->avec;
int ix,iy,iz,image,atom_offset,mol_offset;
double x[3],lamda[3];
double *coord;
int tag_enable = atom->tag_enable;
for (int iproc = 0; iproc < nprocs; iproc++) {
if (me == iproc) {
n = 0;
for (i = 0; i < old->nlocal; i++) n += old_avec->pack_restart(i,&buf[n]);
}
MPI_Bcast(&n,1,MPI_INT,iproc,world);
MPI_Bcast(buf,n,MPI_DOUBLE,iproc,world);
for (ix = 0; ix < nx; ix++) {
for (iy = 0; iy < ny; iy++) {
for (iz = 0; iz < nz; iz++) {
// while loop over one proc's atom list
m = 0;
while (m < n) {
image = (512 << 20) | (512 << 10) | 512;
if (triclinic == 0) {
x[0] = buf[m+1] + ix*old_xprd;
x[1] = buf[m+2] + iy*old_yprd;
x[2] = buf[m+3] + iz*old_zprd;
} else {
x[0] = buf[m+1] + ix*old_xprd + iy*old_xy + iz*old_xz;
x[1] = buf[m+2] + iy*old_yprd + iz*old_yz;
x[2] = buf[m+3] + iz*old_zprd;
}
domain->remap(x,image);
if (triclinic) {
domain->x2lamda(x,lamda);
coord = lamda;
} else coord = x;
if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
coord[1] >= sublo[1] && coord[1] < subhi[1] &&
coord[2] >= sublo[2] && coord[2] < subhi[2]) {
m += avec->unpack_restart(&buf[m]);
i = atom->nlocal - 1;
if (tag_enable)
atom_offset = iz*ny*nx*maxtag + iy*nx*maxtag + ix*maxtag;
else atom_offset = 0;
mol_offset = iz*ny*nx*maxmol + iy*nx*maxmol + ix*maxmol;
atom->x[i][0] = x[0];
atom->x[i][1] = x[1];
atom->x[i][2] = x[2];
atom->tag[i] += atom_offset;
atom->image[i] = image;
if (atom->molecular) {
if (atom->molecule[i] > 0)
atom->molecule[i] += mol_offset;
if (atom->avec->bonds_allow)
for (j = 0; j < atom->num_bond[i]; j++)
atom->bond_atom[i][j] += atom_offset;
if (atom->avec->angles_allow)
for (j = 0; j < atom->num_angle[i]; j++) {
atom->angle_atom1[i][j] += atom_offset;
atom->angle_atom2[i][j] += atom_offset;
atom->angle_atom3[i][j] += atom_offset;
}
if (atom->avec->dihedrals_allow)
for (j = 0; j < atom->num_dihedral[i]; j++) {
atom->dihedral_atom1[i][j] += atom_offset;
atom->dihedral_atom2[i][j] += atom_offset;
atom->dihedral_atom3[i][j] += atom_offset;
atom->dihedral_atom4[i][j] += atom_offset;
}
if (atom->avec->impropers_allow)
for (j = 0; j < atom->num_improper[i]; j++) {
atom->improper_atom1[i][j] += atom_offset;
atom->improper_atom2[i][j] += atom_offset;
atom->improper_atom3[i][j] += atom_offset;
atom->improper_atom4[i][j] += atom_offset;
}
}
} else m += static_cast<int> (buf[m]);
}
}
}
}
} // end of proc loop
// free communication buffer and old atom class
memory->destroy(buf);
delete old;
// check that all atoms were assigned to procs
bigint natoms;
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (me == 0) {
if (screen) fprintf(screen," " BIGINT_FORMAT " atoms\n",natoms);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " atoms\n",natoms);
}
if (natoms != atom->natoms)
- error->all("Replicate did not assign all atoms correctly");
+ error->all(FLERR,"Replicate did not assign all atoms correctly");
if (me == 0) {
if (atom->nbonds) {
if (screen) fprintf(screen," " BIGINT_FORMAT " bonds\n",atom->nbonds);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " bonds\n",atom->nbonds);
}
if (atom->nangles) {
if (screen) fprintf(screen," " BIGINT_FORMAT " angles\n",
atom->nangles);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " angles\n",
atom->nangles);
}
if (atom->ndihedrals) {
if (screen) fprintf(screen," " BIGINT_FORMAT " dihedrals\n",
atom->ndihedrals);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " dihedrals\n",
atom->ndihedrals);
}
if (atom->nimpropers) {
if (screen) fprintf(screen," " BIGINT_FORMAT " impropers\n",
atom->nimpropers);
if (logfile) fprintf(logfile," " BIGINT_FORMAT " impropers\n",
atom->nimpropers);
}
}
// create global mapping and bond topology now that system is defined
if (atom->map_style) {
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
if (atom->molecular) {
Special special(lmp);
special.build();
}
}
diff --git a/src/respa.cpp b/src/respa.cpp
index 83457da73..c283b6454 100644
--- a/src/respa.cpp
+++ b/src/respa.cpp
@@ -1,695 +1,695 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Mark Stevens (SNL), Paul Crozier (SNL)
------------------------------------------------------------------------- */
#include "stdlib.h"
#include "string.h"
#include "respa.h"
#include "neighbor.h"
#include "atom.h"
#include "domain.h"
#include "comm.h"
#include "atom.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "output.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "fix_respa.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Respa::Respa(LAMMPS *lmp, int narg, char **arg) : Integrate(lmp, narg, arg)
{
- if (narg < 1) error->all("Illegal run_style respa command");
+ if (narg < 1) error->all(FLERR,"Illegal run_style respa command");
nlevels = atoi(arg[0]);
- if (nlevels < 1) error->all("Respa levels must be >= 1");
+ if (nlevels < 1) error->all(FLERR,"Respa levels must be >= 1");
- if (narg < nlevels) error->all("Illegal run_style respa command");
+ if (narg < nlevels) error->all(FLERR,"Illegal run_style respa command");
loop = new int[nlevels];
for (int iarg = 1; iarg < nlevels; iarg++) {
loop[iarg-1] = atoi(arg[iarg]);
- if (loop[iarg-1] <= 0) error->all("Illegal run_style respa command");
+ if (loop[iarg-1] <= 0) error->all(FLERR,"Illegal run_style respa command");
}
loop[nlevels-1] = 1;
// set level at which each force is computed
// argument settings override defaults
level_bond = level_angle = level_dihedral = level_improper = -1;
level_pair = level_kspace = -1;
level_inner = level_middle = level_outer = -1;
int iarg = nlevels;
while (iarg < narg) {
if (strcmp(arg[iarg],"bond") == 0) {
- if (iarg+2 > narg) error->all("Illegal run_style respa command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
level_bond = atoi(arg[iarg+1]) - 1;
iarg += 2;
} else if (strcmp(arg[iarg],"angle") == 0) {
- if (iarg+2 > narg) error->all("Illegal run_style respa command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
level_angle = atoi(arg[iarg+1]) - 1;
iarg += 2;
} else if (strcmp(arg[iarg],"dihedral") == 0) {
- if (iarg+2 > narg) error->all("Illegal run_style respa command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
level_dihedral = atoi(arg[iarg+1]) - 1;
iarg += 2;
} else if (strcmp(arg[iarg],"improper") == 0) {
- if (iarg+2 > narg) error->all("Illegal run_style respa command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
level_improper = atoi(arg[iarg+1]) - 1;
iarg += 2;
} else if (strcmp(arg[iarg],"pair") == 0) {
- if (iarg+2 > narg) error->all("Illegal run_style respa command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
level_pair = atoi(arg[iarg+1]) - 1;
iarg += 2;
} else if (strcmp(arg[iarg],"inner") == 0) {
- if (iarg+4 > narg) error->all("Illegal run_style respa command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal run_style respa command");
level_inner = atoi(arg[iarg+1]) - 1;
cutoff[0] = atof(arg[iarg+2]);
cutoff[1] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"middle") == 0) {
- if (iarg+4 > narg) error->all("Illegal run_style respa command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal run_style respa command");
level_middle = atoi(arg[iarg+1]) - 1;
cutoff[2] = atof(arg[iarg+2]);
cutoff[3] = atof(arg[iarg+3]);
iarg += 4;
} else if (strcmp(arg[iarg],"outer") == 0) {
- if (iarg+2 > narg) error->all("Illegal run_style respa command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
level_outer = atoi(arg[iarg+1]) - 1;
iarg += 2;
} else if (strcmp(arg[iarg],"kspace") == 0) {
- if (iarg+2 > narg) error->all("Illegal run_style respa command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
level_kspace = atoi(arg[iarg+1]) - 1;
iarg += 2;
- } else error->all("Illegal run_style respa command");
+ } else error->all(FLERR,"Illegal run_style respa command");
}
// cannot specify both pair and inner/middle/outer
if (level_pair >= 0 &&
(level_inner >= 0 || level_middle >= 0 || level_outer >= 0))
- error->all("Cannot set both respa pair and inner/middle/outer");
+ error->all(FLERR,"Cannot set both respa pair and inner/middle/outer");
// if either inner and outer is specified, then both must be
if ((level_inner >= 0 && level_outer == -1) ||
(level_outer >= 0 && level_inner == -1))
- error->all("Must set both respa inner and outer");
+ error->all(FLERR,"Must set both respa inner and outer");
// middle cannot be set without inner/outer
if (level_middle >= 0 && level_inner == -1)
- error->all("Cannot set respa middle without inner/outer");
+ error->all(FLERR,"Cannot set respa middle without inner/outer");
// set defaults if user did not specify level
// bond to innermost level
// angle same as bond, dihedral same as angle, improper same as dihedral
// pair to outermost level if no inner/middle/outer
// inner/middle/outer have no defaults
// kspace same as pair or outer
if (level_bond == -1) level_bond = 0;
if (level_angle == -1) level_angle = level_bond;
if (level_dihedral == -1) level_dihedral = level_angle;
if (level_improper == -1) level_improper = level_dihedral;
if (level_pair == -1 && level_inner == -1) level_pair = nlevels-1;
if (level_kspace == -1 && level_pair >= 0) level_kspace = level_pair;
if (level_kspace == -1 && level_pair == -1) level_kspace = level_outer;
// print respa levels
if (comm->me == 0) {
if (screen) {
fprintf(screen,"Respa levels:\n");
for (int i = 0; i < nlevels; i++) {
fprintf(screen," %d =",i);
if (level_bond == i) fprintf(screen," bond");
if (level_angle == i) fprintf(screen," angle");
if (level_dihedral == i) fprintf(screen," dihedral");
if (level_improper == i) fprintf(screen," improper");
if (level_pair == i) fprintf(screen," pair");
if (level_inner == i) fprintf(screen," pair-inner");
if (level_middle == i) fprintf(screen," pair-middle");
if (level_outer == i) fprintf(screen," pair-outer");
if (level_kspace == i) fprintf(screen," kspace");
fprintf(screen,"\n");
}
}
if (logfile) {
fprintf(logfile,"Respa levels:\n");
for (int i = 0; i < nlevels; i++) {
fprintf(logfile," %d =",i);
if (level_bond == i) fprintf(logfile," bond");
if (level_angle == i) fprintf(logfile," angle");
if (level_dihedral == i) fprintf(logfile," dihedral");
if (level_improper == i) fprintf(logfile," improper");
if (level_pair == i) fprintf(logfile," pair");
if (level_inner == i) fprintf(logfile," pair-inner");
if (level_middle == i) fprintf(logfile," pair-middle");
if (level_outer == i) fprintf(logfile," pair-outer");
if (level_kspace == i) fprintf(logfile," kspace");
fprintf(logfile,"\n");
}
}
}
// check that levels are in correct order
if (level_angle < level_bond || level_dihedral < level_angle ||
level_improper < level_dihedral)
- error->all("Invalid order of forces within respa levels");
+ error->all(FLERR,"Invalid order of forces within respa levels");
if (level_pair >= 0) {
if (level_pair < level_improper || level_kspace < level_pair)
- error->all("Invalid order of forces within respa levels");
+ error->all(FLERR,"Invalid order of forces within respa levels");
}
if (level_pair == -1 && level_middle == -1) {
if (level_inner < level_improper || level_outer < level_inner ||
level_kspace != level_outer)
- error->all("Invalid order of forces within respa levels");
+ error->all(FLERR,"Invalid order of forces within respa levels");
}
if (level_pair == -1 && level_middle >= 0) {
if (level_inner < level_improper || level_middle < level_inner ||
level_outer < level_inner || level_kspace != level_outer)
- error->all("Invalid order of forces within respa levels");
+ error->all(FLERR,"Invalid order of forces within respa levels");
}
// warn if any levels are devoid of forces
int flag = 0;
for (int i = 0; i < nlevels; i++)
if (level_bond != i && level_angle != i && level_dihedral != i &&
level_improper != i && level_pair != i && level_inner != i &&
level_middle != i && level_outer != i && level_kspace != i) flag = 1;
if (flag && comm->me == 0)
- error->warning("One or more respa levels compute no forces");
+ error->warning(FLERR,"One or more respa levels compute no forces");
// check cutoff consistency if inner/middle/outer are enabled
if (level_inner >= 0 && cutoff[1] < cutoff[0])
- error->all("Respa inner cutoffs are invalid");
+ error->all(FLERR,"Respa inner cutoffs are invalid");
if (level_middle >= 0 && (cutoff[3] < cutoff[2] || cutoff[2] < cutoff[1]))
- error->all("Respa middle cutoffs are invalid");
+ error->all(FLERR,"Respa middle cutoffs are invalid");
// set outer pair of cutoffs to inner pair if middle is not enabled
if (level_inner >= 0 && level_middle < 0) {
cutoff[2] = cutoff[0];
cutoff[3] = cutoff[1];
}
// allocate other needed arrays
newton = new int[nlevels];
step = new double[nlevels];
}
/* ---------------------------------------------------------------------- */
Respa::~Respa()
{
delete [] loop;
delete [] newton;
delete [] step;
}
/* ----------------------------------------------------------------------
initialization before run
------------------------------------------------------------------------- */
void Respa::init()
{
// warn if no fixes
if (modify->nfix == 0 && comm->me == 0)
- error->warning("No fixes defined, atoms won't move");
+ error->warning(FLERR,"No fixes defined, atoms won't move");
// create fix needed for storing atom-based respa level forces
// will delete it at end of run
char **fixarg = new char*[4];
fixarg[0] = (char *) "RESPA";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "RESPA";
fixarg[3] = new char[8];
sprintf(fixarg[3],"%d",nlevels);
modify->add_fix(4,fixarg);
delete [] fixarg[3];
delete [] fixarg;
fix_respa = (FixRespa *) modify->fix[modify->nfix-1];
// insure respa inner/middle/outer is using Pair class that supports it
if (level_inner >= 0)
if (force->pair && force->pair->respa_enable == 0)
- error->all("Pair style does not support rRESPA inner/middle/outer");
+ error->all(FLERR,"Pair style does not support rRESPA inner/middle/outer");
// virial_style = 1 (explicit) since never computed implicitly like Verlet
virial_style = 1;
// setup lists of computes for global and per-atom PE and pressure
ev_setup();
// set flags for what arrays to clear in force_clear()
// need to clear additionals arrays if they exist
torqueflag = 0;
if (atom->torque_flag) torqueflag = 1;
erforceflag = 0;
if (atom->erforce_flag) erforceflag = 1;
e_flag = 0;
if (atom->e_flag) e_flag = 1;
rho_flag = 0;
if (atom->rho_flag) rho_flag = 1;
// step[] = timestep for each level
step[nlevels-1] = update->dt;
for (int ilevel = nlevels-2; ilevel >= 0; ilevel--)
step[ilevel] = step[ilevel+1]/loop[ilevel];
// set newton flag for each level
for (int ilevel = 0; ilevel < nlevels; ilevel++) {
newton[ilevel] = 0;
if (force->newton_bond) {
if (level_bond == ilevel || level_angle == ilevel ||
level_dihedral == ilevel || level_improper == ilevel)
newton[ilevel] = 1;
}
if (force->newton_pair) {
if (level_pair == ilevel || level_inner == ilevel ||
level_middle == ilevel || level_outer == ilevel)
newton[ilevel] = 1;
}
}
// orthogonal vs triclinic simulation box
triclinic = domain->triclinic;
}
/* ----------------------------------------------------------------------
setup before run
------------------------------------------------------------------------- */
void Respa::setup()
{
if (comm->me == 0 && screen) fprintf(screen,"Setting up run ...\n");
update->setupflag = 1;
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
atom->setup();
modify->setup_pre_exchange();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
if (atom->sortfreq > 0) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
neighbor->build();
neighbor->ncalls = 0;
// compute all forces
ev_set(update->ntimestep);
for (int ilevel = 0; ilevel < nlevels; ilevel++) {
force_clear(newton[ilevel]);
modify->setup_pre_force_respa(vflag,ilevel);
if (level_bond == ilevel && force->bond)
force->bond->compute(eflag,vflag);
if (level_angle == ilevel && force->angle)
force->angle->compute(eflag,vflag);
if (level_dihedral == ilevel && force->dihedral)
force->dihedral->compute(eflag,vflag);
if (level_improper == ilevel && force->improper)
force->improper->compute(eflag,vflag);
if (level_pair == ilevel && force->pair)
force->pair->compute(eflag,vflag);
if (level_inner == ilevel && force->pair)
force->pair->compute_inner();
if (level_middle == ilevel && force->pair)
force->pair->compute_middle();
if (level_outer == ilevel && force->pair)
force->pair->compute_outer(eflag,vflag);
if (level_kspace == ilevel && force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if (newton[ilevel]) comm->reverse_comm();
copy_f_flevel(ilevel);
}
modify->setup(vflag);
sum_flevel_f();
output->setup(1);
update->setupflag = 0;
}
/* ----------------------------------------------------------------------
setup without output
flag = 0 = just force calculation
flag = 1 = reneighbor and force calculation
------------------------------------------------------------------------- */
void Respa::setup_minimal(int flag)
{
update->setupflag = 1;
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
if (flag) {
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
neighbor->build();
neighbor->ncalls = 0;
}
// compute all forces
ev_set(update->ntimestep);
for (int ilevel = 0; ilevel < nlevels; ilevel++) {
force_clear(newton[ilevel]);
modify->setup_pre_force_respa(vflag,ilevel);
if (level_bond == ilevel && force->bond)
force->bond->compute(eflag,vflag);
if (level_angle == ilevel && force->angle)
force->angle->compute(eflag,vflag);
if (level_dihedral == ilevel && force->dihedral)
force->dihedral->compute(eflag,vflag);
if (level_improper == ilevel && force->improper)
force->improper->compute(eflag,vflag);
if (level_pair == ilevel && force->pair)
force->pair->compute(eflag,vflag);
if (level_inner == ilevel && force->pair)
force->pair->compute_inner();
if (level_middle == ilevel && force->pair)
force->pair->compute_middle();
if (level_outer == ilevel && force->pair)
force->pair->compute_outer(eflag,vflag);
if (level_kspace == ilevel && force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if (newton[ilevel]) comm->reverse_comm();
copy_f_flevel(ilevel);
}
modify->setup(vflag);
sum_flevel_f();
update->setupflag = 0;
}
/* ----------------------------------------------------------------------
run for N steps
------------------------------------------------------------------------- */
void Respa::run(int n)
{
bigint ntimestep;
for (int i = 0; i < n; i++) {
ntimestep = ++update->ntimestep;
ev_set(ntimestep);
recurse(nlevels-1);
if (modify->n_end_of_step) modify->end_of_step();
if (ntimestep == output->next) {
timer->stamp();
sum_flevel_f();
output->write(update->ntimestep);
timer->stamp(TIME_OUTPUT);
}
}
}
/* ----------------------------------------------------------------------
delete rRESPA fix at end of run, so its atom arrays won't persist
------------------------------------------------------------------------- */
void Respa::cleanup()
{
modify->post_run();
modify->delete_fix("RESPA");
}
/* ---------------------------------------------------------------------- */
void Respa::reset_dt()
{
step[nlevels-1] = update->dt;
for (int ilevel = nlevels-2; ilevel >= 0; ilevel--)
step[ilevel] = step[ilevel+1]/loop[ilevel];
}
/* ---------------------------------------------------------------------- */
void Respa::recurse(int ilevel)
{
copy_flevel_f(ilevel);
for (int iloop = 0; iloop < loop[ilevel]; iloop++) {
modify->initial_integrate_respa(vflag,ilevel,iloop);
if (modify->n_post_integrate_respa)
modify->post_integrate_respa(ilevel,iloop);
if (ilevel) recurse(ilevel-1);
// at outermost level, check on rebuilding neighbor list
// at innermost level, communicate
// at middle levels, do nothing
if (ilevel == nlevels-1) {
int nflag = neighbor->decide();
if (nflag) {
if (modify->n_pre_exchange) modify->pre_exchange();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
if (domain->box_change) {
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
}
timer->stamp();
comm->exchange();
if (atom->sortfreq > 0 &&
update->ntimestep >= atom->nextsort) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
timer->stamp(TIME_COMM);
if (modify->n_pre_neighbor) modify->pre_neighbor();
neighbor->build();
timer->stamp(TIME_NEIGHBOR);
}
} else if (ilevel == 0) {
timer->stamp();
comm->forward_comm();
timer->stamp(TIME_COMM);
}
force_clear(newton[ilevel]);
if (modify->n_pre_force_respa)
modify->pre_force_respa(vflag,ilevel,iloop);
timer->stamp();
if (level_bond == ilevel && force->bond) {
force->bond->compute(eflag,vflag);
timer->stamp(TIME_BOND);
}
if (level_angle == ilevel && force->angle) {
force->angle->compute(eflag,vflag);
timer->stamp(TIME_BOND);
}
if (level_dihedral == ilevel && force->dihedral) {
force->dihedral->compute(eflag,vflag);
timer->stamp(TIME_BOND);
}
if (level_improper == ilevel && force->improper) {
force->improper->compute(eflag,vflag);
timer->stamp(TIME_BOND);
}
if (level_pair == ilevel && force->pair) {
force->pair->compute(eflag,vflag);
timer->stamp(TIME_PAIR);
}
if (level_inner == ilevel && force->pair) {
force->pair->compute_inner();
timer->stamp(TIME_PAIR);
}
if (level_middle == ilevel && force->pair) {
force->pair->compute_middle();
timer->stamp(TIME_PAIR);
}
if (level_outer == ilevel && force->pair) {
force->pair->compute_outer(eflag,vflag);
timer->stamp(TIME_PAIR);
}
if (level_kspace == ilevel && force->kspace) {
force->kspace->compute(eflag,vflag);
timer->stamp(TIME_KSPACE);
}
if (newton[ilevel]) {
comm->reverse_comm();
timer->stamp(TIME_COMM);
}
if (modify->n_post_force_respa)
modify->post_force_respa(vflag,ilevel,iloop);
modify->final_integrate_respa(ilevel,iloop);
}
copy_f_flevel(ilevel);
}
/* ----------------------------------------------------------------------
clear force on own & ghost atoms
------------------------------------------------------------------------- */
void Respa::force_clear(int newtonflag)
{
int i;
// clear global force array
// nall includes ghosts only if newton flag is set
int nall;
if (newtonflag) nall = atom->nlocal + atom->nghost;
else nall = atom->nlocal;
int ntot = nall * comm->nthreads;
double **f = atom->f;
for (i = 0; i < ntot; i++) {
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
}
if (torqueflag) {
double **torque = atom->torque;
for (i = 0; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
if (erforceflag) {
double *erforce = atom->erforce;
for (i = 0; i < nall; i++) erforce[i] = 0.0;
}
if (e_flag) {
double *de = atom->de;
for (i = 0; i < nall; i++) de[i] = 0.0;
}
if (rho_flag) {
double *drho = atom->drho;
for (i = 0; i < nall; i++) drho[i] = 0.0;
}
}
/* ----------------------------------------------------------------------
copy force components from atom->f to FixRespa->f_level
------------------------------------------------------------------------- */
void Respa::copy_f_flevel(int ilevel)
{
double ***f_level = fix_respa->f_level;
double **f = atom->f;
int n = atom->nlocal;
for (int i = 0; i < n; i++) {
f_level[i][ilevel][0] = f[i][0];
f_level[i][ilevel][1] = f[i][1];
f_level[i][ilevel][2] = f[i][2];
}
}
/* ----------------------------------------------------------------------
copy force components from FixRespa->f_level to atom->f
------------------------------------------------------------------------- */
void Respa::copy_flevel_f(int ilevel)
{
double ***f_level = fix_respa->f_level;
double **f = atom->f;
int n = atom->nlocal;
for (int i = 0; i < n; i++) {
f[i][0] = f_level[i][ilevel][0];
f[i][1] = f_level[i][ilevel][1];
f[i][2] = f_level[i][ilevel][2];
}
}
/* ----------------------------------------------------------------------
sum all force components from FixRespa->f_level to create full atom->f
------------------------------------------------------------------------- */
void Respa::sum_flevel_f()
{
copy_flevel_f(0);
double ***f_level = fix_respa->f_level;
double **f = atom->f;
int n = atom->nlocal;
for (int ilevel = 1; ilevel < nlevels; ilevel++) {
for (int i = 0; i < n; i++) {
f[i][0] += f_level[i][ilevel][0];
f[i][1] += f_level[i][ilevel][1];
f[i][2] += f_level[i][ilevel][2];
}
}
}
diff --git a/src/run.cpp b/src/run.cpp
index 667ea84a8..1f413072a 100644
--- a/src/run.cpp
+++ b/src/run.cpp
@@ -1,251 +1,248 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "stdlib.h"
#include "string.h"
#include "run.h"
#include "domain.h"
#include "update.h"
#include "integrate.h"
#include "modify.h"
#include "output.h"
#include "finish.h"
#include "input.h"
#include "timer.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
#define MAXLINE 2048
/* ---------------------------------------------------------------------- */
Run::Run(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void Run::command(int narg, char **arg)
{
- if (narg < 1) error->all("Illegal run command");
+ if (narg < 1) error->all(FLERR,"Illegal run command");
if (domain->box_exist == 0)
- error->all("Run command before simulation box is defined");
+ error->all(FLERR,"Run command before simulation box is defined");
bigint nsteps_input = ATOBIGINT(arg[0]);
// parse optional args
int uptoflag = 0;
int startflag = 0;
int stopflag = 0;
bigint start,stop;
int preflag = 1;
int postflag = 1;
int nevery = 0;
int ncommands = 0;
int first,last;
int iarg = 1;
while (iarg < narg) {
if (strcmp(arg[iarg],"upto") == 0) {
- if (iarg+1 > narg) error->all("Illegal run command");
+ if (iarg+1 > narg) error->all(FLERR,"Illegal run command");
uptoflag = 1;
iarg += 1;
} else if (strcmp(arg[iarg],"start") == 0) {
- if (iarg+2 > narg) error->all("Illegal run command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run command");
startflag = 1;
start = ATOBIGINT(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"stop") == 0) {
- if (iarg+2 > narg) error->all("Illegal run command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run command");
stopflag = 1;
stop = ATOBIGINT(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"pre") == 0) {
- if (iarg+2 > narg) error->all("Illegal run command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run command");
if (strcmp(arg[iarg+1],"no") == 0) preflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) preflag = 1;
- else error->all("Illegal run command");
+ else error->all(FLERR,"Illegal run command");
iarg += 2;
} else if (strcmp(arg[iarg],"post") == 0) {
- if (iarg+2 > narg) error->all("Illegal run command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal run command");
if (strcmp(arg[iarg+1],"no") == 0) postflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) postflag = 1;
- else error->all("Illegal run command");
+ else error->all(FLERR,"Illegal run command");
iarg += 2;
// all remaining args are commands
// first,last = arg index of first/last commands
// set ncommands = 0 if single command and it is NULL
} else if (strcmp(arg[iarg],"every") == 0) {
- if (iarg+3 > narg) error->all("Illegal run command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal run command");
nevery = atoi(arg[iarg+1]);
- if (nevery <= 0) error->all("Illegal run command");
+ if (nevery <= 0) error->all(FLERR,"Illegal run command");
first = iarg+2;
last = narg-1;
ncommands = last-first + 1;
if (ncommands == 1 && strcmp(arg[first],"NULL") == 0) ncommands = 0;
iarg = narg;
- } else error->all("Illegal run command");
+ } else error->all(FLERR,"Illegal run command");
}
// set nsteps as integer, using upto value if specified
int nsteps;
if (!uptoflag) {
if (nsteps_input < 0 || nsteps_input > MAXSMALLINT)
- error->all("Invalid run command N value");
+ error->all(FLERR,"Invalid run command N value");
nsteps = static_cast<int> (nsteps_input);
} else {
bigint delta = nsteps_input - update->ntimestep;
if (delta < 0 || delta > MAXSMALLINT)
- error->all("Invalid run command upto value");
+ error->all(FLERR,"Invalid run command upto value");
nsteps = static_cast<int> (delta);
}
// error check
if (startflag) {
if (start < 0 || start > MAXBIGINT)
- error->all("Invalid run command start/stop value");
+ error->all(FLERR,"Invalid run command start/stop value");
if (start > update->ntimestep)
- error->all("Run command start value is after start of run");
+ error->all(FLERR,"Run command start value is after start of run");
}
if (stopflag) {
if (stop < 0 || stop > MAXBIGINT)
- error->all("Invalid run command start/stop value");
+ error->all(FLERR,"Invalid run command start/stop value");
if (stop < update->ntimestep + nsteps)
- error->all("Run command stop value is before end of run");
+ error->all(FLERR,"Run command stop value is before end of run");
}
// if nevery, make copies of arg strings that are commands
// required because re-parsing commands via input->one() will wipe out args
char **commands = NULL;
if (nevery && ncommands > 0) {
commands = new char*[ncommands];
ncommands = 0;
for (int i = first; i <= last; i++) {
int n = strlen(arg[i]) + 1;
commands[ncommands] = new char[n];
strcpy(commands[ncommands],arg[i]);
ncommands++;
}
}
// perform a single run
// use start/stop to set begin/end step
// if pre or 1st run, do System init/setup,
// else just init timer and setup output
// if post, do full Finish, else just print time
update->whichflag = 1;
if (nevery == 0) {
update->nsteps = nsteps;
update->firststep = update->ntimestep;
update->laststep = update->ntimestep + nsteps;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many timesteps");
+ error->all(FLERR,"Too many timesteps");
if (startflag) update->beginstep = start;
else update->beginstep = update->firststep;
if (stopflag) update->endstep = stop;
else update->endstep = update->laststep;
if (preflag || update->first_update == 0) {
lmp->init();
update->integrate->setup();
} else {
timer->init();
output->setup(0);
}
timer->barrier_start(TIME_LOOP);
update->integrate->run(nsteps);
timer->barrier_stop(TIME_LOOP);
update->integrate->cleanup();
Finish finish(lmp);
finish.end(postflag);
// perform multiple runs optionally interleaved with invocation command(s)
// use start/stop to set begin/end step
// if pre or 1st iteration of multiple runs, do System init/setup,
// else just init timer and setup output
// if post or last iteration, do full Finish, else just print time
} else {
int iter = 0;
int nleft = nsteps;
while (nleft > 0 || iter == 0) {
nsteps = MIN(nleft,nevery);
update->nsteps = nsteps;
update->firststep = update->ntimestep;
update->laststep = update->ntimestep + nsteps;
if (update->laststep < 0 || update->laststep > MAXBIGINT)
- error->all("Too many timesteps");
+ error->all(FLERR,"Too many timesteps");
if (startflag) update->beginstep = start;
else update->beginstep = update->firststep;
if (stopflag) update->endstep = stop;
else update->endstep = update->laststep;
if (preflag || iter == 0) {
lmp->init();
update->integrate->setup();
} else {
timer->init();
output->setup(0);
}
timer->barrier_start(TIME_LOOP);
update->integrate->run(nsteps);
timer->barrier_stop(TIME_LOOP);
update->integrate->cleanup();
Finish finish(lmp);
if (postflag || nleft <= nsteps) finish.end(1);
else finish.end(0);
// wrap command invocation with clearstep/addstep
// since a command may invoke computes via variables
if (ncommands) {
modify->clearstep_compute();
for (int i = 0; i < ncommands; i++) input->one(commands[i]);
modify->addstep_compute(update->ntimestep + nevery);
}
nleft -= nsteps;
iter++;
}
}
update->whichflag = 0;
update->firststep = update->laststep = 0;
update->beginstep = update->endstep = 0;
if (commands) {
for (int i = 0; i < ncommands; i++) delete [] commands[i];
delete [] commands;
}
}
diff --git a/src/set.cpp b/src/set.cpp
index a541fcca9..be3cd5867 100644
--- a/src/set.cpp
+++ b/src/set.cpp
@@ -1,684 +1,684 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "set.h"
#include "atom.h"
#include "atom_vec.h"
#include "atom_vec_ellipsoid.h"
#include "domain.h"
#include "region.h"
#include "group.h"
#include "comm.h"
#include "neighbor.h"
#include "force.h"
#include "pair.h"
#include "random_park.h"
#include "math_extra.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{ATOM_SELECT,MOL_SELECT,TYPE_SELECT,GROUP_SELECT,REGION_SELECT};
enum{TYPE,TYPE_FRACTION,MOLECULE,X,Y,Z,CHARGE,MASS,SHAPE,
DIPOLE,DIPOLE_RANDOM,QUAT,QUAT_RANDOM,
DIAMETER,DENSITY,VOLUME,IMAGE,BOND,ANGLE,DIHEDRAL,IMPROPER,
MESO_E,MESO_CV,MESO_RHO};
#define BIG INT_MAX
/* ---------------------------------------------------------------------- */
Set::Set(LAMMPS *lmp) : Pointers(lmp)
{
PI = 4.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
void Set::command(int narg, char **arg)
{
if (domain->box_exist == 0)
- error->all("Set command before simulation box is defined");
+ error->all(FLERR,"Set command before simulation box is defined");
if (atom->natoms == 0)
- error->all("Set command with no atoms existing");
- if (narg < 3) error->all("Illegal set command");
+ error->all(FLERR,"Set command with no atoms existing");
+ if (narg < 3) error->all(FLERR,"Illegal set command");
// style and ID info
if (strcmp(arg[0],"atom") == 0) style = ATOM_SELECT;
else if (strcmp(arg[0],"mol") == 0) style = MOL_SELECT;
else if (strcmp(arg[0],"type") == 0) style = TYPE_SELECT;
else if (strcmp(arg[0],"group") == 0) style = GROUP_SELECT;
else if (strcmp(arg[0],"region") == 0) style = REGION_SELECT;
- else error->all("Illegal set command");
+ else error->all(FLERR,"Illegal set command");
int n = strlen(arg[1]) + 1;
id = new char[n];
strcpy(id,arg[1]);
select = NULL;
// loop over keyword/value pairs
// call appropriate routine to reset attributes
if (comm->me == 0 && screen) fprintf(screen,"Setting atom values ...\n");
int allcount,origarg;
int iarg = 2;
while (iarg < narg) {
count = 0;
origarg = iarg;
if (strcmp(arg[iarg],"type") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
if (ivalue <= 0 || ivalue > atom->ntypes)
- error->all("Invalid value in set command");
+ error->all(FLERR,"Invalid value in set command");
set(TYPE);
iarg += 2;
} else if (strcmp(arg[iarg],"type/fraction") == 0) {
- if (iarg+4 > narg) error->all("Illegal set command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal set command");
newtype = atoi(arg[iarg+1]);
fraction = atof(arg[iarg+2]);
ivalue = atoi(arg[iarg+3]);
if (newtype <= 0 || newtype > atom->ntypes)
- error->all("Invalid value in set command");
+ error->all(FLERR,"Invalid value in set command");
if (fraction < 0.0 || fraction > 1.0)
- error->all("Invalid value in set command");
- if (ivalue <= 0) error->all("Invalid random number seed in set command");
+ error->all(FLERR,"Invalid value in set command");
+ if (ivalue <= 0) error->all(FLERR,"Invalid random number seed in set command");
setrandom(TYPE_FRACTION);
iarg += 4;
} else if (strcmp(arg[iarg],"mol") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
if (!atom->molecule_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(MOLECULE);
iarg += 2;
} else if (strcmp(arg[iarg],"x") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
set(X);
iarg += 2;
} else if (strcmp(arg[iarg],"y") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
set(Y);
iarg += 2;
} else if (strcmp(arg[iarg],"z") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
set(Z);
iarg += 2;
} else if (strcmp(arg[iarg],"charge") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->q_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(CHARGE);
iarg += 2;
} else if (strcmp(arg[iarg],"mass") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->rmass_flag)
- error->all("Cannot set this attribute for this atom style");
- if (dvalue <= 0.0) error->all("Invalid mass in set command");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
+ if (dvalue <= 0.0) error->all(FLERR,"Invalid mass in set command");
set(MASS);
iarg += 2;
} else if (strcmp(arg[iarg],"shape") == 0) {
- if (iarg+4 > narg) error->all("Illegal set command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal set command");
xvalue = atof(arg[iarg+1]);
yvalue = atof(arg[iarg+2]);
zvalue = atof(arg[iarg+3]);
if (!atom->ellipsoid_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
if (xvalue < 0.0 || yvalue < 0.0 || zvalue < 0.0)
- error->all("Invalid shape in set command");
+ error->all(FLERR,"Invalid shape in set command");
if (xvalue > 0.0 || yvalue > 0.0 || zvalue > 0.0) {
if (xvalue == 0.0 || yvalue == 0.0 || zvalue == 0.0)
- error->one("Invalid shape in set command");
+ error->one(FLERR,"Invalid shape in set command");
}
set(SHAPE);
iarg += 4;
} else if (strcmp(arg[iarg],"dipole") == 0) {
- if (iarg+4 > narg) error->all("Illegal set command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal set command");
xvalue = atof(arg[iarg+1]);
yvalue = atof(arg[iarg+2]);
zvalue = atof(arg[iarg+3]);
if (!atom->mu_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(DIPOLE);
iarg += 4;
} else if (strcmp(arg[iarg],"dipole/random") == 0) {
- if (iarg+3 > narg) error->all("Illegal set command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
dvalue = atof(arg[iarg+2]);
if (!atom->mu_flag)
- error->all("Cannot set this attribute for this atom style");
- if (ivalue <= 0) error->all("Invalid random number seed in set command");
- if (dvalue <= 0.0) error->all("Invalid dipole length in set command");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
+ if (ivalue <= 0) error->all(FLERR,"Invalid random number seed in set command");
+ if (dvalue <= 0.0) error->all(FLERR,"Invalid dipole length in set command");
setrandom(DIPOLE_RANDOM);
iarg += 3;
} else if (strcmp(arg[iarg],"quat") == 0) {
- if (iarg+5 > narg) error->all("Illegal set command");
+ if (iarg+5 > narg) error->all(FLERR,"Illegal set command");
xvalue = atof(arg[iarg+1]);
yvalue = atof(arg[iarg+2]);
zvalue = atof(arg[iarg+3]);
wvalue = atof(arg[iarg+4]);
if (!atom->ellipsoid_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(QUAT);
iarg += 5;
} else if (strcmp(arg[iarg],"quat/random") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
if (!atom->ellipsoid_flag)
- error->all("Cannot set this attribute for this atom style");
- if (ivalue <= 0) error->all("Invalid random number seed in set command");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
+ if (ivalue <= 0) error->all(FLERR,"Invalid random number seed in set command");
setrandom(QUAT_RANDOM);
iarg += 2;
} else if (strcmp(arg[iarg],"diameter") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->radius_flag)
- error->all("Cannot set this attribute for this atom style");
- if (dvalue < 0.0) error->all("Invalid diameter in set command");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
+ if (dvalue < 0.0) error->all(FLERR,"Invalid diameter in set command");
set(DIAMETER);
iarg += 2;
} else if (strcmp(arg[iarg],"density") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->rmass_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(DENSITY);
iarg += 2;
} else if (strcmp(arg[iarg],"volume") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->vfrac_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(VOLUME);
iarg += 2;
} else if (strcmp(arg[iarg],"image") == 0) {
- if (iarg+4 > narg) error->all("Illegal set command");
+ if (iarg+4 > narg) error->all(FLERR,"Illegal set command");
ximageflag = yimageflag = zimageflag = 0;
if (strcmp(arg[iarg+1],"NULL") != 0) {
ximageflag = 1;
ximage = atoi(arg[iarg+1]);
}
if (strcmp(arg[iarg+2],"NULL") != 0) {
yimageflag = 1;
yimage = atoi(arg[iarg+2]);
}
if (strcmp(arg[iarg+3],"NULL") != 0) {
zimageflag = 1;
zimage = atoi(arg[iarg+3]);
}
if (ximageflag && ximage && !domain->xperiodic)
- error->all("Cannot set non-zero image flag for non-periodic dimension");
+ error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension");
if (yimageflag && yimage && !domain->yperiodic)
- error->all("Cannot set non-zero image flag for non-periodic dimension");
+ error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension");
if (zimageflag && zimage && !domain->zperiodic)
- error->all("Cannot set non-zero image flag for non-periodic dimension");
+ error->all(FLERR,"Cannot set non-zero image flag for non-periodic dimension");
set(IMAGE);
iarg += 4;
} else if (strcmp(arg[iarg],"bond") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
if (atom->avec->bonds_allow == 0)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
if (ivalue <= 0 || ivalue > atom->nbondtypes)
- error->all("Invalid value in set command");
+ error->all(FLERR,"Invalid value in set command");
topology(BOND);
iarg += 2;
} else if (strcmp(arg[iarg],"angle") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
if (atom->avec->angles_allow == 0)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
if (ivalue <= 0 || ivalue > atom->nangletypes)
- error->all("Invalid value in set command");
+ error->all(FLERR,"Invalid value in set command");
topology(ANGLE);
iarg += 2;
} else if (strcmp(arg[iarg],"dihedral") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
if (atom->avec->dihedrals_allow == 0)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
if (ivalue <= 0 || ivalue > atom->ndihedraltypes)
- error->all("Invalid value in set command");
+ error->all(FLERR,"Invalid value in set command");
topology(DIHEDRAL);
iarg += 2;
} else if (strcmp(arg[iarg],"improper") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
ivalue = atoi(arg[iarg+1]);
if (atom->avec->impropers_allow == 0)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
if (ivalue <= 0 || ivalue > atom->nimpropertypes)
- error->all("Invalid value in set command");
+ error->all(FLERR,"Invalid value in set command");
topology(IMPROPER);
iarg += 2;
} else if (strcmp(arg[iarg],"meso_e") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->e_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(MESO_E);
iarg += 2;
} else if (strcmp(arg[iarg],"meso_cv") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->cv_flag)
- error->all("Cannot set this attribute for this atom style");
+ error->all(FLERR,"Cannot set this attribute for this atom style");
set(MESO_CV);
iarg += 2;
} else if (strcmp(arg[iarg],"meso_rho") == 0) {
- if (iarg+2 > narg) error->all("Illegal set command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal set command");
dvalue = atof(arg[iarg+1]);
if (!atom->rho_flag)
- error->all("Cannot set meso_rho for this atom style");
+ error->all(FLERR,"Cannot set meso_rho for this atom style");
set(MESO_RHO);
iarg += 2;
- } else error->all("Illegal set command");
+ } else error->all(FLERR,"Illegal set command");
// statistics
MPI_Allreduce(&count,&allcount,1,MPI_INT,MPI_SUM,world);
if (comm->me == 0) {
if (screen) fprintf(screen," %d settings made for %s\n",
allcount,arg[origarg]);
if (logfile) fprintf(logfile," %d settings made for %s\n",
allcount,arg[origarg]);
}
}
// free local memory
delete [] id;
delete [] select;
}
/* ----------------------------------------------------------------------
select atoms according to ATOM, MOLECULE, TYPE, GROUP, REGION style
n = nlocal or nlocal+nghost depending on keyword
------------------------------------------------------------------------- */
void Set::selection(int n)
{
delete [] select;
select = new int[n];
int nlo,nhi;
if (style == ATOM_SELECT) {
if (atom->tag_enable == 0)
- error->all("Cannot use set atom with no atom IDs defined");
+ error->all(FLERR,"Cannot use set atom with no atom IDs defined");
force->bounds(id,BIG,nlo,nhi);
int *tag = atom->tag;
for (int i = 0; i < n; i++)
if (tag[i] >= nlo && tag[i] <= nhi) select[i] = 1;
else select[i] = 0;
} else if (style == MOL_SELECT) {
if (atom->molecule_flag == 0)
- error->all("Cannot use set mol with no molecule IDs defined");
+ error->all(FLERR,"Cannot use set mol with no molecule IDs defined");
if (strcmp(id,"0") == 0) nlo = nhi = 0;
else force->bounds(id,BIG,nlo,nhi);
int *molecule = atom->molecule;
for (int i = 0; i < n; i++)
if (molecule[i] >= nlo && molecule[i] <= nhi) select[i] = 1;
else select[i] = 0;
} else if (style == TYPE_SELECT) {
force->bounds(id,atom->ntypes,nlo,nhi);
int *type = atom->type;
for (int i = 0; i < n; i++)
if (type[i] >= nlo && type[i] <= nhi) select[i] = 1;
else select[i] = 0;
} else if (style == GROUP_SELECT) {
int igroup = group->find(id);
- if (igroup == -1) error->all("Could not find set group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find set group ID");
int groupbit = group->bitmask[igroup];
int *mask = atom->mask;
for (int i = 0; i < n; i++)
if (mask[i] & groupbit) select[i] = 1;
else select[i] = 0;
} else if (style == REGION_SELECT) {
int iregion = domain->find_region(id);
- if (iregion == -1) error->all("Set region ID does not exist");
+ if (iregion == -1) error->all(FLERR,"Set region ID does not exist");
double **x = atom->x;
for (int i = 0; i < n; i++)
if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
select[i] = 1;
else select[i] = 0;
}
}
/* ----------------------------------------------------------------------
set an owned atom property directly
------------------------------------------------------------------------- */
void Set::set(int keyword)
{
AtomVecEllipsoid *avec_ellipsoid =
(AtomVecEllipsoid *) atom->style_match("ellipsoid");
selection(atom->nlocal);
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++) {
if (!select[i]) continue;
if (keyword == TYPE) atom->type[i] = ivalue;
else if (keyword == MOLECULE) atom->molecule[i] = ivalue;
else if (keyword == X) atom->x[i][0] = dvalue;
else if (keyword == Y) atom->x[i][1] = dvalue;
else if (keyword == Z) atom->x[i][2] = dvalue;
else if (keyword == CHARGE) atom->q[i] = dvalue;
else if (keyword == MASS) atom->rmass[i] = dvalue;
else if (keyword == DIAMETER) atom->radius[i] = 0.5 * dvalue;
else if (keyword == VOLUME) atom->vfrac[i] = dvalue;
else if (keyword == MESO_E) atom->e[i] = dvalue;
else if (keyword == MESO_CV) atom->cv[i] = dvalue;
else if (keyword == MESO_RHO) atom->rho[i] = dvalue;
// set shape
else if (keyword == SHAPE)
avec_ellipsoid->set_shape(i,0.5*xvalue,0.5*yvalue,0.5*zvalue);
// set rmass via density
// if radius > 0.0, treat as sphere
// if shape > 0.0, treat as ellipsoid
// else set rmass to density directly
else if (keyword == DENSITY) {
if (atom->radius_flag && atom->radius[i] > 0.0)
atom->rmass[i] = 4.0*PI/3.0 *
atom->radius[i]*atom->radius[i]*atom->radius[i] * dvalue;
else if (atom->ellipsoid_flag && atom->ellipsoid[i] >= 0) {
double *shape = avec_ellipsoid->bonus[atom->ellipsoid[i]].shape;
atom->rmass[i] = 4.0*PI/3.0 * shape[0]*shape[1]*shape[2] * dvalue;
} else atom->rmass[i] = dvalue;
// reset any or all of 3 image flags
} else if (keyword == IMAGE) {
int xbox = (atom->image[i] & 1023) - 512;
int ybox = (atom->image[i] >> 10 & 1023) - 512;
int zbox = (atom->image[i] >> 20) - 512;
if (ximageflag) xbox = ximage;
if (yimageflag) ybox = yimage;
if (zimageflag) zbox = zimage;
atom->image[i] = ((zbox + 512 & 1023) << 20) |
((ybox + 512 & 1023) << 10) | (xbox + 512 & 1023);
// set dipole moment
} else if (keyword == DIPOLE) {
double **mu = atom->mu;
mu[i][0] = xvalue;
mu[i][1] = yvalue;
mu[i][2] = zvalue;
mu[i][3] = sqrt(mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] +
mu[i][2]*mu[i][2]);
// set quaternion orientation
} else if (keyword == QUAT) {
if (atom->ellipsoid[i] < 0)
- error->one("Cannot set quaternion for atom that is not an ellipsoid");
+ error->one(FLERR,"Cannot set quaternion for atom that is not an ellipsoid");
double *quat = avec_ellipsoid->bonus[atom->ellipsoid[i]].quat;
double theta2 = 0.5 * PI * wvalue/180.0;
double sintheta2 = sin(theta2);
quat[0] = cos(theta2);
quat[1] = xvalue * sintheta2;
quat[2] = yvalue * sintheta2;
quat[3] = zvalue * sintheta2;
MathExtra::qnormalize(quat);
}
count++;
}
}
/* ----------------------------------------------------------------------
set an owned atom property randomly
set seed based on atom tag
make atom result independent of what proc owns it
------------------------------------------------------------------------- */
void Set::setrandom(int keyword)
{
int i;
selection(atom->nlocal);
RanPark *random = new RanPark(lmp,1);
double **x = atom->x;
int seed = ivalue;
// set fraction of atom types to newtype
if (keyword == TYPE_FRACTION) {
int nlocal = atom->nlocal;
for (i = 0; i < nlocal; i++)
if (select[i]) {
random->reset(seed,x[i]);
if (random->uniform() > fraction) continue;
atom->type[i] = newtype;
count++;
}
// set dipole moments to random orientations in 3d or 2d
// dipole length is determined by dipole type array
} else if (keyword == DIPOLE_RANDOM) {
double **mu = atom->mu;
int nlocal = atom->nlocal;
double msq,scale;
if (domain->dimension == 3) {
for (i = 0; i < nlocal; i++)
if (select[i]) {
random->reset(seed,x[i]);
mu[i][0] = random->uniform() - 0.5;
mu[i][1] = random->uniform() - 0.5;
mu[i][2] = random->uniform() - 0.5;
msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1] + mu[i][2]*mu[i][2];
scale = dvalue/sqrt(msq);
mu[i][0] *= scale;
mu[i][1] *= scale;
mu[i][2] *= scale;
mu[i][3] = dvalue;
count++;
}
} else {
for (i = 0; i < nlocal; i++)
if (select[i]) {
random->reset(seed,x[i]);
mu[i][0] = random->uniform() - 0.5;
mu[i][1] = random->uniform() - 0.5;
mu[i][2] = 0.0;
msq = mu[i][0]*mu[i][0] + mu[i][1]*mu[i][1];
scale = dvalue/sqrt(msq);
mu[i][0] *= scale;
mu[i][1] *= scale;
mu[i][3] = dvalue;
count++;
}
}
// set quaternions to random orientations in 3d or 2d
// no need to normalize quats since creations algorithms already do
} else if (keyword == QUAT_RANDOM) {
AtomVecEllipsoid *avec_ellipsoid =
(AtomVecEllipsoid *) atom->style_match("ellipsoid");
AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus;
int *ellipsoid = atom->ellipsoid;
int nlocal = atom->nlocal;
double *quat;
if (domain->dimension == 3) {
double s,t1,t2,theta1,theta2;
for (i = 0; i < nlocal; i++)
if (select[i]) {
if (ellipsoid[i] < 0)
- error->one("Cannot set quaternion for atom "
+ error->one(FLERR,"Cannot set quaternion for atom "
"that is not an ellipsoid");
quat = bonus[ellipsoid[i]].quat;
random->reset(seed,x[i]);
s = random->uniform();
t1 = sqrt(1.0-s);
t2 = sqrt(s);
theta1 = 2.0*PI*random->uniform();
theta2 = 2.0*PI*random->uniform();
quat[0] = cos(theta2)*t2;
quat[1] = sin(theta1)*t1;
quat[2] = cos(theta1)*t1;
quat[3] = sin(theta2)*t2;
count++;
}
} else {
double theta2;
for (i = 0; i < nlocal; i++)
if (select[i]) {
if (ellipsoid[i] < 0)
- error->one("Cannot set quaternion for atom "
+ error->one(FLERR,"Cannot set quaternion for atom "
"that is not an ellipsoid");
quat = bonus[ellipsoid[i]].quat;
random->reset(seed,x[i]);
theta2 = PI*random->uniform();
quat[0] = cos(theta2);
quat[1] = 0.0;
quat[2] = 0.0;
quat[3] = sin(theta2);
count++;
}
}
}
delete random;
}
/* ---------------------------------------------------------------------- */
void Set::topology(int keyword)
{
int m,atom1,atom2,atom3,atom4;
// border swap to acquire ghost atom info
// enforce PBC before in case atoms are outside box
// init entire system since comm->exchange is done
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc
if (comm->me == 0 && screen) fprintf(screen," system init for set ...\n");
lmp->init();
if (domain->triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
comm->exchange();
comm->borders();
if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
// select both owned and ghost atoms
selection(atom->nlocal + atom->nghost);
// for BOND, each of 2 atoms must be in group
if (keyword == BOND) {
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_bond[i]; m++) {
atom1 = atom->map(atom->bond_atom[i][m]);
- if (atom1 == -1) error->one("Bond atom missing in set command");
+ if (atom1 == -1) error->one(FLERR,"Bond atom missing in set command");
if (select[i] && select[atom1]) {
atom->bond_type[i][m] = ivalue;
count++;
}
}
}
// for ANGLE, each of 3 atoms must be in group
if (keyword == ANGLE) {
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_angle[i]; m++) {
atom1 = atom->map(atom->angle_atom1[i][m]);
atom2 = atom->map(atom->angle_atom2[i][m]);
atom3 = atom->map(atom->angle_atom3[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1)
- error->one("Angle atom missing in set command");
+ error->one(FLERR,"Angle atom missing in set command");
if (select[atom1] && select[atom2] && select[atom3]) {
atom->angle_type[i][m] = ivalue;
count++;
}
}
}
// for DIHEDRAL, each of 4 atoms must be in group
if (keyword == DIHEDRAL) {
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_dihedral[i]; m++) {
atom1 = atom->map(atom->dihedral_atom1[i][m]);
atom2 = atom->map(atom->dihedral_atom2[i][m]);
atom3 = atom->map(atom->dihedral_atom3[i][m]);
atom4 = atom->map(atom->dihedral_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1)
- error->one("Dihedral atom missing in set command");
+ error->one(FLERR,"Dihedral atom missing in set command");
if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) {
atom->dihedral_type[i][m] = ivalue;
count++;
}
}
}
// for IMPROPER, each of 4 atoms must be in group
if (keyword == IMPROPER) {
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
for (m = 0; m < atom->num_improper[i]; m++) {
atom1 = atom->map(atom->improper_atom1[i][m]);
atom2 = atom->map(atom->improper_atom2[i][m]);
atom3 = atom->map(atom->improper_atom3[i][m]);
atom4 = atom->map(atom->improper_atom4[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 || atom4 == -1)
- error->one("Improper atom missing in set command");
+ error->one(FLERR,"Improper atom missing in set command");
if (select[atom1] && select[atom2] && select[atom3] && select[atom4]) {
atom->improper_type[i][m] = ivalue;
count++;
}
}
}
}
diff --git a/src/special.cpp b/src/special.cpp
index e0ec4ce31..189b2374f 100644
--- a/src/special.cpp
+++ b/src/special.cpp
@@ -1,1029 +1,1026 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "mpi.h"
#include "stdio.h"
#include "special.h"
#include "atom.h"
#include "atom_vec.h"
#include "force.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
Special::Special(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
onetwo = onethree = onefour = NULL;
}
/* ---------------------------------------------------------------------- */
Special::~Special()
{
memory->destroy(onetwo);
memory->destroy(onethree);
memory->destroy(onefour);
}
/* ----------------------------------------------------------------------
create 1-2, 1-3, 1-4 lists of topology neighbors
store in onetwo, onethree, onefour for each atom
store 3 counters in nspecial[i]
------------------------------------------------------------------------- */
void Special::build()
{
int i,j,k,m,n,loop,size,original;
int num12,num13,num14;
int max,maxall,messtag,nbuf,nbufmax;
int *buf,*bufcopy,*count;
MPI_Request request;
MPI_Status status;
MPI_Barrier(world);
int nlocal = atom->nlocal;
int *tag = atom->tag;
int *num_bond = atom->num_bond;
int **bond_atom = atom->bond_atom;
int **nspecial = atom->nspecial;
if (me == 0 && screen) fprintf(screen,"Finding 1-2 1-3 1-4 neighbors ...\n");
// setup ring of procs
int next = me + 1;
int prev = me -1;
if (next == nprocs) next = 0;
if (prev < 0) prev = nprocs - 1;
// initialize nspecial counters to 0
for (i = 0; i < nlocal; i++) {
nspecial[i][0] = 0;
nspecial[i][1] = 0;
nspecial[i][2] = 0;
}
// -----------------------------------------------------
// compute nspecial[i][0] = # of 1-2 neighbors of atom i
// -----------------------------------------------------
// bond partners stored by atom itself
for (i = 0; i < nlocal; i++) nspecial[i][0] = num_bond[i];
// if newton_bond off, then done
// else only counted 1/2 of all bonds, so count other half
if (force->newton_bond) {
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = global tag of 2nd atom in each bond
nbuf = 0;
for (i = 0; i < nlocal; i++) nbuf += num_bond[i];
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with global tags of bond partners of my atoms
size = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < num_bond[i]; j++)
buf[size++] = bond_atom[i][j];
// cycle buffer around ring of procs back to self
// when receive buffer, scan tags for atoms I own
// when find one, increment nspecial count for that atom
messtag = 1;
for (loop = 0; loop < nprocs; loop++) {
for (i = 0; i < size; i++) {
m = atom->map(buf[i]);
if (m >= 0 && m < nlocal) nspecial[m][0]++;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
delete [] buf;
delete [] bufcopy;
}
// ----------------------------------------------------
// create onetwo[i] = list of 1-2 neighbors for atom i
// ----------------------------------------------------
max = 0;
for (i = 0; i < nlocal; i++) max = MAX(max,nspecial[i][0]);
MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
if (me == 0) {
if (screen) fprintf(screen," %d = max # of 1-2 neighbors\n",maxall);
if (logfile) fprintf(logfile," %d = max # of 1-2 neighbors\n",maxall);
}
memory->create(onetwo,nlocal,maxall,"special:onetwo");
// count = accumulating counter
count = new int[nlocal];
for (i = 0; i < nlocal; i++) count[i] = 0;
// add bond partners stored by atom to onetwo list
for (i = 0; i < nlocal; i++)
for (j = 0; j < num_bond[i]; j++)
onetwo[i][count[i]++] = bond_atom[i][j];
// if newton_bond off, then done
// else only stored 1/2 of all bonds, so store other half
if (force->newton_bond) {
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = 2 global tags in each bond
nbuf = 0;
for (i = 0; i < nlocal; i++) nbuf += 2*num_bond[i];
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with global tags of both atoms in bond
size = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < num_bond[i]; j++) {
buf[size++] = tag[i];
buf[size++] = bond_atom[i][j];
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan 2nd-atom tags for atoms I own
// when find one, add 1st-atom tag to onetwo list for 2nd atom
messtag = 2;
for (loop = 0; loop < nprocs; loop++) {
for (i = 1; i < size; i += 2) {
m = atom->map(buf[i]);
if (m >= 0 && m < nlocal) onetwo[m][count[m]++] = buf[i-1];
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
delete [] buf;
delete [] bufcopy;
}
delete [] count;
// -----------------------------------------------------
// done if special_bonds for 1-3, 1-4 are set to 1.0
// -----------------------------------------------------
if (force->special_lj[2] == 1.0 && force->special_coul[2] == 1.0 &&
force->special_lj[3] == 1.0 && force->special_coul[3] == 1.0) {
combine();
return;
}
// -----------------------------------------------------
// compute nspecial[i][1] = # of 1-3 neighbors of atom i
// -----------------------------------------------------
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = 2 scalars + list of 1-2 neighbors
nbuf = 0;
for (i = 0; i < nlocal; i++) nbuf += 2 + nspecial[i][0];
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with:
// (1) = counter for 1-3 neighbors, initialized to 0
// (2) = # of 1-2 neighbors
// (3:N) = list of 1-2 neighbors
size = 0;
for (i = 0; i < nlocal; i++) {
buf[size++] = 0;
buf[size++] = nspecial[i][0];
for (j = 0; j < nspecial[i][0]; j++) buf[size++] = onetwo[i][j];
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan list of 1-2 neighbors for atoms I own
// when find one, increment 1-3 count by # of 1-2 neighbors of my atom,
// subtracting one since my list will contain original atom
messtag = 3;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
n = buf[i];
num12 = buf[i+1];
for (j = 0; j < num12; j++) {
m = atom->map(buf[i+2+j]);
if (m >= 0 && m < nlocal) n += nspecial[m][0] - 1;
}
buf[i] = n;
i += 2 + num12;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// extract count from buffer that has cycled back to me
// nspecial[i][1] = # of 1-3 neighbors of atom i
j = 0;
for (i = 0; i < nlocal; i++) {
nspecial[i][1] = buf[j];
j += 2 + nspecial[i][0];
}
delete [] buf;
delete [] bufcopy;
// ----------------------------------------------------
// create onethree[i] = list of 1-3 neighbors for atom i
// ----------------------------------------------------
max = 0;
for (i = 0; i < nlocal; i++) max = MAX(max,nspecial[i][1]);
MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
if (me == 0) {
if (screen) fprintf(screen," %d = max # of 1-3 neighbors\n",maxall);
if (logfile) fprintf(logfile," %d = max # of 1-3 neighbors\n",maxall);
}
memory->create(onethree,nlocal,maxall,"special:onethree");
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = 4 scalars + list of 1-2 neighs + list of 1-3 neighs
nbuf = 0;
for (i = 0; i < nlocal; i++) nbuf += 4 + nspecial[i][0] + nspecial[i][1];
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with:
// (1) = global tag of original atom
// (2) = # of 1-2 neighbors
// (3) = # of 1-3 neighbors
// (4) = counter for 1-3 neighbors, initialized to 0
// (5:N) = list of 1-2 neighbors
// (N+1:2N) space for list of 1-3 neighbors
size = 0;
for (i = 0; i < nlocal; i++) {
buf[size++] = tag[i];
buf[size++] = nspecial[i][0];
buf[size++] = nspecial[i][1];
buf[size++] = 0;
for (j = 0; j < nspecial[i][0]; j++) buf[size++] = onetwo[i][j];
size += nspecial[i][1];
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan list of 1-2 neighbors for atoms I own
// when find one, add its neighbors to 1-3 list
// increment the count in buf(i+4)
// exclude the atom whose tag = original
// this process may include duplicates but they will be culled later
messtag = 4;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
original = buf[i];
num12 = buf[i+1];
num13 = buf[i+2];
n = buf[i+3];
for (j = 0; j < num12; j++) {
m = atom->map(buf[i+4+j]);
if (m >= 0 && m < nlocal)
for (k = 0; k < nspecial[m][0]; k++)
if (onetwo[m][k] != original)
buf[i+4+num12+(n++)] = onetwo[m][k];
}
buf[i+3] = n;
i += 4 + num12 + num13;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// fill onethree with buffer values that have been returned to me
// sanity check: accumulated buf[i+3] count should equal
// nspecial[i][1] for each atom
j = 0;
for (i = 0; i < nlocal; i++) {
if (buf[j+3] != nspecial[i][1])
- error->one("1-3 bond count is inconsistent");
+ error->one(FLERR,"1-3 bond count is inconsistent");
j += 4 + nspecial[i][0];
for (k = 0; k < nspecial[i][1]; k++)
onethree[i][k] = buf[j++];
}
delete [] buf;
delete [] bufcopy;
// done if special_bonds for 1-4 are set to 1.0
if (force->special_lj[3] == 1.0 && force->special_coul[3] == 1.0) {
combine();
if (force->special_angle) angle_trim();
return;
}
// -----------------------------------------------------
// compute nspecial[i][2] = # of 1-4 neighbors of atom i
// -----------------------------------------------------
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = 2 scalars + list of 1-3 neighbors
nbuf = 0;
for (i = 0; i < nlocal; i++) nbuf += 2 + nspecial[i][1];
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with:
// (1) = counter for 1-4 neighbors, initialized to 0
// (2) = # of 1-3 neighbors
// (3:N) = list of 1-3 neighbors
size = 0;
for (i = 0; i < nlocal; i++) {
buf[size++] = 0;
buf[size++] = nspecial[i][1];
for (j = 0; j < nspecial[i][1]; j++) buf[size++] = onethree[i][j];
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan list of 1-3 neighbors for atoms I own
// when find one, increment 1-4 count by # of 1-2 neighbors of my atom
// may include duplicates and original atom but they will be culled later
messtag = 5;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
n = buf[i];
num13 = buf[i+1];
for (j = 0; j < num13; j++) {
m = atom->map(buf[i+2+j]);
if (m >= 0 && m < nlocal) n += nspecial[m][0];
}
buf[i] = n;
i += 2 + num13;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// extract count from buffer that has cycled back to me
// nspecial[i][2] = # of 1-4 neighbors of atom i
j = 0;
for (i = 0; i < nlocal; i++) {
nspecial[i][2] = buf[j];
j += 2 + nspecial[i][1];
}
delete [] buf;
delete [] bufcopy;
// ----------------------------------------------------
// create onefour[i] = list of 1-4 neighbors for atom i
// ----------------------------------------------------
max = 0;
for (i = 0; i < nlocal; i++) max = MAX(max,nspecial[i][2]);
MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
if (me == 0) {
if (screen) fprintf(screen," %d = max # of 1-4 neighbors\n",maxall);
if (logfile) fprintf(logfile," %d = max # of 1-4 neighbors\n",maxall);
}
memory->create(onefour,nlocal,maxall,"special:onefour");
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = 3 scalars + list of 1-3 neighs + list of 1-4 neighs
nbuf = 0;
for (i = 0; i < nlocal; i++)
nbuf += 3 + nspecial[i][1] + nspecial[i][2];
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
buf = new int[nbufmax];
bufcopy = new int[nbufmax];
// fill buffer with:
// (1) = # of 1-3 neighbors
// (2) = # of 1-4 neighbors
// (3) = counter for 1-4 neighbors, initialized to 0
// (4:N) = list of 1-3 neighbors
// (N+1:2N) space for list of 1-4 neighbors
size = 0;
for (i = 0; i < nlocal; i++) {
buf[size++] = nspecial[i][1];
buf[size++] = nspecial[i][2];
buf[size++] = 0;
for (j = 0; j < nspecial[i][1]; j++) buf[size++] = onethree[i][j];
size += nspecial[i][2];
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan list of 1-3 neighbors for atoms I own
// when find one, add its neighbors to 1-4 list
// incrementing the count in buf(i+4)
// this process may include duplicates but they will be culled later
messtag = 6;
for (loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
num13 = buf[i];
num14 = buf[i+1];
n = buf[i+2];
for (j = 0; j < num13; j++) {
m = atom->map(buf[i+3+j]);
if (m >= 0 && m < nlocal)
for (k = 0; k < nspecial[m][0]; k++)
buf[i+3+num13+(n++)] = onetwo[m][k];
}
buf[i+2] = n;
i += 3 + num13 + num14;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// fill onefour with buffer values that have been returned to me
// sanity check: accumulated buf[i+2] count should equal
// nspecial[i][2] for each atom
j = 0;
for (i = 0; i < nlocal; i++) {
if (buf[j+2] != nspecial[i][2])
- error->one("1-4 bond count is inconsistent");
+ error->one(FLERR,"1-4 bond count is inconsistent");
j += 3 + nspecial[i][1];
for (k = 0; k < nspecial[i][2]; k++)
onefour[i][k] = buf[j++];
}
delete [] buf;
delete [] bufcopy;
combine();
if (force->special_angle) angle_trim();
if (force->special_dihedral) dihedral_trim();
}
/* ----------------------------------------------------------------------
concatenate onetwo, onethree, onefour into master atom->special list
remove duplicates
convert nspecial[0], nspecial[1], nspecial[2] into cumulative counters
------------------------------------------------------------------------- */
void Special::combine()
{
int i,j,m;
int me;
MPI_Comm_rank(world,&me);
int nlocal = atom->nlocal;
int **nspecial = atom->nspecial;
int *tag = atom->tag;
// ----------------------------------------------------
// compute culled maxspecial = max # of special neighs of any atom
// ----------------------------------------------------
// clear map so it can be used as scratch space
atom->map_clear();
// unique = # of unique nspecial neighbors of one atom
// cull duplicates using map to check for them
// exclude original atom explicitly
// must re-clear map for each atom
int unique;
int maxspecial = 0;
for (i = 0; i < nlocal; i++) {
unique = 0;
atom->map_one(tag[i],0);
for (j = 0; j < nspecial[i][0]; j++) {
m = onetwo[i][j];
if (atom->map(m) < 0) {
unique++;
atom->map_one(m,0);
}
}
for (j = 0; j < nspecial[i][1]; j++) {
m = onethree[i][j];
if (atom->map(m) < 0) {
unique++;
atom->map_one(m,0);
}
}
for (j = 0; j < nspecial[i][2]; j++) {
m = onefour[i][j];
if (atom->map(m) < 0) {
unique++;
atom->map_one(m,0);
}
}
maxspecial = MAX(maxspecial,unique);
atom->map_one(tag[i],-1);
for (j = 0; j < nspecial[i][0]; j++) atom->map_one(onetwo[i][j],-1);
for (j = 0; j < nspecial[i][1]; j++) atom->map_one(onethree[i][j],-1);
for (j = 0; j < nspecial[i][2]; j++) atom->map_one(onefour[i][j],-1);
}
// compute global maxspecial, must be at least 1
// add in extra factor from special_bonds command
// allocate correct special array with same nmax, new maxspecial
// previously allocated one must be destroyed
// must make AtomVec class update its ptr to special
MPI_Allreduce(&maxspecial,&atom->maxspecial,1,MPI_INT,MPI_MAX,world);
atom->maxspecial += force->special_extra;
atom->maxspecial = MAX(atom->maxspecial,1);
if (me == 0) {
if (screen)
fprintf(screen," %d = max # of special neighbors\n",atom->maxspecial);
if (logfile)
fprintf(logfile," %d = max # of special neighbors\n",atom->maxspecial);
}
memory->destroy(atom->special);
memory->create(atom->special,atom->nmax,atom->maxspecial,"atom:special");
atom->avec->grow_reset();
int **special = atom->special;
// ----------------------------------------------------
// fill special array with 1-2, 1-3, 1-4 neighs for each atom
// ----------------------------------------------------
// again use map to cull duplicates
// exclude original atom explicitly
// adjust nspecial[i] values to reflect removed duplicates
// nspecial[i][1] and nspecial[i][2] now become cumulative counters
for (i = 0; i < nlocal; i++) {
unique = 0;
atom->map_one(tag[i],0);
for (j = 0; j < nspecial[i][0]; j++) {
m = onetwo[i][j];
if (atom->map(m) < 0) {
special[i][unique++] = m;
atom->map_one(m,0);
}
}
nspecial[i][0] = unique;
for (j = 0; j < nspecial[i][1]; j++) {
m = onethree[i][j];
if (atom->map(m) < 0) {
special[i][unique++] = m;
atom->map_one(m,0);
}
}
nspecial[i][1] = unique;
for (j = 0; j < nspecial[i][2]; j++) {
m = onefour[i][j];
if (atom->map(m) < 0) {
special[i][unique++] = m;
atom->map_one(m,0);
}
}
nspecial[i][2] = unique;
atom->map_one(tag[i],-1);
for (j = 0; j < nspecial[i][2]; j++) atom->map_one(special[i][j],-1);
}
// re-create map
atom->nghost = 0;
atom->map_set();
}
/* ----------------------------------------------------------------------
trim list of 1-3 neighbors by checking defined angles
delete a 1-3 neigh if they are not end atoms of a defined angle
------------------------------------------------------------------------- */
void Special::angle_trim()
{
int i,j,m,n,iglobal,jglobal,ilocal,jlocal;
MPI_Request request;
MPI_Status status;
int *num_angle = atom->num_angle;
int *num_dihedral = atom->num_dihedral;
int **angle_atom1 = atom->angle_atom1;
int **angle_atom3 = atom->angle_atom3;
int **dihedral_atom1 = atom->dihedral_atom1;
int **dihedral_atom2 = atom->dihedral_atom2;
int **dihedral_atom3 = atom->dihedral_atom3;
int **dihedral_atom4 = atom->dihedral_atom4;
int **nspecial = atom->nspecial;
int **special = atom->special;
int nlocal = atom->nlocal;
// stats on old 1-3 neighbor counts
double onethreecount = 0.0;
for (i = 0; i < nlocal; i++)
onethreecount += nspecial[i][1] - nspecial[i][0];
double allcount;
MPI_Allreduce(&onethreecount,&allcount,1,MPI_DOUBLE,MPI_SUM,world);
if (me == 0) {
if (screen)
fprintf(screen,
" %g = # of 1-3 neighbors before angle trim\n",allcount);
if (logfile)
fprintf(logfile,
" %g = # of 1-3 neighbors before angle trim\n",allcount);
}
// if angles or dihedrals are defined,
// flag each 1-3 neigh if it appears in an angle or dihedral
if ((num_angle && atom->nangles) || (num_dihedral && atom->ndihedrals)) {
// dflag = flag for 1-3 neighs of all owned atoms
int maxcount = 0;
for (i = 0; i < nlocal; i++)
maxcount = MAX(maxcount,nspecial[i][1]-nspecial[i][0]);
int **dflag;
memory->create(dflag,nlocal,maxcount,"special::dflag");
for (i = 0; i < nlocal; i++) {
n = nspecial[i][1] - nspecial[i][0];
for (j = 0; j < n; j++) dflag[i][j] = 0;
}
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = list of 1,3 atoms in each angle stored by atom
// and list of 1,3 and 2,4 atoms in each dihedral stored by atom
int nbuf = 0;
for (i = 0; i < nlocal; i++) nbuf += 2*num_angle[i] + 2*2*num_dihedral[i];
int nbufmax;
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
int *buf = new int[nbufmax];
int *bufcopy = new int[nbufmax];
// fill buffer with list of 1,3 atoms in each angle
// and with list of 1,3 and 2,4 atoms in each dihedral
int size = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < num_angle[i]; j++) {
buf[size++] = angle_atom1[i][j];
buf[size++] = angle_atom3[i][j];
}
for (i = 0; i < nlocal; i++)
for (j = 0; j < num_dihedral[i]; j++) {
buf[size++] = dihedral_atom1[i][j];
buf[size++] = dihedral_atom3[i][j];
buf[size++] = dihedral_atom2[i][j];
buf[size++] = dihedral_atom4[i][j];
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan list of 1,3 atoms looking for atoms I own
// when find one, scan its 1-3 neigh list and mark I,J as in an angle
int next = me + 1;
int prev = me -1;
if (next == nprocs) next = 0;
if (prev < 0) prev = nprocs - 1;
int messtag = 7;
for (int loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
iglobal = buf[i];
jglobal = buf[i+1];
ilocal = atom->map(iglobal);
jlocal = atom->map(jglobal);
if (ilocal >= 0 && ilocal < nlocal)
for (m = nspecial[ilocal][0]; m < nspecial[ilocal][1]; m++)
if (jglobal == special[ilocal][m]) {
dflag[ilocal][m-nspecial[ilocal][0]] = 1;
break;
}
if (jlocal >= 0 && jlocal < nlocal)
for (m = nspecial[jlocal][0]; m < nspecial[jlocal][1]; m++)
if (iglobal == special[jlocal][m]) {
dflag[jlocal][m-nspecial[jlocal][0]] = 1;
break;
}
i += 2;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// delete 1-3 neighbors if they are not flagged in dflag
// preserve 1-4 neighbors
int offset;
for (i = 0; i < nlocal; i++) {
offset = m = nspecial[i][0];
for (j = nspecial[i][0]; j < nspecial[i][1]; j++)
if (dflag[i][j-offset]) special[i][m++] = special[i][j];
offset = m;
for (j = nspecial[i][1]; j < nspecial[i][2]; j++)
special[i][m++] = special[i][j];
nspecial[i][1] = offset;
nspecial[i][2] = m;
}
// clean up
memory->destroy(dflag);
delete [] buf;
delete [] bufcopy;
// if no angles or dihedrals are defined,
// delete all 1-3 neighs, preserving 1-4 neighs
} else {
for (i = 0; i < nlocal; i++) {
m = nspecial[i][0];
for (j = nspecial[i][1]; j < nspecial[i][2]; j++)
special[i][m++] = special[i][j];
nspecial[i][1] = nspecial[i][0];
nspecial[i][2] = m;
}
}
// stats on new 1-3 neighbor counts
onethreecount = 0.0;
for (i = 0; i < nlocal; i++)
onethreecount += nspecial[i][1] - nspecial[i][0];
MPI_Allreduce(&onethreecount,&allcount,1,MPI_DOUBLE,MPI_SUM,world);
if (me == 0) {
if (screen)
fprintf(screen,
" %g = # of 1-3 neighbors after angle trim\n",allcount);
if (logfile)
fprintf(logfile,
" %g = # of 1-3 neighbors after angle trim\n",allcount);
}
}
/* ----------------------------------------------------------------------
trim list of 1-4 neighbors by checking defined dihedrals
delete a 1-4 neigh if they are not end atoms of a defined dihedral
------------------------------------------------------------------------- */
void Special::dihedral_trim()
{
int i,j,m,n,iglobal,jglobal,ilocal,jlocal;
MPI_Request request;
MPI_Status status;
int *num_dihedral = atom->num_dihedral;
int **dihedral_atom1 = atom->dihedral_atom1;
int **dihedral_atom4 = atom->dihedral_atom4;
int **nspecial = atom->nspecial;
int **special = atom->special;
int nlocal = atom->nlocal;
// stats on old 1-4 neighbor counts
double onefourcount = 0.0;
for (i = 0; i < nlocal; i++)
onefourcount += nspecial[i][2] - nspecial[i][1];
double allcount;
MPI_Allreduce(&onefourcount,&allcount,1,MPI_DOUBLE,MPI_SUM,world);
if (me == 0) {
if (screen)
fprintf(screen,
" %g = # of 1-4 neighbors before dihedral trim\n",allcount);
if (logfile)
fprintf(logfile,
" %g = # of 1-4 neighbors before dihedral trim\n",allcount);
}
// if dihedrals are defined, flag each 1-4 neigh if it appears in a dihedral
if (num_dihedral && atom->ndihedrals) {
// dflag = flag for 1-4 neighs of all owned atoms
int maxcount = 0;
for (i = 0; i < nlocal; i++)
maxcount = MAX(maxcount,nspecial[i][2]-nspecial[i][1]);
int **dflag;
memory->create(dflag,nlocal,maxcount,"special::dflag");
for (i = 0; i < nlocal; i++) {
n = nspecial[i][2] - nspecial[i][1];
for (j = 0; j < n; j++) dflag[i][j] = 0;
}
// nbufmax = largest buffer needed to hold info from any proc
// info for each atom = list of 1,4 atoms in each dihedral stored by atom
int nbuf = 0;
for (i = 0; i < nlocal; i++) nbuf += 2*num_dihedral[i];
int nbufmax;
MPI_Allreduce(&nbuf,&nbufmax,1,MPI_INT,MPI_MAX,world);
int *buf = new int[nbufmax];
int *bufcopy = new int[nbufmax];
// fill buffer with list of 1,4 atoms in each dihedral
int size = 0;
for (i = 0; i < nlocal; i++)
for (j = 0; j < num_dihedral[i]; j++) {
buf[size++] = dihedral_atom1[i][j];
buf[size++] = dihedral_atom4[i][j];
}
// cycle buffer around ring of procs back to self
// when receive buffer, scan list of 1,4 atoms looking for atoms I own
// when find one, scan its 1-4 neigh list and mark I,J as in a dihedral
int next = me + 1;
int prev = me -1;
if (next == nprocs) next = 0;
if (prev < 0) prev = nprocs - 1;
int messtag = 7;
for (int loop = 0; loop < nprocs; loop++) {
i = 0;
while (i < size) {
iglobal = buf[i];
jglobal = buf[i+1];
ilocal = atom->map(iglobal);
jlocal = atom->map(jglobal);
if (ilocal >= 0 && ilocal < nlocal)
for (m = nspecial[ilocal][1]; m < nspecial[ilocal][2]; m++)
if (jglobal == special[ilocal][m]) {
dflag[ilocal][m-nspecial[ilocal][1]] = 1;
break;
}
if (jlocal >= 0 && jlocal < nlocal)
for (m = nspecial[jlocal][1]; m < nspecial[jlocal][2]; m++)
if (iglobal == special[jlocal][m]) {
dflag[jlocal][m-nspecial[jlocal][1]] = 1;
break;
}
i += 2;
}
if (me != next) {
MPI_Irecv(bufcopy,nbufmax,MPI_INT,prev,messtag,world,&request);
MPI_Send(buf,size,MPI_INT,next,messtag,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_INT,&size);
for (j = 0; j < size; j++) buf[j] = bufcopy[j];
}
}
// delete 1-4 neighbors if they are not flagged in dflag
int offset;
for (i = 0; i < nlocal; i++) {
offset = m = nspecial[i][1];
for (j = nspecial[i][1]; j < nspecial[i][2]; j++)
if (dflag[i][j-offset]) special[i][m++] = special[i][j];
nspecial[i][2] = m;
}
// clean up
memory->destroy(dflag);
delete [] buf;
delete [] bufcopy;
// if no dihedrals are defined, delete all 1-4 neighs
} else for (i = 0; i < nlocal; i++) nspecial[i][2] = nspecial[i][1];
// stats on new 1-4 neighbor counts
onefourcount = 0.0;
for (i = 0; i < nlocal; i++)
onefourcount += nspecial[i][2] - nspecial[i][1];
MPI_Allreduce(&onefourcount,&allcount,1,MPI_DOUBLE,MPI_SUM,world);
if (me == 0) {
if (screen)
fprintf(screen,
" %g = # of 1-4 neighbors after dihedral trim\n",allcount);
if (logfile)
fprintf(logfile,
" %g = # of 1-4 neighbors after dihedral trim\n",allcount);
}
}
diff --git a/src/thermo.cpp b/src/thermo.cpp
index 1653de8f4..5bd877191 100644
--- a/src/thermo.cpp
+++ b/src/thermo.cpp
@@ -1,1934 +1,1931 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "thermo.h"
#include "atom.h"
#include "update.h"
#include "comm.h"
#include "domain.h"
#include "lattice.h"
#include "modify.h"
#include "fix.h"
#include "compute.h"
#include "input.h"
#include "variable.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "output.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
// customize a new keyword by adding to this list:
// step, elapsed, elaplong, dt, cpu, tpcpu, spcpu
// atoms, temp, press, pe, ke, etotal, enthalpy
// evdwl, ecoul, epair, ebond, eangle, edihed, eimp, emol, elong, etail
// vol, lx, ly, lz, xlo, xhi, ylo, yhi, zlo, zhi, xy, xz, yz, xlat, ylat, zlat
// pxx, pyy, pzz, pxy, pxz, pyz
// fmax, fnorm
// cella, cellb, cellc, cellalpha, cellbeta, cellgamma
// customize a new thermo style by adding a DEFINE to this list
#define ONE "step temp epair emol etotal press"
#define MULTI "etotal ke temp pe ebond eangle edihed eimp evdwl ecoul elong press"
enum{IGNORE,WARN,ERROR}; // same as write_restart.cpp
enum{ONELINE,MULTILINE};
enum{INT,FLOAT,BIGINT};
enum{SCALAR,VECTOR,ARRAY};
#define INVOKED_SCALAR 1
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
#define MAXLINE 8192 // make this 4x longer than Input::MAXLINE
#define DELTA 8
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
/* ---------------------------------------------------------------------- */
Thermo::Thermo(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
int n = strlen(arg[0]) + 1;
style = new char[n];
strcpy(style,arg[0]);
// set thermo_modify defaults
modified = 0;
normuserflag = 0;
lineflag = ONELINE;
lostflag = ERROR;
lostbefore = 0;
flushflag = 0;
// set style and corresponding lineflag
// custom style builds its own line of keywords
// customize a new thermo style by adding to if statement
line = new char[MAXLINE];
if (strcmp(style,"one") == 0) {
strcpy(line,ONE);
} else if (strcmp(style,"multi") == 0) {
strcpy(line,MULTI);
lineflag = MULTILINE;
} else if (strcmp(style,"custom") == 0) {
- if (narg == 1) error->all("Illegal thermo style custom command");
+ if (narg == 1) error->all(FLERR,"Illegal thermo style custom command");
line[0] = '\0';
for (int iarg = 1; iarg < narg; iarg++) {
strcat(line,arg[iarg]);
strcat(line," ");
}
line[strlen(line)-1] = '\0';
- } else error->all("Illegal thermo style command");
+ } else error->all(FLERR,"Illegal thermo style command");
// ptrs, flags, IDs for compute objects thermo may use or create
temperature = NULL;
pressure = NULL;
pe = NULL;
index_temp = index_press_scalar = index_press_vector = index_pe = -1;
id_temp = (char *) "thermo_temp";
id_press = (char *) "thermo_press";
id_pe = (char *) "thermo_pe";
// count fields in line
// allocate per-field memory
// process line of keywords
nfield_initial = atom->count_words(line);
allocate();
parse_fields(line);
// format strings
char *bigint_format = BIGINT_FORMAT;
char *fformat_multi = (char *) "---------------- Step %%8%s ----- "
"CPU = %%11.4f (sec) ----------------";
sprintf(format_multi,fformat_multi,&bigint_format[1]);
format_float_one_def = (char *) "%12.8g";
format_float_multi_def = (char *) "%14.4f";
format_int_one_def = (char *) "%8d";
format_int_multi_def = (char *) "%14d";
sprintf(format_bigint_one_def,"%%8%s",&bigint_format[1]);
sprintf(format_bigint_multi_def,"%%14%s",&bigint_format[1]);
format_float_user = NULL;
format_int_user = NULL;
format_bigint_user = NULL;
PI = 4.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
Thermo::~Thermo()
{
delete [] style;
delete [] line;
deallocate();
// format strings
delete [] format_float_user;
delete [] format_int_user;
delete [] format_bigint_user;
}
/* ---------------------------------------------------------------------- */
void Thermo::init()
{
int i,n;
// set normvalue to default setting unless user has specified it
if (normuserflag) normvalue = normuser;
else if (strcmp(update->unit_style,"lj") == 0) normvalue = 1;
else normvalue = 0;
// add Volume field if volume changes and not style = custom
// this check must come after domain init, so box_change is set
nfield = nfield_initial;
if (domain->box_change && strcmp(style,"custom") != 0)
addfield("Volume",&Thermo::compute_vol,FLOAT);
// set format string for each field
// include keyword if lineflag = MULTILINE
// add '/n' every 3 values if lineflag = MULTILINE
// add trailing '/n' to last value
char *ptr;
for (i = 0; i < nfield; i++) {
format[i][0] = '\0';
if (lineflag == MULTILINE && i % 3 == 0) strcat(format[i],"\n");
if (format_user[i]) ptr = format_user[i];
else if (vtype[i] == FLOAT) {
if (format_float_user) ptr = format_float_user;
else if (lineflag == ONELINE) ptr = format_float_one_def;
else if (lineflag == MULTILINE) ptr = format_float_multi_def;
} else if (vtype[i] == INT) {
if (format_int_user) ptr = format_int_user;
else if (lineflag == ONELINE) ptr = format_int_one_def;
else if (lineflag == MULTILINE) ptr = format_int_multi_def;
} else if (vtype[i] == BIGINT) {
if (format_bigint_user) ptr = format_bigint_user;
else if (lineflag == ONELINE) ptr = format_bigint_one_def;
else if (lineflag == MULTILINE) ptr = format_bigint_multi_def;
}
n = strlen(format[i]);
if (lineflag == ONELINE) sprintf(&format[i][n],"%s ",ptr);
else sprintf(&format[i][n],"%-8s = %s ",keyword[i],ptr);
if (i == nfield-1) strcat(format[i],"\n");
}
// find current ptr for each Compute ID
// cudable = 0 if any compute used by Thermo is non-CUDA
cudable = 1;
int icompute;
for (i = 0; i < ncompute; i++) {
icompute = modify->find_compute(id_compute[i]);
- if (icompute < 0) error->all("Could not find thermo compute ID");
+ if (icompute < 0) error->all(FLERR,"Could not find thermo compute ID");
computes[i] = modify->compute[icompute];
cudable = cudable && computes[i]->cudable;
}
// find current ptr for each Fix ID
// check that fix frequency is acceptable with thermo output frequency
int ifix;
for (i = 0; i < nfix; i++) {
ifix = modify->find_fix(id_fix[i]);
- if (ifix < 0) error->all("Could not find thermo fix ID");
+ if (ifix < 0) error->all(FLERR,"Could not find thermo fix ID");
fixes[i] = modify->fix[ifix];
if (output->thermo_every % fixes[i]->global_freq)
- error->all("Thermo and fix not computed at compatible times");
+ error->all(FLERR,"Thermo and fix not computed at compatible times");
}
// find current ptr for each Variable ID
int ivariable;
for (i = 0; i < nvariable; i++) {
ivariable = input->variable->find(id_variable[i]);
if (ivariable < 0)
- error->all("Could not find thermo custom variable name");
+ error->all(FLERR,"Could not find thermo custom variable name");
variables[i] = ivariable;
}
// set ptrs to keyword-specific Compute objects
if (index_temp >= 0) temperature = computes[index_temp];
if (index_press_scalar >= 0) pressure = computes[index_press_scalar];
if (index_press_vector >= 0) pressure = computes[index_press_vector];
if (index_pe >= 0) pe = computes[index_pe];
}
/* ---------------------------------------------------------------------- */
void Thermo::header()
{
if (lineflag == MULTILINE) return;
int loc = 0;
for (int i = 0; i < nfield; i++)
loc += sprintf(&line[loc],"%s ",keyword[i]);
sprintf(&line[loc],"\n");
if (me == 0) {
if (screen) fprintf(screen,line);
if (logfile) fprintf(logfile,line);
}
}
/* ---------------------------------------------------------------------- */
void Thermo::compute(int flag)
{
int i;
firststep = flag;
bigint ntimestep = update->ntimestep;
// check for lost atoms
// turn off normflag if natoms = 0 to avoid divide by 0
natoms = lost_check();
if (natoms == 0) normflag = 0;
else normflag = normvalue;
// invoke Compute methods needed for thermo keywords
// which = 0 is global scalar, which = 1 is global vector
for (i = 0; i < ncompute; i++)
if (compute_which[i] == SCALAR) {
if (!(computes[i]->invoked_flag & INVOKED_SCALAR)) {
computes[i]->compute_scalar();
computes[i]->invoked_flag |= INVOKED_SCALAR;
}
} else if (compute_which[i] == VECTOR) {
if (!(computes[i]->invoked_flag & INVOKED_VECTOR)) {
computes[i]->compute_vector();
computes[i]->invoked_flag |= INVOKED_VECTOR;
}
} else if (compute_which[i] == ARRAY) {
if (!(computes[i]->invoked_flag & INVOKED_ARRAY)) {
computes[i]->compute_array();
computes[i]->invoked_flag |= INVOKED_ARRAY;
}
}
// if lineflag = MULTILINE, prepend step/cpu header line
int loc = 0;
if (lineflag == MULTILINE) {
double cpu;
if (flag) cpu = timer->elapsed(TIME_LOOP);
else cpu = 0.0;
loc = sprintf(&line[loc],format_multi,ntimestep,cpu);
}
// add each thermo value to line with its specific format
for (ifield = 0; ifield < nfield; ifield++) {
(this->*vfunc[ifield])();
if (vtype[ifield] == FLOAT)
loc += sprintf(&line[loc],format[ifield],dvalue);
else if (vtype[ifield] == INT)
loc += sprintf(&line[loc],format[ifield],ivalue);
else if (vtype[ifield] == BIGINT) {
loc += sprintf(&line[loc],format[ifield],bivalue);
}
}
// kludge for RedStorm timing issue
// if (ntimestep == 100) return;
// print line to screen and logfile
if (me == 0) {
if (screen) fprintf(screen,line);
if (logfile) {
fprintf(logfile,line);
if (flushflag) fflush(logfile);
}
}
}
/* ----------------------------------------------------------------------
check for lost atoms, return current number of atoms
------------------------------------------------------------------------- */
bigint Thermo::lost_check()
{
// ntotal = current # of atoms
bigint ntotal;
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&ntotal,1,MPI_LMP_BIGINT,MPI_SUM,world);
- if (ntotal < 0 || ntotal > MAXBIGINT) error->all("Too many total atoms");
+ if (ntotal < 0 || ntotal > MAXBIGINT) error->all(FLERR,"Too many total atoms");
if (ntotal == atom->natoms) return ntotal;
// if not checking or already warned, just return
// reset total atom count
if (lostflag == IGNORE) return ntotal;
if (lostflag == WARN && lostbefore == 1) {
atom->natoms = ntotal;
return ntotal;
}
// error message
if (lostflag == ERROR) {
char str[64];
sprintf(str,
"Lost atoms: original " BIGINT_FORMAT " current " BIGINT_FORMAT,
atom->natoms,ntotal);
- error->all(str);
+ error->all(FLERR,str);
}
// warning message
char str[64];
sprintf(str,
"Lost atoms: original " BIGINT_FORMAT " current " BIGINT_FORMAT,
atom->natoms,ntotal);
- if (me == 0) error->warning(str,0);
+ if (me == 0) error->warning(FLERR,str,0);
// reset total atom count
atom->natoms = ntotal;
lostbefore = 1;
return ntotal;
}
/* ----------------------------------------------------------------------
modify thermo parameters
------------------------------------------------------------------------- */
void Thermo::modify_params(int narg, char **arg)
{
- if (narg == 0) error->all("Illegal thermo_modify command");
+ if (narg == 0) error->all(FLERR,"Illegal thermo_modify command");
modified = 1;
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"every") == 0) {
- if (iarg+2 > narg) error->all("Illegal thermo_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
if (strstr(arg[iarg+1],"v_") == arg[iarg+1]) {
delete [] output->var_thermo;
int n = strlen(&arg[iarg+1][2]) + 1;
output->var_thermo = new char[n];
strcpy(output->var_thermo,&arg[iarg+1][2]);
- } else error->all("Illegal thermo_modify command");
+ } else error->all(FLERR,"Illegal thermo_modify command");
output->thermo_every = 0;
iarg += 2;
} else if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+2 > narg) error->all("Illegal thermo_modify command");
- if (index_temp < 0) error->all("Thermo style does not use temp");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
+ if (index_temp < 0) error->all(FLERR,"Thermo style does not use temp");
delete [] id_compute[index_temp];
int n = strlen(arg[iarg+1]) + 1;
id_compute[index_temp] = new char[n];
strcpy(id_compute[index_temp],arg[iarg+1]);
int icompute = modify->find_compute(arg[iarg+1]);
if (icompute < 0)
- error->all("Could not find thermo_modify temperature ID");
+ error->all(FLERR,"Could not find thermo_modify temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Thermo_modify temperature ID does not "
+ error->all(FLERR,"Thermo_modify temperature ID does not "
"compute temperature");
if (temperature->igroup != 0 && comm->me == 0)
- error->warning("Temperature for thermo pressure is not for group all");
+ error->warning(FLERR,"Temperature for thermo pressure is not for group all");
// reset id_temp of pressure to new temperature ID
// either pressure currently being used by thermo or "thermo_press"
if (index_press_scalar >= 0) {
icompute = modify->find_compute(id_compute[index_press_scalar]);
- if (icompute < 0) error->all("Pressure ID for thermo does not exist");
+ if (icompute < 0) error->all(FLERR,"Pressure ID for thermo does not exist");
} else if (index_press_vector >= 0) {
icompute = modify->find_compute(id_compute[index_press_vector]);
- if (icompute < 0) error->all("Pressure ID for thermo does not exist");
+ if (icompute < 0) error->all(FLERR,"Pressure ID for thermo does not exist");
} else icompute = modify->find_compute((char *) "thermo_press");
modify->compute[icompute]->reset_extra_compute_fix(arg[iarg+1]);
iarg += 2;
} else if (strcmp(arg[iarg],"press") == 0) {
- if (iarg+2 > narg) error->all("Illegal thermo_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
if (index_press_scalar < 0 && index_press_vector < 0)
- error->all("Thermo style does not use press");
+ error->all(FLERR,"Thermo style does not use press");
if (index_press_scalar >= 0) {
delete [] id_compute[index_press_scalar];
int n = strlen(arg[iarg+1]) + 1;
id_compute[index_press_scalar] = new char[n];
strcpy(id_compute[index_press_scalar],arg[iarg+1]);
}
if (index_press_vector >= 0) {
delete [] id_compute[index_press_vector];
int n = strlen(arg[iarg+1]) + 1;
id_compute[index_press_vector] = new char[n];
strcpy(id_compute[index_press_vector],arg[iarg+1]);
}
int icompute = modify->find_compute(arg[iarg+1]);
- if (icompute < 0) error->all("Could not find thermo_modify pressure ID");
+ if (icompute < 0) error->all(FLERR,"Could not find thermo_modify pressure ID");
pressure = modify->compute[icompute];
if (pressure->pressflag == 0)
- error->all("Thermo_modify pressure ID does not compute pressure");
+ error->all(FLERR,"Thermo_modify pressure ID does not compute pressure");
iarg += 2;
} else if (strcmp(arg[iarg],"lost") == 0) {
- if (iarg+2 > narg) error->all("Illegal thermo_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
if (strcmp(arg[iarg+1],"ignore") == 0) lostflag = IGNORE;
else if (strcmp(arg[iarg+1],"warn") == 0) lostflag = WARN;
else if (strcmp(arg[iarg+1],"error") == 0) lostflag = ERROR;
- else error->all("Illegal thermo_modify command");
+ else error->all(FLERR,"Illegal thermo_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"norm") == 0) {
- if (iarg+2 > narg) error->all("Illegal thermo_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
normuserflag = 1;
if (strcmp(arg[iarg+1],"no") == 0) normuser = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) normuser = 1;
- else error->all("Illegal thermo_modify command");
+ else error->all(FLERR,"Illegal thermo_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"flush") == 0) {
- if (iarg+2 > narg) error->all("Illegal thermo_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
if (strcmp(arg[iarg+1],"no") == 0) flushflag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) flushflag = 1;
- else error->all("Illegal thermo_modify command");
+ else error->all(FLERR,"Illegal thermo_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"line") == 0) {
- if (iarg+2 > narg) error->all("Illegal thermo_modify command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
if (strcmp(arg[iarg+1],"one") == 0) lineflag = ONELINE;
else if (strcmp(arg[iarg+1],"multi") == 0) lineflag = MULTILINE;
- else error->all("Illegal thermo_modify command");
+ else error->all(FLERR,"Illegal thermo_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"format") == 0) {
- if (iarg+3 > narg) error->all("Illegal thermo_modify command");
+ if (iarg+3 > narg) error->all(FLERR,"Illegal thermo_modify command");
if (strcmp(arg[iarg+1],"int") == 0) {
if (format_int_user) delete [] format_int_user;
int n = strlen(arg[iarg+2]) + 1;
format_int_user = new char[n];
strcpy(format_int_user,arg[iarg+2]);
if (format_bigint_user) delete [] format_bigint_user;
n = strlen(format_int_user) + 3;
format_bigint_user = new char[n];
char *ptr = strchr(format_int_user,'d');
if (ptr == NULL)
- error->all("Thermo_modify int format does not contain d character");
+ error->all(FLERR,"Thermo_modify int format does not contain d character");
*ptr = '\0';
sprintf(format_bigint_user,"%s%s%s",format_int_user,
BIGINT_FORMAT,ptr+1);
*ptr = 'd';
} else if (strcmp(arg[iarg+1],"float") == 0) {
if (format_float_user) delete [] format_float_user;
int n = strlen(arg[iarg+2]) + 1;
format_float_user = new char[n];
strcpy(format_float_user,arg[iarg+2]);
} else {
int i = atoi(arg[iarg+1]) - 1;
if (i < 0 || i >= nfield_initial)
- error->all("Illegal thermo_modify command");
+ error->all(FLERR,"Illegal thermo_modify command");
if (format_user[i]) delete [] format_user[i];
int n = strlen(arg[iarg+2]) + 1;
format_user[i] = new char[n];
strcpy(format_user[i],arg[iarg+2]);
}
iarg += 3;
- } else error->all("Illegal thermo_modify command");
+ } else error->all(FLERR,"Illegal thermo_modify command");
}
}
/* ----------------------------------------------------------------------
allocate all per-field memory
------------------------------------------------------------------------- */
void Thermo::allocate()
{
// n = specified fields + Volume field (added at run time)
int n = nfield_initial + 1;
keyword = new char*[n];
for (int i = 0; i < n; i++) keyword[i] = new char[32];
vfunc = new FnPtr[n];
vtype = new int[n];
format = new char*[n];
for (int i = 0; i < n; i++) format[i] = new char[32];
format_user = new char*[n];
for (int i = 0; i < n; i++) format_user[i] = NULL;
field2index = new int[n];
argindex1 = new int[n];
argindex2 = new int[n];
// factor of 3 is max number of computes a single field can add
ncompute = 0;
id_compute = new char*[3*n];
compute_which = new int[3*n];
computes = new Compute*[3*n];
nfix = 0;
id_fix = new char*[n];
fixes = new Fix*[n];
nvariable = 0;
id_variable = new char*[n];
variables = new int[n];
}
/* ----------------------------------------------------------------------
deallocate all per-field memory
------------------------------------------------------------------------- */
void Thermo::deallocate()
{
int n = nfield_initial + 1;
for (int i = 0; i < n; i++) delete [] keyword[i];
delete [] keyword;
delete [] vfunc;
delete [] vtype;
for (int i = 0; i < n; i++) delete [] format[i];
delete [] format;
for (int i = 0; i < n; i++) delete [] format_user[i];
delete [] format_user;
delete [] field2index;
delete [] argindex1;
delete [] argindex2;
for (int i = 0; i < ncompute; i++) delete [] id_compute[i];
delete [] id_compute;
delete [] compute_which;
delete [] computes;
for (int i = 0; i < nfix; i++) delete [] id_fix[i];
delete [] id_fix;
delete [] fixes;
for (int i = 0; i < nvariable; i++) delete [] id_variable[i];
delete [] id_variable;
delete [] variables;
}
/* ----------------------------------------------------------------------
parse list of thermo keywords from str
set compute flags (temp, press, pe, etc)
------------------------------------------------------------------------- */
void Thermo::parse_fields(char *str)
{
nfield = 0;
// customize a new keyword by adding to if statement
char *word = strtok(str," \0");
while (word) {
if (strcmp(word,"step") == 0) {
addfield("Step",&Thermo::compute_step,BIGINT);
} else if (strcmp(word,"elapsed") == 0) {
addfield("Elapsed",&Thermo::compute_elapsed,BIGINT);
} else if (strcmp(word,"elaplong") == 0) {
addfield("Elaplong",&Thermo::compute_elapsed_long,BIGINT);
} else if (strcmp(word,"dt") == 0) {
addfield("Dt",&Thermo::compute_dt,FLOAT);
} else if (strcmp(word,"cpu") == 0) {
addfield("CPU",&Thermo::compute_cpu,FLOAT);
} else if (strcmp(word,"tpcpu") == 0) {
addfield("T/CPU",&Thermo::compute_tpcpu,FLOAT);
} else if (strcmp(word,"spcpu") == 0) {
addfield("S/CPU",&Thermo::compute_spcpu,FLOAT);
} else if (strcmp(word,"atoms") == 0) {
addfield("Atoms",&Thermo::compute_atoms,BIGINT);
} else if (strcmp(word,"temp") == 0) {
addfield("Temp",&Thermo::compute_temp,FLOAT);
index_temp = add_compute(id_temp,SCALAR);
} else if (strcmp(word,"press") == 0) {
addfield("Press",&Thermo::compute_press,FLOAT);
index_press_scalar = add_compute(id_press,SCALAR);
} else if (strcmp(word,"pe") == 0) {
addfield("PotEng",&Thermo::compute_pe,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"ke") == 0) {
addfield("KinEng",&Thermo::compute_ke,FLOAT);
index_temp = add_compute(id_temp,SCALAR);
} else if (strcmp(word,"etotal") == 0) {
addfield("TotEng",&Thermo::compute_etotal,FLOAT);
index_temp = add_compute(id_temp,SCALAR);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"enthalpy") == 0) {
addfield("Enthalpy",&Thermo::compute_enthalpy,FLOAT);
index_temp = add_compute(id_temp,SCALAR);
index_press_scalar = add_compute(id_press,SCALAR);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"evdwl") == 0) {
addfield("E_vdwl",&Thermo::compute_evdwl,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"ecoul") == 0) {
addfield("E_coul",&Thermo::compute_ecoul,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"epair") == 0) {
addfield("E_pair",&Thermo::compute_epair,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"ebond") == 0) {
addfield("E_bond",&Thermo::compute_ebond,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"eangle") == 0) {
addfield("E_angle",&Thermo::compute_eangle,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"edihed") == 0) {
addfield("E_dihed",&Thermo::compute_edihed,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"eimp") == 0) {
addfield("E_impro",&Thermo::compute_eimp,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"emol") == 0) {
addfield("E_mol",&Thermo::compute_emol,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"elong") == 0) {
addfield("E_long",&Thermo::compute_elong,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"etail") == 0) {
addfield("E_tail",&Thermo::compute_etail,FLOAT);
index_pe = add_compute(id_pe,SCALAR);
} else if (strcmp(word,"vol") == 0) {
addfield("Volume",&Thermo::compute_vol,FLOAT);
} else if (strcmp(word,"lx") == 0) {
addfield("Lx",&Thermo::compute_lx,FLOAT);
} else if (strcmp(word,"ly") == 0) {
addfield("Ly",&Thermo::compute_ly,FLOAT);
} else if (strcmp(word,"lz") == 0) {
addfield("Lz",&Thermo::compute_lz,FLOAT);
} else if (strcmp(word,"xlo") == 0) {
addfield("Xlo",&Thermo::compute_xlo,FLOAT);
} else if (strcmp(word,"xhi") == 0) {
addfield("Xhi",&Thermo::compute_xhi,FLOAT);
} else if (strcmp(word,"ylo") == 0) {
addfield("Ylo",&Thermo::compute_ylo,FLOAT);
} else if (strcmp(word,"yhi") == 0) {
addfield("Yhi",&Thermo::compute_yhi,FLOAT);
} else if (strcmp(word,"zlo") == 0) {
addfield("Zlo",&Thermo::compute_zlo,FLOAT);
} else if (strcmp(word,"zhi") == 0) {
addfield("Zhi",&Thermo::compute_zhi,FLOAT);
} else if (strcmp(word,"xy") == 0) {
addfield("Xy",&Thermo::compute_xy,FLOAT);
} else if (strcmp(word,"xz") == 0) {
addfield("Xz",&Thermo::compute_xz,FLOAT);
} else if (strcmp(word,"yz") == 0) {
addfield("Yz",&Thermo::compute_yz,FLOAT);
} else if (strcmp(word,"xlat") == 0) {
if (domain->lattice == NULL)
- error->all("Thermo keyword requires lattice be defined");
+ error->all(FLERR,"Thermo keyword requires lattice be defined");
addfield("Xlat",&Thermo::compute_xlat,FLOAT);
} else if (strcmp(word,"ylat") == 0) {
if (domain->lattice == NULL)
- error->all("Thermo keyword requires lattice be defined");
+ error->all(FLERR,"Thermo keyword requires lattice be defined");
addfield("Ylat",&Thermo::compute_ylat,FLOAT);
} else if (strcmp(word,"zlat") == 0) {
if (domain->lattice == NULL)
- error->all("Thermo keyword requires lattice be defined");
+ error->all(FLERR,"Thermo keyword requires lattice be defined");
addfield("Zlat",&Thermo::compute_zlat,FLOAT);
} else if (strcmp(word,"pxx") == 0) {
addfield("Pxx",&Thermo::compute_pxx,FLOAT);
index_press_vector = add_compute(id_press,VECTOR);
} else if (strcmp(word,"pyy") == 0) {
addfield("Pyy",&Thermo::compute_pyy,FLOAT);
index_press_vector = add_compute(id_press,VECTOR);
} else if (strcmp(word,"pzz") == 0) {
addfield("Pzz",&Thermo::compute_pzz,FLOAT);
index_press_vector = add_compute(id_press,VECTOR);
} else if (strcmp(word,"pxy") == 0) {
addfield("Pxy",&Thermo::compute_pxy,FLOAT);
index_press_vector = add_compute(id_press,VECTOR);
} else if (strcmp(word,"pxz") == 0) {
addfield("Pxz",&Thermo::compute_pxz,FLOAT);
index_press_vector = add_compute(id_press,VECTOR);
} else if (strcmp(word,"pyz") == 0) {
addfield("Pyz",&Thermo::compute_pyz,FLOAT);
index_press_vector = add_compute(id_press,VECTOR);
} else if (strcmp(word,"fmax") == 0) {
addfield("Fmax",&Thermo::compute_fmax,FLOAT);
} else if (strcmp(word,"fnorm") == 0) {
addfield("Fnorm",&Thermo::compute_fnorm,FLOAT);
} else if (strcmp(word,"cella") == 0) {
addfield("Cella",&Thermo::compute_cella,FLOAT);
} else if (strcmp(word,"cellb") == 0) {
addfield("Cellb",&Thermo::compute_cellb,FLOAT);
} else if (strcmp(word,"cellc") == 0) {
addfield("Cellc",&Thermo::compute_cellc,FLOAT);
} else if (strcmp(word,"cellalpha") == 0) {
addfield("CellAlpha",&Thermo::compute_cellalpha,FLOAT);
} else if (strcmp(word,"cellbeta") == 0) {
addfield("CellBeta",&Thermo::compute_cellbeta,FLOAT);
} else if (strcmp(word,"cellgamma") == 0) {
addfield("CellGamma",&Thermo::compute_cellgamma,FLOAT);
// compute value = c_ID, fix value = f_ID, variable value = v_ID
// count trailing [] and store int arguments
// copy = at most 8 chars of ID to pass to addfield
} else if ((strncmp(word,"c_",2) == 0) || (strncmp(word,"f_",2) == 0) ||
(strncmp(word,"v_",2) == 0)) {
int n = strlen(word);
char *id = new char[n];
strcpy(id,&word[2]);
char copy[9];
strncpy(copy,id,8);
copy[8] = '\0';
// parse zero or one or two trailing brackets from ID
// argindex1,argindex2 = int inside each bracket pair, 0 if no bracket
char *ptr = strchr(id,'[');
if (ptr == NULL) argindex1[nfield] = 0;
else {
*ptr = '\0';
argindex1[nfield] = input->variable->int_between_brackets(ptr);
ptr++;
if (*ptr == '[') {
argindex2[nfield] = input->variable->int_between_brackets(ptr);
ptr++;
} else argindex2[nfield] = 0;
}
if (word[0] == 'c') {
n = modify->find_compute(id);
- if (n < 0) error->all("Could not find thermo custom compute ID");
+ if (n < 0) error->all(FLERR,"Could not find thermo custom compute ID");
if (argindex1[nfield] == 0 && modify->compute[n]->scalar_flag == 0)
- error->all("Thermo compute does not compute scalar");
+ error->all(FLERR,"Thermo compute does not compute scalar");
if (argindex1[nfield] > 0 && argindex2[nfield] == 0) {
if (modify->compute[n]->vector_flag == 0)
- error->all("Thermo compute does not compute vector");
+ error->all(FLERR,"Thermo compute does not compute vector");
if (argindex1[nfield] > modify->compute[n]->size_vector)
- error->all("Thermo compute vector is accessed out-of-range");
+ error->all(FLERR,"Thermo compute vector is accessed out-of-range");
}
if (argindex1[nfield] > 0 && argindex2[nfield] > 0) {
if (modify->compute[n]->array_flag == 0)
- error->all("Thermo compute does not compute array");
+ error->all(FLERR,"Thermo compute does not compute array");
if (argindex1[nfield] > modify->compute[n]->size_array_rows ||
argindex2[nfield] > modify->compute[n]->size_array_cols)
- error->all("Thermo compute array is accessed out-of-range");
+ error->all(FLERR,"Thermo compute array is accessed out-of-range");
}
if (argindex1[nfield] == 0)
field2index[nfield] = add_compute(id,SCALAR);
else if (argindex2[nfield] == 0)
field2index[nfield] = add_compute(id,VECTOR);
else
field2index[nfield] = add_compute(id,ARRAY);
addfield(copy,&Thermo::compute_compute,FLOAT);
} else if (word[0] == 'f') {
n = modify->find_fix(id);
- if (n < 0) error->all("Could not find thermo custom fix ID");
+ if (n < 0) error->all(FLERR,"Could not find thermo custom fix ID");
if (argindex1[nfield] == 0 && modify->fix[n]->scalar_flag == 0)
- error->all("Thermo fix does not compute scalar");
+ error->all(FLERR,"Thermo fix does not compute scalar");
if (argindex1[nfield] > 0 && argindex2[nfield] == 0) {
if (modify->fix[n]->vector_flag == 0)
- error->all("Thermo fix does not compute vector");
+ error->all(FLERR,"Thermo fix does not compute vector");
if (argindex1[nfield] > modify->fix[n]->size_vector)
- error->all("Thermo fix vector is accessed out-of-range");
+ error->all(FLERR,"Thermo fix vector is accessed out-of-range");
}
if (argindex1[nfield] > 0 && argindex2[nfield] > 0) {
if (modify->fix[n]->array_flag == 0)
- error->all("Thermo fix does not compute array");
+ error->all(FLERR,"Thermo fix does not compute array");
if (argindex1[nfield] > modify->fix[n]->size_array_rows ||
argindex2[nfield] > modify->fix[n]->size_array_cols)
- error->all("Thermo fix array is accessed out-of-range");
+ error->all(FLERR,"Thermo fix array is accessed out-of-range");
}
field2index[nfield] = add_fix(id);
addfield(copy,&Thermo::compute_fix,FLOAT);
} else if (word[0] == 'v') {
n = input->variable->find(id);
- if (n < 0) error->all("Could not find thermo custom variable name");
+ if (n < 0) error->all(FLERR,"Could not find thermo custom variable name");
if (input->variable->equalstyle(n) == 0)
- error->all("Thermo custom variable is not equal-style variable");
+ error->all(FLERR,"Thermo custom variable is not equal-style variable");
if (argindex1[nfield])
- error->all("Thermo custom variable cannot be indexed");
+ error->all(FLERR,"Thermo custom variable cannot be indexed");
field2index[nfield] = add_variable(id);
addfield(copy,&Thermo::compute_variable,FLOAT);
}
delete [] id;
- } else error->all("Invalid keyword in thermo_style custom command");
+ } else error->all(FLERR,"Invalid keyword in thermo_style custom command");
word = strtok(NULL," \0");
}
}
/* ----------------------------------------------------------------------
add field to list of quantities to print
------------------------------------------------------------------------- */
void Thermo::addfield(const char *key, FnPtr func, int typeflag)
{
strcpy(keyword[nfield],key);
vfunc[nfield] = func;
vtype[nfield] = typeflag;
nfield++;
}
/* ----------------------------------------------------------------------
add compute ID to list of Compute objects to call
return location of where this Compute is in list
if already in list with same which, do not add, just return index
------------------------------------------------------------------------- */
int Thermo::add_compute(const char *id, int which)
{
int icompute;
for (icompute = 0; icompute < ncompute; icompute++)
if ((strcmp(id,id_compute[icompute]) == 0) &&
which == compute_which[icompute]) break;
if (icompute < ncompute) return icompute;
int n = strlen(id) + 1;
id_compute[ncompute] = new char[n];
strcpy(id_compute[ncompute],id);
compute_which[ncompute] = which;
ncompute++;
return ncompute-1;
}
/* ----------------------------------------------------------------------
add fix ID to list of Fix objects to call
------------------------------------------------------------------------- */
int Thermo::add_fix(const char *id)
{
int n = strlen(id) + 1;
id_fix[nfix] = new char[n];
strcpy(id_fix[nfix],id);
nfix++;
return nfix-1;
}
/* ----------------------------------------------------------------------
add variable ID to list of Variables to evaluate
------------------------------------------------------------------------- */
int Thermo::add_variable(const char *id)
{
int n = strlen(id) + 1;
id_variable[nvariable] = new char[n];
strcpy(id_variable[nvariable],id);
nvariable++;
return nvariable-1;
}
/* ----------------------------------------------------------------------
compute a single thermodyanmic value, word is any keyword in custom list
called when a variable is evaluated by Variable class
return value as double in answer
return 0 if str is recoginzed keyword, 1 if unrecognized
customize a new keyword by adding to if statement
------------------------------------------------------------------------- */
int Thermo::evaluate_keyword(char *word, double *answer)
{
// invoke a lo-level thermo routine to compute the variable value
// if keyword requires a compute, error if thermo doesn't use the compute
// if inbetween runs and needed compute is not current, error
// if in middle of run and needed compute is not current, invoke it
// for keywords that use pe indirectly (evdwl, ebond, etc):
// check if energy was tallied on this timestep and set pe->invoked_flag
// this will trigger next timestep for energy tallying via addstep()
if (strcmp(word,"step") == 0) {
compute_step();
dvalue = bivalue;
} else if (strcmp(word,"elapsed") == 0) {
if (update->whichflag == 0)
- error->all("This variable thermo keyword cannot be used between runs");
+ error->all(FLERR,"This variable thermo keyword cannot be used between runs");
compute_elapsed();
dvalue = bivalue;
} else if (strcmp(word,"elaplong") == 0) {
if (update->whichflag == 0)
- error->all("This variable thermo keyword cannot be used between runs");
+ error->all(FLERR,"This variable thermo keyword cannot be used between runs");
compute_elapsed_long();
dvalue = bivalue;
} else if (strcmp(word,"dt") == 0) {
compute_dt();
} else if (strcmp(word,"cpu") == 0) {
if (update->whichflag == 0)
- error->all("This variable thermo keyword cannot be used between runs");
+ error->all(FLERR,"This variable thermo keyword cannot be used between runs");
compute_cpu();
} else if (strcmp(word,"tpcpu") == 0) {
if (update->whichflag == 0)
- error->all("This variable thermo keyword cannot be used between runs");
+ error->all(FLERR,"This variable thermo keyword cannot be used between runs");
compute_tpcpu();
} else if (strcmp(word,"spcpu") == 0) {
if (update->whichflag == 0)
- error->all("This variable thermo keyword cannot be used between runs");
+ error->all(FLERR,"This variable thermo keyword cannot be used between runs");
compute_spcpu();
} else if (strcmp(word,"atoms") == 0) {
compute_atoms();
dvalue = bivalue;
} else if (strcmp(word,"temp") == 0) {
if (!temperature)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init temp");
if (update->whichflag == 0) {
if (temperature->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
temperature->compute_scalar();
temperature->invoked_flag |= INVOKED_SCALAR;
}
compute_temp();
} else if (strcmp(word,"press") == 0) {
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_SCALAR)) {
pressure->compute_scalar();
pressure->invoked_flag |= INVOKED_SCALAR;
}
compute_press();
} else if (strcmp(word,"pe") == 0) {
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
if (update->whichflag == 0) {
if (pe->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pe->invoked_flag & INVOKED_SCALAR)) {
pe->compute_scalar();
pe->invoked_flag |= INVOKED_SCALAR;
}
compute_pe();
} else if (strcmp(word,"ke") == 0) {
if (!temperature)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init temp");
if (update->whichflag == 0) {
if (temperature->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
temperature->compute_scalar();
temperature->invoked_flag |= INVOKED_SCALAR;
}
compute_ke();
} else if (strcmp(word,"etotal") == 0) {
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
if (update->whichflag == 0) {
if (pe->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pe->invoked_flag & INVOKED_SCALAR)) {
pe->compute_scalar();
pe->invoked_flag |= INVOKED_SCALAR;
}
if (!temperature)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init temp");
if (update->whichflag == 0) {
if (temperature->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
temperature->compute_scalar();
temperature->invoked_flag |= INVOKED_SCALAR;
}
compute_etotal();
} else if (strcmp(word,"enthalpy") == 0) {
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
if (update->whichflag == 0) {
if (pe->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pe->invoked_flag & INVOKED_SCALAR)) {
pe->compute_scalar();
pe->invoked_flag |= INVOKED_SCALAR;
}
if (!temperature)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init temp");
if (update->whichflag == 0) {
if (temperature->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
temperature->compute_scalar();
temperature->invoked_flag |= INVOKED_SCALAR;
}
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_SCALAR)) {
pressure->compute_scalar();
pressure->invoked_flag |= INVOKED_SCALAR;
}
compute_enthalpy();
} else if (strcmp(word,"evdwl") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_evdwl();
} else if (strcmp(word,"ecoul") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_ecoul();
} else if (strcmp(word,"epair") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_epair();
} else if (strcmp(word,"ebond") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_ebond();
} else if (strcmp(word,"eangle") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_eangle();
} else if (strcmp(word,"edihed") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_edihed();
} else if (strcmp(word,"eimp") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_eimp();
} else if (strcmp(word,"emol") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_emol();
} else if (strcmp(word,"elong") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_elong();
} else if (strcmp(word,"etail") == 0) {
if (update->eflag_global != update->ntimestep)
- error->all("Energy was not tallied on needed timestep");
+ error->all(FLERR,"Energy was not tallied on needed timestep");
if (!pe)
- error->all("Thermo keyword in variable requires thermo to use/init pe");
+ error->all(FLERR,"Thermo keyword in variable requires thermo to use/init pe");
pe->invoked_flag |= INVOKED_SCALAR;
compute_etail();
} else if (strcmp(word,"vol") == 0) compute_vol();
else if (strcmp(word,"lx") == 0) compute_lx();
else if (strcmp(word,"ly") == 0) compute_ly();
else if (strcmp(word,"lz") == 0) compute_lz();
else if (strcmp(word,"xlo") == 0) compute_xlo();
else if (strcmp(word,"xhi") == 0) compute_xhi();
else if (strcmp(word,"ylo") == 0) compute_ylo();
else if (strcmp(word,"yhi") == 0) compute_yhi();
else if (strcmp(word,"zlo") == 0) compute_zlo();
else if (strcmp(word,"zhi") == 0) compute_zhi();
else if (strcmp(word,"xy") == 0) compute_xy();
else if (strcmp(word,"xz") == 0) compute_xz();
else if (strcmp(word,"yz") == 0) compute_yz();
else if (strcmp(word,"xlat") == 0) {
if (domain->lattice == NULL)
- error->all("Thermo keyword in variable requires lattice be defined");
+ error->all(FLERR,"Thermo keyword in variable requires lattice be defined");
compute_xlat();
} else if (strcmp(word,"ylat") == 0) {
if (domain->lattice == NULL)
- error->all("Thermo keyword in variable requires lattice be defined");
+ error->all(FLERR,"Thermo keyword in variable requires lattice be defined");
compute_ylat();
} else if (strcmp(word,"zlat") == 0) {
if (domain->lattice == NULL)
- error->all("Thermo keyword in variable requires lattice be defined");
+ error->all(FLERR,"Thermo keyword in variable requires lattice be defined");
compute_zlat();
} else if (strcmp(word,"pxx") == 0) {
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_vector != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
pressure->compute_vector();
pressure->invoked_flag |= INVOKED_VECTOR;
}
compute_pxx();
} else if (strcmp(word,"pyy") == 0) {
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_vector != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
pressure->compute_vector();
pressure->invoked_flag |= INVOKED_VECTOR;
}
compute_pyy();
} else if (strcmp(word,"pzz") == 0) {
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_vector != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
pressure->compute_vector();
pressure->invoked_flag |= INVOKED_VECTOR;
}
compute_pzz();
} else if (strcmp(word,"pxy") == 0) {
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_vector != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
pressure->compute_vector();
pressure->invoked_flag |= INVOKED_VECTOR;
}
compute_pxy();
} else if (strcmp(word,"pxz") == 0) {
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_vector != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
pressure->compute_vector();
pressure->invoked_flag |= INVOKED_VECTOR;
}
compute_pxz();
} else if (strcmp(word,"pyz") == 0) {
if (!pressure)
- error->all("Thermo keyword in variable requires "
+ error->all(FLERR,"Thermo keyword in variable requires "
"thermo to use/init press");
if (update->whichflag == 0) {
if (pressure->invoked_vector != update->ntimestep)
- error->all("Compute used in variable thermo keyword between runs "
+ error->all(FLERR,"Compute used in variable thermo keyword between runs "
"is not current");
} else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
pressure->compute_vector();
pressure->invoked_flag |= INVOKED_VECTOR;
}
compute_pyz();
} else if (strcmp(word,"fmax") == 0) compute_fmax();
else if (strcmp(word,"fnorm") == 0) compute_fnorm();
else if (strcmp(word,"cella") == 0) compute_cella();
else if (strcmp(word,"cellb") == 0) compute_cellb();
else if (strcmp(word,"cellc") == 0) compute_cellc();
else if (strcmp(word,"cellalpha") == 0) compute_cellalpha();
else if (strcmp(word,"cellbeta") == 0) compute_cellbeta();
else if (strcmp(word,"cellgamma") == 0) compute_cellgamma();
else return 1;
*answer = dvalue;
return 0;
}
/* ----------------------------------------------------------------------
extraction of Compute, Fix, Variable results
compute/fix are normalized by atoms if returning extensive value
variable value is not normalized (formula should normalize if desired)
------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
void Thermo::compute_compute()
{
int m = field2index[ifield];
Compute *compute = computes[m];
if (compute_which[m] == SCALAR) {
dvalue = compute->scalar;
if (normflag && compute->extscalar) dvalue /= natoms;
} else if (compute_which[m] == VECTOR) {
dvalue = compute->vector[argindex1[ifield]-1];
if (normflag) {
if (compute->extvector == 0) return;
else if (compute->extvector == 1) dvalue /= natoms;
else if (compute->extlist[argindex1[ifield]-1]) dvalue /= natoms;
}
} else {
dvalue = compute->array[argindex1[ifield]-1][argindex2[ifield]-1];
if (normflag && compute->extarray) dvalue /= natoms;
}
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_fix()
{
int m = field2index[ifield];
Fix *fix = fixes[m];
if (argindex1[ifield] == 0) {
dvalue = fix->compute_scalar();
if (normflag && fix->extscalar) dvalue /= natoms;
} else if (argindex2[ifield] == 0) {
dvalue = fix->compute_vector(argindex1[ifield]-1);
if (normflag) {
if (fix->extvector == 0) return;
else if (fix->extvector == 1) dvalue /= natoms;
else if (fix->extlist[argindex1[ifield]-1]) dvalue /= natoms;
}
} else {
dvalue = fix->compute_array(argindex1[ifield]-1,argindex2[ifield]-1);
if (normflag && fix->extarray) dvalue /= natoms;
}
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_variable()
{
dvalue = input->variable->compute_equal(variables[field2index[ifield]]);
}
/* ----------------------------------------------------------------------
one method for every keyword thermo can output
called by compute() or evaluate_keyword()
compute will have already been called
set ivalue/dvalue/bivalue if value is int/double/bigint
customize a new keyword by adding a method
------------------------------------------------------------------------- */
void Thermo::compute_step()
{
bivalue = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_elapsed()
{
bivalue = update->ntimestep - update->firststep;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_elapsed_long()
{
bivalue = update->ntimestep - update->beginstep;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_dt()
{
dvalue = update->dt;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_cpu()
{
if (firststep == 0) dvalue = 0.0;
else dvalue = timer->elapsed(TIME_LOOP);
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_tpcpu()
{
double new_cpu;
double new_time = update->ntimestep * update->dt;
if (firststep == 0) {
new_cpu = 0.0;
dvalue = 0.0;
} else {
new_cpu = timer->elapsed(TIME_LOOP);
double cpu_diff = new_cpu - last_tpcpu;
double time_diff = new_time - last_time;
if (time_diff > 0.0 && cpu_diff > 0.0) dvalue = time_diff/cpu_diff;
else dvalue = 0.0;
}
last_time = new_time;
last_tpcpu = new_cpu;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_spcpu()
{
double new_cpu;
int new_step = update->ntimestep;
if (firststep == 0) {
new_cpu = 0.0;
dvalue = 0.0;
} else {
new_cpu = timer->elapsed(TIME_LOOP);
double cpu_diff = new_cpu - last_spcpu;
int step_diff = new_step - last_step;
if (cpu_diff > 0.0) dvalue = step_diff/cpu_diff;
else dvalue = 0.0;
}
last_step = new_step;
last_spcpu = new_cpu;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_atoms()
{
bivalue = natoms;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_temp()
{
dvalue = temperature->scalar;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_press()
{
dvalue = pressure->scalar;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_pe()
{
dvalue = pe->scalar;
if (normflag) dvalue /= natoms;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_ke()
{
dvalue = temperature->scalar;
dvalue *= 0.5 * temperature->dof * force->boltz;
if (normflag) dvalue /= natoms;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_etotal()
{
compute_pe();
double ke = temperature->scalar;
ke *= 0.5 * temperature->dof * force->boltz;
if (normflag) ke /= natoms;
dvalue += ke;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_enthalpy()
{
compute_etotal();
double etmp = dvalue;
compute_vol();
double vtmp = dvalue;
if (normflag) vtmp /= natoms;
compute_press();
double ptmp = dvalue;
dvalue = etmp + ptmp*vtmp/(force->nktv2p);
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_evdwl()
{
double tmp = 0.0;
if (force->pair) tmp += force->pair->eng_vdwl;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (force->pair && force->pair->tail_flag) {
double volume = domain->xprd * domain->yprd * domain->zprd;
dvalue += force->pair->etail / volume;
}
if (normflag) dvalue /= natoms;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_ecoul()
{
double tmp = 0.0;
if (force->pair) tmp += force->pair->eng_coul;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (normflag) dvalue /= natoms;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_epair()
{
double tmp = 0.0;
if (force->pair) tmp += force->pair->eng_vdwl + force->pair->eng_coul;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (force->kspace) dvalue += force->kspace->energy;
if (force->pair && force->pair->tail_flag) {
double volume = domain->xprd * domain->yprd * domain->zprd;
dvalue += force->pair->etail / volume;
}
if (normflag) dvalue /= natoms;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_ebond()
{
if (force->bond) {
double tmp = force->bond->energy;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (normflag) dvalue /= natoms;
} else dvalue = 0.0;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_eangle()
{
if (force->angle) {
double tmp = force->angle->energy;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (normflag) dvalue /= natoms;
} else dvalue = 0.0;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_edihed()
{
if (force->dihedral) {
double tmp = force->dihedral->energy;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (normflag) dvalue /= natoms;
} else dvalue = 0.0;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_eimp()
{
if (force->improper) {
double tmp = force->improper->energy;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (normflag) dvalue /= natoms;
} else dvalue = 0.0;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_emol()
{
double tmp = 0.0;
if (atom->molecular) {
if (force->bond) tmp += force->bond->energy;
if (force->angle) tmp += force->angle->energy;
if (force->dihedral) tmp += force->dihedral->energy;
if (force->improper) tmp += force->improper->energy;
MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
if (normflag) dvalue /= natoms;
} else dvalue = 0.0;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_elong()
{
if (force->kspace) {
dvalue = force->kspace->energy;
if (normflag) dvalue /= natoms;
} else dvalue = 0.0;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_etail()
{
if (force->pair && force->pair->tail_flag) {
double volume = domain->xprd * domain->yprd * domain->zprd;
dvalue = force->pair->etail / volume;
if (normflag) dvalue /= natoms;
} else dvalue = 0.0;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_vol()
{
if (domain->dimension == 3)
dvalue = domain->xprd * domain->yprd * domain->zprd;
else
dvalue = domain->xprd * domain->yprd;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_lx()
{
dvalue = domain->xprd;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_ly()
{
dvalue = domain->yprd;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_lz()
{
dvalue = domain->zprd;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_xlo()
{
dvalue = domain->boxlo[0];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_xhi()
{
dvalue = domain->boxhi[0];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_ylo()
{
dvalue = domain->boxlo[1];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_yhi()
{
dvalue = domain->boxhi[1];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_zlo()
{
dvalue = domain->boxlo[2];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_zhi()
{
dvalue = domain->boxhi[2];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_xy()
{
dvalue = domain->xy;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_xz()
{
dvalue = domain->xz;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_yz()
{
dvalue = domain->yz;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_xlat()
{
dvalue = domain->lattice->xlattice;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_ylat()
{
dvalue = domain->lattice->ylattice;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_zlat()
{
dvalue = domain->lattice->zlattice;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_pxx()
{
dvalue = pressure->vector[0];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_pyy()
{
dvalue = pressure->vector[1];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_pzz()
{
dvalue = pressure->vector[2];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_pxy()
{
dvalue = pressure->vector[3];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_pxz()
{
dvalue = pressure->vector[4];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_pyz()
{
dvalue = pressure->vector[5];
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_fmax()
{
double **f = atom->f;
int nlocal = atom->nlocal;
double max = 0.0;
for (int i = 0; i < nlocal; i++) {
max = MAX(max,fabs(f[i][0]));
max = MAX(max,fabs(f[i][1]));
max = MAX(max,fabs(f[i][2]));
}
double maxall;
MPI_Allreduce(&max,&maxall,1,MPI_DOUBLE,MPI_MAX,world);
dvalue = maxall;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_fnorm()
{
double **f = atom->f;
int nlocal = atom->nlocal;
double dot = 0.0;
for (int i = 0; i < nlocal; i++)
dot += f[i][0]*f[i][0] + f[i][1]*f[i][1] + f[i][2]*f[i][2];
double dotall;
MPI_Allreduce(&dot,&dotall,1,MPI_DOUBLE,MPI_SUM,world);
dvalue = sqrt(dotall);
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_cella()
{
dvalue = domain->xprd;
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_cellb()
{
if (!domain->triclinic)
dvalue = domain->yprd;
else {
double* h = domain->h;
dvalue = sqrt(h[1]*h[1]+h[5]*h[5]);
}
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_cellc()
{
if (!domain->triclinic)
dvalue = domain->zprd;
else {
double* h = domain->h;
dvalue = sqrt(h[2]*h[2]+h[3]*h[3]+h[4]*h[4]);
}
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_cellalpha()
{
if (!domain->triclinic)
dvalue = 90.0;
else {
// Cos(alpha) = (xy.xz + ly.yz)/(b.c)
double* h = domain->h;
double cosalpha = (h[5]*h[4]+h[1]*h[3])/
sqrt((h[1]*h[1]+h[5]*h[5])*(h[2]*h[2]+h[3]*h[3]+h[4]*h[4]));
dvalue = acos(cosalpha)*180.0/PI;
}
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_cellbeta()
{
if (!domain->triclinic)
dvalue = 90.0;
else {
// Cos(beta) = xz/c
double* h = domain->h;
double cosbeta = h[4]/sqrt(h[2]*h[2]+h[3]*h[3]+h[4]*h[4]);
dvalue = acos(cosbeta)*180.0/PI;
}
}
/* ---------------------------------------------------------------------- */
void Thermo::compute_cellgamma()
{
if (!domain->triclinic)
dvalue = 90.0;
else {
// Cos(gamma) = xy/b
double* h = domain->h;
double cosgamma = h[5]/sqrt(h[1]*h[1]+h[5]*h[5]);
dvalue = acos(cosgamma)*180.0/PI;
}
}
diff --git a/src/update.cpp b/src/update.cpp
index 947bba8c1..1ac25170d 100644
--- a/src/update.cpp
+++ b/src/update.cpp
@@ -1,384 +1,384 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "string.h"
#include "stdlib.h"
#include "update.h"
#include "style_integrate.h"
#include "style_minimize.h"
#include "neighbor.h"
#include "force.h"
#include "modify.h"
#include "fix.h"
#include "domain.h"
#include "region.h"
#include "compute.h"
#include "output.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Update::Update(LAMMPS *lmp) : Pointers(lmp)
{
char *str;
ntimestep = 0;
first_update = 0;
whichflag = 0;
firststep = laststep = 0;
beginstep = endstep = 0;
setupflag = 0;
multireplica = 0;
restrict_output = 0;
eflag_global = vflag_global = -1;
unit_style = NULL;
set_units("lj");
integrate_style = NULL;
integrate = NULL;
minimize_style = NULL;
minimize = NULL;
if (lmp->cuda) {
str = (char *) "verlet/cuda";
create_integrate(1,&str,NULL);
} else {
str = (char *) "verlet";
create_integrate(1,&str,NULL);
}
str = (char *) "cg";
create_minimize(1,&str);
}
/* ---------------------------------------------------------------------- */
Update::~Update()
{
delete [] unit_style;
delete [] integrate_style;
delete integrate;
delete [] minimize_style;
delete minimize;
}
/* ---------------------------------------------------------------------- */
void Update::init()
{
// if USER-CUDA mode is enabled:
// integrate/minimize style must be CUDA variant
if (whichflag == 1 && lmp->cuda)
if (strstr(integrate_style,"cuda") == NULL)
- error->all("USER-CUDA mode requires CUDA variant of run style");
+ error->all(FLERR,"USER-CUDA mode requires CUDA variant of run style");
if (whichflag == 2 && lmp->cuda)
if (strstr(minimize_style,"cuda") == NULL)
- error->all("USER-CUDA mode requires CUDA variant of min style");
+ error->all(FLERR,"USER-CUDA mode requires CUDA variant of min style");
// init the appropriate integrate and/or minimize class
// if neither (e.g. from write_restart) then just return
if (whichflag == 0) return;
if (whichflag == 1) integrate->init();
else if (whichflag == 2) minimize->init();
// only set first_update if a run or minimize is being performed
first_update = 1;
}
/* ---------------------------------------------------------------------- */
void Update::set_units(const char *style)
{
// physical constants from:
// http://physics.nist.gov/cuu/Constants/Table/allascii.txt
// using thermochemical calorie = 4.184 J
if (strcmp(style,"lj") == 0) {
force->boltz = 1.0;
force->hplanck = 0.18292026; // using LJ parameters for argon
force->mvv2e = 1.0;
force->ftm2v = 1.0;
force->mv2d = 1.0;
force->nktv2p = 1.0;
force->qqr2e = 1.0;
force->qe2f = 1.0;
force->vxmu2f = 1.0;
force->xxt2kmu = 1.0;
force->e_mass = 0.0; // not yet set
force->hhmrr2e = 0.0;
force->mvh2r = 0.0;
dt = 0.005;
neighbor->skin = 0.3;
} else if (strcmp(style,"real") == 0) {
force->boltz = 0.0019872067;
force->hplanck = 95.306976368;
force->mvv2e = 48.88821291 * 48.88821291;
force->ftm2v = 1.0 / 48.88821291 / 48.88821291;
force->mv2d = 1.0 / 0.602214179;
force->nktv2p = 68568.415;
force->qqr2e = 332.06371;
force->qe2f = 23.060549;
force->vxmu2f = 1.4393264316e4;
force->xxt2kmu = 0.1;
force->e_mass = 1.0/1836.1527556560675;
force->hhmrr2e = 0.0957018663603261;
force->mvh2r = 1.5339009481951;
dt = 1.0;
neighbor->skin = 2.0;
} else if (strcmp(style,"metal") == 0) {
force->boltz = 8.617343e-5;
force->hplanck = 4.135667403e-3;
force->mvv2e = 1.0364269e-4;
force->ftm2v = 1.0 / 1.0364269e-4;
force->mv2d = 1.0 / 0.602214179;
force->nktv2p = 1.6021765e6;
force->qqr2e = 14.399645;
force->qe2f = 1.0;
force->vxmu2f = 0.6241509647;
force->xxt2kmu = 1.0e-4;
force->e_mass = 0.0; // not yet set
force->hhmrr2e = 0.0;
force->mvh2r = 0.0;
dt = 0.001;
neighbor->skin = 2.0;
} else if (strcmp(style,"si") == 0) {
force->boltz = 1.3806504e-23;
force->hplanck = 6.62606896e-34;
force->mvv2e = 1.0;
force->ftm2v = 1.0;
force->mv2d = 1.0;
force->nktv2p = 1.0;
force->qqr2e = 8.9876e9;
force->qe2f = 1.0;
force->vxmu2f = 1.0;
force->xxt2kmu = 1.0;
force->e_mass = 0.0; // not yet set
force->hhmrr2e = 0.0;
force->mvh2r = 0.0;
dt = 1.0e-8;
neighbor->skin = 0.001;
} else if (strcmp(style,"cgs") == 0) {
force->boltz = 1.3806504e-16;
force->hplanck = 6.62606896e-27;
force->mvv2e = 1.0;
force->ftm2v = 1.0;
force->mv2d = 1.0;
force->nktv2p = 1.0;
force->qqr2e = 1.0;
force->qe2f = 1.0;
force->vxmu2f = 1.0;
force->xxt2kmu = 1.0;
force->e_mass = 0.0; // not yet set
force->hhmrr2e = 0.0;
force->mvh2r = 0.0;
dt = 1.0e-8;
neighbor->skin = 0.1;
} else if (strcmp(style,"electron") == 0) {
force->boltz = 3.16681534e-6;
force->hplanck = 0.1519829846;
force->mvv2e = 1.06657236;
force->ftm2v = 0.937582899;
force->mv2d = 1.0;
force->nktv2p = 2.94210108e13;
force->qqr2e = 1.0;
force->qe2f = 1.94469051e-10;
force->vxmu2f = 3.39893149e1;
force->xxt2kmu = 3.13796367e-2;
force->e_mass = 0.0; // not yet set
force->hhmrr2e = 0.0;
force->mvh2r = 0.0;
dt = 0.001;
neighbor->skin = 2.0;
- } else error->all("Illegal units command");
+ } else error->all(FLERR,"Illegal units command");
delete [] unit_style;
int n = strlen(style) + 1;
unit_style = new char[n];
strcpy(unit_style,style);
}
/* ---------------------------------------------------------------------- */
void Update::create_integrate(int narg, char **arg, char *suffix)
{
- if (narg < 1) error->all("Illegal run_style command");
+ if (narg < 1) error->all(FLERR,"Illegal run_style command");
delete [] integrate_style;
delete integrate;
int sflag;
new_integrate(arg[0],narg-1,&arg[1],suffix,sflag);
if (sflag) {
char estyle[256];
sprintf(estyle,"%s/%s",arg[0],suffix);
int n = strlen(estyle) + 1;
integrate_style = new char[n];
strcpy(integrate_style,estyle);
} else {
int n = strlen(arg[0]) + 1;
integrate_style = new char[n];
strcpy(integrate_style,arg[0]);
}
}
/* ----------------------------------------------------------------------
create the Integrate style, first with suffix appended
------------------------------------------------------------------------- */
void Update::new_integrate(char *style, int narg, char **arg,
char *suffix, int &sflag)
{
int success = 0;
if (suffix && lmp->suffix_enable) {
sflag = 1;
char estyle[256];
sprintf(estyle,"%s/%s",style,suffix);
success = 1;
if (0) return;
#define INTEGRATE_CLASS
#define IntegrateStyle(key,Class) \
else if (strcmp(estyle,#key) == 0) integrate = new Class(lmp,narg,arg);
#include "style_integrate.h"
#undef IntegrateStyle
#undef INTEGRATE_CLASS
else success = 0;
}
if (!success) {
sflag = 0;
if (0) return;
#define INTEGRATE_CLASS
#define IntegrateStyle(key,Class) \
else if (strcmp(style,#key) == 0) integrate = new Class(lmp,narg,arg);
#include "style_integrate.h"
#undef IntegrateStyle
#undef INTEGRATE_CLASS
- else error->all("Illegal integrate style");
+ else error->all(FLERR,"Illegal integrate style");
}
}
/* ---------------------------------------------------------------------- */
void Update::create_minimize(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal min_style command");
+ if (narg != 1) error->all(FLERR,"Illegal min_style command");
delete [] minimize_style;
delete minimize;
if (0) return; // dummy line to enable else-if macro expansion
#define MINIMIZE_CLASS
#define MinimizeStyle(key,Class) \
else if (strcmp(arg[0],#key) == 0) minimize = new Class(lmp);
#include "style_minimize.h"
#undef MINIMIZE_CLASS
- else error->all("Illegal min_style command");
+ else error->all(FLERR,"Illegal min_style command");
int n = strlen(arg[0]) + 1;
minimize_style = new char[n];
strcpy(minimize_style,arg[0]);
}
/* ----------------------------------------------------------------------
reset timestep from input script
do not allow dump files or a restart to be defined
do not allow any timestep-dependent fixes to be defined
do not allow any dynamic regions to be defined
reset eflag/vflag global so nothing will think eng/virial are current
reset invoked flags of computes,
so nothing will think they are current between runs
clear timestep list of computes that store future invocation times
------------------------------------------------------------------------- */
void Update::reset_timestep(int narg, char **arg)
{
- if (narg != 1) error->all("Illegal reset_timestep command");
+ if (narg != 1) error->all(FLERR,"Illegal reset_timestep command");
for (int i = 0; i < output->ndump; i++)
if (output->last_dump[i] >= 0)
- error->all("Cannot reset timestep with dump file already written to");
+ error->all(FLERR,"Cannot reset timestep with dump file already written to");
if (output->restart && output->last_restart >= 0)
- error->all("Cannot reset timestep with restart file already written");
+ error->all(FLERR,"Cannot reset timestep with restart file already written");
for (int i = 0; i < modify->nfix; i++)
if (modify->fix[i]->time_depend)
- error->all("Cannot reset timestep with a time-dependent fix defined");
+ error->all(FLERR,"Cannot reset timestep with a time-dependent fix defined");
for (int i = 0; i < domain->nregion; i++)
if (domain->regions[i]->dynamic_check())
- error->all("Cannot reset timestep with a dynamic region defined");
+ error->all(FLERR,"Cannot reset timestep with a dynamic region defined");
eflag_global = vflag_global = -1;
for (int i = 0; i < modify->ncompute; i++) {
modify->compute[i]->invoked_scalar = -1;
modify->compute[i]->invoked_vector = -1;
modify->compute[i]->invoked_array = -1;
modify->compute[i]->invoked_peratom = -1;
modify->compute[i]->invoked_local = -1;
}
for (int i = 0; i < modify->ncompute; i++)
if (modify->compute[i]->timeflag) modify->compute[i]->clearstep();
ntimestep = ATOBIGINT(arg[0]);
- if (ntimestep < 0) error->all("Timestep must be >= 0");
- if (ntimestep > MAXBIGINT) error->all("Too big a timestep");
+ if (ntimestep < 0) error->all(FLERR,"Timestep must be >= 0");
+ if (ntimestep > MAXBIGINT) error->all(FLERR,"Too big a timestep");
}
/* ----------------------------------------------------------------------
memory usage of update and integrate/minimize
------------------------------------------------------------------------- */
bigint Update::memory_usage()
{
bigint bytes = 0;
if (whichflag == 1) bytes += integrate->memory_usage();
else if (whichflag == 2) bytes += minimize->memory_usage();
return bytes;
}
diff --git a/src/variable.cpp b/src/variable.cpp
index b8ec5e589..a88445513 100644
--- a/src/variable.cpp
+++ b/src/variable.cpp
@@ -1,3309 +1,3306 @@
/* ----------------------------------------------------------------------
- LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+ LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "unistd.h"
#include "variable.h"
#include "universe.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "domain.h"
#include "region.h"
#include "modify.h"
#include "compute.h"
#include "fix.h"
#include "output.h"
#include "thermo.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
#define VARDELTA 4
#define MAXLEVEL 4
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
#define MYROUND(a) (( a-floor(a) ) >= .5) ? ceil(a) : floor(a)
enum{INDEX,LOOP,WORLD,UNIVERSE,ULOOP,STRING,EQUAL,ATOM};
enum{ARG,OP};
// customize by adding a function
enum{DONE,ADD,SUBTRACT,MULTIPLY,DIVIDE,CARAT,UNARY,
NOT,EQ,NE,LT,LE,GT,GE,AND,OR,
SQRT,EXP,LN,LOG,SIN,COS,TAN,ASIN,ACOS,ATAN,ATAN2,
RANDOM,NORMAL,CEIL,FLOOR,ROUND,RAMP,STAGGER,LOGFREQ,
VDISPLACE,SWIGGLE,CWIGGLE,GMASK,RMASK,GRMASK,
VALUE,ATOMARRAY,TYPEARRAY,INTARRAY};
// customize by adding a special function
enum{SUM,XMIN,XMAX,AVE,TRAP};
#define INVOKED_SCALAR 1
#define INVOKED_VECTOR 2
#define INVOKED_ARRAY 4
#define INVOKED_PERATOM 8
#define BIG 1.0e20
/* ---------------------------------------------------------------------- */
Variable::Variable(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
nvar = maxvar = 0;
names = NULL;
style = NULL;
num = NULL;
which = NULL;
pad = NULL;
data = NULL;
randomequal = NULL;
randomatom = NULL;
precedence[DONE] = 0;
precedence[OR] = 1;
precedence[AND] = 2;
precedence[EQ] = precedence[NE] = 3;
precedence[LT] = precedence[LE] = precedence[GT] = precedence[GE] = 4;
precedence[ADD] = precedence[SUBTRACT] = 5;
precedence[MULTIPLY] = precedence[DIVIDE] = 6;
precedence[CARAT] = 7;
precedence[UNARY] = precedence[NOT] = 8;
PI = 4.0*atan(1.0);
}
/* ---------------------------------------------------------------------- */
Variable::~Variable()
{
for (int i = 0; i < nvar; i++) {
delete [] names[i];
if (style[i] == LOOP || style[i] == ULOOP) delete [] data[i][0];
else for (int j = 0; j < num[i]; j++) delete [] data[i][j];
delete [] data[i];
}
memory->sfree(names);
memory->destroy(style);
memory->destroy(num);
memory->destroy(which);
memory->destroy(pad);
memory->sfree(data);
delete randomequal;
delete randomatom;
}
/* ----------------------------------------------------------------------
called by variable command in input script
------------------------------------------------------------------------- */
void Variable::set(int narg, char **arg)
{
- if (narg < 2) error->all("Illegal variable command");
+ if (narg < 2) error->all(FLERR,"Illegal variable command");
// DELETE
// doesn't matter if variable no longer exists
if (strcmp(arg[1],"delete") == 0) {
- if (narg != 2) error->all("Illegal variable command");
+ if (narg != 2) error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) remove(find(arg[0]));
return;
// INDEX
// num = listed args, which = 1st value, data = copied args
} else if (strcmp(arg[1],"index") == 0) {
- if (narg < 3) error->all("Illegal variable command");
+ if (narg < 3) error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) return;
if (nvar == maxvar) extend();
style[nvar] = INDEX;
num[nvar] = narg - 2;
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(num[nvar],&arg[2],data[nvar]);
// LOOP
// 1 arg + pad: num = N, which = 1st value, data = single string
// 2 args + pad: num = N2, which = N1, data = single string
} else if (strcmp(arg[1],"loop") == 0) {
if (find(arg[0]) >= 0) return;
if (nvar == maxvar) extend();
style[nvar] = LOOP;
int nfirst,nlast;
if (narg == 3 || (narg == 4 && strcmp(arg[3],"pad") == 0)) {
nfirst = 1;
nlast = atoi(arg[2]);
- if (nlast <= 0) error->all("Illegal variable command");
+ if (nlast <= 0) error->all(FLERR,"Illegal variable command");
if (narg == 4 && strcmp(arg[3],"pad") == 0) {
char digits[12];
sprintf(digits,"%d",nlast);
pad[nvar] = strlen(digits);
} else pad[nvar] = 0;
} else if (narg == 4 || (narg == 5 && strcmp(arg[4],"pad") == 0)) {
nfirst = atoi(arg[2]);
nlast = atoi(arg[3]);
- if (nfirst > nlast || nlast <= 0) error->all("Illegal variable command");
+ if (nfirst > nlast || nlast <= 0) error->all(FLERR,"Illegal variable command");
if (narg == 5 && strcmp(arg[4],"pad") == 0) {
char digits[12];
sprintf(digits,"%d",nlast);
pad[nvar] = strlen(digits);
} else pad[nvar] = 0;
- } else error->all("Illegal variable command");
+ } else error->all(FLERR,"Illegal variable command");
num[nvar] = nlast;
which[nvar] = nfirst-1;
data[nvar] = new char*[1];
data[nvar][0] = NULL;
// WORLD
// num = listed args, which = partition this proc is in, data = copied args
// error check that num = # of worlds in universe
} else if (strcmp(arg[1],"world") == 0) {
- if (narg < 3) error->all("Illegal variable command");
+ if (narg < 3) error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) return;
if (nvar == maxvar) extend();
style[nvar] = WORLD;
num[nvar] = narg - 2;
if (num[nvar] != universe->nworlds)
- error->all("World variable count doesn't match # of partitions");
+ error->all(FLERR,"World variable count doesn't match # of partitions");
which[nvar] = universe->iworld;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(num[nvar],&arg[2],data[nvar]);
// UNIVERSE and ULOOP
// for UNIVERSE: num = listed args, data = copied args
// for ULOOP: num = N, data = single string
// which = partition this proc is in
// universe proc 0 creates lock file
// error check that all other universe/uloop variables are same length
} else if (strcmp(arg[1],"universe") == 0 || strcmp(arg[1],"uloop") == 0) {
if (strcmp(arg[1],"universe") == 0) {
- if (narg < 3) error->all("Illegal variable command");
+ if (narg < 3) error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) return;
if (nvar == maxvar) extend();
style[nvar] = UNIVERSE;
num[nvar] = narg - 2;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(num[nvar],&arg[2],data[nvar]);
} else if (strcmp(arg[1],"uloop") == 0) {
if (narg < 3 || narg > 4 || (narg == 4 && strcmp(arg[3],"pad") != 0))
- error->all("Illegal variable command");
+ error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) return;
if (nvar == maxvar) extend();
style[nvar] = ULOOP;
num[nvar] = atoi(arg[2]);
data[nvar] = new char*[1];
data[nvar][0] = NULL;
if (narg == 4) {
char digits[12];
sprintf(digits,"%d",num[nvar]);
pad[nvar] = strlen(digits);
} else pad[nvar] = 0;
}
if (num[nvar] < universe->nworlds)
- error->all("Universe/uloop variable count < # of partitions");
+ error->all(FLERR,"Universe/uloop variable count < # of partitions");
which[nvar] = universe->iworld;
if (universe->me == 0) {
FILE *fp = fopen("tmp.lammps.variable","w");
fprintf(fp,"%d\n",universe->nworlds);
fclose(fp);
}
for (int jvar = 0; jvar < nvar; jvar++)
if (num[jvar] && (style[jvar] == UNIVERSE || style[jvar] == ULOOP) &&
num[nvar] != num[jvar])
- error->all("All universe/uloop variables must have same # of values");
+ error->all(FLERR,"All universe/uloop variables must have same # of values");
// STRING
// remove pre-existing var if also style STRING (allows it to be reset)
// num = 1, which = 1st value
// data = 1 value, string to eval
} else if (strcmp(arg[1],"string") == 0) {
- if (narg != 3) error->all("Illegal variable command");
+ if (narg != 3) error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) {
if (style[find(arg[0])] != STRING)
- error->all("Cannot redefine variable as a different style");
+ error->all(FLERR,"Cannot redefine variable as a different style");
remove(find(arg[0]));
}
if (nvar == maxvar) extend();
style[nvar] = STRING;
num[nvar] = 1;
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
// EQUAL
// remove pre-existing var if also style EQUAL (allows it to be reset)
// num = 2, which = 1st value
// data = 2 values, 1st is string to eval, 2nd is filled on retrieval
} else if (strcmp(arg[1],"equal") == 0) {
- if (narg != 3) error->all("Illegal variable command");
+ if (narg != 3) error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) {
if (style[find(arg[0])] != EQUAL)
- error->all("Cannot redefine variable as a different style");
+ error->all(FLERR,"Cannot redefine variable as a different style");
remove(find(arg[0]));
}
if (nvar == maxvar) extend();
style[nvar] = EQUAL;
num[nvar] = 2;
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
data[nvar][1] = NULL;
// ATOM
// remove pre-existing var if also style ATOM (allows it to be reset)
// num = 1, which = 1st value
// data = 1 value, string to eval
} else if (strcmp(arg[1],"atom") == 0) {
- if (narg != 3) error->all("Illegal variable command");
+ if (narg != 3) error->all(FLERR,"Illegal variable command");
if (find(arg[0]) >= 0) {
if (style[find(arg[0])] != ATOM)
- error->all("Cannot redefine variable as a different style");
+ error->all(FLERR,"Cannot redefine variable as a different style");
remove(find(arg[0]));
}
if (nvar == maxvar) extend();
style[nvar] = ATOM;
num[nvar] = 1;
which[nvar] = 0;
pad[nvar] = 0;
data[nvar] = new char*[num[nvar]];
copy(1,&arg[2],data[nvar]);
- } else error->all("Illegal variable command");
+ } else error->all(FLERR,"Illegal variable command");
// set name of variable
// must come at end, since STRING/EQUAL/ATOM reset may have removed name
// name must be all alphanumeric chars or underscores
int n = strlen(arg[0]) + 1;
names[nvar] = new char[n];
strcpy(names[nvar],arg[0]);
for (int i = 0; i < n-1; i++)
if (!isalnum(names[nvar][i]) && names[nvar][i] != '_')
- error->all("Variable name must be alphanumeric or "
+ error->all(FLERR,"Variable name must be alphanumeric or "
"underscore characters");
nvar++;
}
/* ----------------------------------------------------------------------
INDEX variable created by command-line argument
make it INDEX rather than STRING so cannot be re-defined in input script
------------------------------------------------------------------------- */
void Variable::set(char *name, int narg, char **arg)
{
char **newarg = new char*[2+narg];
newarg[0] = name;
newarg[1] = (char *) "index";
for (int i = 0; i < narg; i++) newarg[2+i] = arg[i];
set(2+narg,newarg);
delete [] newarg;
}
/* ----------------------------------------------------------------------
increment variable(s)
return 0 if OK if successfully incremented
return 1 if any variable is exhausted, free the variable to allow re-use
------------------------------------------------------------------------- */
int Variable::next(int narg, char **arg)
{
int ivar;
- if (narg == 0) error->all("Illegal next command");
+ if (narg == 0) error->all(FLERR,"Illegal next command");
// check that variables exist and are all the same style
// exception: UNIVERSE and ULOOP variables can be mixed in same next command
for (int iarg = 0; iarg < narg; iarg++) {
ivar = find(arg[iarg]);
- if (ivar == -1) error->all("Invalid variable in next command");
+ if (ivar == -1) error->all(FLERR,"Invalid variable in next command");
if (style[ivar] == ULOOP && style[find(arg[0])] == UNIVERSE) continue;
else if (style[ivar] == UNIVERSE && style[find(arg[0])] == ULOOP) continue;
else if (style[ivar] != style[find(arg[0])])
- error->all("All variables in next command must be same style");
+ error->all(FLERR,"All variables in next command must be same style");
}
// invalid styles STRING or EQUAL or WORLD or ATOM
int istyle = style[find(arg[0])];
if (istyle == STRING || istyle == EQUAL || istyle == WORLD || istyle == ATOM)
- error->all("Invalid variable style with next command");
+ error->all(FLERR,"Invalid variable style with next command");
// increment all variables in list
// if any variable is exhausted, set flag = 1 and remove var to allow re-use
int flag = 0;
if (istyle == INDEX || istyle == LOOP) {
for (int iarg = 0; iarg < narg; iarg++) {
ivar = find(arg[iarg]);
which[ivar]++;
if (which[ivar] >= num[ivar]) {
flag = 1;
remove(ivar);
}
}
} else if (istyle == UNIVERSE || istyle == ULOOP) {
// wait until lock file can be created and owned by proc 0 of this world
// read next available index and Bcast it within my world
// set all variables in list to nextindex
int nextindex;
if (me == 0) {
while (1) {
if (!rename("tmp.lammps.variable","tmp.lammps.variable.lock")) break;
usleep(100000);
}
FILE *fp = fopen("tmp.lammps.variable.lock","r");
fscanf(fp,"%d",&nextindex);
fclose(fp);
fp = fopen("tmp.lammps.variable.lock","w");
fprintf(fp,"%d\n",nextindex+1);
fclose(fp);
rename("tmp.lammps.variable.lock","tmp.lammps.variable");
if (universe->uscreen)
fprintf(universe->uscreen,
"Increment via next: value %d on partition %d\n",
nextindex+1,universe->iworld);
if (universe->ulogfile)
fprintf(universe->ulogfile,
"Increment via next: value %d on partition %d\n",
nextindex+1,universe->iworld);
}
MPI_Bcast(&nextindex,1,MPI_INT,0,world);
for (int iarg = 0; iarg < narg; iarg++) {
ivar = find(arg[iarg]);
which[ivar] = nextindex;
if (which[ivar] >= num[ivar]) {
flag = 1;
remove(ivar);
}
}
}
return flag;
}
/* ----------------------------------------------------------------------
return ptr to the data text associated with a variable
if INDEX or WORLD or UNIVERSE or STRING var, return ptr to stored string
if LOOP or ULOOP var, write int to data[0] and return ptr to string
if EQUAL var, evaluate variable and put result in str
if ATOM var, return NULL
return NULL if no variable or which is bad, caller must respond
------------------------------------------------------------------------- */
char *Variable::retrieve(char *name)
{
int ivar = find(name);
if (ivar == -1) return NULL;
if (which[ivar] >= num[ivar]) return NULL;
char *str;
if (style[ivar] == INDEX || style[ivar] == WORLD ||
style[ivar] == UNIVERSE || style[ivar] == STRING) {
str = data[ivar][which[ivar]];
} else if (style[ivar] == LOOP || style[ivar] == ULOOP) {
char result[16];
if (pad[ivar] == 0) sprintf(result,"%d",which[ivar]+1);
else {
char padstr[16];
sprintf(padstr,"%%0%dd",pad[ivar]);
sprintf(result,padstr,which[ivar]+1);
}
int n = strlen(result) + 1;
delete [] data[ivar][0];
data[ivar][0] = new char[n];
strcpy(data[ivar][0],result);
str = data[ivar][0];
} else if (style[ivar] == EQUAL) {
char result[32];
double answer = evaluate(data[ivar][0],NULL);
sprintf(result,"%.10g",answer);
int n = strlen(result) + 1;
if (data[ivar][1]) delete [] data[ivar][1];
data[ivar][1] = new char[n];
strcpy(data[ivar][1],result);
str = data[ivar][1];
} else if (style[ivar] == ATOM) return NULL;
return str;
}
/* ----------------------------------------------------------------------
return result of equal-style variable evaluation
------------------------------------------------------------------------- */
double Variable::compute_equal(int ivar)
{
return evaluate(data[ivar][0],NULL);
}
/* ----------------------------------------------------------------------
compute result of atom-style variable evaluation
only computed for atoms in igroup, else result is 0.0
answers are placed every stride locations into result
if sumflag, add variable values to existing result
------------------------------------------------------------------------- */
void Variable::compute_atom(int ivar, int igroup,
double *result, int stride, int sumflag)
{
Tree *tree;
double tmp = evaluate(data[ivar][0],&tree);
tmp = collapse_tree(tree);
int groupbit = group->bitmask[igroup];
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (sumflag == 0) {
int m = 0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) result[m] = eval_tree(tree,i);
else result[m] = 0.0;
m += stride;
}
} else {
int m = 0;
for (int i = 0; i < nlocal; i++) {
if (mask[i] && groupbit) result[m] += eval_tree(tree,i);
m += stride;
}
}
free_tree(tree);
}
/* ----------------------------------------------------------------------
search for name in list of variables names
return index or -1 if not found
------------------------------------------------------------------------- */
int Variable::find(char *name)
{
for (int i = 0; i < nvar; i++)
if (strcmp(name,names[i]) == 0) return i;
return -1;
}
/* ----------------------------------------------------------------------
return 1 if variable is EQUAL style, 0 if not
------------------------------------------------------------------------- */
int Variable::equalstyle(int ivar)
{
if (style[ivar] == EQUAL) return 1;
return 0;
}
/* ----------------------------------------------------------------------
return 1 if variable is ATOM style, 0 if not
------------------------------------------------------------------------- */
int Variable::atomstyle(int ivar)
{
if (style[ivar] == ATOM) return 1;
return 0;
}
/* ----------------------------------------------------------------------
remove Nth variable from list and compact list
------------------------------------------------------------------------- */
void Variable::remove(int n)
{
delete [] names[n];
if (style[n] == LOOP || style[n] == ULOOP) delete [] data[n][0];
else for (int i = 0; i < num[n]; i++) delete [] data[n][i];
delete [] data[n];
for (int i = n+1; i < nvar; i++) {
names[i-1] = names[i];
style[i-1] = style[i];
num[i-1] = num[i];
which[i-1] = which[i];
pad[i-1] = pad[i];
data[i-1] = data[i];
}
nvar--;
}
/* ----------------------------------------------------------------------
make space in arrays for new variable
------------------------------------------------------------------------- */
void Variable::extend()
{
maxvar += VARDELTA;
names = (char **)
memory->srealloc(names,maxvar*sizeof(char *),"var:names");
memory->grow(style,maxvar,"var:style");
memory->grow(num,maxvar,"var:num");
memory->grow(which,maxvar,"var:which");
memory->grow(pad,maxvar,"var:pad");
data = (char ***)
memory->srealloc(data,maxvar*sizeof(char **),"var:data");
}
/* ----------------------------------------------------------------------
copy narg strings from **from to **to, and allocate space for them
------------------------------------------------------------------------- */
void Variable::copy(int narg, char **from, char **to)
{
int n;
for (int i = 0; i < narg; i++) {
n = strlen(from[i]) + 1;
to[i] = new char[n];
strcpy(to[i],from[i]);
}
}
/* ----------------------------------------------------------------------
recursive evaluation of a string str
str is an equal-style or atom-style formula containing one or more items:
number = 0.0, -5.45, 2.8e-4, ...
constant = PI
thermo keyword = ke, vol, atoms, ...
math operation = (),-x,x+y,x-y,x*y,x/y,x^y,
x==y,x!=y,x<y,x<=y,x>y,x>=y,x&&y,x||y,
sqrt(x),exp(x),ln(x),log(x),
sin(x),cos(x),tan(x),asin(x),atan2(y,x),...
group function = count(group), mass(group), xcm(group,x), ...
special function = sum(x),min(x), ...
atom value = x[i], y[i], vx[i], ...
atom vector = x, y, vx, ...
compute = c_ID, c_ID[i], c_ID[i][j]
fix = f_ID, f_ID[i], f_ID[i][j]
variable = v_name, v_name[i]
equal-style variables passes in tree = NULL:
evaluate the formula, return result as a double
atom-style variable passes in tree = non-NULL:
parse the formula but do not evaluate it
create a parse tree and return it
------------------------------------------------------------------------- */
double Variable::evaluate(char *str, Tree **tree)
{
int op,opprevious;
double value1,value2;
char onechar;
char *ptr;
double argstack[MAXLEVEL];
Tree *treestack[MAXLEVEL];
int opstack[MAXLEVEL];
int nargstack = 0;
int ntreestack = 0;
int nopstack = 0;
int i = 0;
int expect = ARG;
while (1) {
onechar = str[i];
// whitespace: just skip
if (isspace(onechar)) i++;
// ----------------
// parentheses: recursively evaluate contents of parens
// ----------------
else if (onechar == '(') {
- if (expect == OP) error->all("Invalid syntax in variable formula");
+ if (expect == OP) error->all(FLERR,"Invalid syntax in variable formula");
expect = OP;
char *contents;
i = find_matching_paren(str,i,contents);
i++;
// evaluate contents and push on stack
if (tree) {
Tree *newtree;
evaluate(contents,&newtree);
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = evaluate(contents,NULL);
delete [] contents;
// ----------------
// number: push value onto stack
// ----------------
} else if (isdigit(onechar) || onechar == '.') {
- if (expect == OP) error->all("Invalid syntax in variable formula");
+ if (expect == OP) error->all(FLERR,"Invalid syntax in variable formula");
expect = OP;
// istop = end of number, including scientific notation
int istart = i;
while (isdigit(str[i]) || str[i] == '.') i++;
if (str[i] == 'e' || str[i] == 'E') {
i++;
if (str[i] == '+' || str[i] == '-') i++;
while (isdigit(str[i])) i++;
}
int istop = i - 1;
int n = istop - istart + 1;
char *number = new char[n+1];
strncpy(number,&str[istart],n);
number[n] = '\0';
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = atof(number);
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = atof(number);
delete [] number;
// ----------------
// letter: c_ID, c_ID[], c_ID[][], f_ID, f_ID[], f_ID[][],
// v_name, v_name[], exp(), xcm(,), x, x[], PI, vol
// ----------------
} else if (isalpha(onechar)) {
- if (expect == OP) error->all("Invalid syntax in variable formula");
+ if (expect == OP) error->all(FLERR,"Invalid syntax in variable formula");
expect = OP;
// istop = end of word
// word = all alphanumeric or underscore
int istart = i;
while (isalnum(str[i]) || str[i] == '_') i++;
int istop = i-1;
int n = istop - istart + 1;
char *word = new char[n+1];
strncpy(word,&str[istart],n);
word[n] = '\0';
// ----------------
// compute
// ----------------
if (strncmp(word,"c_",2) == 0) {
if (domain->box_exist == 0)
- error->all("Variable evaluation before simulation box is defined");
+ error->all(FLERR,"Variable evaluation before simulation box is defined");
n = strlen(word) - 2 + 1;
char *id = new char[n];
strcpy(id,&word[2]);
int icompute = modify->find_compute(id);
- if (icompute < 0) error->all("Invalid compute ID in variable formula");
+ if (icompute < 0) error->all(FLERR,"Invalid compute ID in variable formula");
Compute *compute = modify->compute[icompute];
delete [] id;
// parse zero or one or two trailing brackets
// point i beyond last bracket
// nbracket = # of bracket pairs
// index1,index2 = int inside each bracket pair
int nbracket,index1,index2;
if (str[i] != '[') nbracket = 0;
else {
nbracket = 1;
ptr = &str[i];
index1 = int_between_brackets(ptr);
i = ptr-str+1;
if (str[i] == '[') {
nbracket = 2;
ptr = &str[i];
index2 = int_between_brackets(ptr);
i = ptr-str+1;
}
}
// c_ID = scalar from global scalar
if (nbracket == 0 && compute->scalar_flag) {
if (update->whichflag == 0) {
if (compute->invoked_scalar != update->ntimestep)
- error->all("Compute used in variable between runs "
+ error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_SCALAR)) {
compute->compute_scalar();
compute->invoked_flag |= INVOKED_SCALAR;
}
value1 = compute->scalar;
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// c_ID[i] = scalar from global vector
} else if (nbracket == 1 && compute->vector_flag) {
if (index1 > compute->size_vector)
- error->all("Variable formula compute vector "
+ error->all(FLERR,"Variable formula compute vector "
"is accessed out-of-range");
if (update->whichflag == 0) {
if (compute->invoked_vector != update->ntimestep)
- error->all("Compute used in variable between runs "
+ error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
value1 = compute->vector[index1-1];
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// c_ID[i][j] = scalar from global array
} else if (nbracket == 2 && compute->array_flag) {
if (index1 > compute->size_array_rows)
- error->all("Variable formula compute array "
+ error->all(FLERR,"Variable formula compute array "
"is accessed out-of-range");
if (index2 > compute->size_array_cols)
- error->all("Variable formula compute array "
+ error->all(FLERR,"Variable formula compute array "
"is accessed out-of-range");
if (update->whichflag == 0) {
if (compute->invoked_array != update->ntimestep)
- error->all("Compute used in variable between runs "
+ error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
}
value1 = compute->array[index1-1][index2-1];
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// c_ID[i] = scalar from per-atom vector
} else if (nbracket == 1 && compute->peratom_flag &&
compute->size_peratom_cols == 0) {
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
- error->all("Compute used in variable between runs "
+ error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
peratom2global(1,NULL,compute->vector_atom,1,index1,
tree,treestack,ntreestack,argstack,nargstack);
// c_ID[i][j] = scalar from per-atom array
} else if (nbracket == 2 && compute->peratom_flag &&
compute->size_peratom_cols > 0) {
if (index2 > compute->size_peratom_cols)
- error->all("Variable formula compute array "
+ error->all(FLERR,"Variable formula compute array "
"is accessed out-of-range");
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
- error->all("Compute used in variable between runs "
+ error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
peratom2global(1,NULL,&compute->array_atom[0][index2-1],
compute->size_peratom_cols,index1,
tree,treestack,ntreestack,argstack,nargstack);
// c_ID = vector from per-atom vector
} else if (nbracket == 0 && compute->peratom_flag &&
compute->size_peratom_cols == 0) {
if (tree == NULL)
- error->all("Per-atom compute in equal-style variable formula");
+ error->all(FLERR,"Per-atom compute in equal-style variable formula");
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
- error->all("Compute used in variable between runs "
+ error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = compute->vector_atom;
newtree->nstride = 1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
// c_ID[i] = vector from per-atom array
} else if (nbracket == 1 && compute->peratom_flag &&
compute->size_peratom_cols > 0) {
if (tree == NULL)
- error->all("Per-atom compute in equal-style variable formula");
+ error->all(FLERR,"Per-atom compute in equal-style variable formula");
if (index1 > compute->size_peratom_cols)
- error->all("Variable formula compute array "
+ error->all(FLERR,"Variable formula compute array "
"is accessed out-of-range");
if (update->whichflag == 0) {
if (compute->invoked_peratom != update->ntimestep)
- error->all("Compute used in variable between runs "
+ error->all(FLERR,"Compute used in variable between runs "
"is not current");
} else if (!(compute->invoked_flag & INVOKED_PERATOM)) {
compute->compute_peratom();
compute->invoked_flag |= INVOKED_PERATOM;
}
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = &compute->array_atom[0][index1-1];
newtree->nstride = compute->size_peratom_cols;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
- } else error->all("Mismatched compute in variable formula");
+ } else error->all(FLERR,"Mismatched compute in variable formula");
// ----------------
// fix
// ----------------
} else if (strncmp(word,"f_",2) == 0) {
if (domain->box_exist == 0)
- error->all("Variable evaluation before simulation box is defined");
+ error->all(FLERR,"Variable evaluation before simulation box is defined");
n = strlen(word) - 2 + 1;
char *id = new char[n];
strcpy(id,&word[2]);
int ifix = modify->find_fix(id);
- if (ifix < 0) error->all("Invalid fix ID in variable formula");
+ if (ifix < 0) error->all(FLERR,"Invalid fix ID in variable formula");
Fix *fix = modify->fix[ifix];
delete [] id;
// parse zero or one or two trailing brackets
// point i beyond last bracket
// nbracket = # of bracket pairs
// index1,index2 = int inside each bracket pair
int nbracket,index1,index2;
if (str[i] != '[') nbracket = 0;
else {
nbracket = 1;
ptr = &str[i];
index1 = int_between_brackets(ptr);
i = ptr-str+1;
if (str[i] == '[') {
nbracket = 2;
ptr = &str[i];
index2 = int_between_brackets(ptr);
i = ptr-str+1;
}
}
// f_ID = scalar from global scalar
if (nbracket == 0 && fix->scalar_flag) {
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
value1 = fix->compute_scalar();
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// f_ID[i] = scalar from global vector
} else if (nbracket == 1 && fix->vector_flag) {
if (index1 > fix->size_vector)
- error->all("Variable formula fix vector is accessed out-of-range");
+ error->all(FLERR,"Variable formula fix vector is accessed out-of-range");
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
value1 = fix->compute_vector(index1-1);
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// f_ID[i][j] = scalar from global array
} else if (nbracket == 2 && fix->array_flag) {
if (index1 > fix->size_array_rows)
- error->all("Variable formula fix array is accessed out-of-range");
+ error->all(FLERR,"Variable formula fix array is accessed out-of-range");
if (index2 > fix->size_array_cols)
- error->all("Variable formula fix array is accessed out-of-range");
+ error->all(FLERR,"Variable formula fix array is accessed out-of-range");
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
value1 = fix->compute_array(index1-1,index2-1);
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// f_ID[i] = scalar from per-atom vector
} else if (nbracket == 1 && fix->peratom_flag &&
fix->size_peratom_cols == 0) {
if (update->whichflag > 0 &&
update->ntimestep % fix->peratom_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
peratom2global(1,NULL,fix->vector_atom,1,index1,
tree,treestack,ntreestack,argstack,nargstack);
// f_ID[i][j] = scalar from per-atom array
} else if (nbracket == 2 && fix->peratom_flag &&
fix->size_peratom_cols > 0) {
if (index2 > fix->size_peratom_cols)
- error->all("Variable formula fix array is accessed out-of-range");
+ error->all(FLERR,"Variable formula fix array is accessed out-of-range");
if (update->whichflag > 0 &&
update->ntimestep % fix->peratom_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
peratom2global(1,NULL,&fix->array_atom[0][index2-1],
fix->size_peratom_cols,index1,
tree,treestack,ntreestack,argstack,nargstack);
// f_ID = vector from per-atom vector
} else if (nbracket == 0 && fix->peratom_flag &&
fix->size_peratom_cols == 0) {
if (tree == NULL)
- error->all("Per-atom fix in equal-style variable formula");
+ error->all(FLERR,"Per-atom fix in equal-style variable formula");
if (update->whichflag > 0 &&
update->ntimestep % fix->peratom_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = fix->vector_atom;
newtree->nstride = 1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
// f_ID[i] = vector from per-atom array
} else if (nbracket == 1 && fix->peratom_flag &&
fix->size_peratom_cols > 0) {
if (tree == NULL)
- error->all("Per-atom fix in equal-style variable formula");
+ error->all(FLERR,"Per-atom fix in equal-style variable formula");
if (index1 > fix->size_peratom_cols)
- error->all("Variable formula fix array is accessed out-of-range");
+ error->all(FLERR,"Variable formula fix array is accessed out-of-range");
if (update->whichflag > 0 &&
update->ntimestep % fix->peratom_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->array = &fix->array_atom[0][index1-1];
newtree->nstride = fix->size_peratom_cols;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
- } else error->all("Mismatched fix in variable formula");
+ } else error->all(FLERR,"Mismatched fix in variable formula");
// ----------------
// variable
// ----------------
} else if (strncmp(word,"v_",2) == 0) {
n = strlen(word) - 2 + 1;
char *id = new char[n];
strcpy(id,&word[2]);
int ivar = find(id);
- if (ivar < 0) error->all("Invalid variable name in variable formula");
+ if (ivar < 0) error->all(FLERR,"Invalid variable name in variable formula");
// parse zero or one trailing brackets
// point i beyond last bracket
// nbracket = # of bracket pairs
// index = int inside bracket
int nbracket,index;
if (str[i] != '[') nbracket = 0;
else {
nbracket = 1;
ptr = &str[i];
index = int_between_brackets(ptr);
i = ptr-str+1;
}
// v_name = scalar from non atom-style global scalar
if (nbracket == 0 && style[ivar] != ATOM) {
char *var = retrieve(id);
if (var == NULL)
- error->all("Invalid variable evaluation in variable formula");
+ error->all(FLERR,"Invalid variable evaluation in variable formula");
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = atof(var);
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = atof(var);
// v_name = vector from atom-style per-atom vector
} else if (nbracket == 0 && style[ivar] == ATOM) {
if (tree == NULL)
- error->all("Atom-style variable in equal-style variable formula");
+ error->all(FLERR,"Atom-style variable in equal-style variable formula");
Tree *newtree;
evaluate(data[ivar][0],&newtree);
treestack[ntreestack++] = newtree;
// v_name[N] = scalar from atom-style per-atom vector
// compute the per-atom variable in result
// use peratom2global to extract single value from result
} else if (nbracket && style[ivar] == ATOM) {
double *result;
memory->create(result,atom->nlocal,"variable:result");
compute_atom(ivar,0,result,1,0);
peratom2global(1,NULL,result,1,index,
tree,treestack,ntreestack,argstack,nargstack);
memory->destroy(result);
- } else error->all("Mismatched variable in variable formula");
+ } else error->all(FLERR,"Mismatched variable in variable formula");
delete [] id;
// ----------------
// math/group/special function or atom value/vector or
// constant or thermo keyword
// ----------------
} else {
// ----------------
// math or group or special function
// ----------------
if (str[i] == '(') {
char *contents;
i = find_matching_paren(str,i,contents);
i++;
if (math_function(word,contents,tree,
treestack,ntreestack,argstack,nargstack));
else if (group_function(word,contents,tree,
treestack,ntreestack,argstack,nargstack));
else if (special_function(word,contents,tree,
treestack,ntreestack,argstack,nargstack));
- else error->all("Invalid math/group/special function "
+ else error->all(FLERR,"Invalid math/group/special function "
"in variable formula");
delete [] contents;
// ----------------
// atom value
// ----------------
} else if (str[i] == '[') {
if (domain->box_exist == 0)
- error->all("Variable evaluation before simulation box is defined");
+ error->all(FLERR,"Variable evaluation before simulation box is defined");
ptr = &str[i];
int id = int_between_brackets(ptr);
i = ptr-str+1;
peratom2global(0,word,NULL,0,id,
tree,treestack,ntreestack,argstack,nargstack);
// ----------------
// atom vector
// ----------------
} else if (is_atom_vector(word)) {
if (domain->box_exist == 0)
- error->all("Variable evaluation before simulation box is defined");
+ error->all(FLERR,"Variable evaluation before simulation box is defined");
atom_vector(word,tree,treestack,ntreestack);
// ----------------
// constant
// ----------------
} else if (is_constant(word)) {
value1 = constant(word);
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
// ----------------
// thermo keyword
// ----------------
} else {
if (domain->box_exist == 0)
- error->all("Variable evaluation before simulation box is defined");
+ error->all(FLERR,"Variable evaluation before simulation box is defined");
int flag = output->thermo->evaluate_keyword(word,&value1);
- if (flag) error->all("Invalid thermo keyword in variable formula");
+ if (flag) error->all(FLERR,"Invalid thermo keyword in variable formula");
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value1;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value1;
}
}
delete [] word;
// ----------------
// math operator, including end-of-string
// ----------------
} else if (strchr("+-*/^<>=!&|\0",onechar)) {
if (onechar == '+') op = ADD;
else if (onechar == '-') op = SUBTRACT;
else if (onechar == '*') op = MULTIPLY;
else if (onechar == '/') op = DIVIDE;
else if (onechar == '^') op = CARAT;
else if (onechar == '=') {
- if (str[i+1] != '=') error->all("Invalid syntax in variable formula");
+ if (str[i+1] != '=') error->all(FLERR,"Invalid syntax in variable formula");
op = EQ;
i++;
} else if (onechar == '!') {
if (str[i+1] == '=') {
op = NE;
i++;
} else op = NOT;
} else if (onechar == '<') {
if (str[i+1] != '=') op = LT;
else {
op = LE;
i++;
}
} else if (onechar == '>') {
if (str[i+1] != '=') op = GT;
else {
op = GE;
i++;
}
} else if (onechar == '&') {
- if (str[i+1] != '&') error->all("Invalid syntax in variable formula");
+ if (str[i+1] != '&') error->all(FLERR,"Invalid syntax in variable formula");
op = AND;
i++;
} else if (onechar == '|') {
- if (str[i+1] != '|') error->all("Invalid syntax in variable formula");
+ if (str[i+1] != '|') error->all(FLERR,"Invalid syntax in variable formula");
op = OR;
i++;
} else op = DONE;
i++;
if (op == SUBTRACT && expect == ARG) {
opstack[nopstack++] = UNARY;
continue;
}
if (op == NOT && expect == ARG) {
opstack[nopstack++] = op;
continue;
}
- if (expect == ARG) error->all("Invalid syntax in variable formula");
+ if (expect == ARG) error->all(FLERR,"Invalid syntax in variable formula");
expect = ARG;
// evaluate stack as deep as possible while respecting precedence
// before pushing current op onto stack
while (nopstack && precedence[opstack[nopstack-1]] >= precedence[op]) {
opprevious = opstack[--nopstack];
if (tree) {
Tree *newtree = new Tree();
newtree->type = opprevious;
if (opprevious == UNARY) {
newtree->left = treestack[--ntreestack];
newtree->middle = newtree->right = NULL;
} else {
newtree->right = treestack[--ntreestack];
newtree->middle = NULL;
newtree->left = treestack[--ntreestack];
}
treestack[ntreestack++] = newtree;
} else {
value2 = argstack[--nargstack];
if (opprevious != UNARY && opprevious != NOT)
value1 = argstack[--nargstack];
if (opprevious == ADD)
argstack[nargstack++] = value1 + value2;
else if (opprevious == SUBTRACT)
argstack[nargstack++] = value1 - value2;
else if (opprevious == MULTIPLY)
argstack[nargstack++] = value1 * value2;
else if (opprevious == DIVIDE) {
- if (value2 == 0.0) error->all("Divide by 0 in variable formula");
+ if (value2 == 0.0) error->all(FLERR,"Divide by 0 in variable formula");
argstack[nargstack++] = value1 / value2;
} else if (opprevious == CARAT) {
- if (value2 == 0.0) error->all("Power by 0 in variable formula");
+ if (value2 == 0.0) error->all(FLERR,"Power by 0 in variable formula");
argstack[nargstack++] = pow(value1,value2);
} else if (opprevious == UNARY) {
argstack[nargstack++] = -value2;
} else if (opprevious == NOT) {
if (value2 == 0.0) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == EQ) {
if (value1 == value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == NE) {
if (value1 != value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == LT) {
if (value1 < value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == LE) {
if (value1 <= value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == GT) {
if (value1 > value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == GE) {
if (value1 >= value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == AND) {
if (value1 != 0.0 && value2 != 0.0) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == OR) {
if (value1 != 0.0 || value2 != 0.0) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
}
}
}
// if end-of-string, break out of entire formula evaluation loop
if (op == DONE) break;
// push current operation onto stack
opstack[nopstack++] = op;
- } else error->all("Invalid syntax in variable formula");
+ } else error->all(FLERR,"Invalid syntax in variable formula");
}
- if (nopstack) error->all("Invalid syntax in variable formula");
+ if (nopstack) error->all(FLERR,"Invalid syntax in variable formula");
// for atom-style variable, return remaining tree
// for equal-style variable, return remaining arg
if (tree) {
- if (ntreestack != 1) error->all("Invalid syntax in variable formula");
+ if (ntreestack != 1) error->all(FLERR,"Invalid syntax in variable formula");
*tree = treestack[0];
return 0.0;
} else {
- if (nargstack != 1) error->all("Invalid syntax in variable formula");
+ if (nargstack != 1) error->all(FLERR,"Invalid syntax in variable formula");
return argstack[0];
}
}
/* ----------------------------------------------------------------------
one-time collapse of an atom-style variable parse tree
tree was created by one-time parsing of formula string via evaulate()
only keep tree nodes that depend on ATOMARRAY, TYPEARRAY, INTARRAY
remainder is converted to single VALUE
this enables optimal eval_tree loop over atoms
customize by adding a function:
sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(),
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),
ramp(x,y),stagger(x,y),logfreq(x,y,z),
vdisplace(x,y),swiggle(x,y,z),cwiggle(x,y,z),
gmask(x),rmask(x),grmask(x,y)
---------------------------------------------------------------------- */
double Variable::collapse_tree(Tree *tree)
{
double arg1,arg2;
if (tree->type == VALUE) return tree->value;
if (tree->type == ATOMARRAY) return 0.0;
if (tree->type == TYPEARRAY) return 0.0;
if (tree->type == INTARRAY) return 0.0;
if (tree->type == ADD) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = arg1 + arg2;
return tree->value;
}
if (tree->type == SUBTRACT) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = arg1 - arg2;
return tree->value;
}
if (tree->type == MULTIPLY) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = arg1 * arg2;
return tree->value;
}
if (tree->type == DIVIDE) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
- if (arg2 == 0.0) error->one("Divide by 0 in variable formula");
+ if (arg2 == 0.0) error->one(FLERR,"Divide by 0 in variable formula");
tree->value = arg1 / arg2;
return tree->value;
}
if (tree->type == CARAT) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
- if (arg2 == 0.0) error->one("Power by 0 in variable formula");
+ if (arg2 == 0.0) error->one(FLERR,"Power by 0 in variable formula");
tree->value = pow(arg1,arg2);
return tree->value;
}
if (tree->type == UNARY) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = -arg1;
return tree->value;
}
if (tree->type == NOT) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 == 0.0) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == EQ) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 == arg2) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == NE) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 != arg2) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == LT) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 < arg2) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == LE) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 <= arg2) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == GT) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 > arg2) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == GE) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 >= arg2) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == AND) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 != 0.0 && arg2 != 0.0) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == OR) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 != 0.0 || arg2 != 0.0) tree->value = 1.0;
else tree->value = 0.0;
return tree->value;
}
if (tree->type == SQRT) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
- if (arg1 < 0.0) error->one("Sqrt of negative value in variable formula");
+ if (arg1 < 0.0) error->one(FLERR,"Sqrt of negative value in variable formula");
tree->value = sqrt(arg1);
return tree->value;
}
if (tree->type == EXP) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = exp(arg1);
return tree->value;
}
if (tree->type == LN) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 <= 0.0)
- error->one("Log of zero/negative value in variable formula");
+ error->one(FLERR,"Log of zero/negative value in variable formula");
tree->value = log(arg1);
return tree->value;
}
if (tree->type == LOG) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 <= 0.0)
- error->one("Log of zero/negative value in variable formula");
+ error->one(FLERR,"Log of zero/negative value in variable formula");
tree->value = log10(arg1);
return tree->value;
}
if (tree->type == SIN) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = sin(arg1);
return tree->value;
}
if (tree->type == COS) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = cos(arg1);
return tree->value;
}
if (tree->type == TAN) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = tan(arg1);
return tree->value;
}
if (tree->type == ASIN) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 < -1.0 || arg1 > 1.0)
- error->one("Arcsin of invalid value in variable formula");
+ error->one(FLERR,"Arcsin of invalid value in variable formula");
tree->value = asin(arg1);
return tree->value;
}
if (tree->type == ACOS) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
if (arg1 < -1.0 || arg1 > 1.0)
- error->one("Arccos of invalid value in variable formula");
+ error->one(FLERR,"Arccos of invalid value in variable formula");
tree->value = acos(arg1);
return tree->value;
}
if (tree->type == ATAN) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = atan(arg1);
return tree->value;
}
if (tree->type == ATAN2) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = atan2(arg1,arg2);
return tree->value;
}
// random() or normal() do not become a single collapsed value
if (tree->type == RANDOM) {
collapse_tree(tree->left);
collapse_tree(tree->middle);
if (randomatom == NULL) {
int seed = static_cast<int> (collapse_tree(tree->right));
- if (seed <= 0) error->one("Invalid math function in variable formula");
+ if (seed <= 0) error->one(FLERR,"Invalid math function in variable formula");
randomatom = new RanMars(lmp,seed+me);
}
return 0.0;
}
if (tree->type == NORMAL) {
collapse_tree(tree->left);
double sigma = collapse_tree(tree->middle);
- if (sigma < 0.0) error->one("Invalid math function in variable formula");
+ if (sigma < 0.0) error->one(FLERR,"Invalid math function in variable formula");
if (randomatom == NULL) {
int seed = static_cast<int> (collapse_tree(tree->right));
- if (seed <= 0) error->one("Invalid math function in variable formula");
+ if (seed <= 0) error->one(FLERR,"Invalid math function in variable formula");
randomatom = new RanMars(lmp,seed+me);
}
return 0.0;
}
if (tree->type == CEIL) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = ceil(arg1);
return tree->value;
}
if (tree->type == FLOOR) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = floor(arg1);
return tree->value;
}
if (tree->type == ROUND) {
arg1 = collapse_tree(tree->left);
if (tree->left->type != VALUE) return 0.0;
tree->type = VALUE;
tree->value = MYROUND(arg1);
return tree->value;
}
if (tree->type == RAMP) {
arg1 = collapse_tree(tree->left);
arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
tree->value = arg1 + delta*(arg2-arg1);
return tree->value;
}
if (tree->type == STAGGER) {
int ivalue1 = static_cast<int> (collapse_tree(tree->left));
int ivalue2 = static_cast<int> (collapse_tree(tree->right));
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2)
- error->one("Invalid math function in variable formula");
+ error->one(FLERR,"Invalid math function in variable formula");
int lower = update->ntimestep/ivalue1 * ivalue1;
int delta = update->ntimestep - lower;
if (delta < ivalue2) tree->value = lower+ivalue2;
else tree->value = lower+ivalue1;
return tree->value;
}
if (tree->type == LOGFREQ) {
int ivalue1 = static_cast<int> (collapse_tree(tree->left));
int ivalue2 = static_cast<int> (collapse_tree(tree->middle));
int ivalue3 = static_cast<int> (collapse_tree(tree->right));
if (tree->left->type != VALUE || tree->middle->type != VALUE ||
tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3)
- error->one("Invalid math function in variable formula");
+ error->one(FLERR,"Invalid math function in variable formula");
if (update->ntimestep < ivalue1) tree->value = ivalue1;
else {
int lower = ivalue1;
while (update->ntimestep >= ivalue3*lower) lower *= ivalue3;
int multiple = update->ntimestep/lower;
if (multiple < ivalue2) tree->value = (multiple+1)*lower;
else tree->value = lower*ivalue3;
}
return tree->value;
}
if (tree->type == VDISPLACE) {
double arg1 = collapse_tree(tree->left);
double arg2 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
double delta = update->ntimestep - update->beginstep;
tree->value = arg1 + arg2*delta*update->dt;
return tree->value;
}
if (tree->type == SWIGGLE) {
double arg1 = collapse_tree(tree->left);
double arg2 = collapse_tree(tree->middle);
double arg3 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->middle->type != VALUE ||
tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
- if (arg3 == 0.0) error->one("Invalid math function in variable formula");
+ if (arg3 == 0.0) error->one(FLERR,"Invalid math function in variable formula");
double delta = update->ntimestep - update->beginstep;
double omega = 2.0*PI/arg3;
tree->value = arg1 + arg2*sin(omega*delta*update->dt);
return tree->value;
}
if (tree->type == CWIGGLE) {
double arg1 = collapse_tree(tree->left);
double arg2 = collapse_tree(tree->middle);
double arg3 = collapse_tree(tree->right);
if (tree->left->type != VALUE || tree->middle->type != VALUE ||
tree->right->type != VALUE) return 0.0;
tree->type = VALUE;
- if (arg3 == 0.0) error->one("Invalid math function in variable formula");
+ if (arg3 == 0.0) error->one(FLERR,"Invalid math function in variable formula");
double delta = update->ntimestep - update->beginstep;
double omega = 2.0*PI/arg3;
tree->value = arg1 + arg2*(1.0-cos(omega*delta*update->dt));
return tree->value;
}
// mask functions do not become a single collapsed value
if (tree->type == GMASK) return 0.0;
if (tree->type == RMASK) return 0.0;
if (tree->type == GRMASK) return 0.0;
return 0.0;
}
/* ----------------------------------------------------------------------
evaluate an atom-style variable parse tree for atom I
tree was created by one-time parsing of formula string via evaulate()
customize by adding a function:
sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(),
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),
ramp(x,y),stagger(x,y),logfreq(x,y,z),
vdisplace(x,y),swiggle(x,y,z),cwiggle(x,y,z),
gmask(x),rmask(x),grmask(x,y)
---------------------------------------------------------------------- */
double Variable::eval_tree(Tree *tree, int i)
{
double arg,arg1,arg2,arg3;
if (tree->type == VALUE) return tree->value;
if (tree->type == ATOMARRAY) return tree->array[i*tree->nstride];
if (tree->type == TYPEARRAY) return tree->array[atom->type[i]];
if (tree->type == INTARRAY) return (double) tree->iarray[i*tree->nstride];
if (tree->type == ADD)
return eval_tree(tree->left,i) + eval_tree(tree->right,i);
if (tree->type == SUBTRACT)
return eval_tree(tree->left,i) - eval_tree(tree->right,i);
if (tree->type == MULTIPLY)
return eval_tree(tree->left,i) * eval_tree(tree->right,i);
if (tree->type == DIVIDE) {
double denom = eval_tree(tree->right,i);
- if (denom == 0.0) error->one("Divide by 0 in variable formula");
+ if (denom == 0.0) error->one(FLERR,"Divide by 0 in variable formula");
return eval_tree(tree->left,i) / denom;
}
if (tree->type == CARAT) {
double exponent = eval_tree(tree->right,i);
- if (exponent == 0.0) error->one("Power by 0 in variable formula");
+ if (exponent == 0.0) error->one(FLERR,"Power by 0 in variable formula");
return pow(eval_tree(tree->left,i),exponent);
}
if (tree->type == UNARY) return -eval_tree(tree->left,i);
if (tree->type == NOT) {
if (eval_tree(tree->left,i) == 0.0) return 1.0;
else return 0.0;
}
if (tree->type == EQ) {
if (eval_tree(tree->left,i) == eval_tree(tree->right,i)) return 1.0;
else return 0.0;
}
if (tree->type == NE) {
if (eval_tree(tree->left,i) != eval_tree(tree->right,i)) return 1.0;
else return 0.0;
}
if (tree->type == LT) {
if (eval_tree(tree->left,i) < eval_tree(tree->right,i)) return 1.0;
else return 0.0;
}
if (tree->type == LE) {
if (eval_tree(tree->left,i) <= eval_tree(tree->right,i)) return 1.0;
else return 0.0;
}
if (tree->type == GT) {
if (eval_tree(tree->left,i) > eval_tree(tree->right,i)) return 1.0;
else return 0.0;
}
if (tree->type == GE) {
if (eval_tree(tree->left,i) >= eval_tree(tree->right,i)) return 1.0;
else return 0.0;
}
if (tree->type == AND) {
if (eval_tree(tree->left,i) != 0.0 && eval_tree(tree->right,i) != 0.0)
return 1.0;
else return 0.0;
}
if (tree->type == OR) {
if (eval_tree(tree->left,i) != 0.0 || eval_tree(tree->right,i) != 0.0)
return 1.0;
else return 0.0;
}
if (tree->type == SQRT) {
arg1 = eval_tree(tree->left,i);
- if (arg1 < 0.0) error->one("Sqrt of negative value in variable formula");
+ if (arg1 < 0.0) error->one(FLERR,"Sqrt of negative value in variable formula");
return sqrt(arg1);
}
if (tree->type == EXP)
return exp(eval_tree(tree->left,i));
if (tree->type == LN) {
arg1 = eval_tree(tree->left,i);
if (arg1 <= 0.0)
- error->one("Log of zero/negative value in variable formula");
+ error->one(FLERR,"Log of zero/negative value in variable formula");
return log(arg1);
}
if (tree->type == LOG) {
arg1 = eval_tree(tree->left,i);
if (arg1 <= 0.0)
- error->one("Log of zero/negative value in variable formula");
+ error->one(FLERR,"Log of zero/negative value in variable formula");
return log10(arg1);
}
if (tree->type == SIN)
return sin(eval_tree(tree->left,i));
if (tree->type == COS)
return cos(eval_tree(tree->left,i));
if (tree->type == TAN)
return tan(eval_tree(tree->left,i));
if (tree->type == ASIN) {
arg1 = eval_tree(tree->left,i);
if (arg1 < -1.0 || arg1 > 1.0)
- error->one("Arcsin of invalid value in variable formula");
+ error->one(FLERR,"Arcsin of invalid value in variable formula");
return asin(arg1);
}
if (tree->type == ACOS) {
arg1 = eval_tree(tree->left,i);
if (arg1 < -1.0 || arg1 > 1.0)
- error->one("Arccos of invalid value in variable formula");
+ error->one(FLERR,"Arccos of invalid value in variable formula");
return acos(arg1);
}
if (tree->type == ATAN)
return atan(eval_tree(tree->left,i));
if (tree->type == ATAN2)
return atan2(eval_tree(tree->left,i),eval_tree(tree->right,i));
if (tree->type == RANDOM) {
double lower = eval_tree(tree->left,i);
double upper = eval_tree(tree->middle,i);
if (randomatom == NULL) {
int seed = static_cast<int> (eval_tree(tree->right,i));
- if (seed <= 0) error->one("Invalid math function in variable formula");
+ if (seed <= 0) error->one(FLERR,"Invalid math function in variable formula");
randomatom = new RanMars(lmp,seed+me);
}
return randomatom->uniform()*(upper-lower)+lower;
}
if (tree->type == NORMAL) {
double mu = eval_tree(tree->left,i);
double sigma = eval_tree(tree->middle,i);
- if (sigma < 0.0) error->one("Invalid math function in variable formula");
+ if (sigma < 0.0) error->one(FLERR,"Invalid math function in variable formula");
if (randomatom == NULL) {
int seed = static_cast<int> (eval_tree(tree->right,i));
- if (seed <= 0) error->one("Invalid math function in variable formula");
+ if (seed <= 0) error->one(FLERR,"Invalid math function in variable formula");
randomatom = new RanMars(lmp,seed+me);
}
return mu + sigma*randomatom->gaussian();
}
if (tree->type == CEIL)
return ceil(eval_tree(tree->left,i));
if (tree->type == FLOOR)
return floor(eval_tree(tree->left,i));
if (tree->type == ROUND)
return MYROUND(eval_tree(tree->left,i));
if (tree->type == RAMP) {
arg1 = eval_tree(tree->left,i);
arg2 = eval_tree(tree->right,i);
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
arg = arg1 + delta*(arg2-arg1);
return arg;
}
if (tree->type == STAGGER) {
int ivalue1 = static_cast<int> (eval_tree(tree->left,i));
int ivalue2 = static_cast<int> (eval_tree(tree->right,i));
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2)
- error->one("Invalid math function in variable formula");
+ error->one(FLERR,"Invalid math function in variable formula");
int lower = update->ntimestep/ivalue1 * ivalue1;
int delta = update->ntimestep - lower;
if (delta < ivalue2) arg = lower+ivalue2;
else arg = lower+ivalue1;
return arg;
}
if (tree->type == LOGFREQ) {
int ivalue1 = static_cast<int> (eval_tree(tree->left,i));
int ivalue2 = static_cast<int> (eval_tree(tree->middle,i));
int ivalue3 = static_cast<int> (eval_tree(tree->right,i));
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3)
- error->one("Invalid math function in variable formula");
+ error->one(FLERR,"Invalid math function in variable formula");
if (update->ntimestep < ivalue1) arg = ivalue1;
else {
int lower = ivalue1;
while (update->ntimestep >= ivalue3*lower) lower *= ivalue3;
int multiple = update->ntimestep/lower;
if (multiple < ivalue2) arg = (multiple+1)*lower;
else arg = lower*ivalue3;
}
return arg;
}
if (tree->type == VDISPLACE) {
arg1 = eval_tree(tree->left,i);
arg2 = eval_tree(tree->right,i);
double delta = update->ntimestep - update->beginstep;
arg = arg1 + arg2*delta*update->dt;
return arg;
}
if (tree->type == SWIGGLE) {
arg1 = eval_tree(tree->left,i);
arg2 = eval_tree(tree->middle,i);
arg3 = eval_tree(tree->right,i);
- if (arg3 == 0.0) error->one("Invalid math function in variable formula");
+ if (arg3 == 0.0) error->one(FLERR,"Invalid math function in variable formula");
double delta = update->ntimestep - update->beginstep;
double omega = 2.0*PI/arg3;
arg = arg1 + arg2*sin(omega*delta*update->dt);
return arg;
}
if (tree->type == CWIGGLE) {
arg1 = eval_tree(tree->left,i);
arg2 = eval_tree(tree->middle,i);
arg3 = eval_tree(tree->right,i);
- if (arg3 == 0.0) error->one("Invalid math function in variable formula");
+ if (arg3 == 0.0) error->one(FLERR,"Invalid math function in variable formula");
double delta = update->ntimestep - update->beginstep;
double omega = 2.0*PI/arg3;
arg = arg1 + arg2*(1.0-cos(omega*delta*update->dt));
return arg;
}
if (tree->type == GMASK) {
if (atom->mask[i] & tree->ivalue1) return 1.0;
else return 0.0;
}
if (tree->type == RMASK) {
if (domain->regions[tree->ivalue1]->inside(atom->x[i][0],
atom->x[i][1],
atom->x[i][2])) return 1.0;
else return 0.0;
}
if (tree->type == GRMASK) {
if ((atom->mask[i] & tree->ivalue1) &&
(domain->regions[tree->ivalue2]->inside(atom->x[i][0],
atom->x[i][1],
atom->x[i][2]))) return 1.0;
else return 0.0;
}
return 0.0;
}
/* ---------------------------------------------------------------------- */
void Variable::free_tree(Tree *tree)
{
if (tree->left) free_tree(tree->left);
if (tree->middle) free_tree(tree->middle);
if (tree->right) free_tree(tree->right);
delete tree;
}
/* ----------------------------------------------------------------------
find matching parenthesis in str, allocate contents = str between parens
i = left paren
return loc or right paren
------------------------------------------------------------------------- */
int Variable::find_matching_paren(char *str, int i,char *&contents)
{
// istop = matching ')' at same level, allowing for nested parens
int istart = i;
int ilevel = 0;
while (1) {
i++;
if (!str[i]) break;
if (str[i] == '(') ilevel++;
else if (str[i] == ')' && ilevel) ilevel--;
else if (str[i] == ')') break;
}
- if (!str[i]) error->all("Invalid syntax in variable formula");
+ if (!str[i]) error->all(FLERR,"Invalid syntax in variable formula");
int istop = i;
int n = istop - istart - 1;
contents = new char[n+1];
strncpy(contents,&str[istart+1],n);
contents[n] = '\0';
return istop;
}
/* ----------------------------------------------------------------------
find int between brackets and return it
ptr initially points to left bracket
return it pointing to right bracket
error if no right bracket or brackets are empty
error if any between-bracket chars are non-digits or value == 0
------------------------------------------------------------------------- */
int Variable::int_between_brackets(char *&ptr)
{
char *start = ++ptr;
while (*ptr && *ptr != ']') {
if (!isdigit(*ptr))
- error->all("Non digit character between brackets in variable");
+ error->all(FLERR,"Non digit character between brackets in variable");
ptr++;
}
- if (*ptr != ']') error->all("Mismatched brackets in variable");
- if (ptr == start) error->all("Empty brackets in variable");
+ if (*ptr != ']') error->all(FLERR,"Mismatched brackets in variable");
+ if (ptr == start) error->all(FLERR,"Empty brackets in variable");
*ptr = '\0';
int index = atoi(start);
*ptr = ']';
if (index == 0)
- error->all("Index between variable brackets must be positive");
+ error->all(FLERR,"Index between variable brackets must be positive");
return index;
}
/* ----------------------------------------------------------------------
process a math function in formula
push result onto tree or arg stack
word = math function
contents = str between parentheses with one,two,three args
return 0 if not a match, 1 if successfully processed
customize by adding a math function:
sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(),
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),
ramp(x,y),stagger(x,y),logfreq(x,y,z),
vdisplace(x,y),swiggle(x,y,z),cwiggle(x,y,z)
------------------------------------------------------------------------- */
int Variable::math_function(char *word, char *contents, Tree **tree,
Tree **treestack, int &ntreestack,
double *argstack, int &nargstack)
{
// word not a match to any math function
if (strcmp(word,"sqrt") && strcmp(word,"exp") &&
strcmp(word,"ln") && strcmp(word,"log") &&
strcmp(word,"sin") && strcmp(word,"cos") &&
strcmp(word,"tan") && strcmp(word,"asin") &&
strcmp(word,"acos") && strcmp(word,"atan") &&
strcmp(word,"atan2") && strcmp(word,"random") &&
strcmp(word,"normal") && strcmp(word,"ceil") &&
strcmp(word,"floor") && strcmp(word,"round") &&
strcmp(word,"ramp") && strcmp(word,"stagger") &&
strcmp(word,"logfreq") && strcmp(word,"vdisplace") &&
strcmp(word,"swiggle") && strcmp(word,"cwiggle"))
return 0;
// parse contents for arg1,arg2,arg3 separated by commas
// ptr1,ptr2 = location of 1st and 2nd comma, NULL if none
char *arg1,*arg2,*arg3;
char *ptr1,*ptr2;
ptr1 = find_next_comma(contents);
if (ptr1) {
*ptr1 = '\0';
ptr2 = find_next_comma(ptr1+1);
if (ptr2) *ptr2 = '\0';
} else ptr2 = NULL;
int n = strlen(contents) + 1;
arg1 = new char[n];
strcpy(arg1,contents);
int narg = 1;
if (ptr1) {
n = strlen(ptr1+1) + 1;
arg2 = new char[n];
strcpy(arg2,ptr1+1);
narg = 2;
} else arg2 = NULL;
if (ptr2) {
n = strlen(ptr2+1) + 1;
arg3 = new char[n];
strcpy(arg3,ptr2+1);
narg = 3;
} else arg3 = NULL;
// evaluate args
Tree *newtree;
double tmp,value1,value2,value3;
if (tree) {
newtree = new Tree();
Tree *argtree;
if (narg == 1) {
tmp = evaluate(arg1,&argtree);
newtree->left = argtree;
newtree->middle = newtree->right = NULL;
} else if (narg == 2) {
tmp = evaluate(arg1,&argtree);
newtree->left = argtree;
newtree->middle = NULL;
tmp = evaluate(arg2,&argtree);
newtree->right = argtree;
} else if (narg == 3) {
tmp = evaluate(arg1,&argtree);
newtree->left = argtree;
tmp = evaluate(arg2,&argtree);
newtree->middle = argtree;
tmp = evaluate(arg3,&argtree);
newtree->right = argtree;
}
treestack[ntreestack++] = newtree;
} else {
if (narg == 1) {
value1 = evaluate(arg1,NULL);
} else if (narg == 2) {
value1 = evaluate(arg1,NULL);
value2 = evaluate(arg2,NULL);
} else if (narg == 3) {
value1 = evaluate(arg1,NULL);
value2 = evaluate(arg2,NULL);
value3 = evaluate(arg3,NULL);
}
}
if (strcmp(word,"sqrt") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = SQRT;
else {
if (value1 < 0.0)
- error->all("Sqrt of negative value in variable formula");
+ error->all(FLERR,"Sqrt of negative value in variable formula");
argstack[nargstack++] = sqrt(value1);
}
} else if (strcmp(word,"exp") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = EXP;
else argstack[nargstack++] = exp(value1);
} else if (strcmp(word,"ln") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = LN;
else {
if (value1 <= 0.0)
- error->all("Log of zero/negative value in variable formula");
+ error->all(FLERR,"Log of zero/negative value in variable formula");
argstack[nargstack++] = log(value1);
}
} else if (strcmp(word,"log") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = LOG;
else {
if (value1 <= 0.0)
- error->all("Log of zero/negative value in variable formula");
+ error->all(FLERR,"Log of zero/negative value in variable formula");
argstack[nargstack++] = log10(value1);
}
} else if (strcmp(word,"sin") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = SIN;
else argstack[nargstack++] = sin(value1);
} else if (strcmp(word,"cos") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = COS;
else argstack[nargstack++] = cos(value1);
} else if (strcmp(word,"tan") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = TAN;
else argstack[nargstack++] = tan(value1);
} else if (strcmp(word,"asin") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = ASIN;
else {
if (value1 < -1.0 || value1 > 1.0)
- error->all("Arcsin of invalid value in variable formula");
+ error->all(FLERR,"Arcsin of invalid value in variable formula");
argstack[nargstack++] = asin(value1);
}
} else if (strcmp(word,"acos") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = ACOS;
else {
if (value1 < -1.0 || value1 > 1.0)
- error->all("Arccos of invalid value in variable formula");
+ error->all(FLERR,"Arccos of invalid value in variable formula");
argstack[nargstack++] = acos(value1);
}
} else if (strcmp(word,"atan") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = ATAN;
else argstack[nargstack++] = atan(value1);
} else if (strcmp(word,"atan2") == 0) {
- if (narg != 2) error->all("Invalid math function in variable formula");
+ if (narg != 2) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = ATAN2;
else argstack[nargstack++] = atan2(value1,value2);
} else if (strcmp(word,"random") == 0) {
- if (narg != 3) error->all("Invalid math function in variable formula");
+ if (narg != 3) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = RANDOM;
else {
if (randomequal == NULL) {
int seed = static_cast<int> (value3);
- if (seed <= 0) error->all("Invalid math function in variable formula");
+ if (seed <= 0) error->all(FLERR,"Invalid math function in variable formula");
randomequal = new RanMars(lmp,seed);
}
argstack[nargstack++] = randomequal->uniform()*(value2-value1) + value1;
}
} else if (strcmp(word,"normal") == 0) {
- if (narg != 3) error->all("Invalid math function in variable formula");
+ if (narg != 3) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = NORMAL;
else {
if (value2 < 0.0)
- error->all("Invalid math function in variable formula");
+ error->all(FLERR,"Invalid math function in variable formula");
if (randomequal == NULL) {
int seed = static_cast<int> (value3);
- if (seed <= 0) error->all("Invalid math function in variable formula");
+ if (seed <= 0) error->all(FLERR,"Invalid math function in variable formula");
randomequal = new RanMars(lmp,seed);
}
argstack[nargstack++] = value1 + value2*randomequal->gaussian();
}
} else if (strcmp(word,"ceil") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = CEIL;
else argstack[nargstack++] = ceil(value1);
} else if (strcmp(word,"floor") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = FLOOR;
else argstack[nargstack++] = floor(value1);
} else if (strcmp(word,"round") == 0) {
- if (narg != 1) error->all("Invalid math function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = ROUND;
else argstack[nargstack++] = MYROUND(value1);
} else if (strcmp(word,"ramp") == 0) {
- if (narg != 2) error->all("Invalid math function in variable formula");
+ if (narg != 2) error->all(FLERR,"Invalid math function in variable formula");
if (update->whichflag == 0)
- error->all("Cannot use ramp in variable formula between runs");
+ error->all(FLERR,"Cannot use ramp in variable formula between runs");
if (tree) newtree->type = RAMP;
else {
double delta = update->ntimestep - update->beginstep;
delta /= update->endstep - update->beginstep;
double value = value1 + delta*(value2-value1);
argstack[nargstack++] = value;
}
} else if (strcmp(word,"stagger") == 0) {
- if (narg != 2) error->all("Invalid math function in variable formula");
+ if (narg != 2) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = STAGGER;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2)
- error->all("Invalid math function in variable formula");
+ error->all(FLERR,"Invalid math function in variable formula");
int lower = update->ntimestep/ivalue1 * ivalue1;
int delta = update->ntimestep - lower;
double value;
if (delta < ivalue2) value = lower+ivalue2;
else value = lower+ivalue1;
argstack[nargstack++] = value;
}
} else if (strcmp(word,"logfreq") == 0) {
- if (narg != 3) error->all("Invalid math function in variable formula");
+ if (narg != 3) error->all(FLERR,"Invalid math function in variable formula");
if (tree) newtree->type = LOGFREQ;
else {
int ivalue1 = static_cast<int> (value1);
int ivalue2 = static_cast<int> (value2);
int ivalue3 = static_cast<int> (value3);
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue3 <= 0 || ivalue2 >= ivalue3)
- error->all("Invalid math function in variable formula");
+ error->all(FLERR,"Invalid math function in variable formula");
double value;
if (update->ntimestep < ivalue1) value = ivalue1;
else {
int lower = ivalue1;
while (update->ntimestep >= ivalue3*lower) lower *= ivalue3;
int multiple = update->ntimestep/lower;
if (multiple < ivalue2) value = (multiple+1)*lower;
else value = lower*ivalue3;
}
argstack[nargstack++] = value;
}
} else if (strcmp(word,"vdisplace") == 0) {
- if (narg != 2) error->all("Invalid math function in variable formula");
+ if (narg != 2) error->all(FLERR,"Invalid math function in variable formula");
if (update->whichflag == 0)
- error->all("Cannot use vdisplace in variable formula between runs");
+ error->all(FLERR,"Cannot use vdisplace in variable formula between runs");
if (tree) newtree->type = VDISPLACE;
else {
double delta = update->ntimestep - update->beginstep;
double value = value1 + value2*delta*update->dt;
argstack[nargstack++] = value;
}
} else if (strcmp(word,"swiggle") == 0) {
- if (narg != 3) error->all("Invalid math function in variable formula");
+ if (narg != 3) error->all(FLERR,"Invalid math function in variable formula");
if (update->whichflag == 0)
- error->all("Cannot use swiggle in variable formula between runs");
+ error->all(FLERR,"Cannot use swiggle in variable formula between runs");
if (tree) newtree->type = CWIGGLE;
else {
if (value3 == 0.0)
- error->all("Invalid math function in variable formula");
+ error->all(FLERR,"Invalid math function in variable formula");
double delta = update->ntimestep - update->beginstep;
double omega = 2.0*PI/value3;
double value = value1 + value2*sin(omega*delta*update->dt);
argstack[nargstack++] = value;
}
} else if (strcmp(word,"cwiggle") == 0) {
- if (narg != 3) error->all("Invalid math function in variable formula");
+ if (narg != 3) error->all(FLERR,"Invalid math function in variable formula");
if (update->whichflag == 0)
- error->all("Cannot use cwiggle in variable formula between runs");
+ error->all(FLERR,"Cannot use cwiggle in variable formula between runs");
if (tree) newtree->type = CWIGGLE;
else {
if (value3 == 0.0)
- error->all("Invalid math function in variable formula");
+ error->all(FLERR,"Invalid math function in variable formula");
double delta = update->ntimestep - update->beginstep;
double omega = 2.0*PI/value3;
double value = value1 + value2*(1.0-cos(omega*delta*update->dt));
argstack[nargstack++] = value;
}
}
delete [] arg1;
delete [] arg2;
delete [] arg3;
return 1;
}
/* ----------------------------------------------------------------------
process a group function in formula with optional region arg
push result onto tree or arg stack
word = group function
contents = str between parentheses with one,two,three args
return 0 if not a match, 1 if successfully processed
customize by adding a group function with optional region arg:
count(group),mass(group),charge(group),
xcm(group,dim),vcm(group,dim),fcm(group,dim),
bound(group,xmin),gyration(group),ke(group),angmom(group,dim),
torque(group,dim),inertia(group,dim),omega(group,dim)
------------------------------------------------------------------------- */
int Variable::group_function(char *word, char *contents, Tree **tree,
Tree **treestack, int &ntreestack,
double *argstack, int &nargstack)
{
// word not a match to any group function
if (strcmp(word,"count") && strcmp(word,"mass") &&
strcmp(word,"charge") && strcmp(word,"xcm") &&
strcmp(word,"vcm") && strcmp(word,"fcm") &&
strcmp(word,"bound") && strcmp(word,"gyration") &&
strcmp(word,"ke") && strcmp(word,"angmom") &&
strcmp(word,"torque") && strcmp(word,"inertia") &&
strcmp(word,"omega"))
return 0;
// parse contents for arg1,arg2,arg3 separated by commas
// ptr1,ptr2 = location of 1st and 2nd comma, NULL if none
char *arg1,*arg2,*arg3;
char *ptr1,*ptr2;
ptr1 = find_next_comma(contents);
if (ptr1) {
*ptr1 = '\0';
ptr2 = find_next_comma(ptr1+1);
if (ptr2) *ptr2 = '\0';
} else ptr2 = NULL;
int n = strlen(contents) + 1;
arg1 = new char[n];
strcpy(arg1,contents);
int narg = 1;
if (ptr1) {
n = strlen(ptr1+1) + 1;
arg2 = new char[n];
strcpy(arg2,ptr1+1);
narg = 2;
} else arg2 = NULL;
if (ptr2) {
n = strlen(ptr2+1) + 1;
arg3 = new char[n];
strcpy(arg3,ptr2+1);
narg = 3;
} else arg3 = NULL;
// group to operate on
int igroup = group->find(arg1);
if (igroup == -1)
- error->all("Group ID in variable formula does not exist");
+ error->all(FLERR,"Group ID in variable formula does not exist");
// match word to group function
double value;
if (strcmp(word,"count") == 0) {
if (narg == 1) value = group->count(igroup);
else if (narg == 2) value = group->count(igroup,region_function(arg2));
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"mass") == 0) {
if (narg == 1) value = group->mass(igroup);
else if (narg == 2) value = group->mass(igroup,region_function(arg2));
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"charge") == 0) {
if (narg == 1) value = group->charge(igroup);
else if (narg == 2) value = group->charge(igroup,region_function(arg2));
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"xcm") == 0) {
atom->check_mass();
double xcm[3];
if (narg == 2) {
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
} else if (narg == 3) {
int iregion = region_function(arg3);
double masstotal = group->mass(igroup,iregion);
group->xcm(igroup,masstotal,xcm,iregion);
- } else error->all("Invalid group function in variable formula");
+ } else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"x") == 0) value = xcm[0];
else if (strcmp(arg2,"y") == 0) value = xcm[1];
else if (strcmp(arg2,"z") == 0) value = xcm[2];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"vcm") == 0) {
atom->check_mass();
double vcm[3];
if (narg == 2) {
double masstotal = group->mass(igroup);
group->vcm(igroup,masstotal,vcm);
} else if (narg == 3) {
int iregion = region_function(arg3);
double masstotal = group->mass(igroup,iregion);
group->vcm(igroup,masstotal,vcm,iregion);
- } else error->all("Invalid group function in variable formula");
+ } else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"x") == 0) value = vcm[0];
else if (strcmp(arg2,"y") == 0) value = vcm[1];
else if (strcmp(arg2,"z") == 0) value = vcm[2];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"fcm") == 0) {
double fcm[3];
if (narg == 2) group->fcm(igroup,fcm);
else if (narg == 3) group->fcm(igroup,fcm,region_function(arg3));
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"x") == 0) value = fcm[0];
else if (strcmp(arg2,"y") == 0) value = fcm[1];
else if (strcmp(arg2,"z") == 0) value = fcm[2];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"bound") == 0) {
double minmax[6];
if (narg == 2) group->bounds(igroup,minmax);
else if (narg == 3) group->bounds(igroup,minmax,region_function(arg3));
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"xmin") == 0) value = minmax[0];
else if (strcmp(arg2,"xmax") == 0) value = minmax[1];
else if (strcmp(arg2,"ymin") == 0) value = minmax[2];
else if (strcmp(arg2,"ymax") == 0) value = minmax[3];
else if (strcmp(arg2,"zmin") == 0) value = minmax[4];
else if (strcmp(arg2,"zmax") == 0) value = minmax[5];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"gyration") == 0) {
atom->check_mass();
double xcm[3];
if (narg == 1) {
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
value = group->gyration(igroup,masstotal,xcm);
} else if (narg == 2) {
int iregion = region_function(arg2);
double masstotal = group->mass(igroup,iregion);
group->xcm(igroup,masstotal,xcm,iregion);
value = group->gyration(igroup,masstotal,xcm,iregion);
- } else error->all("Invalid group function in variable formula");
+ } else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"ke") == 0) {
if (narg == 1) value = group->ke(igroup);
else if (narg == 2) value = group->ke(igroup,region_function(arg2));
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"angmom") == 0) {
atom->check_mass();
double xcm[3],lmom[3];
if (narg == 2) {
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
group->angmom(igroup,xcm,lmom);
} else if (narg == 3) {
int iregion = region_function(arg3);
double masstotal = group->mass(igroup,iregion);
group->xcm(igroup,masstotal,xcm,iregion);
group->angmom(igroup,xcm,lmom,iregion);
- } else error->all("Invalid group function in variable formula");
+ } else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"x") == 0) value = lmom[0];
else if (strcmp(arg2,"y") == 0) value = lmom[1];
else if (strcmp(arg2,"z") == 0) value = lmom[2];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"torque") == 0) {
atom->check_mass();
double xcm[3],tq[3];
if (narg == 2) {
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
group->torque(igroup,xcm,tq);
} else if (narg == 3) {
int iregion = region_function(arg3);
double masstotal = group->mass(igroup,iregion);
group->xcm(igroup,masstotal,xcm,iregion);
group->torque(igroup,xcm,tq,iregion);
- } else error->all("Invalid group function in variable formula");
+ } else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"x") == 0) value = tq[0];
else if (strcmp(arg2,"y") == 0) value = tq[1];
else if (strcmp(arg2,"z") == 0) value = tq[2];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"inertia") == 0) {
atom->check_mass();
double xcm[3],inertia[3][3];
if (narg == 2) {
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
group->inertia(igroup,xcm,inertia);
} else if (narg == 3) {
int iregion = region_function(arg3);
double masstotal = group->mass(igroup,iregion);
group->xcm(igroup,masstotal,xcm,iregion);
group->inertia(igroup,xcm,inertia,iregion);
- } else error->all("Invalid group function in variable formula");
+ } else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"xx") == 0) value = inertia[0][0];
else if (strcmp(arg2,"yy") == 0) value = inertia[1][1];
else if (strcmp(arg2,"zz") == 0) value = inertia[2][2];
else if (strcmp(arg2,"xy") == 0) value = inertia[0][1];
else if (strcmp(arg2,"yz") == 0) value = inertia[1][2];
else if (strcmp(arg2,"xz") == 0) value = inertia[0][2];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
} else if (strcmp(word,"omega") == 0) {
atom->check_mass();
double xcm[3],angmom[3],inertia[3][3],omega[3];
if (narg == 2) {
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
group->angmom(igroup,xcm,angmom);
group->inertia(igroup,xcm,inertia);
group->omega(angmom,inertia,omega);
} else if (narg == 3) {
int iregion = region_function(arg3);
double masstotal = group->mass(igroup,iregion);
group->xcm(igroup,masstotal,xcm,iregion);
group->angmom(igroup,xcm,angmom,iregion);
group->inertia(igroup,xcm,inertia,iregion);
group->omega(angmom,inertia,omega);
- } else error->all("Invalid group function in variable formula");
+ } else error->all(FLERR,"Invalid group function in variable formula");
if (strcmp(arg2,"x") == 0) value = omega[0];
else if (strcmp(arg2,"y") == 0) value = omega[1];
else if (strcmp(arg2,"z") == 0) value = omega[2];
- else error->all("Invalid group function in variable formula");
+ else error->all(FLERR,"Invalid group function in variable formula");
}
delete [] arg1;
delete [] arg2;
delete [] arg3;
// save value in tree or on argstack
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value;
return 1;
}
/* ---------------------------------------------------------------------- */
int Variable::region_function(char *id)
{
int iregion = domain->find_region(id);
if (iregion == -1)
- error->all("Region ID in variable formula does not exist");
+ error->all(FLERR,"Region ID in variable formula does not exist");
return iregion;
}
/* ----------------------------------------------------------------------
process a special function in formula
push result onto tree or arg stack
word = special function
contents = str between parentheses with one,two,three args
return 0 if not a match, 1 if successfully processed
customize by adding a special function:
sum(x),min(x),max(x),ave(x),trap(x),gmask(x),rmask(x),grmask(x,y)
------------------------------------------------------------------------- */
int Variable::special_function(char *word, char *contents, Tree **tree,
Tree **treestack, int &ntreestack,
double *argstack, int &nargstack)
{
// word not a match to any special function
if (strcmp(word,"sum") && strcmp(word,"min") && strcmp(word,"max") &&
strcmp(word,"ave") && strcmp(word,"trap") && strcmp(word,"gmask") &&
strcmp(word,"rmask") && strcmp(word,"grmask"))
return 0;
// parse contents for arg1,arg2,arg3 separated by commas
// ptr1,ptr2 = location of 1st and 2nd comma, NULL if none
char *arg1,*arg2,*arg3;
char *ptr1,*ptr2;
ptr1 = find_next_comma(contents);
if (ptr1) {
*ptr1 = '\0';
ptr2 = find_next_comma(ptr1+1);
if (ptr2) *ptr2 = '\0';
} else ptr2 = NULL;
int n = strlen(contents) + 1;
arg1 = new char[n];
strcpy(arg1,contents);
int narg = 1;
if (ptr1) {
n = strlen(ptr1+1) + 1;
arg2 = new char[n];
strcpy(arg2,ptr1+1);
narg = 2;
} else arg2 = NULL;
if (ptr2) {
n = strlen(ptr2+1) + 1;
arg3 = new char[n];
strcpy(arg3,ptr2+1);
narg = 3;
} else arg3 = NULL;
// special functions that operate on global vectors
if (strcmp(word,"sum") == 0 || strcmp(word,"min") == 0 ||
strcmp(word,"max") == 0 || strcmp(word,"ave") == 0 ||
strcmp(word,"trap") == 0) {
int method;
if (strcmp(word,"sum") == 0) method = SUM;
else if (strcmp(word,"min") == 0) method = XMIN;
else if (strcmp(word,"max") == 0) method = XMAX;
else if (strcmp(word,"ave") == 0) method = AVE;
else if (strcmp(word,"trap") == 0) method = TRAP;
- if (narg != 1) error->all("Invalid special function in variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid special function in variable formula");
Compute *compute = NULL;
Fix *fix = NULL;
int index,nvec,nstride;
if (strstr(arg1,"c_") == arg1) {
ptr1 = strchr(arg1,'[');
if (ptr1) {
ptr2 = ptr1;
index = int_between_brackets(ptr2);
*ptr1 = '\0';
} else index = 0;
int icompute = modify->find_compute(&arg1[2]);
- if (icompute < 0) error->all("Invalid compute ID in variable formula");
+ if (icompute < 0) error->all(FLERR,"Invalid compute ID in variable formula");
compute = modify->compute[icompute];
if (index == 0 && compute->vector_flag) {
if (update->whichflag == 0) {
if (compute->invoked_vector != update->ntimestep)
- error->all("Compute used in variable between runs is not current");
+ error->all(FLERR,"Compute used in variable between runs is not current");
} else if (!(compute->invoked_flag & INVOKED_VECTOR)) {
compute->compute_vector();
compute->invoked_flag |= INVOKED_VECTOR;
}
nvec = compute->size_vector;
nstride = 1;
} else if (index && compute->array_flag) {
if (index > compute->size_array_cols)
- error->all("Variable formula compute array "
+ error->all(FLERR,"Variable formula compute array "
"is accessed out-of-range");
if (update->whichflag == 0) {
if (compute->invoked_array != update->ntimestep)
- error->all("Compute used in variable between runs is not current");
+ error->all(FLERR,"Compute used in variable between runs is not current");
} else if (!(compute->invoked_flag & INVOKED_ARRAY)) {
compute->compute_array();
compute->invoked_flag |= INVOKED_ARRAY;
}
nvec = compute->size_array_rows;
nstride = compute->size_array_cols;
- } else error->all("Mismatched compute in variable formula");
+ } else error->all(FLERR,"Mismatched compute in variable formula");
} else if (strstr(arg1,"f_") == arg1) {
ptr1 = strchr(arg1,'[');
if (ptr1) {
ptr2 = ptr1;
index = int_between_brackets(ptr2);
*ptr1 = '\0';
} else index = 0;
int ifix = modify->find_fix(&arg1[2]);
- if (ifix < 0) error->all("Invalid fix ID in variable formula");
+ if (ifix < 0) error->all(FLERR,"Invalid fix ID in variable formula");
fix = modify->fix[ifix];
if (index == 0 && fix->vector_flag) {
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
nvec = fix->size_vector;
nstride = 1;
} else if (index && fix->array_flag) {
if (index > fix->size_array_cols)
- error->all("Variable formula fix array is accessed out-of-range");
+ error->all(FLERR,"Variable formula fix array is accessed out-of-range");
if (update->whichflag > 0 && update->ntimestep % fix->global_freq)
- error->all("Fix in variable not computed at compatible time");
+ error->all(FLERR,"Fix in variable not computed at compatible time");
nvec = fix->size_array_rows;
nstride = fix->size_array_cols;
- } else error->all("Mismatched fix in variable formula");
+ } else error->all(FLERR,"Mismatched fix in variable formula");
- } else error->all("Invalid special function in variable formula");
+ } else error->all(FLERR,"Invalid special function in variable formula");
double value = 0.0;
if (method == XMIN) value = BIG;
if (method == XMAX) value = -BIG;
if (compute) {
double *vec;
if (index) vec = &compute->array[0][index-1];
else vec = compute->vector;
int j = 0;
for (int i = 0; i < nvec; i++) {
if (method == SUM) value += vec[j];
else if (method == XMIN) value = MIN(value,vec[j]);
else if (method == XMAX) value = MAX(value,vec[j]);
else if (method == AVE) value += vec[j];
else if (method == TRAP) {
if (i > 0 && i < nvec-1) value += vec[j];
else value += 0.5*vec[j];
}
j += nstride;
}
}
if (fix) {
double one;
for (int i = 0; i < nvec; i++) {
if (index) one = fix->compute_array(i,index-1);
else one = fix->compute_vector(i);
if (method == SUM) value += one;
else if (method == XMIN) value = MIN(value,one);
else if (method == XMAX) value = MAX(value,one);
else if (method == AVE) value += one;
else if (method == TRAP) {
if (i > 1 && i < nvec) value += one;
else value += 0.5*one;
}
}
}
if (method == AVE) value /= nvec;
delete [] arg1;
delete [] arg2;
delete [] arg3;
// save value in tree or on argstack
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value;
// mask special functions
} else if (strcmp(word,"gmask") == 0) {
if (tree == NULL)
- error->all("Gmask function in equal-style variable formula");
- if (narg != 1) error->all("Invalid special function in variable formula");
+ error->all(FLERR,"Gmask function in equal-style variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid special function in variable formula");
int igroup = group->find(arg1);
if (igroup == -1)
- error->all("Group ID in variable formula does not exist");
+ error->all(FLERR,"Group ID in variable formula does not exist");
Tree *newtree = new Tree();
newtree->type = GMASK;
newtree->ivalue1 = group->bitmask[igroup];
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else if (strcmp(word,"rmask") == 0) {
if (tree == NULL)
- error->all("Rmask function in equal-style variable formula");
- if (narg != 1) error->all("Invalid special function in variable formula");
+ error->all(FLERR,"Rmask function in equal-style variable formula");
+ if (narg != 1) error->all(FLERR,"Invalid special function in variable formula");
int iregion = region_function(arg1);
Tree *newtree = new Tree();
newtree->type = RMASK;
newtree->ivalue1 = iregion;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else if (strcmp(word,"grmask") == 0) {
if (tree == NULL)
- error->all("Grmask function in equal-style variable formula");
- if (narg != 2) error->all("Invalid special function in variable formula");
+ error->all(FLERR,"Grmask function in equal-style variable formula");
+ if (narg != 2) error->all(FLERR,"Invalid special function in variable formula");
int igroup = group->find(arg1);
if (igroup == -1)
- error->all("Group ID in variable formula does not exist");
+ error->all(FLERR,"Group ID in variable formula does not exist");
int iregion = region_function(arg2);
Tree *newtree = new Tree();
newtree->type = RMASK;
newtree->ivalue1 = group->bitmask[igroup];
newtree->ivalue2 = iregion;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
}
return 1;
}
/* ----------------------------------------------------------------------
extract a global value from a per-atom quantity in a formula
flag = 0 -> word is an atom vector
flag = 1 -> vector is a per-atom compute or fix quantity with nstride
id = positive global ID of atom, converted to local index
push result onto tree or arg stack
customize by adding an atom vector:
mass,type,x,y,z,vx,vy,vz,fx,fy,fz
------------------------------------------------------------------------- */
void Variable::peratom2global(int flag, char *word,
double *vector, int nstride, int id,
Tree **tree, Tree **treestack, int &ntreestack,
double *argstack, int &nargstack)
{
if (atom->map_style == 0)
- error->all("Indexed per-atom vector in variable formula without atom map");
+ error->all(FLERR,"Indexed per-atom vector in variable formula without atom map");
int index = atom->map(id);
double mine;
if (index >= 0 && index < atom->nlocal) {
if (flag == 0) {
if (strcmp(word,"mass") == 0) {
if (atom->rmass) mine = atom->rmass[index];
else mine = atom->mass[atom->type[index]];
}
else if (strcmp(word,"type") == 0) mine = atom->type[index];
else if (strcmp(word,"x") == 0) mine = atom->x[index][0];
else if (strcmp(word,"y") == 0) mine = atom->x[index][1];
else if (strcmp(word,"z") == 0) mine = atom->x[index][2];
else if (strcmp(word,"vx") == 0) mine = atom->v[index][0];
else if (strcmp(word,"vy") == 0) mine = atom->v[index][1];
else if (strcmp(word,"vz") == 0) mine = atom->v[index][2];
else if (strcmp(word,"fx") == 0) mine = atom->f[index][0];
else if (strcmp(word,"fy") == 0) mine = atom->f[index][1];
else if (strcmp(word,"fz") == 0) mine = atom->f[index][2];
- else error->one("Invalid atom vector in variable formula");
+ else error->one(FLERR,"Invalid atom vector in variable formula");
} else mine = vector[index*nstride];
} else mine = 0.0;
double value;
MPI_Allreduce(&mine,&value,1,MPI_DOUBLE,MPI_SUM,world);
if (tree) {
Tree *newtree = new Tree();
newtree->type = VALUE;
newtree->value = value;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
} else argstack[nargstack++] = value;
}
/* ----------------------------------------------------------------------
check if word matches an atom vector
return 1 if yes, else 0
customize by adding an atom vector:
mass,type,x,y,z,vx,vy,vz,fx,fy,fz
------------------------------------------------------------------------- */
int Variable::is_atom_vector(char *word)
{
if (strcmp(word,"mass") == 0) return 1;
if (strcmp(word,"type") == 0) return 1;
if (strcmp(word,"x") == 0) return 1;
if (strcmp(word,"y") == 0) return 1;
if (strcmp(word,"z") == 0) return 1;
if (strcmp(word,"vx") == 0) return 1;
if (strcmp(word,"vy") == 0) return 1;
if (strcmp(word,"vz") == 0) return 1;
if (strcmp(word,"fx") == 0) return 1;
if (strcmp(word,"fy") == 0) return 1;
if (strcmp(word,"fz") == 0) return 1;
return 0;
}
/* ----------------------------------------------------------------------
process an atom vector in formula
push result onto tree
word = atom vector
customize by adding an atom vector:
mass,type,x,y,z,vx,vy,vz,fx,fy,fz
------------------------------------------------------------------------- */
void Variable::atom_vector(char *word, Tree **tree,
Tree **treestack, int &ntreestack)
{
if (tree == NULL)
- error->all("Atom vector in equal-style variable formula");
+ error->all(FLERR,"Atom vector in equal-style variable formula");
Tree *newtree = new Tree();
newtree->type = ATOMARRAY;
newtree->nstride = 3;
newtree->left = newtree->middle = newtree->right = NULL;
treestack[ntreestack++] = newtree;
if (strcmp(word,"mass") == 0) {
if (atom->rmass) {
newtree->nstride = 1;
newtree->array = atom->rmass;
} else {
newtree->type = TYPEARRAY;
newtree->array = atom->mass;
}
} else if (strcmp(word,"type") == 0) {
newtree->type = INTARRAY;
newtree->nstride = 1;
newtree->iarray = atom->type;
}
else if (strcmp(word,"x") == 0) newtree->array = &atom->x[0][0];
else if (strcmp(word,"y") == 0) newtree->array = &atom->x[0][1];
else if (strcmp(word,"z") == 0) newtree->array = &atom->x[0][2];
else if (strcmp(word,"vx") == 0) newtree->array = &atom->v[0][0];
else if (strcmp(word,"vy") == 0) newtree->array = &atom->v[0][1];
else if (strcmp(word,"vz") == 0) newtree->array = &atom->v[0][2];
else if (strcmp(word,"fx") == 0) newtree->array = &atom->f[0][0];
else if (strcmp(word,"fy") == 0) newtree->array = &atom->f[0][1];
else if (strcmp(word,"fz") == 0) newtree->array = &atom->f[0][2];
}
/* ----------------------------------------------------------------------
check if word matches a constant
return 1 if yes, else 0
customize by adding a constant: PI
------------------------------------------------------------------------- */
int Variable::is_constant(char *word)
{
if (strcmp(word,"PI") == 0) return 1;
return 0;
}
/* ----------------------------------------------------------------------
process a constant in formula
customize by adding a constant: PI
------------------------------------------------------------------------- */
double Variable::constant(char *word)
{
if (strcmp(word,"PI") == 0) return PI;
return 0.0;
}
/* ----------------------------------------------------------------------
read a floating point value from a string
generate an error if not a legitimate floating point value
------------------------------------------------------------------------- */
double Variable::numeric(char *str)
{
int n = strlen(str);
for (int i = 0; i < n; i++) {
if (isdigit(str[i])) continue;
if (str[i] == '-' || str[i] == '+' || str[i] == '.') continue;
if (str[i] == 'e' || str[i] == 'E') continue;
- error->all("Expected floating point parameter in variable definition");
+ error->all(FLERR,"Expected floating point parameter in variable definition");
}
return atof(str);
}
/* ----------------------------------------------------------------------
read an integer value from a string
generate an error if not a legitimate integer value
------------------------------------------------------------------------- */
int Variable::inumeric(char *str)
{
int n = strlen(str);
for (int i = 0; i < n; i++) {
if (isdigit(str[i]) || str[i] == '-' || str[i] == '+') continue;
- error->all("Expected integer parameter in variable definition");
+ error->all(FLERR,"Expected integer parameter in variable definition");
}
return atoi(str);
}
/* ----------------------------------------------------------------------
find next comma in str
skip commas inside one or more nested parenthesis
only return ptr to comma at level 0, else NULL if not found
------------------------------------------------------------------------- */
char *Variable::find_next_comma(char *str)
{
int level = 0;
for (char *p = str; *p; ++p) {
if ('(' == *p) level++;
else if (')' == *p) level--;
else if (',' == *p && !level) return p;
}
return NULL;
}
/* ----------------------------------------------------------------------
debug routine for printing formula tree recursively
------------------------------------------------------------------------- */
void Variable::print_tree(Tree *tree, int level)
{
printf("TREE %d: %d %g\n",level,tree->type,tree->value);
if (tree->left) print_tree(tree->left,level+1);
if (tree->middle) print_tree(tree->middle,level+1);
if (tree->right) print_tree(tree->right,level+1);
return;
}
/* ----------------------------------------------------------------------
recursive evaluation of string str
called from "if" command in input script
str is a boolean expression containing one or more items:
number = 0.0, -5.45, 2.8e-4, ...
math operation = (),x==y,x!=y,x<y,x<=y,x>y,x>=y,x&&y,x||y
------------------------------------------------------------------------- */
double Variable::evaluate_boolean(char *str)
{
int op,opprevious;
double value1,value2;
char onechar;
double argstack[MAXLEVEL];
int opstack[MAXLEVEL];
int nargstack = 0;
int nopstack = 0;
int i = 0;
int expect = ARG;
while (1) {
onechar = str[i];
// whitespace: just skip
if (isspace(onechar)) i++;
// ----------------
// parentheses: recursively evaluate contents of parens
// ----------------
else if (onechar == '(') {
- if (expect == OP) error->all("Invalid Boolean syntax in if command");
+ if (expect == OP) error->all(FLERR,"Invalid Boolean syntax in if command");
expect = OP;
char *contents;
i = find_matching_paren(str,i,contents);
i++;
// evaluate contents and push on stack
argstack[nargstack++] = evaluate_boolean(contents);
delete [] contents;
// ----------------
// number: push value onto stack
// ----------------
} else if (isdigit(onechar) || onechar == '.' || onechar == '-') {
- if (expect == OP) error->all("Invalid Boolean syntax in if command");
+ if (expect == OP) error->all(FLERR,"Invalid Boolean syntax in if command");
expect = OP;
// istop = end of number, including scientific notation
int istart = i++;
while (isdigit(str[i]) || str[i] == '.') i++;
if (str[i] == 'e' || str[i] == 'E') {
i++;
if (str[i] == '+' || str[i] == '-') i++;
while (isdigit(str[i])) i++;
}
int istop = i - 1;
int n = istop - istart + 1;
char *number = new char[n+1];
strncpy(number,&str[istart],n);
number[n] = '\0';
argstack[nargstack++] = atof(number);
delete [] number;
// ----------------
// Boolean operator, including end-of-string
// ----------------
} else if (strchr("<>=!&|\0",onechar)) {
if (onechar == '=') {
if (str[i+1] != '=')
- error->all("Invalid Boolean syntax in if command");
+ error->all(FLERR,"Invalid Boolean syntax in if command");
op = EQ;
i++;
} else if (onechar == '!') {
if (str[i+1] == '=') {
op = NE;
i++;
} else op = NOT;
} else if (onechar == '<') {
if (str[i+1] != '=') op = LT;
else {
op = LE;
i++;
}
} else if (onechar == '>') {
if (str[i+1] != '=') op = GT;
else {
op = GE;
i++;
}
} else if (onechar == '&') {
if (str[i+1] != '&')
- error->all("Invalid Boolean syntax in if command");
+ error->all(FLERR,"Invalid Boolean syntax in if command");
op = AND;
i++;
} else if (onechar == '|') {
if (str[i+1] != '|')
- error->all("Invalid Boolean syntax in if command");
+ error->all(FLERR,"Invalid Boolean syntax in if command");
op = OR;
i++;
} else op = DONE;
i++;
if (op == NOT && expect == ARG) {
opstack[nopstack++] = op;
continue;
}
- if (expect == ARG) error->all("Invalid Boolean syntax in if command");
+ if (expect == ARG) error->all(FLERR,"Invalid Boolean syntax in if command");
expect = ARG;
// evaluate stack as deep as possible while respecting precedence
// before pushing current op onto stack
while (nopstack && precedence[opstack[nopstack-1]] >= precedence[op]) {
opprevious = opstack[--nopstack];
value2 = argstack[--nargstack];
if (opprevious != NOT) value1 = argstack[--nargstack];
if (opprevious == NOT) {
if (value2 == 0.0) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == EQ) {
if (value1 == value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == NE) {
if (value1 != value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == LT) {
if (value1 < value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == LE) {
if (value1 <= value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == GT) {
if (value1 > value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == GE) {
if (value1 >= value2) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == AND) {
if (value1 != 0.0 && value2 != 0.0) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
} else if (opprevious == OR) {
if (value1 != 0.0 || value2 != 0.0) argstack[nargstack++] = 1.0;
else argstack[nargstack++] = 0.0;
}
}
// if end-of-string, break out of entire formula evaluation loop
if (op == DONE) break;
// push current operation onto stack
opstack[nopstack++] = op;
- } else error->all("Invalid Boolean syntax in if command");
+ } else error->all(FLERR,"Invalid Boolean syntax in if command");
}
- if (nopstack) error->all("Invalid Boolean syntax in if command");
- if (nargstack != 1) error->all("Invalid Boolean syntax in if command");
+ if (nopstack) error->all(FLERR,"Invalid Boolean syntax in if command");
+ if (nargstack != 1) error->all(FLERR,"Invalid Boolean syntax in if command");
return argstack[0];
}
diff --git a/src/velocity.cpp b/src/velocity.cpp
index c590ece9d..ef95a873a 100644
--- a/src/velocity.cpp
+++ b/src/velocity.cpp
@@ -1,799 +1,796 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "math.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "velocity.h"
#include "atom.h"
#include "update.h"
#include "domain.h"
#include "lattice.h"
#include "input.h"
#include "variable.h"
#include "force.h"
#include "modify.h"
#include "compute.h"
#include "compute_temp.h"
#include "random_park.h"
#include "group.h"
#include "comm.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
enum{CREATE,SET,SCALE,RAMP,ZERO};
enum{ALL,LOCAL,GEOM};
enum{NONE,CONSTANT,EQUAL,ATOM};
#define WARMUP 100
#define SMALL 0.001
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
/* ---------------------------------------------------------------------- */
Velocity::Velocity(LAMMPS *lmp) : Pointers(lmp) {}
/* ---------------------------------------------------------------------- */
void Velocity::command(int narg, char **arg)
{
- if (narg < 2) error->all("Illegal velocity command");
+ if (narg < 2) error->all(FLERR,"Illegal velocity command");
if (domain->box_exist == 0)
- error->all("Velocity command before simulation box is defined");
+ error->all(FLERR,"Velocity command before simulation box is defined");
if (atom->natoms == 0)
- error->all("Velocity command with no atoms existing");
+ error->all(FLERR,"Velocity command with no atoms existing");
// atom masses must all be set
atom->check_mass();
// identify group
igroup = group->find(arg[0]);
- if (igroup == -1) error->all("Could not find velocity group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find velocity group ID");
groupbit = group->bitmask[igroup];
// identify style
if (strcmp(arg[1],"create") == 0) style = CREATE;
else if (strcmp(arg[1],"set") == 0) style = SET;
else if (strcmp(arg[1],"scale") == 0) style = SCALE;
else if (strcmp(arg[1],"ramp") == 0) style = RAMP;
else if (strcmp(arg[1],"zero") == 0) style = ZERO;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
// set defaults
temperature = NULL;
dist_flag = 0;
sum_flag = 0;
momentum_flag = 1;
rotation_flag = 0;
loop_flag = ALL;
scale_flag = 1;
// read options from end of input line
// change defaults as options specify
if (style == CREATE) options(narg-4,&arg[4]);
else if (style == SET) options(narg-5,&arg[5]);
else if (style == SCALE) options(narg-3,&arg[3]);
else if (style == RAMP) options(narg-8,&arg[8]);
else if (style == ZERO) options(narg-3,&arg[3]);
// initialize velocities based on style
// create() invoked differently, so can be called externally
if (style == CREATE) {
double t_desired = atof(arg[2]);
int seed = atoi(arg[3]);
create(t_desired,seed);
}
else if (style == SET) set(narg-2,&arg[2]);
else if (style == SCALE) scale(narg-2,&arg[2]);
else if (style == RAMP) ramp(narg-2,&arg[2]);
else if (style == ZERO) zero(narg-2,&arg[2]);
}
/* ----------------------------------------------------------------------
initialization of defaults before calling velocity methods externaly
------------------------------------------------------------------------- */
void Velocity::init_external(char *extgroup)
{
igroup = group->find(extgroup);
- if (igroup == -1) error->all("Could not find velocity group ID");
+ if (igroup == -1) error->all(FLERR,"Could not find velocity group ID");
groupbit = group->bitmask[igroup];
temperature = NULL;
dist_flag = 0;
sum_flag = 0;
momentum_flag = 1;
rotation_flag = 0;
loop_flag = ALL;
scale_flag = 1;
}
/* ---------------------------------------------------------------------- */
void Velocity::create(double t_desired, int seed)
{
int i;
- if (seed <= 0) error->all("Illegal velocity create command");
+ if (seed <= 0) error->all(FLERR,"Illegal velocity create command");
// if temperature = NULL, create a new ComputeTemp with the velocity group
int tflag = 0;
if (temperature == NULL) {
char **arg = new char*[3];
arg[0] = (char *) "velocity_temp";
arg[1] = group->names[igroup];
arg[2] = (char *) "temp";
temperature = new ComputeTemp(lmp,3,arg);
tflag = 1;
delete [] arg;
}
// initialize temperature computation
// warn if groups don't match
if (igroup != temperature->igroup && comm->me == 0)
- error->warning("Mismatch between velocity and compute groups");
+ error->warning(FLERR,"Mismatch between velocity and compute groups");
temperature->init();
// store a copy of current velocities
double **v = atom->v;
int nlocal = atom->nlocal;
double **vhold;
memory->create(vhold,nlocal,3,"velocity:vnew");
for (i = 0; i < nlocal; i++) {
vhold[i][0] = v[i][0];
vhold[i][1] = v[i][1];
vhold[i][2] = v[i][2];
}
// create new velocities, in uniform or gaussian distribution
// loop option determines looping style, ALL is default
// ALL = loop over all natoms, only set those I own via atom->map
// cannot do this if atom IDs do not span 1-Natoms (some were deleted)
// will produce same V, independent of P, if atoms were read-in
// will NOT produce same V, independent of P, if used create_atoms
// LOCAL = only loop over my atoms, adjust RNG to be proc-specific
// will never produce same V, independent of P
// GEOM = only loop over my atoms
// choose RNG for each atom based on its xyz coord (geometry)
// via random->reset()
// will always produce same V, independent of P
// adjust by factor for atom mass
// for 2d, set Vz to 0.0
double *rmass = atom->rmass;
double *mass = atom->mass;
int *type = atom->type;
int *mask = atom->mask;
int dimension = domain->dimension;
int m;
double vx,vy,vz,factor;
RanPark *random;
if (loop_flag == ALL) {
// create an atom map if one doesn't exist already
int mapflag = 0;
if (atom->map_style == 0) {
mapflag = 1;
atom->map_style = 1;
atom->nghost = 0;
atom->map_init();
atom->map_set();
}
// error check
if (atom->natoms > MAXSMALLINT)
- error->all("Too big a problem to use velocity create loop all");
+ error->all(FLERR,"Too big a problem to use velocity create loop all");
if (atom->tag_enable == 0)
- error->all("Cannot use velocity create loop all unless atoms have IDs");
+ error->all(FLERR,"Cannot use velocity create loop all unless atoms have IDs");
if (atom->tag_consecutive() == 0)
- error->all("Atom IDs must be consecutive for velocity create loop all");
+ error->all(FLERR,"Atom IDs must be consecutive for velocity create loop all");
// loop over all atoms in system
// generate RNGs for all atoms, only assign to ones I own
// use either per-type mass or per-atom rmass
random = new RanPark(lmp,seed);
int natoms = static_cast<int> (atom->natoms);
for (i = 1; i <= natoms; i++) {
if (dist_flag == 0) {
vx = random->uniform();
vy = random->uniform();
vz = random->uniform();
} else {
vx = random->gaussian();
vy = random->gaussian();
vz = random->gaussian();
}
m = atom->map(i);
if (m >= 0 && m < nlocal) {
if (mask[m] & groupbit) {
if (rmass) factor = 1.0/sqrt(rmass[m]);
else factor = 1.0/sqrt(mass[type[m]]);
v[m][0] = vx * factor;
v[m][1] = vy * factor;
if (dimension == 3) v[m][2] = vz * factor;
else v[m][2] = 0.0;
}
}
}
// delete temporary atom map
if (mapflag) {
atom->map_delete();
atom->map_style = 0;
}
} else if (loop_flag == LOCAL) {
random = new RanPark(lmp,seed + comm->me);
for (i = 0; i < WARMUP; i++) random->uniform();
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (dist_flag == 0) {
vx = random->uniform();
vy = random->uniform();
vz = random->uniform();
} else {
vx = random->gaussian();
vy = random->gaussian();
vz = random->gaussian();
}
if (rmass) factor = 1.0/sqrt(rmass[i]);
else factor = 1.0/sqrt(mass[type[i]]);
v[i][0] = vx * factor;
v[i][1] = vy * factor;
if (dimension == 3) v[i][2] = vz * factor;
else v[i][2] = 0.0;
}
}
} else if (loop_flag == GEOM) {
random = new RanPark(lmp,1);
double **x = atom->x;
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
random->reset(seed,x[i]);
if (dist_flag == 0) {
vx = random->uniform();
vy = random->uniform();
vz = random->uniform();
} else {
vx = random->gaussian();
vy = random->gaussian();
vz = random->gaussian();
}
if (rmass) factor = 1.0/sqrt(rmass[i]);
else factor = 1.0/sqrt(mass[type[i]]);
v[i][0] = vx * factor;
v[i][1] = vy * factor;
if (dimension == 3) v[i][2] = vz * factor;
else v[i][2] = 0.0;
}
}
}
// apply momentum and rotation zeroing
if (momentum_flag) zero_momentum();
if (rotation_flag) zero_rotation();
// scale temp to desired value
double t = temperature->compute_scalar();
rescale(t,t_desired);
// if sum_flag set, add back in previous velocities
if (sum_flag) {
for (i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
v[i][0] += vhold[i][0];
v[i][1] += vhold[i][1];
v[i][2] += vhold[i][2];
}
}
}
// free local memory
// if temperature was created, delete it
memory->destroy(vhold);
delete random;
if (tflag) delete temperature;
}
/* ---------------------------------------------------------------------- */
void Velocity::set(int narg, char **arg)
{
int xstyle,ystyle,zstyle,varflag;
double vx,vy,vz;
char *xstr,*ystr,*zstr;
int xvar,yvar,zvar;
// parse 3 args
xstyle = ystyle = zstyle = CONSTANT;
xstr = ystr = zstr = NULL;
if (strstr(arg[0],"v_") == arg[0]) {
int n = strlen(&arg[0][2]) + 1;
xstr = new char[n];
strcpy(xstr,&arg[0][2]);
} else if (strcmp(arg[0],"NULL") == 0) xstyle = NONE;
else vx = atof(arg[0]);
if (strstr(arg[1],"v_") == arg[1]) {
int n = strlen(&arg[1][2]) + 1;
ystr = new char[n];
strcpy(ystr,&arg[1][2]);
} else if (strcmp(arg[1],"NULL") == 0) ystyle = NONE;
else vy = atof(arg[1]);
if (strstr(arg[2],"v_") == arg[2]) {
int n = strlen(&arg[2][2]) + 1;
zstr = new char[n];
strcpy(zstr,&arg[2][2]);
} else if (strcmp(arg[2],"NULL") == 0) zstyle = NONE;
else vz = atof(arg[2]);
// set and apply scale factors
xscale = yscale = zscale = 1.0;
if (xstyle && !xstr) {
if (scale_flag && domain->lattice == NULL)
- error->all("Use of velocity with undefined lattice");
+ error->all(FLERR,"Use of velocity with undefined lattice");
if (scale_flag) xscale = domain->lattice->xlattice;
vx *= xscale;
}
if (ystyle && !ystr) {
if (scale_flag && domain->lattice == NULL)
- error->all("Use of velocity with undefined lattice");
+ error->all(FLERR,"Use of velocity with undefined lattice");
if (scale_flag) yscale = domain->lattice->ylattice;
vy *= yscale;
}
if (zstyle && !zstr) {
if (scale_flag && domain->lattice == NULL)
- error->all("Use of velocity with undefined lattice");
+ error->all(FLERR,"Use of velocity with undefined lattice");
if (scale_flag) zscale = domain->lattice->zlattice;
vz *= zscale;
}
// check variables
if (xstr) {
xvar = input->variable->find(xstr);
- if (xvar < 0) error->all("Variable name for velocity set does not exist");
+ if (xvar < 0) error->all(FLERR,"Variable name for velocity set does not exist");
if (input->variable->equalstyle(xvar)) xstyle = EQUAL;
else if (input->variable->atomstyle(xvar)) xstyle = ATOM;
- else error->all("Variable for velocity set is invalid style");
+ else error->all(FLERR,"Variable for velocity set is invalid style");
}
if (ystr) {
yvar = input->variable->find(ystr);
- if (yvar < 0) error->all("Variable name for velocity set does not exist");
+ if (yvar < 0) error->all(FLERR,"Variable name for velocity set does not exist");
if (input->variable->equalstyle(yvar)) ystyle = EQUAL;
else if (input->variable->atomstyle(yvar)) ystyle = ATOM;
- else error->all("Variable for velocity set is invalid style");
+ else error->all(FLERR,"Variable for velocity set is invalid style");
}
if (zstr) {
zvar = input->variable->find(zstr);
- if (zvar < 0) error->all("Variable name for velocity set does not exist");
+ if (zvar < 0) error->all(FLERR,"Variable name for velocity set does not exist");
if (input->variable->equalstyle(zvar)) zstyle = EQUAL;
else if (input->variable->atomstyle(zvar)) zstyle = ATOM;
- else error->all("Variable for velocity set is invalid style");
+ else error->all(FLERR,"Variable for velocity set is invalid style");
}
if (xstyle == ATOM || ystyle == ATOM || zstyle == ATOM)
varflag = ATOM;
else if (xstyle == EQUAL || ystyle == EQUAL || zstyle == EQUAL)
varflag = EQUAL;
else varflag = CONSTANT;
// error check for 2d models
if (domain->dimension == 2) {
if (zstyle == CONSTANT && vz != 0.0)
- error->all("Cannot set non-zero z velocity for 2d simulation");
+ error->all(FLERR,"Cannot set non-zero z velocity for 2d simulation");
if (zstyle == EQUAL || zstyle == ATOM)
- error->all("Cannot set variable z velocity for 2d simulation");
+ error->all(FLERR,"Cannot set variable z velocity for 2d simulation");
}
// allocate vfield array if necessary
double **vfield = NULL;
if (varflag == ATOM) memory->create(vfield,atom->nlocal,3,"velocity:vfield");
// set velocities via constants
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
if (varflag == CONSTANT) {
for (int i = 0; i < nlocal; i++) {
if (mask[i] & groupbit) {
if (sum_flag == 0) {
if (xstyle) v[i][0] = vx;
if (ystyle) v[i][1] = vy;
if (zstyle) v[i][2] = vz;
} else {
if (xstyle) v[i][0] += vx;
if (ystyle) v[i][1] += vy;
if (zstyle) v[i][2] += vz;
}
}
}
// set velocities via variables
} else {
if (xstyle == EQUAL) vx = input->variable->compute_equal(xvar);
else if (xstyle == ATOM && vfield)
input->variable->compute_atom(xvar,igroup,&vfield[0][0],3,0);
if (ystyle == EQUAL) vy = input->variable->compute_equal(yvar);
else if (ystyle == ATOM && vfield)
input->variable->compute_atom(yvar,igroup,&vfield[0][1],3,0);
if (zstyle == EQUAL) vz = input->variable->compute_equal(zvar);
else if (zstyle == ATOM && vfield)
input->variable->compute_atom(zvar,igroup,&vfield[0][2],3,0);
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
if (sum_flag == 0) {
if (xstyle == ATOM) v[i][0] = vfield[i][0];
else if (xstyle) v[i][0] = vx;
if (ystyle == ATOM) v[i][1] = vfield[i][1];
else if (ystyle) v[i][1] = vy;
if (zstyle == ATOM) v[i][2] = vfield[i][2];
else if (zstyle) v[i][2] = vz;
} else {
if (xstyle == ATOM) v[i][0] += vfield[i][0];
else if (xstyle) v[i][0] += vx;
if (ystyle == ATOM) v[i][1] += vfield[i][1];
else if (ystyle) v[i][1] += vy;
if (zstyle == ATOM) v[i][2] += vfield[i][2];
else if (zstyle) v[i][2] += vz;
}
}
}
// clean up
delete [] xstr;
delete [] ystr;
delete [] zstr;
memory->destroy(vfield);
}
/* ----------------------------------------------------------------------
rescale velocities of a group after computing its temperature
------------------------------------------------------------------------- */
void Velocity::scale(int narg, char **arg)
{
double t_desired = atof(arg[0]);
// if temperature = NULL, create a new ComputeTemp with the velocity group
int tflag = 0;
if (temperature == NULL) {
char **arg = new char*[3];
arg[0] = (char *) "velocity_temp";
arg[1] = group->names[igroup];
arg[2] = (char *) "temp";
temperature = new ComputeTemp(lmp,3,arg);
tflag = 1;
delete [] arg;
}
// initialize temperature computation
// warn if groups don't match
if (igroup != temperature->igroup && comm->me == 0)
- error->warning("Mismatch between velocity and compute groups");
+ error->warning(FLERR,"Mismatch between velocity and compute groups");
temperature->init();
// scale temp to desired value
double t = temperature->compute_scalar();
rescale(t,t_desired);
// if temperature was created, delete it
if (tflag) delete temperature;
}
/* ----------------------------------------------------------------------
apply a ramped set of velocities
------------------------------------------------------------------------- */
void Velocity::ramp(int narg, char **arg)
{
// set scale factors
if (scale_flag && domain->lattice == NULL)
- error->all("Use of velocity with undefined lattice");
+ error->all(FLERR,"Use of velocity with undefined lattice");
if (scale_flag) {
xscale = domain->lattice->xlattice;
yscale = domain->lattice->ylattice;
zscale = domain->lattice->zlattice;
}
else xscale = yscale = zscale = 1.0;
// parse args
int v_dim;
if (strcmp(arg[0],"vx") == 0) v_dim = 0;
else if (strcmp(arg[0],"vy") == 0) v_dim = 1;
else if (strcmp(arg[0],"vz") == 0) v_dim = 2;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
if (v_dim == 2 && domain->dimension == 2)
- error->all("Velocity ramp in z for a 2d problem");
+ error->all(FLERR,"Velocity ramp in z for a 2d problem");
double v_lo,v_hi;
if (v_dim == 0) {
v_lo = xscale*atof(arg[1]);
v_hi = xscale*atof(arg[2]);
} else if (v_dim == 1) {
v_lo = yscale*atof(arg[1]);
v_hi = yscale*atof(arg[2]);
} else if (v_dim == 2) {
v_lo = zscale*atof(arg[1]);
v_hi = zscale*atof(arg[2]);
}
int coord_dim;
if (strcmp(arg[3],"x") == 0) coord_dim = 0;
else if (strcmp(arg[3],"y") == 0) coord_dim = 1;
else if (strcmp(arg[3],"z") == 0) coord_dim = 2;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
double coord_lo,coord_hi;
if (coord_dim == 0) {
coord_lo = xscale*atof(arg[4]);
coord_hi = xscale*atof(arg[5]);
} else if (coord_dim == 1) {
coord_lo = yscale*atof(arg[4]);
coord_hi = yscale*atof(arg[5]);
} else if (coord_dim == 2) {
coord_lo = zscale*atof(arg[4]);
coord_hi = zscale*atof(arg[5]);
}
// vramp = ramped velocity component for v_dim
// add or set based on sum_flag
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
double fraction,vramp;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
fraction = (x[i][coord_dim] - coord_lo) / (coord_hi - coord_lo);
fraction = MAX(fraction,0.0);
fraction = MIN(fraction,1.0);
vramp = v_lo + fraction*(v_hi - v_lo);
if (sum_flag) v[i][v_dim] += vramp;
else v[i][v_dim] = vramp;
}
}
/* ----------------------------------------------------------------------
zero linear or angular momentum of a group
------------------------------------------------------------------------- */
void Velocity::zero(int narg, char **arg)
{
if (strcmp(arg[0],"linear") == 0) zero_momentum();
else if (strcmp(arg[0],"angular") == 0) zero_rotation();
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
}
/* ----------------------------------------------------------------------
rescale velocities of group atoms to t_new from t_old
------------------------------------------------------------------------- */
void Velocity::rescale(double t_old, double t_new)
{
- if (t_old == 0.0) error->all("Attempting to rescale a 0.0 temperature");
+ if (t_old == 0.0) error->all(FLERR,"Attempting to rescale a 0.0 temperature");
double factor = sqrt(t_new/t_old);
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] *= factor;
v[i][1] *= factor;
v[i][2] *= factor;
}
}
/* ----------------------------------------------------------------------
zero the linear momentum of a group of atoms by adjusting v by -Vcm
------------------------------------------------------------------------- */
void Velocity::zero_momentum()
{
// cannot have 0 atoms in group
if (group->count(igroup) == 0)
- error->all("Cannot zero momentum of 0 atoms");
+ error->all(FLERR,"Cannot zero momentum of 0 atoms");
// compute velocity of center-of-mass of group
double masstotal = group->mass(igroup);
double vcm[3];
group->vcm(igroup,masstotal,vcm);
// adjust velocities by vcm to zero linear momentum
double **v = atom->v;
int *mask = atom->mask;
int nlocal = atom->nlocal;
for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
v[i][0] -= vcm[0];
v[i][1] -= vcm[1];
v[i][2] -= vcm[2];
}
}
/* ----------------------------------------------------------------------
zero the angular momentum of a group of atoms by adjusting v by -(w x r)
------------------------------------------------------------------------- */
void Velocity::zero_rotation()
{
int i;
// cannot have 0 atoms in group
if (group->count(igroup) == 0)
- error->all("Cannot zero momentum of 0 atoms");
+ error->all(FLERR,"Cannot zero momentum of 0 atoms");
// compute omega (angular velocity) of group around center-of-mass
double xcm[3],angmom[3],inertia[3][3],omega[3];
double masstotal = group->mass(igroup);
group->xcm(igroup,masstotal,xcm);
group->angmom(igroup,xcm,angmom);
group->inertia(igroup,xcm,inertia);
group->omega(angmom,inertia,omega);
// adjust velocities to zero omega
// vnew_i = v_i - w x r_i
// must use unwrapped coords to compute r_i correctly
double **x = atom->x;
double **v = atom->v;
int *mask = atom->mask;
int *image = atom->image;
int nlocal = atom->nlocal;
int xbox,ybox,zbox;
double dx,dy,dz;
double xprd = domain->xprd;
double yprd = domain->yprd;
double zprd = domain->zprd;
for (i = 0; i < nlocal; i++)
if (mask[i] & groupbit) {
xbox = (image[i] & 1023) - 512;
ybox = (image[i] >> 10 & 1023) - 512;
zbox = (image[i] >> 20) - 512;
dx = (x[i][0] + xbox*xprd) - xcm[0];
dy = (x[i][1] + ybox*yprd) - xcm[1];
dz = (x[i][2] + zbox*zprd) - xcm[2];
v[i][0] -= omega[1]*dz - omega[2]*dy;
v[i][1] -= omega[2]*dx - omega[0]*dz;
v[i][2] -= omega[0]*dy - omega[1]*dx;
}
}
/* ----------------------------------------------------------------------
parse optional parameters at end of velocity input line
------------------------------------------------------------------------- */
void Velocity::options(int narg, char **arg)
{
- if (narg < 0) error->all("Illegal velocity command");
+ if (narg < 0) error->all(FLERR,"Illegal velocity command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"dist") == 0) {
- if (iarg+2 > narg) error->all("Illegal velocity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command");
if (strcmp(arg[iarg+1],"uniform") == 0) dist_flag = 0;
else if (strcmp(arg[iarg+1],"gaussian") == 0) dist_flag = 1;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
iarg += 2;
} else if (strcmp(arg[iarg],"sum") == 0) {
- if (iarg+2 > narg) error->all("Illegal velocity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command");
if (strcmp(arg[iarg+1],"no") == 0) sum_flag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) sum_flag = 1;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
iarg += 2;
} else if (strcmp(arg[iarg],"mom") == 0) {
- if (iarg+2 > narg) error->all("Illegal velocity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command");
if (strcmp(arg[iarg+1],"no") == 0) momentum_flag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) momentum_flag = 1;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
iarg += 2;
} else if (strcmp(arg[iarg],"rot") == 0) {
- if (iarg+2 > narg) error->all("Illegal velocity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command");
if (strcmp(arg[iarg+1],"no") == 0) rotation_flag = 0;
else if (strcmp(arg[iarg+1],"yes") == 0) rotation_flag = 1;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
iarg += 2;
} else if (strcmp(arg[iarg],"temp") == 0) {
- if (iarg+2 > narg) error->all("Illegal velocity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command");
int icompute;
for (icompute = 0; icompute < modify->ncompute; icompute++)
if (strcmp(arg[iarg+1],modify->compute[icompute]->id) == 0) break;
if (icompute == modify->ncompute)
- error->all("Could not find velocity temperature ID");
+ error->all(FLERR,"Could not find velocity temperature ID");
temperature = modify->compute[icompute];
if (temperature->tempflag == 0)
- error->all("Velocity temperature ID does not compute temperature");
+ error->all(FLERR,"Velocity temperature ID does not compute temperature");
iarg += 2;
} else if (strcmp(arg[iarg],"loop") == 0) {
- if (iarg+2 > narg) error->all("Illegal velocity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command");
if (strcmp(arg[iarg+1],"all") == 0) loop_flag = ALL;
else if (strcmp(arg[iarg+1],"local") == 0) loop_flag = LOCAL;
else if (strcmp(arg[iarg+1],"geom") == 0) loop_flag = GEOM;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
iarg += 2;
} else if (strcmp(arg[iarg],"units") == 0) {
- if (iarg+2 > narg) error->all("Illegal velocity command");
+ if (iarg+2 > narg) error->all(FLERR,"Illegal velocity command");
if (strcmp(arg[iarg+1],"box") == 0) scale_flag = 0;
else if (strcmp(arg[iarg+1],"lattice") == 0) scale_flag = 1;
- else error->all("Illegal velocity command");
+ else error->all(FLERR,"Illegal velocity command");
iarg += 2;
- } else error->all("Illegal velocity command");
+ } else error->all(FLERR,"Illegal velocity command");
}
}
diff --git a/src/verlet.cpp b/src/verlet.cpp
index 4fc4024f4..7e3836740 100644
--- a/src/verlet.cpp
+++ b/src/verlet.cpp
@@ -1,423 +1,423 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "string.h"
#include "verlet.h"
#include "neighbor.h"
#include "domain.h"
#include "comm.h"
#include "atom.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "kspace.h"
#include "output.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "fix.h"
#include "timer.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Verlet::Verlet(LAMMPS *lmp, int narg, char **arg) :
Integrate(lmp, narg, arg) {}
/* ----------------------------------------------------------------------
initialization before run
------------------------------------------------------------------------- */
void Verlet::init()
{
// warn if no fixes
if (modify->nfix == 0 && comm->me == 0)
- error->warning("No fixes defined, atoms won't move");
+ error->warning(FLERR,"No fixes defined, atoms won't move");
// virial_style:
// 1 if computed explicitly by pair->compute via sum over pair interactions
// 2 if computed implicitly by pair->virial_fdotr_compute via sum over ghosts
if (force->newton_pair) virial_style = 2;
else virial_style = 1;
// setup lists of computes for global and per-atom PE and pressure
ev_setup();
// set flags for what arrays to clear in force_clear()
// need to clear additionals arrays if they exist
torqueflag = 0;
if (atom->torque_flag) torqueflag = 1;
erforceflag = 0;
if (atom->erforce_flag) erforceflag = 1;
e_flag = 0;
if (atom->e_flag) e_flag = 1;
rho_flag = 0;
if (atom->rho_flag) rho_flag = 1;
// orthogonal vs triclinic simulation box
triclinic = domain->triclinic;
}
/* ----------------------------------------------------------------------
setup before run
------------------------------------------------------------------------- */
void Verlet::setup()
{
if (comm->me == 0 && screen) fprintf(screen,"Setting up run ...\n");
update->setupflag = 1;
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
atom->setup();
modify->setup_pre_exchange();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
if (atom->sortfreq > 0) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
neighbor->build();
neighbor->ncalls = 0;
// compute all forces
ev_set(update->ntimestep);
force_clear();
modify->setup_pre_force(vflag);
if (force->pair) force->pair->compute(eflag,vflag);
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if (force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if (force->newton) comm->reverse_comm();
modify->setup(vflag);
output->setup(1);
update->setupflag = 0;
}
/* ----------------------------------------------------------------------
setup without output
flag = 0 = just force calculation
flag = 1 = reneighbor and force calculation
------------------------------------------------------------------------- */
void Verlet::setup_minimal(int flag)
{
update->setupflag = 1;
// setup domain, communication and neighboring
// acquire ghosts
// build neighbor lists
if (flag) {
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
comm->exchange();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
neighbor->build();
neighbor->ncalls = 0;
}
// compute all forces
ev_set(update->ntimestep);
force_clear();
modify->setup_pre_force(vflag);
if (force->pair) force->pair->compute(eflag,vflag);
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
}
if (force->kspace) {
force->kspace->setup();
force->kspace->compute(eflag,vflag);
}
if (force->newton) comm->reverse_comm();
modify->setup(vflag);
update->setupflag = 0;
}
/* ----------------------------------------------------------------------
run for N steps
------------------------------------------------------------------------- */
void Verlet::run(int n)
{
bigint ntimestep;
int nflag,sortflag;
int n_post_integrate = modify->n_post_integrate;
int n_pre_exchange = modify->n_pre_exchange;
int n_pre_neighbor = modify->n_pre_neighbor;
int n_pre_force = modify->n_pre_force;
int n_post_force = modify->n_post_force;
int n_end_of_step = modify->n_end_of_step;
if (atom->sortfreq > 0) sortflag = 1;
else sortflag = 0;
for (int i = 0; i < n; i++) {
ntimestep = ++update->ntimestep;
ev_set(ntimestep);
// initial time integration
modify->initial_integrate(vflag);
if (n_post_integrate) modify->post_integrate();
// regular communication vs neighbor list rebuild
nflag = neighbor->decide();
if (nflag == 0) {
timer->stamp();
comm->forward_comm();
timer->stamp(TIME_COMM);
} else {
if (n_pre_exchange) modify->pre_exchange();
if (triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
if (domain->box_change) {
domain->reset_box();
comm->setup();
if (neighbor->style) neighbor->setup_bins();
}
timer->stamp();
comm->exchange();
if (sortflag && ntimestep >= atom->nextsort) atom->sort();
comm->borders();
if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
timer->stamp(TIME_COMM);
if (n_pre_neighbor) modify->pre_neighbor();
neighbor->build();
timer->stamp(TIME_NEIGHBOR);
}
// force computations
force_clear();
if (n_pre_force) modify->pre_force(vflag);
timer->stamp();
if (force->pair) {
force->pair->compute(eflag,vflag);
timer->stamp(TIME_PAIR);
}
if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vflag);
if (force->angle) force->angle->compute(eflag,vflag);
if (force->dihedral) force->dihedral->compute(eflag,vflag);
if (force->improper) force->improper->compute(eflag,vflag);
timer->stamp(TIME_BOND);
}
if (force->kspace) {
force->kspace->compute(eflag,vflag);
timer->stamp(TIME_KSPACE);
}
// reverse communication of forces
if (force->newton) {
comm->reverse_comm();
timer->stamp(TIME_COMM);
}
// force modifications, final time integration, diagnostics
if (n_post_force) modify->post_force(vflag);
modify->final_integrate();
if (n_end_of_step) modify->end_of_step();
// all output
if (ntimestep == output->next) {
timer->stamp();
output->write(ntimestep);
timer->stamp(TIME_OUTPUT);
}
}
}
/* ---------------------------------------------------------------------- */
void Verlet::cleanup()
{
modify->post_run();
}
/* ----------------------------------------------------------------------
clear force on own & ghost atoms
setup and clear other arrays as needed
------------------------------------------------------------------------- */
void Verlet::force_clear()
{
int i;
// clear force on all particles
// if either newton flag is set, also include ghosts
if (neighbor->includegroup == 0) {
int nall;
if (force->newton) nall = atom->nlocal + atom->nghost;
else nall = atom->nlocal;
int ntot = nall * comm->nthreads;
double **f = atom->f;
for (i = 0; i < ntot; i++) {
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
}
if (torqueflag) {
double **torque = atom->torque;
for (i = 0; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
if (erforceflag) {
double *erforce = atom->erforce;
for (i = 0; i < nall; i++) erforce[i] = 0.0;
}
if (e_flag) {
double *de = atom->de;
for (i = 0; i < nall; i++) de[i] = 0.0;
}
if (rho_flag) {
double *drho = atom->drho;
for (i = 0; i < nall; i++) drho[i] = 0.0;
}
// neighbor includegroup flag is set
// clear force only on initial nfirst particles
// if either newton flag is set, also include ghosts
} else {
int nall = atom->nfirst;
double **f = atom->f;
for (i = 0; i < nall; i++) {
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
}
if (torqueflag) {
double **torque = atom->torque;
for (i = 0; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
if (erforceflag) {
double *erforce = atom->erforce;
for (i = 0; i < nall; i++) erforce[i] = 0.0;
}
if (e_flag) {
double *de = atom->de;
for (i = 0; i < nall; i++) de[i] = 0.0;
}
if (rho_flag) {
double *drho = atom->drho;
for (i = 0; i < nall; i++) drho[i] = 0.0;
}
if (force->newton) {
nall = atom->nlocal + atom->nghost;
for (i = atom->nlocal; i < nall; i++) {
f[i][0] = 0.0;
f[i][1] = 0.0;
f[i][2] = 0.0;
}
if (torqueflag) {
double **torque = atom->torque;
for (i = atom->nlocal; i < nall; i++) {
torque[i][0] = 0.0;
torque[i][1] = 0.0;
torque[i][2] = 0.0;
}
}
if (erforceflag) {
double *erforce = atom->erforce;
for (i = atom->nlocal; i < nall; i++) erforce[i] = 0.0;
}
if (e_flag) {
double *de = atom->de;
for (i = 0; i < nall; i++) de[i] = 0.0;
}
if (rho_flag) {
double *drho = atom->drho;
for (i = 0; i < nall; i++) drho[i] = 0.0;
}
}
}
}
diff --git a/src/version.h b/src/version.h
index 719b5561f..ba2ffff87 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define LAMMPS_VERSION "17 Sep 2011"
+#define LAMMPS_VERSION "25 Sep 2011"
diff --git a/src/write_restart.cpp b/src/write_restart.cpp
index 260dcbe3d..6a909ae10 100644
--- a/src/write_restart.cpp
+++ b/src/write_restart.cpp
@@ -1,498 +1,495 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "lmptype.h"
#include "mpi.h"
#include "string.h"
#include "write_restart.h"
#include "atom.h"
#include "atom_vec.h"
#include "atom_vec_hybrid.h"
#include "group.h"
#include "force.h"
#include "pair.h"
#include "bond.h"
#include "angle.h"
#include "dihedral.h"
#include "improper.h"
#include "update.h"
#include "neighbor.h"
#include "domain.h"
#include "modify.h"
#include "universe.h"
#include "comm.h"
#include "output.h"
#include "thermo.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
-#define MIN(A,B) ((A) < (B)) ? (A) : (B)
-#define MAX(A,B) ((A) > (B)) ? (A) : (B)
-
// same as read_restart.cpp and tools/restart2data.cpp
enum{VERSION,SMALLINT,TAGINT,BIGINT,
UNITS,NTIMESTEP,DIMENSION,NPROCS,PROCGRID_0,PROCGRID_1,PROCGRID_2,
NEWTON_PAIR,NEWTON_BOND,XPERIODIC,YPERIODIC,ZPERIODIC,
BOUNDARY_00,BOUNDARY_01,BOUNDARY_10,BOUNDARY_11,BOUNDARY_20,BOUNDARY_21,
ATOM_STYLE,NATOMS,NTYPES,
NBONDS,NBONDTYPES,BOND_PER_ATOM,
NANGLES,NANGLETYPES,ANGLE_PER_ATOM,
NDIHEDRALS,NDIHEDRALTYPES,DIHEDRAL_PER_ATOM,
NIMPROPERS,NIMPROPERTYPES,IMPROPER_PER_ATOM,
BOXLO_0,BOXHI_0,BOXLO_1,BOXHI_1,BOXLO_2,BOXHI_2,
SPECIAL_LJ_1,SPECIAL_LJ_2,SPECIAL_LJ_3,
SPECIAL_COUL_1,SPECIAL_COUL_2,SPECIAL_COUL_3,
XY,XZ,YZ};
enum{MASS};
enum{PAIR,BOND,ANGLE,DIHEDRAL,IMPROPER};
enum{IGNORE,WARN,ERROR}; // same as thermo.cpp
/* ---------------------------------------------------------------------- */
WriteRestart::WriteRestart(LAMMPS *lmp) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
}
/* ----------------------------------------------------------------------
called as write_restart command in input script
------------------------------------------------------------------------- */
void WriteRestart::command(int narg, char **arg)
{
if (domain->box_exist == 0)
- error->all("Write_restart command before simulation box is defined");
- if (narg != 1) error->all("Illegal write_restart command");
+ error->all(FLERR,"Write_restart command before simulation box is defined");
+ if (narg != 1) error->all(FLERR,"Illegal write_restart command");
// if filename contains a "*", replace with current timestep
char *ptr;
int n = strlen(arg[0]) + 16;
char *file = new char[n];
if (ptr = strchr(arg[0],'*')) {
*ptr = '\0';
sprintf(file,"%s" BIGINT_FORMAT "%s",arg[0],update->ntimestep,ptr+1);
} else strcpy(file,arg[0]);
// init entire system since comm->exchange is done
// comm::init needs neighbor::init needs pair::init needs kspace::init, etc
if (comm->me == 0 && screen)
fprintf(screen,"System init for write_restart ...\n");
lmp->init();
// move atoms to new processors before writing file
// enforce PBC before in case atoms are outside box
// call borders() to rebuild atom map since exchange() destroys map
if (domain->triclinic) domain->x2lamda(atom->nlocal);
domain->pbc();
domain->reset_box();
comm->setup();
comm->exchange();
comm->borders();
if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
write(file);
delete [] file;
}
/* ----------------------------------------------------------------------
called from command() and directly from output within run/minimize loop
file = final file name to write, except may contain a "%"
------------------------------------------------------------------------- */
void WriteRestart::write(char *file)
{
// special case where reneighboring is not done in integrator
// on timestep restart file is written (due to build_once being set)
// if box is changing, must be reset, else restart file will have
// wrong box size and atoms will be lost when restart file is read
// other calls to pbc and domain and comm are not made,
// b/c they only make sense if reneighboring is actually performed
if (neighbor->build_once) domain->reset_box();
// natoms = sum of nlocal = value to write into restart file
// if unequal and thermo lostflag is "error", don't write restart file
bigint nblocal = atom->nlocal;
MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
if (natoms != atom->natoms && output->thermo->lostflag == ERROR)
- error->all("Atom count is inconsistent, cannot write restart file");
+ error->all(FLERR,"Atom count is inconsistent, cannot write restart file");
// check if filename contains "%"
int multiproc;
if (strchr(file,'%')) multiproc = 1;
else multiproc = 0;
// open single restart file or base file for multiproc case
if (me == 0) {
char *hfile;
if (multiproc) {
hfile = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(hfile,"%s%s%s",file,"base",ptr+1);
*ptr = '%';
} else hfile = file;
fp = fopen(hfile,"wb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",hfile);
- error->one(str);
+ error->one(FLERR,str);
}
if (multiproc) delete [] hfile;
}
// proc 0 writes header, groups, ntype-length arrays, force field
// all procs write fix info
if (me == 0) {
header();
group->write_restart(fp);
type_arrays();
force_fields();
}
modify->write_restart(fp);
// communication buffer for all my atom's info
// max_size = largest buffer needed by any proc
int max_size;
int send_size = atom->avec->size_restart();
MPI_Allreduce(&send_size,&max_size,1,MPI_INT,MPI_MAX,world);
double *buf;
if (me == 0) memory->create(buf,max_size,"write_restart:buf");
else memory->create(buf,send_size,"write_restart:buf");
// pack my atom data into buf
AtomVec *avec = atom->avec;
int n = 0;
for (int i = 0; i < atom->nlocal; i++) n += avec->pack_restart(i,&buf[n]);
// if any fix requires it, remap each atom's coords via PBC
// is because fix changes atom coords (excepting an integrate fix)
// just remap in buffer, not actual atoms
if (modify->restart_pbc_any) {
int triclinic = domain->triclinic;
double *lo,*hi,*period;
if (triclinic == 0) {
lo = domain->boxlo;
hi = domain->boxhi;
period = domain->prd;
} else {
lo = domain->boxlo_lamda;
hi = domain->boxhi_lamda;
period = domain->prd_lamda;
}
int xperiodic = domain->xperiodic;
int yperiodic = domain->yperiodic;
int zperiodic = domain->zperiodic;
double *x;
int m = 0;
for (int i = 0; i < atom->nlocal; i++) {
x = &buf[m+1];
if (triclinic) domain->x2lamda(x,x);
if (xperiodic) {
if (x[0] < lo[0]) x[0] += period[0];
if (x[0] >= hi[0]) x[0] -= period[0];
x[0] = MAX(x[0],lo[0]);
}
if (yperiodic) {
if (x[1] < lo[1]) x[1] += period[1];
if (x[1] >= hi[1]) x[1] -= period[1];
x[1] = MAX(x[1],lo[1]);
}
if (zperiodic) {
if (x[2] < lo[2]) x[2] += period[2];
if (x[2] >= hi[2]) x[2] -= period[2];
x[2] = MAX(x[2],lo[2]);
}
if (triclinic) domain->lamda2x(x,x);
m += static_cast<int> (buf[m]);
}
}
// if single file:
// write one chunk of atoms per proc to file
// proc 0 pings each proc, receives its chunk, writes to file
// all other procs wait for ping, send their chunk to proc 0
// else if one file per proc:
// each proc opens its own file and writes its chunk directly
if (multiproc == 0) {
int tmp,recv_size;
MPI_Status status;
MPI_Request request;
if (me == 0) {
for (int iproc = 0; iproc < nprocs; iproc++) {
if (iproc) {
MPI_Irecv(buf,max_size,MPI_DOUBLE,iproc,0,world,&request);
MPI_Send(&tmp,0,MPI_INT,iproc,0,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_DOUBLE,&recv_size);
} else recv_size = send_size;
fwrite(&recv_size,sizeof(int),1,fp);
fwrite(buf,sizeof(double),recv_size,fp);
}
fclose(fp);
} else {
MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status);
MPI_Rsend(buf,send_size,MPI_DOUBLE,0,0,world);
}
} else {
if (me == 0) fclose(fp);
char *perproc = new char[strlen(file) + 16];
char *ptr = strchr(file,'%');
*ptr = '\0';
sprintf(perproc,"%s%d%s",file,me,ptr+1);
*ptr = '%';
fp = fopen(perproc,"wb");
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open restart file %s",perproc);
- error->one(str);
+ error->one(FLERR,str);
}
delete [] perproc;
fwrite(&send_size,sizeof(int),1,fp);
fwrite(buf,sizeof(double),send_size,fp);
fclose(fp);
}
memory->destroy(buf);
}
/* ----------------------------------------------------------------------
proc 0 writes out problem description
------------------------------------------------------------------------- */
void WriteRestart::header()
{
write_char(VERSION,universe->version);
write_int(SMALLINT,sizeof(smallint));
write_int(TAGINT,sizeof(tagint));
write_int(BIGINT,sizeof(bigint));
write_char(UNITS,update->unit_style);
write_bigint(NTIMESTEP,update->ntimestep);
write_int(DIMENSION,domain->dimension);
write_int(NPROCS,nprocs);
write_int(PROCGRID_0,comm->procgrid[0]);
write_int(PROCGRID_1,comm->procgrid[1]);
write_int(PROCGRID_2,comm->procgrid[2]);
write_int(NEWTON_PAIR,force->newton_pair);
write_int(NEWTON_BOND,force->newton_bond);
write_int(XPERIODIC,domain->xperiodic);
write_int(YPERIODIC,domain->yperiodic);
write_int(ZPERIODIC,domain->zperiodic);
write_int(BOUNDARY_00,domain->boundary[0][0]);
write_int(BOUNDARY_01,domain->boundary[0][1]);
write_int(BOUNDARY_10,domain->boundary[1][0]);
write_int(BOUNDARY_11,domain->boundary[1][1]);
write_int(BOUNDARY_20,domain->boundary[2][0]);
write_int(BOUNDARY_21,domain->boundary[2][1]);
// atom_style must be written before atom class values
// so read_restart can create class before reading class values
// if style = hybrid, also write sub-class styles
write_char(ATOM_STYLE,atom->atom_style);
if (strcmp(atom->atom_style,"hybrid") == 0) {
AtomVecHybrid *avec_hybrid = (AtomVecHybrid *) atom->avec;
int nstyles = avec_hybrid->nstyles;
char **keywords = avec_hybrid->keywords;
fwrite(&nstyles,sizeof(int),1,fp);
for (int i = 0; i < nstyles; i++) {
int n = strlen(keywords[i]) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(keywords[i],sizeof(char),n,fp);
}
}
write_bigint(NATOMS,natoms);
write_int(NTYPES,atom->ntypes);
write_bigint(NBONDS,atom->nbonds);
write_int(NBONDTYPES,atom->nbondtypes);
write_int(BOND_PER_ATOM,atom->bond_per_atom);
write_bigint(NANGLES,atom->nangles);
write_int(NANGLETYPES,atom->nangletypes);
write_int(ANGLE_PER_ATOM,atom->angle_per_atom);
write_bigint(NDIHEDRALS,atom->ndihedrals);
write_int(NDIHEDRALTYPES,atom->ndihedraltypes);
write_int(DIHEDRAL_PER_ATOM,atom->dihedral_per_atom);
write_bigint(NIMPROPERS,atom->nimpropers);
write_int(NIMPROPERTYPES,atom->nimpropertypes);
write_int(IMPROPER_PER_ATOM,atom->improper_per_atom);
write_double(BOXLO_0,domain->boxlo[0]);
write_double(BOXHI_0,domain->boxhi[0]);
write_double(BOXLO_1,domain->boxlo[1]);
write_double(BOXHI_1,domain->boxhi[1]);
write_double(BOXLO_2,domain->boxlo[2]);
write_double(BOXHI_2,domain->boxhi[2]);
write_double(SPECIAL_LJ_1,force->special_lj[1]);
write_double(SPECIAL_LJ_2,force->special_lj[2]);
write_double(SPECIAL_LJ_3,force->special_lj[3]);
write_double(SPECIAL_COUL_1,force->special_coul[1]);
write_double(SPECIAL_COUL_2,force->special_coul[2]);
write_double(SPECIAL_COUL_3,force->special_coul[3]);
if (domain->triclinic) {
write_double(XY,domain->xy);
write_double(XZ,domain->xz);
write_double(YZ,domain->yz);
}
// -1 flag signals end of header
int flag = -1;
fwrite(&flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 writes out any type-based arrays that are defined
------------------------------------------------------------------------- */
void WriteRestart::type_arrays()
{
if (atom->mass) {
int flag = MASS;
fwrite(&flag,sizeof(int),1,fp);
fwrite(&atom->mass[1],sizeof(double),atom->ntypes,fp);
}
// -1 flag signals end of type arrays
int flag = -1;
fwrite(&flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
proc 0 writes out and force field styles and data that are defined
------------------------------------------------------------------------- */
void WriteRestart::force_fields()
{
if (force->pair) {
int flag = PAIR;
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->pair_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->pair_style,sizeof(char),n,fp);
force->pair->write_restart(fp);
}
if (atom->avec->bonds_allow && force->bond) {
int flag = BOND;
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->bond_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->bond_style,sizeof(char),n,fp);
force->bond->write_restart(fp);
}
if (atom->avec->angles_allow && force->angle) {
int flag = ANGLE;
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->angle_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->angle_style,sizeof(char),n,fp);
force->angle->write_restart(fp);
}
if (atom->avec->dihedrals_allow && force->dihedral) {
int flag = DIHEDRAL;
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->dihedral_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->dihedral_style,sizeof(char),n,fp);
force->dihedral->write_restart(fp);
}
if (atom->avec->impropers_allow && force->improper) {
int flag = IMPROPER;
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(force->improper_style) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(force->improper_style,sizeof(char),n,fp);
force->improper->write_restart(fp);
}
// -1 flag signals end of force field info
int flag = -1;
fwrite(&flag,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
write a flag and an int into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_int(int flag, int value)
{
fwrite(&flag,sizeof(int),1,fp);
fwrite(&value,sizeof(int),1,fp);
}
/* ----------------------------------------------------------------------
write a flag and a double into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_double(int flag, double value)
{
fwrite(&flag,sizeof(int),1,fp);
fwrite(&value,sizeof(double),1,fp);
}
/* ----------------------------------------------------------------------
write a flag and a char str into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_char(int flag, char *value)
{
fwrite(&flag,sizeof(int),1,fp);
int n = strlen(value) + 1;
fwrite(&n,sizeof(int),1,fp);
fwrite(value,sizeof(char),n,fp);
}
/* ----------------------------------------------------------------------
write a flag and a bigint into restart file
------------------------------------------------------------------------- */
void WriteRestart::write_bigint(int flag, bigint value)
{
fwrite(&flag,sizeof(int),1,fp);
fwrite(&value,sizeof(bigint),1,fp);
}
diff --git a/tools/msi2lmp/README b/tools/msi2lmp/README
index a70a67b84..ac565ce47 100644
--- a/tools/msi2lmp/README
+++ b/tools/msi2lmp/README
@@ -1,132 +1,141 @@
+Stephanie Teich-McGoldrick (Sandai) is the current maintainer
+of the msi2lmp tool. She can be contacted at steichm at sandia.gov
+
+23 Sep 2011
+
+added support for triclinic boxes
+see msi2lmp/TriclinicModification.pdf doc for details
+
+-----------------------------
msi2lmp V3.6 4/10/2005
This program uses the .car and .mdf files from MSI/Biosyms's INSIGHT
program to produce a LAMMPS data file.
1. Building msi2lmp3
Use the Makefile in the src directory. It is
currently set up for gcc. One will have to modify
it to use a different compiler.
2. Testing the program
There are three pairs (.car and .mdf) files in the
test directory: crambin, nylon and phen3_cff97. The
atom types in crambin and nylon are cvff (Class I) atom
types and those in phen3_cff97 are cff9x (Class II) atom types.
Two forcefield files, cvff.frc and cff91.frc, are needed
generate lammps data files for these three test files. To
run it you would:
% setenv BIOSYM_LIBRARY ../biosym_frc_files
% ../src/msi2lmp.exe nylon -class I -frc cvff > data.nylon
% ../src/msi2lmp.exe crambin -class I -frc cvff > data.crambin
% ../src/msi2lmp.exe phen3_cff97 -class II -frc cff91 > data.phen3_cff97
Three files should be generated: data.nylon, data.crambin
and data.phen3_cff97. These can be compared against
data.x in the directory correct. If there are differences,
first recompile the program with no optimization and try again.
If there are still differences, send email to jec@mayo.edu
Note: you will see many "Unable to find..." parameters messages
in the phen3_cff97 test case. Most of those parameters
exist in cff95.frc, but not in cff91.frc
3. To run the program
The program is started by supplying information at the command prompt
according to the usage described below.
USAGE: msi2lmp.exe ROOTNAME {-2001} {-print #} {-class #} {-frc FRC_FILE}
-- msi2lmp.exe is the name of the executable
-- ROOTNAME is the base name of the .car and .mdf files
-- -2001
Output lammps files for LAMMPS version 2001 (F90 version)
The default is for LAMMPS 2005 (C++ version)
-- -print
# is the print level 0 - silent except for error messages
1 - minimal (default)
2 - verbose (usual for developing and
checking new data files for consistency)
-- -class
# is the class of forcefield to use (I = Class I e.g., CVFF)
(II = Class II e.g., CFFx )
default is -class I
-- -frc - specifies name of the forcefield file (e.g., cff91)
If the name includes a hard wired directory (i.e., if the name
starts with . or /), then the name is used alone. Otherwise,
the program looks for the forcefield file in $BIOSYM_LIBRARY.
If $BIOSYM_LIBRARY is not set, then the current directory is
used.
If the file name does not include a dot after the first
character, then .frc is appended to the name.
For example, -frc cvff (assumes cvff.frc is in $BIOSYM_LIBRARY
or .)
-frc cff/cff91 (assumes cff91.frc is in
$BIOSYM_LIBRARY/cff or ./cff)
-frc /usr/local/biosym/forcefields/cff95 (absolute
location)
By default, the program uses $BIOSYM_LIBRARY/cvff.frc
-- the LAMMPS data file is written to ROOTNAME.lammps{01/05}
commentary is written to standard error.
****************************************************************
*
* Msi2lmp3
*
* This is the third version of a program that generates a LAMMPS
* data file based on the information in MSI .car (atom
* coordinates), .mdf (molecular topology) and .frc (forcefield)
* files. The .car and .mdf files are specific to a molecular
* system while the .frc file is specific to a forcefield version.
* The only coherency needed between .frc and .car/.mdf files are
* the atom types.
*
* The first version was written by Steve Lustig at Dupont, but
* required using Discover to derive internal coordinates and
* forcefield parameters
*
* The second version was written by Michael Peachey while an
* intern in the Cray Chemistry Applications Group managed
* by John Carpenter. This version derived internal coordinates
* from the mdf file and looked up parameters in the frc file
* thus eliminating the need for Discover.
*
* The third version was written by John Carpenter to optimize
* the performance of the program for large molecular systems
* (the original code for deriving atom numbers was quadratic in time)
* and to make the program fully dynamic. The second version used
* fixed dimension arrays for the internal coordinates.
*
* The current maintainer is only reluctantly doing so because John Mayo no longer
* needs this code.
*
* V3.2 corresponds to adding code to MakeLists.c to gracefully deal with
* systems that may only be molecules of 1 to 3 atoms. In V3.1, the values
* for number_of_dihedrals, etc. could be unpredictable in these systems.
*
* V3.3 was generated in response to a strange error reading a MDF file generated by
* Accelys' Materials Studio GUI. Simply rewriting the input part of ReadMdfFile.c
* seems to have fixed the problem.
*
* V3.4 and V3.5 are minor upgrades to fix bugs associated mostly with .car and .mdf files
* written by Accelys' Materials Studio GUI.
*
* V3.6 outputs to LAMMPS 2005 (C++ version).
*
* Contact: Kelly L. Anderson, kelly.anderson@cantab.net
*
* April 2005
diff --git a/tools/msi2lmp/TriclinicModification.pdf b/tools/msi2lmp/TriclinicModification.pdf
new file mode 100644
index 000000000..a88bb902f
Binary files /dev/null and b/tools/msi2lmp/TriclinicModification.pdf differ
diff --git a/tools/msi2lmp/biosym_frc_files/clayff.frc b/tools/msi2lmp/biosym_frc_files/clayff.frc
new file mode 100644
index 000000000..bdc9c2c00
--- /dev/null
+++ b/tools/msi2lmp/biosym_frc_files/clayff.frc
@@ -0,0 +1,154 @@
+!CLAYFF forcefield
+
+#atom_types cvff
+
+!Ver Ref Type Mass Element Connections Comment
+!---- --- ---- ---------- ------- -----------------------------------------
+ 1.0 1 st 28.08550 Si 4
+ 1.0 1 ao 26.98154 Al 6
+ 1.0 1 at 26.98154 Al 4
+ 1.0 1 mgo 24.30500 Mg 6
+ 1.0 1 cao 40.08000 Ca 6
+ 1.0 1 feo 55.84700 Fe 6
+ 1.0 1 lio 6.941000 Li 6
+ 1.0 1 ob 15.99940 O 2
+ 1.0 1 obss 15.99940 O 3
+ 1.0 1 obts 15.99940 O 2
+ 1.0 1 obos 15.99940 O 2
+ 1.0 1 ohs 15.99940 O 2
+ 1.0 1 oh 15.99940 O 2
+ 1.0 1 oh- 15.99940 O 1
+ 1.0 1 o* 15.99940 O 2
+ 1.0 1 ho 1.007970 H 1
+ 1.0 1 h* 1.007970 H 1
+ 1.0 1 Na 22.99000 Na 0
+ 1.0 1 K 39.10 K 0
+ 1.0 1 Cs 132.9100 Cs 0
+ 1.0 1 Ca 40.07980 Ca 0
+ 1.0 1 Ba 137.3300 Ba 0
+ 1.0 1 Mg 24.3050 Mg 0
+ 1.0 1 Sr 87.6200 Sr 0
+ 1.0 1 Pb 207.2000 Pb 0
+ 1.0 1 Cl 35.45300 Cl 0
+
+
+#equivalence cvff
+
+> Equivalence table for any variant of cvff
+
+! Equivalences
+! -----------------------------------------
+!Ver Ref Type NonB Bond Angle Torsion OOP
+!---- --- ---- ---- ---- ----- ------- ----
+ 1.0 1 h h h h h h
+
+
+
+#auto_equivalence cvff_auto
+
+! Equivalences
+! -----------------------------------------
+!Ver Ref Type NonB Bond Bond Angle Angle Torsion Torsion OOP OOP
+! Inct End atom Apex atom End Atoms Center Atoms End Atom Center Atom
+!---- --- ---- ---- ------ ---- ---------- --------- --------- ----------- -------- -----------
+ 2.0 18 h h h h_ h_ h_ h_ h_ h_ h_
+
+
+
+#hbond_definition cvff
+
+
+#morse_bond cvff
+
+> E = D * (1 - exp(-ALPHA*(R - R0)))^2
+
+!Ver Ref I J R0 D ALPHA
+!---- --- ---- ---- ------- -------- -------
+ 2.3 23 no o- 1.2178 140.2486 2.0000
+
+
+
+#quadratic_bond cvff
+
+> E = K2 * (R - R0)^2
+
+!Ver Ref I J R0 K2
+!---- --- ---- ---- ------- --------
+ 2.1 28 oh ho 1.0000 553.9350
+ 2.1 28 ohs ho 1.0000 553.9350
+
+
+#quadratic_angle cvff
+
+> E = K2 * (Theta - Theta0)^2
+
+!Ver Ref I J K Theta0 K2
+!---- --- ---- ---- ---- -------- -------
+ 2.3 23 cp cp c' 120.0000 34.6799
+
+
+
+#torsion_1 cvff_auto
+
+> E = Kphi * [ 1 + cos(n*Phi - Phi0) ]
+
+!Ver Ref I J K L Kphi n Phi0
+!---- --- ---- ---- ---- ---- ------- ------ -------
+ 2.0 18 * c_ n3n_ * 0.0500 3 0.
+
+
+
+#out_of_plane cvff_auto
+
+> E = Kchi * [ 1 + cos(n*Chi - Chi0) ]
+
+!Ver Ref I J K L Kchi n Chi0
+!---- --- ---- ---- ---- ---- ------- ------ -------
+ 2.0 18 * c'_ * * 10.0000 2 180.0000
+
+
+#nonbond(12-6) cvff
+
+@type A-B
+@combination geometric
+
+> E = Aij/r^12 - Bij/r^6
+> where Aij = sqrt( Ai * Aj )
+> Bij = sqrt( Bi * Bj )
+
+!Ver Ref I A B
+!---- --- ---- ----------- -----------
+ 1.0 1 st 12.3645 0.00954
+ 1.0 1 ao 196.1446 0.03230
+ 1.0 1 at 12.3645 0.00954
+ 1.0 1 mgo 1636.3265 0.07688
+ 1.0 1 cao 17814.73 0.5987
+ 1.0 1 feo 702.54 0.0504
+ 1.0 1 lio 112.01 0.0201
+ 1.0 1 ob 629358.0000 625.50000
+ 1.0 1 obss 629358.0000 625.50000
+ 1.0 1 obts 629358.0000 625.50000
+ 1.0 1 obos 629358.0000 625.50000
+ 1.0 1 ohs 629358.0000 625.50000
+ 1.0 1 oh 629358.0000 625.50000
+ 1.0 1 oh- 629358.0000 625.50000
+ 1.0 1 o* 629358.0000 625.50000
+ 1.0 1 ho 0.00000001 0.00000
+ 1.0 1 h* 0.00000001 0.00000
+ 1.0 1 Na 14763.1719 87.65132
+ 1.0 1 K 754506.86 549.37
+ 1.0 1 Cs 3998193.96 1264.63
+ 1.0 1 Ca 125966.6068 224.46969
+ 1.0 1 Ba 1799606.56 582.25
+ 1.0 1 Mg 1369.00 69.22
+ 1.0 1 Sr 1185860.37 688.73
+ 1.0 1 Pb 861150.71 638.08
+ 1.0 1 Cl 21081006.97 2905.31
+
+
+#bond_increments cvff
+
+!Ver Ref I J DeltaIJ DeltaJI
+!---- --- ---- ---- ------- -------
+ 2.3 23 no o- 0.1684 -0.1684
+
diff --git a/tools/msi2lmp/src/GetParameters.c b/tools/msi2lmp/src/GetParameters.c
index bd945a927..cd0f3bbbf 100644
--- a/tools/msi2lmp/src/GetParameters.c
+++ b/tools/msi2lmp/src/GetParameters.c
@@ -1,1323 +1,1323 @@
#include "Msi2LMP2.h"
#include "Forcefield.h"
int find_improper_body_data(char [][5],struct FrcFieldItem,int *);
void rearrange_improper(int,int);
int find_trigonal_body_data(char [][5],struct FrcFieldItem);
int find_angleangle_data(char [][5],struct FrcFieldItem,int[]);
int find_match(int, char [][5],struct FrcFieldItem,int *);
int match_types(int,int,char [][5],char [][5],int *);
double get_r0(int,int);
double get_t0(int,int,int);
int quo_cp();
void get_equivs(int,char [][5],char[][5]);
int find_equiv_type(char[]);
/**********************************************************************/
/* */
/* GetParameters is a long routine for searching the forcefield */
/* parameters (read in by ReadFrcFile) for parameters corresponding */
/* to the different internal coordinate types derived by MakeLists */
/* */
/**********************************************************************/
/* #define PRINT_DATA */
/* #define PRINT_USE_EQUIV */
void GetParameters(int Forcefield)
{
int i,j,k,backwards,cp_type,rearrange;
int kloc[3],multiplicity;
char potential_types[4][5];
char equiv_types[4][5];
double rab,rbc,rcd,tabc,tbcd,tabd,tcbd;
if (pflag > 1) fprintf(stderr," Try Atom Equivalences if needed\n");
/**********************************************************************/
/* */
/* Find masses of atom types */
/* */
/**********************************************************************/
for (i=0; i < no_atom_types; i++) {
backwards = -1;
strncpy(potential_types[0],atomtypes[i].potential,5);
k = find_match(1,potential_types,ff_atomtypes,&backwards);
if (k < 0) {
fprintf(stderr,"Unable to find mass for %s\n",atomtypes[i].potential);
}
else {
atomtypes[i].mass = ff_atomtypes.data[k].ff_param[0];
}
}
/**********************************************************************/
/* */
/* Find VDW parameters for atom types */
/* */
/**********************************************************************/
for (i=0; i < no_atom_types; i++) {
backwards = 0;
for (j=0; j < 2; j++) atomtypes[i].params[j] = 0.0;
strncpy(potential_types[0],atomtypes[i].potential,5);
k = find_match(1,potential_types,ff_vdw,&backwards);
if (k < 0) {
get_equivs(1,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for VDW %s -> %s\n",
potential_types[0],equiv_types[0]);
#endif
k = find_match(1,equiv_types,ff_vdw,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find vdw data for %s\n",atomtypes[i].potential);
}
else {
if (Forcefield == 1) {
if((ff_vdw.data[k].ff_param[0] != 0.0 ) &&
(ff_vdw.data[k].ff_param[1] != 0.0)) {
atomtypes[i].params[0] =
(ff_vdw.data[k].ff_param[1]*
ff_vdw.data[k].ff_param[1])/(4.0*ff_vdw.data[k].ff_param[0]);
atomtypes[i].params[1] = pow((ff_vdw.data[k].ff_param[0]/
ff_vdw.data[k].ff_param[1]),
(1.0/6.0));
}
}
else {
atomtypes[i].params[0] = ff_vdw.data[k].ff_param[1];
atomtypes[i].params[1] = ff_vdw.data[k].ff_param[0];
}
}
}
#ifdef PRINT_DATA
fprintf(stderr,"\n Atom Types, Masses and VDW Parameters\n");
for (i=0; i < no_atom_types; i++) {
fprintf(stderr," %3s %8.4f %8.4f %8.4f\n",atomtypes[i].potential,
atomtypes[i].mass, atomtypes[i].params[0],
atomtypes[i].params[1]);
}
#endif
/**********************************************************************/
/* */
/* Find parameters for bond types */
/* */
/**********************************************************************/
for (i=0; i < no_bond_types; i++) {
backwards = 0;
for (j=0; j < 4; j++) bondtypes[i].params[j] = 0.0;
for (j=0; j < 2; j++)
strncpy(potential_types[j],
atomtypes[bondtypes[i].types[j]].potential,5);
k = find_match(2,potential_types,ff_bond,&backwards);
if (k < 0) {
get_equivs(2,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for bond %s %s -> %s %s\n",
potential_types[0],potential_types[1],
equiv_types[0],equiv_types[1]);
#endif
k = find_match(2,equiv_types,ff_bond,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find bond data for %s %s\n",
potential_types[0],potential_types[1]);
}
else {
if (Forcefield == 1) {
bondtypes[i].params[0] = ff_bond.data[k].ff_param[1];
bondtypes[i].params[1] = ff_bond.data[k].ff_param[0];
}
else {
for (j=0; j < 4; j++)
bondtypes[i].params[j] = ff_bond.data[k].ff_param[j];
}
}
}
#ifdef PRINT_DATA
printf ("\n Bond Types and Parameters\n");
for (i=0; i < no_bond_types; i++) {
for (j=0; j < 2; j++) fprintf(stderr,"%-3s",
atomtypes[bondtypes[i].types[j]].potential);
for (j=0; j < 4; j++) fprintf(stderr," %8.4f",bondtypes[i].params[j]);
fprintf(stderr,"\n");
}
#endif
/**********************************************************************/
/* */
/* Find parameters for angle types including bondbond, */
/* and bondangle parameters if Class II */
/* */
/* Each of the cross terms are searched separately even though */
/* they share a given angle type. This allows parameters to be */
/* in different order in the forcefield for each cross term or */
/* maybe not even there. */
/* */
/**********************************************************************/
for (i=0; i < no_angle_types; i++) {
backwards = 0;
for (j=0; j < 4; j++) angletypes[i].params[j] = 0.0;
for (j=0; j < 3; j++)
strncpy(potential_types[j],atomtypes[angletypes[i].types[j]].potential,5);
k = find_match(3,potential_types,ff_ang,&backwards);
if (k < 0) {
get_equivs(3,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for angle %s %s %s -> %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],
equiv_types[0],equiv_types[1],
equiv_types[2]);
#endif
k = find_match(3,equiv_types,ff_ang,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find angle data for %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2]);
}
else {
if (Forcefield == 1) {
angletypes[i].params[0] = ff_ang.data[k].ff_param[1];
angletypes[i].params[1] = ff_ang.data[k].ff_param[0];
}
else {
for (j=0; j < 4; j++)
angletypes[i].params[j] = ff_ang.data[k].ff_param[j];
}
}
if (Forcefield > 1) {
get_equivs(3,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for 3 body cross terms %s %s %s -> %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],
equiv_types[0],equiv_types[1],
equiv_types[2]);
#endif
for (j=0; j < 3; j++)
angletypes[i].bondbond_cross_term[j] = 0.0;
for (j=0; j < 4; j++) angletypes[i].bondangle_cross_term[j] = 0.0;
rab = get_r0(angletypes[i].types[0],angletypes[i].types[1]);
rbc = get_r0(angletypes[i].types[1],angletypes[i].types[2]);
angletypes[i].bondbond_cross_term[1] = rab;
angletypes[i].bondbond_cross_term[2] = rbc;
angletypes[i].bondangle_cross_term[2] = rab;
angletypes[i].bondangle_cross_term[3] = rbc;
k = find_match(3,potential_types,ff_bonbon,&backwards);
if (k < 0) {
k = find_match(3,equiv_types,ff_bonbon,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find bondbond data for %s %s %s\n",
potential_types[0],
potential_types[1],potential_types[2]);
}
else {
angletypes[i].bondbond_cross_term[0] = ff_bonbon.data[k].ff_param[0];
}
k = find_match(3,potential_types,ff_bonang,&backwards);
if (k < 0) {
k = find_match(3,equiv_types,ff_bonang,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find bondangle data for %s %s %s\n",
potential_types[0],
potential_types[1],potential_types[2]);
}
else {
if (backwards) {
angletypes[i].bondangle_cross_term[0] =
ff_bonang.data[k].ff_param[1];
angletypes[i].bondangle_cross_term[1] =
ff_bonang.data[k].ff_param[0];
}
else {
angletypes[i].bondangle_cross_term[0] =
ff_bonang.data[k].ff_param[0];
angletypes[i].bondangle_cross_term[1] =
ff_bonang.data[k].ff_param[1];
}
}
}
}
#ifdef PRINT_DATA
printf ("\n Angle Types and Parameters\n");
for (i=0; i < no_angle_types; i++) {
for (j=0; j < 3; j++)
fprintf(stderr," %-3s", atomtypes[angletypes[i].types[j]].potential);
for (j=0; j < 4; j++) fprintf(stderr," %8.4f",angletypes[i].params[j]);
fprintf(stderr,"\n");
}
if (forcefield > 1) {
printf ("\n BondBond Types and Parameters\n");
for (i=0; i < no_angle_types; i++) {
for (j=0; j < 3; j++)
fprintf(stderr,"%-3s",atomtypes[angletypes[i].types[j]].potential);
for (j=0; j < 3; j++)
fprintf(stderr," %8.4f",angletypes[i].bondbond_cross_term[j]);
fprintf(stderr,"\n");
}
printf ("\n BondAngle Types and Parameters\n");
for (i=0; i < no_angle_types; i++) {
for (j=0; j < 3; j++)
fprintf(stderr,"%-3s",atomtypes[angletypes[i].types[j]].potential);
for (j=0; j < 4; j++)
fprintf(stderr," %8.4f",angletypes[i].bondangle_cross_term[j]);
fprintf(stderr,"\n");
}
}
#endif
/**********************************************************************/
/* */
/* Find parameters for dihedral types including endbonddihedral, */
/* midbonddihedral, angledihedral, angleangledihedral and */
/* bondbond13 parameters if Class II */
/* */
/* Each of the cross terms are searched separately even though */
/* they share a given dihedral type. This allows parameters to be */
/* in different order in the forcefield for each cross term or */
/* maybe not even there. */
/* */
/**********************************************************************/
for (i=0; i < no_dihedral_types; i++) {
for (j=0; j < 6; j++)
dihedraltypes[i].params[j] = 0.0;
for (j=0; j < 4; j++)
strncpy(potential_types[j],
atomtypes[dihedraltypes[i].types[j]].potential,5);
backwards = 0;
k = find_match(4,potential_types,ff_tor,&backwards);
if (k < 0) {
get_equivs(4,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for dihedral %s %s %s %s -> %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3],
equiv_types[0],equiv_types[1],
equiv_types[2],equiv_types[3]);
#endif
k = find_match(4,equiv_types,ff_tor,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find torsion data for %s %s %s %s\n",
potential_types[0],
potential_types[1],
potential_types[2],
potential_types[3]);
}
else {
if (Forcefield == 1) {
multiplicity = 1;
if (ff_tor.data[k].ff_types[0][0] == '*')
multiplicity =
atomtypes[dihedraltypes[i].types[1]].no_connect-1;
if (ff_tor.data[k].ff_types[3][0] == '*')
multiplicity *=
atomtypes[dihedraltypes[i].types[2]].no_connect-1;
dihedraltypes[i].params[0] = ff_tor.data[k].ff_param[0]/(double) multiplicity;
if (ff_tor.data[k].ff_param[2] == 0.0)
dihedraltypes[i].params[1] = 1.0;
else if (ff_tor.data[k].ff_param[2] == 180.0)
dihedraltypes[i].params[1] = -1.0;
else {
fprintf(stderr,"Non planar phi0 for %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3]);
dihedraltypes[i].params[1] = 0.0;
}
dihedraltypes[i].params[2] = ff_tor.data[k].ff_param[1];
}
else {
for (j=0; j < 6; j++)
dihedraltypes[i].params[j] = ff_tor.data[k].ff_param[j];
}
}
if (Forcefield > 1) {
get_equivs(4,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for linear 4 body cross terms %s %s %s %s -> %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3],
equiv_types[0],equiv_types[1],
equiv_types[2],equiv_types[3]);
#endif
for (j=0; j < 8; j++)
dihedraltypes[i].endbonddihedral_cross_term[j] = 0.0;
for (j=0; j < 4; j++)
dihedraltypes[i].midbonddihedral_cross_term[j] = 0.0;
for (j=0; j < 8; j++)
dihedraltypes[i].angledihedral_cross_term[j] = 0.0;
for (j=0; j < 3; j++)
dihedraltypes[i].angleangledihedral_cross_term[j] = 0.0;
for (j=0; j < 3; j++)
dihedraltypes[i].bond13_cross_term[j] = 0.0;
rab = get_r0(dihedraltypes[i].types[0],dihedraltypes[i].types[1]);
rbc = get_r0(dihedraltypes[i].types[1],dihedraltypes[i].types[2]);
rcd = get_r0(dihedraltypes[i].types[2],dihedraltypes[i].types[3]);
tabc = get_t0(dihedraltypes[i].types[0],
dihedraltypes[i].types[1],
dihedraltypes[i].types[2]);
tbcd = get_t0(dihedraltypes[i].types[1],
dihedraltypes[i].types[2],
dihedraltypes[i].types[3]);
dihedraltypes[i].endbonddihedral_cross_term[6] = rab;
dihedraltypes[i].endbonddihedral_cross_term[7] = rcd;
dihedraltypes[i].midbonddihedral_cross_term[3] = rbc;
dihedraltypes[i].angledihedral_cross_term[6] = tabc;
dihedraltypes[i].angledihedral_cross_term[7] = tbcd;
dihedraltypes[i].angleangledihedral_cross_term[1] = tabc;
dihedraltypes[i].angleangledihedral_cross_term[2] = tbcd;
dihedraltypes[i].bond13_cross_term[1] = rab;
dihedraltypes[i].bond13_cross_term[2] = rcd;
backwards = 0;
k = find_match(4,potential_types,ff_endbontor,&backwards);
if (k < 0) {
k = find_match(4,equiv_types,ff_endbontor,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find endbonddihedral data for %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3]);
}
else {
if (backwards) {
dihedraltypes[i].endbonddihedral_cross_term[0] =
ff_endbontor.data[k].ff_param[3];
dihedraltypes[i].endbonddihedral_cross_term[1] =
ff_endbontor.data[k].ff_param[4];
dihedraltypes[i].endbonddihedral_cross_term[2] =
ff_endbontor.data[k].ff_param[5];
dihedraltypes[i].endbonddihedral_cross_term[3] =
ff_endbontor.data[k].ff_param[0];
dihedraltypes[i].endbonddihedral_cross_term[4] =
ff_endbontor.data[k].ff_param[1];
dihedraltypes[i].endbonddihedral_cross_term[5] =
ff_endbontor.data[k].ff_param[2];
}
else {
dihedraltypes[i].endbonddihedral_cross_term[0] =
ff_endbontor.data[k].ff_param[0];
dihedraltypes[i].endbonddihedral_cross_term[1] =
ff_endbontor.data[k].ff_param[1];
dihedraltypes[i].endbonddihedral_cross_term[2] =
ff_endbontor.data[k].ff_param[2];
dihedraltypes[i].endbonddihedral_cross_term[3] =
ff_endbontor.data[k].ff_param[3];
dihedraltypes[i].endbonddihedral_cross_term[4] =
ff_endbontor.data[k].ff_param[4];
dihedraltypes[i].endbonddihedral_cross_term[5] =
ff_endbontor.data[k].ff_param[5];
}
}
backwards = 0;
k = find_match(4,potential_types,ff_midbontor,&backwards);
if (k < 0) {
k = find_match(4,equiv_types,ff_midbontor,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find midbonddihedral data for %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3]);
}
else {
dihedraltypes[i].midbonddihedral_cross_term[0] =
ff_midbontor.data[k].ff_param[0];
dihedraltypes[i].midbonddihedral_cross_term[1] =
ff_midbontor.data[k].ff_param[1];
dihedraltypes[i].midbonddihedral_cross_term[2] =
ff_midbontor.data[k].ff_param[2];
}
backwards = 0;
k = find_match(4,potential_types,ff_angtor,&backwards);
if (k < 0) {
k = find_match(4,equiv_types,ff_angtor,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find angledihedral data for %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3]);
}
else {
if (backwards) {
dihedraltypes[i].angledihedral_cross_term[0] =
ff_angtor.data[k].ff_param[3];
dihedraltypes[i].angledihedral_cross_term[1] =
ff_angtor.data[k].ff_param[4];
dihedraltypes[i].angledihedral_cross_term[2] =
ff_angtor.data[k].ff_param[5];
dihedraltypes[i].angledihedral_cross_term[3] =
ff_angtor.data[k].ff_param[0];
dihedraltypes[i].angledihedral_cross_term[4] =
ff_angtor.data[k].ff_param[1];
dihedraltypes[i].angledihedral_cross_term[5] =
ff_angtor.data[k].ff_param[2];
}
else {
dihedraltypes[i].angledihedral_cross_term[0] =
ff_angtor.data[k].ff_param[0];
dihedraltypes[i].angledihedral_cross_term[1] =
ff_angtor.data[k].ff_param[1];
dihedraltypes[i].angledihedral_cross_term[2] =
ff_angtor.data[k].ff_param[2];
dihedraltypes[i].angledihedral_cross_term[3] =
ff_angtor.data[k].ff_param[3];
dihedraltypes[i].angledihedral_cross_term[4] =
ff_angtor.data[k].ff_param[4];
dihedraltypes[i].angledihedral_cross_term[5] =
ff_angtor.data[k].ff_param[5];
}
}
backwards = 0;
k = find_match(4,potential_types,ff_angangtor,&backwards);
if (k < 0) {
k = find_match(4,equiv_types,ff_angangtor,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find angleangledihedral data for %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3]);
}
else {
dihedraltypes[i].angleangledihedral_cross_term[0] =
ff_angangtor.data[k].ff_param[0];
}
cp_type = quo_cp();
if ((cp_type >= 0) &&
((dihedraltypes[i].types[0] == cp_type) ||
(dihedraltypes[i].types[1] == cp_type) ||
(dihedraltypes[i].types[2] == cp_type) ||
(dihedraltypes[i].types[3] == cp_type) )) {
backwards = 0;
k = find_match(4,potential_types,ff_bonbon13,&backwards);
if (k < 0) {
k = find_match(4,equiv_types,ff_bonbon13,&backwards);
}
if (k < 0) {
fprintf(stderr," Unable to find bond13 data for %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3]);
}
else {
dihedraltypes[i].bond13_cross_term[0] =
ff_bonbon13.data[k].ff_param[0];
}
}
}
}
#ifdef PRINT_DATA
printf ("\n Dihedral Types and Parameters\n");
for (i=0; i < no_dihedral_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr,"%-3s",atomtypes[dihedraltypes[i].types[j]].potential);
for (j=0; j < 6; j++)
fprintf(stderr," %8.4f",dihedraltypes[i].params[j]);
fprintf(stderr,"\n");
}
if (forcefield > 1) {
printf ("\n EndBondDihedral Types and Parameters\n");
for (i=0; i < no_dihedral_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr,"%-3s",atomtypes[dihedraltypes[i].types[j]].potential);
for (j=0; j < 8; j++)
fprintf(stderr," %8.4f",dihedraltypes[i].endbonddihedral_cross_term[j]);
fprintf(stderr,"\n");
}
printf ("\n MidBondDihedral Types and Parameters\n");
for (i=0; i < no_dihedral_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr," %-3s",atomtypes[dihedraltypes[i].types[j]].potential);
for (j=0; j < 4; j++)
fprintf(stderr," %8.4f",dihedraltypes[i].midbonddihedral_cross_term[j]);
fprintf(stderr,"\n");
}
printf ("\n AngleDihedral Types and Parameters\n");
for (i=0; i < no_dihedral_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr,"%-3s",atomtypes[dihedraltypes[i].types[j]].potential);
for (j=0; j < 8; j++)
fprintf(stderr," %8.4f",dihedraltypes[i].angledihedral_cross_term[j]);
fprintf(stderr,"\n");
}
printf ("\n AngleAngleDihedral Types and Parameters\n");
for (i=0; i < no_dihedral_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr," %-3s",atomtypes[dihedraltypes[i].types[j]].potential);
for (j=0; j < 3; j++)
fprintf(stderr,"%8.4f",dihedraltypes[i].angleangledihedral_cross_term[j]);
fprintf(stderr,"\n");
}
printf ("\n Bond13 Types and Parameters\n");
for (i=0; i < no_dihedral_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr," %-3s",atomtypes[dihedraltypes[i].types[j]].potential);
for (j=0; j < 3; j++)
fprintf(stderr," %8.4f",dihedraltypes[i].bond13_cross_term[j]);
fprintf(stderr,"\n");
}
}
#endif
/**********************************************************************/
/* */
/* Find parameters for oop types */
/* */
/* This is the most complicated of all the types because the */
/* the class I oop is actually an improper torsion and does */
/* not have the permutation symmetry of a well defined oop */
/* The net result is that if one does not find the current */
/* atom type ordering in the Forcefield file then one must try each */
/* of the next permutations (6 in total) and when a match is found */
/* the program must go back and rearrange the oop type AND the atom */
/* ordering in the oop lists for those with the current type */
/* */
/* The Class II oop types are easier but also tedious since the */
/* program has to try all permutations of the a c and d atom */
/* types to find a match. A special routine is used to do this. */
/* */
/* Fortunately, there are typically few oop types */
/* */
/**********************************************************************/
if (forcefield == 1) {
for (i=0; i < no_oop_types; i++) {
for (j=0; j < 3; j++) ooptypes[i].params[j] = 0.0;
for (j=0; j < 4; j++)
strncpy(potential_types[j],
atomtypes[ooptypes[i].types[j]].potential,5);
k = find_improper_body_data(potential_types,ff_oop,&rearrange);
if (k < 0) {
get_equivs(5,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for oop %s %s %s %s -> %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3],
equiv_types[0],equiv_types[1],
equiv_types[2],equiv_types[3]);
#endif
k = find_improper_body_data(equiv_types,ff_oop,&rearrange);
}
if (k < 0) {
fprintf(stderr," Unable to find oop data for %s %s %s %s\n",
potential_types[0],
potential_types[1],potential_types[2],potential_types[3]);
}
else {
ooptypes[i].params[0] = ff_oop.data[k].ff_param[0];
if (ff_oop.data[k].ff_param[2] == 0.0)
ooptypes[i].params[1] = 1.0;
else if (ff_oop.data[k].ff_param[2] == 180.0)
ooptypes[i].params[1] = -1.0;
else {
fprintf(stderr,"Non planar phi0 for %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3]);
ooptypes[i].params[1] = 0.0;
}
ooptypes[i].params[2] = ff_oop.data[k].ff_param[1];
if (rearrange > 0) rearrange_improper(i,rearrange);
}
}
}
else {
for (i=0; i < no_oop_types; i++) {
for (j=0; j < 3; j++)
ooptypes[i].params[j] = 0.0;
for (j=0; j < 4; j++)
strncpy(potential_types[j],
atomtypes[ooptypes[i].types[j]].potential,5);
k = find_trigonal_body_data(potential_types,ff_oop);
if (k < 0) {
get_equivs(5,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for oop %s %s %s %s -> %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3],
equiv_types[0],equiv_types[1],
equiv_types[2],equiv_types[3]);
#endif
k = find_trigonal_body_data(equiv_types,ff_oop);
}
if (k < 0) {
fprintf(stderr," Unable to find oop data for %s %s %s %s\n",
potential_types[0],
potential_types[1],potential_types[2],potential_types[3]);
}
else {
for (j=0; j < 2; j++)
ooptypes[i].params[j] = ff_oop.data[k].ff_param[j];
}
}
}
#ifdef PRINT_DATA
fprintf(stderr,"\n OOP Types and Parameters\n");
for (i=0; i < no_oop_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr,"%-3s",atomtypes[ooptypes[i].types[j]].potential);
for (j=0; j < 3; j++)
fprintf(stderr," %8.4f",ooptypes[i].params[j]);
fprintf(stderr,"\n");
}
#endif
/**********************************************************************/
/* */
/* Find parameters for angleangle types (Class II only) */
/* */
/* This is somewhat complicated in that one set of four types */
/* a b c d has three angleangle combinations so for each type */
/* the program needs to find three sets of parameters by */
/* progressively looking for data for different permutations of */
/* a c and d */
/* */
/**********************************************************************/
if (forcefield > 1) {
for (i=0; i < no_oop_types; i++) {
for (j=0; j < 6; j++) ooptypes[i].angleangle_params[j] = 0.0;
for (j=0; j < 4; j++)
strncpy(potential_types[j],
atomtypes[ooptypes[i].types[j]].potential,5);
tabc = get_t0(ooptypes[i].types[0],
ooptypes[i].types[1],
ooptypes[i].types[2]);
tabd = get_t0(ooptypes[i].types[0],
ooptypes[i].types[1],
ooptypes[i].types[3]);
tcbd = get_t0(ooptypes[i].types[2],
ooptypes[i].types[1],
ooptypes[i].types[3]);
ooptypes[i].angleangle_params[3] = tabc;
- ooptypes[i].angleangle_params[4] = tabd;
- ooptypes[i].angleangle_params[5] = tcbd;
+ ooptypes[i].angleangle_params[4] = tcbd;
+ ooptypes[i].angleangle_params[5] = tabd;
k = find_angleangle_data(potential_types,ff_angang,kloc);
if (k < 0) {
get_equivs(5,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for angleangle %s %s %s %s -> %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3],
equiv_types[0],equiv_types[1],
equiv_types[2],equiv_types[3]);
k = find_angleangle_data(equiv_types,ff_angang,kloc);
#endif
}
if (k < 0) {
fprintf(stderr," Unable to find angleangle data for %s %s %s %s\n",
potential_types[0],
potential_types[1],potential_types[2],potential_types[3]);
}
else {
for (j=0; j < 3; j++) {
if (kloc[j] > -1)
ooptypes[i].angleangle_params[j] = ff_angang.data[kloc[j]].ff_param[0];
}
}
}
for (i=0; i < no_angleangle_types; i++) {
for (j=0; j < 6; j++) angleangletypes[i].params[j] = 0.0;
for (j=0; j < 4; j++)
strncpy(potential_types[j],
atomtypes[angleangletypes[i].types[j]].potential,5);
tabc = get_t0(angleangletypes[i].types[0],
angleangletypes[i].types[1],
angleangletypes[i].types[2]);
tabd = get_t0(angleangletypes[i].types[0],
angleangletypes[i].types[1],
angleangletypes[i].types[3]);
tcbd = get_t0(angleangletypes[i].types[2],
angleangletypes[i].types[1],
angleangletypes[i].types[3]);
angleangletypes[i].params[3] = tabc;
angleangletypes[i].params[4] = tcbd;
angleangletypes[i].params[5] = tabd;
k = find_angleangle_data(potential_types,ff_angang,kloc);
if (k < 0) {
get_equivs(5,potential_types,equiv_types);
#ifdef PRINT_USE_EQUIV
fprintf(stderr,"Using equivalences for angleangle %s %s %s %s -> %s %s %s %s\n",
potential_types[0],potential_types[1],
potential_types[2],potential_types[3],
equiv_types[0],equiv_types[1],
equiv_types[2],equiv_types[3]);
#endif
k = find_angleangle_data(equiv_types,ff_angang,kloc);
}
if (k < 0) {
fprintf(stderr," Unable to find angleangle data for %s %s %s %s\n",
potential_types[0],
potential_types[1],potential_types[2],potential_types[3]);
}
else {
for (j=0; j < 3; j++) {
if (kloc[j] > -1)
angleangletypes[i].params[j] =
ff_angang.data[kloc[j]].ff_param[0];
}
}
}
#ifdef PRINT_DATA
printf ("\n AngleAngle Types and Parameters\n");
for (i=0; i < no_oop_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr,"%-3s",atomtypes[ooptypes[i].types[j]].potential);
for (j=0; j < 6; j++)
fprintf(stderr," %8.4f",ooptypes[i].angleangle_params[j]);
fprintf(stderr,"\n");
}
for (i=0; i < no_angleangle_types; i++) {
for (j=0; j < 4; j++)
fprintf(stderr," %-3s",atomtypes[angleangletypes[i].types[j]].potential);
for (j=0; j < 6; j++) fprintf(stderr," %8.4f",angleangletypes[i].params[j]);
fprintf(stderr,"\n");
}
#endif
}
}
int find_improper_body_data(char types1[][5],struct FrcFieldItem item,
int *rearrange_ptr)
{
int k,backwards;
char mirror_types[4][5];
backwards = 0;
/* a b c d */
*rearrange_ptr = 0;
k = find_match(4,types1,item,&backwards);
if (k >= 0) return k;
/* a b d c */
*rearrange_ptr = 1;
strncpy(mirror_types[0],types1[0],5);
strncpy(mirror_types[1],types1[1],5);
strncpy(mirror_types[2],types1[3],5);
strncpy(mirror_types[3],types1[2],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* d b a c */
*rearrange_ptr = 2;
strncpy(mirror_types[0],types1[3],5);
strncpy(mirror_types[2],types1[0],5);
strncpy(mirror_types[3],types1[2],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* d b c a */
*rearrange_ptr = 3;
strncpy(mirror_types[2],types1[2],5);
strncpy(mirror_types[3],types1[0],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* c b a d */
*rearrange_ptr = 4;
strncpy(mirror_types[0],types1[2],5);
strncpy(mirror_types[2],types1[0],5);
strncpy(mirror_types[3],types1[3],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* c b d a */
*rearrange_ptr = 5;
strncpy(mirror_types[2],types1[3],5);
strncpy(mirror_types[3],types1[0],5);
k = find_match(4,mirror_types,item,&backwards);
return k;
}
void rearrange_improper(int ooptype,int rearrange)
{
int i,j,temp[4];
for (i=0; i < 4; i++) temp[i] = ooptypes[ooptype].types[i];
switch (rearrange) {
case 1:
ooptypes[ooptype].types[0] = temp[0];
ooptypes[ooptype].types[2] = temp[3];
ooptypes[ooptype].types[3] = temp[2];
for (i=0; i < total_no_oops; i++) {
if (oops[i].type == ooptype) {
for (j=0; j < 4; j++) temp[j] = oops[i].members[j];
oops[i].members[2] = temp[3];
oops[i].members[3] = temp[2];
}
}
break;
case 2:
ooptypes[ooptype].types[0] = temp[3];
ooptypes[ooptype].types[2] = temp[0];
ooptypes[ooptype].types[3] = temp[2];
for (i=0; i < total_no_oops; i++) {
if (oops[i].type == ooptype) {
for (j=0; j < 4; j++) temp[j] = oops[i].members[j];
oops[i].members[0] = temp[3];
oops[i].members[2] = temp[0];
oops[i].members[3] = temp[2];
}
}
break;
case 3:
ooptypes[ooptype].types[0] = temp[3];
ooptypes[ooptype].types[2] = temp[2];
ooptypes[ooptype].types[3] = temp[0];
for (i=0; i < total_no_oops; i++) {
if (oops[i].type == ooptype) {
for (j=0; j < 4; j++) temp[j] = oops[i].members[j];
oops[i].members[0] = temp[3];
oops[i].members[2] = temp[2];
oops[i].members[3] = temp[0];
}
}
break;
case 4:
ooptypes[ooptype].types[0] = temp[2];
ooptypes[ooptype].types[2] = temp[0];
ooptypes[ooptype].types[3] = temp[3];
for (i=0; i < total_no_oops; i++) {
if (oops[i].type == ooptype) {
for (j=0; j < 4; j++) temp[j] = oops[i].members[j];
oops[i].members[0] = temp[2];
oops[i].members[2] = temp[0];
oops[i].members[3] = temp[3];
}
}
break;
case 5:
ooptypes[ooptype].types[0] = temp[2];
ooptypes[ooptype].types[2] = temp[3];
ooptypes[ooptype].types[3] = temp[0];
for (i=0; i < total_no_oops; i++) {
if (oops[i].type == ooptype) {
for (j=0; j < 4; j++) temp[j] = oops[i].members[j];
oops[i].members[0] = temp[2];
oops[i].members[2] = temp[3];
oops[i].members[3] = temp[0];
}
}
break;
default:
break;
}
}
int find_trigonal_body_data(char types1[][5],struct FrcFieldItem item)
{
int k,backwards;
char mirror_types[4][5];
backwards = -1;
/* a b c d */
k = find_match(4,types1,item,&backwards);
if (k >= 0) return k;
/* a b d c */
strncpy(mirror_types[0],types1[0],5);
strncpy(mirror_types[1],types1[1],5);
strncpy(mirror_types[2],types1[3],5);
strncpy(mirror_types[3],types1[2],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* d b a c */
strncpy(mirror_types[0],types1[3],5);
strncpy(mirror_types[2],types1[0],5);
strncpy(mirror_types[3],types1[2],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* d b c a */
strncpy(mirror_types[2],types1[2],5);
strncpy(mirror_types[3],types1[0],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* c b a d */
strncpy(mirror_types[0],types1[2],5);
strncpy(mirror_types[2],types1[0],5);
strncpy(mirror_types[3],types1[3],5);
k = find_match(4,mirror_types,item,&backwards);
if (k >= 0) return k;
/* c b d a */
strncpy(mirror_types[2],types1[3],5);
strncpy(mirror_types[3],types1[0],5);
k = find_match(4,mirror_types,item,&backwards);
return k;
}
int find_angleangle_data(char types1[][5],struct FrcFieldItem item,int kloc[3])
{
int k,backwards = -1;
char mirror_types[4][5];
strncpy(mirror_types[1],types1[1],5);
/* go for first parameter a b c d or d b c a */
k = find_match(4,types1,item,&backwards);
if (k < 0) {
strncpy(mirror_types[0],types1[3],5);
strncpy(mirror_types[2],types1[2],5);
strncpy(mirror_types[3],types1[0],5);
k = find_match(4,mirror_types,item,&backwards);
}
kloc[0] = k;
/* go for second parameter d b a c or c b a d */
strncpy(mirror_types[0],types1[3],5);
strncpy(mirror_types[2],types1[0],5);
strncpy(mirror_types[3],types1[2],5);
k = find_match(4,mirror_types,item,&backwards);
if (k < 0) {
strncpy(mirror_types[0],types1[2],5);
strncpy(mirror_types[3],types1[3],5);
k = find_match(4,mirror_types,item,&backwards);
}
kloc[1] = k;
/* go for third parameter a b d c or c b d a */
strncpy(mirror_types[0],types1[0],5);
strncpy(mirror_types[2],types1[3],5);
strncpy(mirror_types[3],types1[2],5);
k = find_match(4,mirror_types,item,&backwards);
if (k < 0) {
strncpy(mirror_types[0],types1[2],5);
strncpy(mirror_types[3],types1[0],5);
k = find_match(4,mirror_types,item,&backwards);
}
kloc[2] = k;
k = 0;
if ((kloc[0] < 0) && (kloc[1] < 0) && (kloc[2] < 0)) k = -1;
return k;
}
int find_match(int n, char types1[][5],struct FrcFieldItem item,int
*backwards_ptr)
{
int k,match;
match = 0;
k=0;
/* Try for an exact match (no wildcards) first */
while (!match && (k < item.entries)) {
if (match_types(n, 0,types1,item.data[k].ff_types,backwards_ptr) == 1)
match = 1;
else
k++;
}
/* Try again - allow wildcard matching */
if (!match) {
k=0;
while (!match && (k < item.entries)) {
if (match_types(n,1,types1,item.data[k].ff_types,backwards_ptr) == 1)
match = 1;
else
k++;
}
}
if (match) return k;
else return -1;
}
int match_types(int n,int wildcard,char types1[][5],char types2[][5],
int *backwards_ptr)
{
int k,match;
/* Routine to match short arrays of characters strings which contain
atom potential types. The arrays range from 1 to 4 (VDW or equivalences,
bond, angle, dihedrals or oops). There are potentially four ways the
arrays can match: exact match (forwards), exact match when one array is
run backwards (backwards), forwards with wildcard character match allowed
(forwards *) and finally backwards with wildcard character match
(backwards *). If the variable, backwards (pointed by backwards_ptr)
is -1, then the backwards options are not to be used (such when
matching oop types)
*/
if (wildcard == 0) {
/* forwards */
k=0;
match = 1;
while (match && (k < n)) {
if (strncmp(types1[k],types2[k],5) == 0)
k++;
else
match = 0;
}
}
else {
/* forwards * */
k=0;
match = 1;
while (match && (k < n)) {
if ((strncmp(types1[k],types2[k],5) == 0) ||
(types2[k][0] == '*'))
k++;
else
match = 0;
}
}
if (match) {
*backwards_ptr = 0;
return 1;
}
if ((n < 2) || (*backwards_ptr == -1)) return 0;
if (wildcard == 0) {
/* backwards */
k=0;
match = 1;
while (match && (k < n)) {
if (strncmp(types1[n-k-1],types2[k],5) == 0)
k++;
else
match = 0;
}
}
else {
/* backwards * */
k=0;
match = 1;
while (match && (k < n)) {
if ((strncmp(types1[n-k-1],types2[k],5) == 0) ||
(types2[k][0] == '*') )
k++;
else
match = 0;
}
}
if (match) {
*backwards_ptr = 1;
return 1;
}
else return 0;
}
double get_r0(int typei,int typej)
{
int k,match;
double r;
k=0;
match=0;
r = 0.0;
while (!match && (k < no_bond_types)) {
if (((typei == bondtypes[k].types[0]) &&
(typej == bondtypes[k].types[1])) ||
((typej == bondtypes[k].types[0]) &&
(typei == bondtypes[k].types[1])) ) {
r = bondtypes[k].params[0];
match = 1;
}
else
k++;
}
if (match == 0)
fprintf(stderr,"Unable to find r0 for types %d %d\n",
typei,typej);
return r;
}
double get_t0(int typei,int typej,int typek)
{
int k,match;
double theta;
k=0;
match=0;
theta = 0.0;
while (!match && (k < no_angle_types)) {
if (((typei == angletypes[k].types[0]) &&
(typej == angletypes[k].types[1]) &&
(typek == angletypes[k].types[2])) ||
((typek == angletypes[k].types[0]) &&
(typej == angletypes[k].types[1]) &&
(typei == angletypes[k].types[2])) ) {
theta = angletypes[k].params[0];
match = 1;
}
else
k++;
}
if (match == 0)
fprintf(stderr," Unable to find t0 for types %d %d %d\n",
typei,typej,typek);
return theta;
}
int quo_cp()
{
char cp[] = "cp ";
int i,type,found;
i = 0;
type = -1;
found = 0;
while (!found && (i < no_atom_types)) {
if (strncmp(atomtypes[i].potential,cp,2) == 0) {
found = 1;
type = i;
}
else
i++;
}
return type;
}
void get_equivs(int ic,char potential_types[][5],char equiv_types[][5])
{
int i,k;
switch (ic) {
case 1:
k = find_equiv_type(potential_types[0]);
if (k > -1) strncpy(equiv_types[0],equivalence.data[k].ff_types[1],5);
break;
case 2:
for (i=0; i < 2; i++) {
k = find_equiv_type(potential_types[i]);
if (k > -1) strncpy(equiv_types[i],equivalence.data[k].ff_types[2],5);
}
break;
case 3:
for (i=0; i < 3; i++) {
k = find_equiv_type(potential_types[i]);
if (k > -1) strncpy(equiv_types[i],equivalence.data[k].ff_types[3],5);
}
break;
case 4:
for (i=0; i < 4; i++) {
k = find_equiv_type(potential_types[i]);
if (k > -1) strncpy(equiv_types[i],equivalence.data[k].ff_types[4],5);
}
break;
case 5:
for (i=0; i < 4; i++) {
k = find_equiv_type(potential_types[i]);
if (k > -1)
strncpy(equiv_types[i],equivalence.data[k].ff_types[5],5);
}
break;
default:
break;
}
return;
}
int find_equiv_type(char potential_type[5])
{
int j,k,match;
j = -1;
k = 0;
match = 0;
while (!match && (k < equivalence.entries)) {
if (strncmp(potential_type,
equivalence.data[k].ff_types[0],5) == 0) {
match = 1;
j = k;
}
else {
k++;
}
}
if (j < 0)
fprintf(stderr," Unable to find equivalent type for %s\n",potential_type);
return j;
}
diff --git a/tools/msi2lmp/src/Makefile b/tools/msi2lmp/src/Makefile
index 21ac46268..354246e20 100644
--- a/tools/msi2lmp/src/Makefile
+++ b/tools/msi2lmp/src/Makefile
@@ -1,37 +1,37 @@
TARGET = msi2lmp.exe
SRCS = msi2lmp.c \
ReadCarFile.c \
ReadMdfFile.c \
MakeLists.c \
ReadFrcFile.c \
InitializeItems.c \
SearchAndFill.c \
GetParameters.c \
CheckLists.c \
WriteDataFile05.c \
WriteDataFile01.c
OBJS = $(SRCS:.c=.o)
HEADERS = Msi2LMP2.h Forcefield.h
CC = gcc
-CFLAGS = -O2
+CFLAGS = -O3
FRCFILE = cvff.frc
FRCFILE2 = cff91.frc
README = README
MKFILE = Makefile
$(TARGET) : $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) -lm
$(OBJS) : $(HEADERS)
.c.o:
$(CC) $(CFLAGS) -c $<
clean:
rm -f $(OBJS) $(TARGET)
diff --git a/tools/msi2lmp/src/Msi2LMP2.h b/tools/msi2lmp/src/Msi2LMP2.h
index ed79c2611..14105a8b0 100644
--- a/tools/msi2lmp/src/Msi2LMP2.h
+++ b/tools/msi2lmp/src/Msi2LMP2.h
@@ -1,209 +1,213 @@
/********************************
*
* Header file for Msi2LMP2 conversion program.
*
* Msi2lmp3
*
* This is the header file for the third version of a program
* that generates a LAMMPS data file based on the information
* in an MSI car file (atom coordinates) and mdf file (molecular
* topology). A key part of the program looks up forcefield parameters
* from an MSI frc file.
*
* The first version was written by Steve Lustig at Dupont, but
* required using Discover to derive internal coordinates and
* forcefield parameters
*
* The second version was written by Michael Peachey while an
* intern in the Cray Chemistry Applications Group managed
* by John Carpenter. This version derived internal coordinates
* from the mdf file and looked up parameters in the frc file
* thus eliminating the need for Discover.
*
* The third version was written by John Carpenter to optimize
* the performance of the program for large molecular systems
* (the original code for derving atom numbers was quadratic in time)
* and to make the program fully dynamic. The second version used
* fixed dimension arrays for the internal coordinates.
*
* John Carpenter can be contacted by sending email to
* jec374@earthlink.net
*
* November 2000
*
*/
# include <string.h>
# include <stddef.h>
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
#ifdef MAIN
#define _EX
#define _ARG(arg) = (arg)
#else
#define _EX extern
#define _ARG(arg)
#endif
#define MAX_ATOM_TYPES 100
#define MAX_BOND_TYPES 200
#define MAX_ANGLE_TYPES 300
#define MAX_DIHEDRAL_TYPES 400
#define MAX_OOP_TYPES 400
#define MAX_ANGLEANGLE_TYPES 400
#define MAX_TYPES 12000
#define MAX_MEMBERS 5
#define MAX_LINE_LENGTH 200
#define MAX_PARAMS 8
#define PI_180 0.01745329252
#define MAX_CONNECTIONS 6
#define MAX_STRING 50
+
+
struct ResidueList {
int start;
int end;
char name[16];
};
struct MoleculeList {
int start;
int end;
int no_residues;
struct ResidueList *residue;
};
/* Internal coodinate Lists */
struct BondList {
int type;
int members[2];
};
struct AngleList {
int type;
int members[3];
};
struct DihedralList {
int type;
int members[4];
};
struct OOPList {
int type;
int members[4];
};
struct AngleAngleList {
int type;
int members[4];
};
/* Internal coodinate Types Lists */
struct AtomTypeList
{
char potential[5];
float mass;
double params[2];
int no_connect;
};
struct BondTypeList {
int types[2];
double params[4];
};
struct AngleTypeList {
int types[3];
double params[4];
double bondangle_cross_term[4];
double bondbond_cross_term[3];
};
struct DihedralTypeList {
int types[4];
double params[6];
double endbonddihedral_cross_term[8];
double midbonddihedral_cross_term[4];
double angledihedral_cross_term[8];
double angleangledihedral_cross_term[3];
double bond13_cross_term[3];
};
struct OOPTypeList {
int types[4];
double params[3];
double angleangle_params[6];
};
struct AngleAngleTypeList {
int types[4];
double params[6];
};
/* ---------------------------------------------- */
struct Atom {
int molecule; /* molecule id */
int no; /* atom id */
char name[10]; /* atom name */
double x[3]; /* position vector */
char potential[5]; /* atom potential type */
char element[2]; /* atom element */
float q; /* charge */
char residue_string[16]; /* residue string */
int no_connect; /* number of connections to atom */
char connections[MAX_CONNECTIONS][MAX_STRING]; /* long form, connection name*/
double bond_order[6];
int conn_no[6]; /* Atom number to which atom is connected */
int type;
};
_EX char rootname[20];
_EX char path[20];
_EX double pbc[9];
_EX int periodic _ARG( 1 ); /* 0= nonperiodic 1= 3-D periodic */
+// Added triclinic flag for non-orthogonal boxes Oct 5, 2010 SLTM
+_EX int TriclinicFlag; // 1 for non-orthoganal boxes, 0 for orthogonal boxes
_EX int forcefield _ARG( 0 ); /* 0= ClassI 1= ClassII */
_EX int pflag;
_EX int *no_atoms;
_EX int no_molecules;
_EX int replicate[3];
_EX int total_no_atoms;
_EX int total_no_bonds;
_EX int total_no_angles;
_EX int total_no_dihedrals;
_EX int total_no_angle_angles;
_EX int total_no_oops;
_EX int no_atom_types;
_EX int no_bond_types;
_EX int no_angle_types;
_EX int no_dihedral_types;
_EX int no_oop_types;
_EX int no_angleangle_types;
_EX char FrcFileName[MAX_LINE_LENGTH];
_EX FILE *CarF;
_EX FILE *FrcF;
_EX FILE *PrmF;
_EX FILE *MdfF;
_EX FILE *RptF;
_EX struct Atom *atoms;
_EX struct MoleculeList *molecule;
_EX struct BondList *bonds;
_EX struct AngleList *angles;
_EX struct DihedralList *dihedrals;
_EX struct OOPList *oops;
_EX struct AngleAngleList *angleangles;
_EX struct AtomTypeList *atomtypes;
_EX struct BondTypeList *bondtypes;
_EX struct AngleTypeList *angletypes;
_EX struct DihedralTypeList *dihedraltypes;
_EX struct OOPTypeList *ooptypes;
_EX struct AngleAngleTypeList *angleangletypes;
#undef _EX
#undef _ARG
diff --git a/tools/msi2lmp/src/ReadCarFile.c b/tools/msi2lmp/src/ReadCarFile.c
index 7adfe8d82..af34c15be 100644
--- a/tools/msi2lmp/src/ReadCarFile.c
+++ b/tools/msi2lmp/src/ReadCarFile.c
@@ -1,171 +1,216 @@
/*
* This function opens the .car file and extracts coordinate information
* into the atoms Atom structure
*/
#include "Msi2LMP2.h"
void ReadCarFile(void)
{
char line[MAX_LINE_LENGTH]; /* Stores lines as they are read in */
int k,m,n; /* counters */
int skip; /* lines to skip at beginning of file */
double lowest, highest; /* temp coordinate finding variables */
double total_q;
+ double sq_c;
+ double cos_alpha; // Added by SLTM Sept 13, 2010
+ double cos_gamma;
+ double sin_gamma;
+ double cos_beta;
+ double sin_beta;
+ double A, B, C;
/* Open .car file for reading */
sprintf(line,"%s.car",rootname);
if (pflag > 0) fprintf(stderr," Reading car file: %s\n",line);
if( (CarF = fopen(line,"r")) == NULL ) {
fprintf(stderr,"Cannot open %s\n",line);
exit(2);
}
/* Determine Number of molecules & atoms */
rewind(CarF);
no_molecules = -1; /* Set to -1 because counter will be incremented an
extra time at the end of the file */
fgets(line,MAX_LINE_LENGTH,CarF); /* Read header line */
/* Check for periodicity, if present, read cell constants */
if( strncmp(fgets(line,MAX_LINE_LENGTH,CarF),"PBC=ON",6) == 0) {
periodic = 1;
skip = 5; /* Data starts 5 lines from beginning of file */
fgets(line,MAX_LINE_LENGTH,CarF); /* Comment line */
fgets(line,MAX_LINE_LENGTH,CarF); /* Date stamp */
fscanf(CarF,"%*s %lf %lf %lf %lf %lf %lf %*s",
&pbc[0],&pbc[1],&pbc[2],&pbc[3],&pbc[4],&pbc[5]);
- if(pbc[3] != 90.0 || pbc[4] != 90.0 || pbc[5] != 90.0) {
- fprintf(stderr,"The system is not rectangular- LAMMPS can't handle it!!");
- exit(2);
+
+ // Added triclinic flag for non-orthogonal boxes Oct 5, 2010 SLTM
+ if(pbc[3] != 90.0 || pbc[4] != 90.0 || pbc[5] != 90.0) {
+ TriclinicFlag = 1;
}
+ else TriclinicFlag = 0;
}
else {
periodic = 0;
skip = 4;
if (pflag > 1) {
fprintf(stderr," %s is not a periodic system\n", rootname);
fprintf(stderr," Assigning cell parameters based on coordinates\n");
}
fgets(line,MAX_LINE_LENGTH, CarF); /* Comment line */
fgets(line,MAX_LINE_LENGTH, CarF); /* Date Stamp */
}
/* First pass through file -- Count molecules */
while(fgets(line,MAX_LINE_LENGTH,CarF) != NULL )
if( strncmp(line,"end",3) == 0 )
no_molecules++;
/* Allocate space to keep track of the number of atoms within a molecule */
no_atoms = (int *) calloc(no_molecules,sizeof(int));
if ( no_atoms == NULL ) {
fprintf(stderr,"Could not allocate memory for no_atoms\n");
exit(2);
}
/* Second pass through file -- Count atoms */
rewind(CarF);
for(n=0; n < skip; n++) /* Skip beginning lines */
fgets(line,MAX_LINE_LENGTH,CarF);
for(n=0; n < no_molecules; n++)
while( strncmp(fgets(line,MAX_LINE_LENGTH,CarF),"end",3) )
no_atoms[n]++;
for( total_no_atoms=0, n=0; n < no_molecules; n++ )
total_no_atoms += no_atoms[n];
molecule = (struct MoleculeList *) calloc(no_molecules,
sizeof(struct MoleculeList));
if (molecule == NULL) {
fprintf(stderr,"Unable to allocate memory for molecule structure\n");
exit(2);
}
molecule[0].start = 0;
molecule[0].end = no_atoms[0];
for (n=1; n < no_molecules; n++) {
molecule[n].start = molecule[n-1].end;
molecule[n].end = molecule[n].start + no_atoms[n];
}
/* Allocate space for atoms Atom structures */
atoms = (struct Atom *) calloc(total_no_atoms,sizeof(struct Atom));
if( atoms == NULL ) {
fprintf(stderr,"Could not allocate memory for AtomList\n");
exit(2);
}
/* Third pass through file -- Read+Parse Car File */
rewind(CarF);
for(n=0; n < skip; n++)
fgets(line,MAX_LINE_LENGTH,CarF);
for(m=0; m < no_molecules; m++) {
for(k=molecule[m].start; k <
molecule[m].end; k++) {
atoms[k].molecule = m;
atoms[k].no = k;
fscanf(CarF,"%s %lf %lf %lf %*s %*s %s %s %f",
atoms[k].name,
&(atoms[k].x[0]),
&(atoms[k].x[1]),
&(atoms[k].x[2]),
atoms[k].potential,
atoms[k].element,
&(atoms[k].q));
}
fgets(line,MAX_LINE_LENGTH,CarF);
fgets(line,MAX_LINE_LENGTH,CarF);
} /* End m (molecule) loop */
for (total_q=0.0,k=0; k < total_no_atoms; k++)
total_q += atoms[k].q;
if (pflag > 1) {
fprintf(stderr," There are %d atoms in %d molecules in this file\n",
total_no_atoms,no_molecules);
fprintf(stderr," The total charge in the system is %7.3f.\n\n",total_q);
}
/* Search coordinates to find lowest and highest for x, y, and z */
if (periodic == 0) {
- for ( k = 0; k < 3; k++) {
- lowest = atoms[0].x[k];
- highest = atoms[0].x[k];
-
- for ( m = 1; m < total_no_atoms; m++) {
- if (atoms[m].x[k] < lowest) lowest = atoms[m].x[k];
- if (atoms[m].x[k] > highest) highest = atoms[m].x[k];
+ // Added if/else statment STLM Oct 5 2010
+ if (TriclinicFlag == 0)
+ {
+ for ( k = 0; k < 3; k++) {
+ lowest = atoms[0].x[k];
+ highest = atoms[0].x[k];
+
+ for ( m = 1; m < total_no_atoms; m++) {
+ if (atoms[m].x[k] < lowest) lowest = atoms[m].x[k];
+ if (atoms[m].x[k] > highest) highest = atoms[m].x[k];
+ }
+ pbc[k] = lowest;
+ pbc[k+3] = highest;
}
- pbc[k] = lowest;
- pbc[k+3] = highest;
- }
+ }
+ else {
+ printf("Code only works for periodic systems with triclinic boxes");
+ exit(2);
+ }
+
}
else {
- for (k=0; k < 3; k++) {
- pbc[k+3] = pbc[k];
- pbc[k] = 0.0;
- }
+ // Modified lines 176 - 201 Oct 5th 2010
+ if (TriclinicFlag == 0) {
+ for (k=0; k < 3; k++) {
+ pbc[k+3] = pbc[k];
+ pbc[k] = 0.0;
+ }
+ }
+ else {
+ sq_c = pbc[2]*pbc[2];
+ cos_alpha = cos(pbc[3]*3.14159265358979323846/180.0);
+ cos_gamma = cos(pbc[5]*3.14159265358979323846/180.0);
+ sin_gamma = sin(pbc[5]*3.14159265358979323846/180.0);
+ cos_beta = cos(pbc[4]*3.14159265358979323846/180.0);
+ sin_beta = sin(pbc[4]*3.14159265358979323846/180.0);
+ printf("pbc[3] %lf pbc[4] %lf pbc[5] %lf\n", pbc[3] ,pbc[4] ,pbc[5]);
+ printf("cos_alpha %lf cos_beta %lf cos_gamma %lf\n", cos_alpha ,cos_beta ,cos_gamma);
+ A = pbc[0];
+ B = pbc[1];
+ C = pbc[2];
+
+
+ pbc[0] = A;
+ pbc[1] = B*sin_gamma;
+ pbc[2] = sqrt(sq_c * sin_beta*sin_beta - C*(cos_alpha-cos_gamma*cos_beta)/sin_gamma);
+ pbc[3] = B * cos_gamma; // This is xy SLTM
+ pbc[4] = C * cos_beta; // This is xz SLTM
+ pbc[5] = C*(cos_alpha-cos_gamma*cos_beta)/sin_gamma; // This is yz SLTM
+ }
+
+
+
}
/* Close .car file */
if (fclose(CarF) !=0) {
fprintf(stderr,"Error closing %s.car\n", rootname);
exit(1);
}
}
/* End ReadCarFile() */
diff --git a/tools/msi2lmp/src/WriteDataFile.c b/tools/msi2lmp/src/WriteDataFile.c
index 050240dcc..cca6db09d 100644
--- a/tools/msi2lmp/src/WriteDataFile.c
+++ b/tools/msi2lmp/src/WriteDataFile.c
@@ -1,313 +1,316 @@
/*
* This function creates and writes the data file to be used with LAMMPS
*/
#include "Msi2LMP2.h"
#include "Forcefield.h"
void WriteDataFile(FILE *DatF,char *nameroot,int forcefield)
{
int i,j,k,m;
char line[MAX_LINE_LENGTH];
if (forcefield == 1) total_no_angle_angles = 0;
fprintf(DatF, "LAMMPS data file for %s\n\n", nameroot);
fprintf(DatF, " %6d atoms\n", total_no_atoms);
fprintf(DatF, " %6d bonds\n", total_no_bonds);
fprintf(DatF, " %6d angles\n",total_no_angles);
fprintf(DatF, " %6d dihedrals\n", total_no_dihedrals);
fprintf(DatF, " %6d impropers\n", total_no_oops+total_no_angle_angles);
fprintf(DatF, "\n");
fprintf(DatF, " %3d atom types\n", no_atom_types);
if (no_bond_types > 0)
fprintf(DatF, " %3d bond types\n", no_bond_types);
if (no_angle_types> 0)
fprintf(DatF, " %3d angle types\n", no_angle_types);
if (no_dihedral_types > 0) fprintf (DatF," %3d dihedral types\n",
no_dihedral_types);
if (forcefield > 1) {
if ((no_oop_types + no_angleangle_types) > 0)
fprintf (DatF, " %3d improper types\n",
no_oop_types + no_angleangle_types);
}
else {
if (no_oop_types > 0)
fprintf (DatF, " %3d improper types\n", no_oop_types);
}
-
+
+
fprintf(DatF, "\n");
- fprintf(DatF, " %15.9f %15.9f xlo xhi\n", pbc[0], pbc[3]);
- fprintf(DatF, " %15.9f %15.9f ylo yhi\n", pbc[1], pbc[4]);
- fprintf(DatF, " %15.9f %15.9f zlo zhi\n", pbc[2], pbc[5]);
+ fprintf(DatF, " %15.9f %15.9f xlo xhi\n", 0.0, pbc[0]);
+ fprintf(DatF, " %15.9f %15.9f ylo yhi\n", 0.0, pbc[1]);
+ fprintf(DatF, " %15.9f %15.9f zlo zhi\n", 0.0, pbc[2]);
+ fprintf(DatF, " %15.9f %15.9f %15.9f xy xz yz\n", pbc[3], pbc[4], pbc[5]);
+
/* MASSES */
fprintf(DatF, "\nMasses\n\n");
for(k=0; k < no_atom_types; k++)
fprintf(DatF, " %3d %10.6f\n",k+1,atomtypes[k].mass);
fprintf(DatF, "\n");
/* COEFFICIENTS */
fprintf(DatF,"Nonbond Coeffs\n\n");
for (i=0; i < no_atom_types; i++) {
fprintf(DatF, " %3i ", i+1);
for ( j = 0; j < 2; j++)
fprintf(DatF, "%14.10f ", atomtypes[i].params[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
if (no_bond_types > 0) {
if (forcefield == 1) m = 2;
if (forcefield == 2) m = 4;
fprintf(DatF,"Bond Coeffs\n\n");
for (i=0; i < no_bond_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < m; j++)
fprintf(DatF, "%10.4f ", bondtypes[i].params[j]);
fprintf(DatF,"\n");
}
fprintf(DatF, "\n");
}
if (no_angle_types > 0) {
if (forcefield == 1) m = 2;
if (forcefield == 2) m = 4;
fprintf(DatF,"Angle Coeffs\n\n");
for (i=0; i < no_angle_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < m; j++)
fprintf(DatF, "%10.4f ", angletypes[i].params[j]);
fprintf(DatF,"\n");
}
fprintf(DatF, "\n");
}
if (no_dihedral_types > 0) {
if (forcefield == 1) m = 3;
if (forcefield == 2) m = 6;
fprintf(DatF,"Dihedral Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < m; j++)
fprintf(DatF, "%10.4f ", dihedraltypes[i].params[j]);
fprintf(DatF,"\n");
}
fprintf(DatF, "\n");
}
if (forcefield == 1) {
if (no_oop_types > 0) {
fprintf(DatF,"Improper Coeffs\n\n");
for (i=0; i < no_oop_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
fprintf(DatF, "%10.4f ", ooptypes[i].params[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
}
else if (forcefield == 2) {
if ((no_oop_types + no_angleangle_types) > 0) {
fprintf(DatF,"Improper Coeffs\n\n");
for (i=0; i < no_oop_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 2; j++)
fprintf(DatF, "%10.4f ", ooptypes[i].params[j]);
fprintf(DatF, "\n");
}
for (i=0; i < no_angleangle_types; i++) {
fprintf(DatF, "%3i ", i+no_oop_types+1);
for ( j = 0; j < 2; j++)
fprintf(DatF, "%10.4f ", 0.0);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
}
if (forcefield == 2) {
if (no_angle_types > 0) {
fprintf(DatF,"BondBond Coeffs\n\n");
for (i=0; i < no_angle_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
fprintf(DatF, "%10.4f ", angletypes[i].bondbond_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"BondAngle Coeffs\n\n");
for (i=0; i < no_angle_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 4; j++)
fprintf(DatF, "%10.4f ",angletypes[i].bondangle_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
if ((no_oop_types+no_angleangle_types) > 0) {
fprintf(DatF,"AngleAngle Coeffs\n\n");
for (i=0; i < no_oop_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 6; j++)
fprintf(DatF, "%10.4f ", ooptypes[i].angleangle_params[j]);
fprintf(DatF, "\n");
}
for (i=0; i < no_angleangle_types; i++) {
fprintf(DatF, "%3i ", i+no_oop_types+1);
for ( j = 0; j < 6; j++)
fprintf(DatF, "%10.4f ", angleangletypes[i].params[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
if (no_dihedral_types > 0) {
fprintf(DatF,"AngleAngleTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
fprintf(DatF,"%10.4f ",
dihedraltypes[i].angleangledihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"EndBondTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%i ", i+1);
for ( j = 0; j < 8; j++)
fprintf(DatF, "%10.4f ",
dihedraltypes[i].endbonddihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"MiddleBondTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 4; j++)
fprintf(DatF,"%10.4f ",
dihedraltypes[i].midbonddihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"BondBond13 Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
fprintf(DatF, "%10.4f ",
dihedraltypes[i].bond13_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"AngleTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 8; j++)
fprintf(DatF, "%10.4f ",
dihedraltypes[i].angledihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
}
/*--------------------------------------------------------------------*/
/* ATOMS */
fprintf(DatF, "Atoms\n\n");
for(k=0; k < total_no_atoms; k++) {
fprintf(DatF, " %6i %6i %3i %9.6f %15.9f %15.9f %15.9f\n",
k+1,
atoms[k].molecule,
atoms[k].type+1,
atoms[k].q,
atoms[k].x[0],
atoms[k].x[1],
atoms[k].x[2]);
}
fprintf(DatF, "\n");
/***** BONDS *****/
if (total_no_bonds > 0) {
fprintf(DatF, "Bonds\n\n");
for(k=0; k < total_no_bonds; k++)
fprintf(DatF, "%6i %3i %6i %6i\n",k+1,
bonds[k].type+1,
bonds[k].members[0]+1,
bonds[k].members[1]+1);
fprintf(DatF,"\n");
}
/***** ANGLES *****/
if (total_no_angles > 0) {
fprintf(DatF, "Angles\n\n");
for(k=0; k < total_no_angles; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i\n",k+1,
angles[k].type+1,
angles[k].members[0]+1,
angles[k].members[1]+1,
angles[k].members[2]+1);
fprintf(DatF, "\n");
}
/***** TORSIONS *****/
if (total_no_dihedrals > 0) {
fprintf(DatF,"Dihedrals\n\n");
for(k=0; k < total_no_dihedrals; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i %6i\n",k+1,
dihedrals[k].type+1,
dihedrals[k].members[0]+1,
dihedrals[k].members[1]+1,
dihedrals[k].members[2]+1,
dihedrals[k].members[3]+1);
fprintf(DatF, "\n");
}
/***** OUT-OF-PLANES *****/
if (total_no_oops+total_no_angle_angles > 0) {
fprintf(DatF,"Impropers\n\n");
for (k=0; k < total_no_oops; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i %6i \n", k+1,
oops[k].type+1,
oops[k].members[0]+1,
oops[k].members[1]+1,
oops[k].members[2]+1,
oops[k].members[3]+1);
if (forcefield == 2) {
for (k=0; k < total_no_angle_angles; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i %6i \n",k+total_no_oops+1,
angleangles[k].type+no_oop_types+1,
angleangles[k].members[0]+1,
angleangles[k].members[1]+1,
angleangles[k].members[2]+1,
angleangles[k].members[3]+1);
}
fprintf(DatF, "\n");
}
}
diff --git a/tools/msi2lmp/src/WriteDataFile05.c b/tools/msi2lmp/src/WriteDataFile05.c
index ac195803b..504314e12 100644
--- a/tools/msi2lmp/src/WriteDataFile05.c
+++ b/tools/msi2lmp/src/WriteDataFile05.c
@@ -1,333 +1,352 @@
/*
* This function creates and writes the data file to be used with LAMMPS
*/
#include "Msi2LMP2.h"
#include "Forcefield.h"
void WriteDataFile05(char *nameroot,int forcefield)
{
int i,j,k,m;
char line[MAX_LINE_LENGTH];
FILE *DatF;
/* Open data file */
sprintf(line,"%s.lammps05",rootname);
if (pflag > 0) fprintf(stderr," Writing LAMMPS 2005 data file: %s\n",line);
if( (DatF = fopen(line,"w")) == NULL ) {
fprintf(stderr,"Cannot open %s\n",line);
exit(2);
}
if (forcefield == 1) total_no_angle_angles = 0;
fprintf(DatF, "LAMMPS 2005 data file for %s\n\n", nameroot);
fprintf(DatF, " %6d atoms\n", total_no_atoms);
fprintf(DatF, " %6d bonds\n", total_no_bonds);
fprintf(DatF, " %6d angles\n",total_no_angles);
fprintf(DatF, " %6d dihedrals\n", total_no_dihedrals);
fprintf(DatF, " %6d impropers\n", total_no_oops+total_no_angle_angles);
fprintf(DatF, "\n");
fprintf(DatF, " %3d atom types\n", no_atom_types);
if (no_bond_types > 0)
fprintf(DatF, " %3d bond types\n", no_bond_types);
if (no_angle_types> 0)
fprintf(DatF, " %3d angle types\n", no_angle_types);
if (no_dihedral_types > 0) fprintf (DatF," %3d dihedral types\n",
no_dihedral_types);
if (forcefield > 1) {
if ((no_oop_types + no_angleangle_types) > 0)
fprintf (DatF, " %3d improper types\n",
no_oop_types + no_angleangle_types);
}
else {
if (no_oop_types > 0)
fprintf (DatF, " %3d improper types\n", no_oop_types);
}
-
- fprintf(DatF, "\n");
- fprintf(DatF, " %15.9f %15.9f xlo xhi\n", pbc[0], pbc[3]);
- fprintf(DatF, " %15.9f %15.9f ylo yhi\n", pbc[1], pbc[4]);
- fprintf(DatF, " %15.9f %15.9f zlo zhi\n", pbc[2], pbc[5]);
-
+
+
+ // Modified by SLTM to print out triclinic box types 10/05/10 - lines 56-68
+
+ if (TriclinicFlag == 0) {
+ fprintf(DatF, "\n");
+ fprintf(DatF, " %15.9f %15.9f xlo xhi\n", pbc[0], pbc[3]);
+ fprintf(DatF, " %15.9f %15.9f ylo yhi\n", pbc[1], pbc[4]);
+ fprintf(DatF, " %15.9f %15.9f zlo zhi\n", pbc[2], pbc[5]);
+ }
+ else {
+ fprintf(DatF, "\n");
+ fprintf(DatF, " %15.9f %15.9f xlo xhi\n", 0.0, pbc[0]);
+ fprintf(DatF, " %15.9f %15.9f ylo yhi\n", 0.0, pbc[1]);
+ fprintf(DatF, " %15.9f %15.9f zlo zhi\n", 0.0, pbc[2]);
+ fprintf(DatF, " %15.9f %15.9f %15.9f xy xz yz\n", pbc[3], pbc[4], pbc[5]);
+ }
+
+
/* MASSES */
fprintf(DatF, "\nMasses\n\n");
for(k=0; k < no_atom_types; k++)
fprintf(DatF, " %3d %10.6f\n",k+1,atomtypes[k].mass);
fprintf(DatF, "\n");
/* COEFFICIENTS */
fprintf(DatF,"Pair Coeffs\n\n");
for (i=0; i < no_atom_types; i++) {
fprintf(DatF, " %3i ", i+1);
for ( j = 0; j < 2; j++)
fprintf(DatF, "%14.10f ", atomtypes[i].params[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
if (no_bond_types > 0) {
if (forcefield == 1) m = 2;
if (forcefield == 2) m = 4;
fprintf(DatF,"Bond Coeffs\n\n");
for (i=0; i < no_bond_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < m; j++)
fprintf(DatF, "%10.4f ", bondtypes[i].params[j]);
fprintf(DatF,"\n");
}
fprintf(DatF, "\n");
}
if (no_angle_types > 0) {
if (forcefield == 1) m = 2;
if (forcefield == 2) m = 4;
fprintf(DatF,"Angle Coeffs\n\n");
for (i=0; i < no_angle_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < m; j++)
fprintf(DatF, "%10.4f ", angletypes[i].params[j]);
fprintf(DatF,"\n");
}
fprintf(DatF, "\n");
}
if (no_dihedral_types > 0) {
if (forcefield == 1) m = 3;
if (forcefield == 2) m = 6;
fprintf(DatF,"Dihedral Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < m; j++)
- fprintf(DatF, "%10.4f ", dihedraltypes[i].params[j]);
+ // Modified on 10/05/2010 by STLM to match with lammps reading in integers for the all but the first coefficients
+ if (j == 0)
+ fprintf(DatF, "%10.4f ", dihedraltypes[i].params[j]);
+ else fprintf(DatF, "%10.0f ", dihedraltypes[i].params[j]);
fprintf(DatF,"\n");
}
fprintf(DatF, "\n");
}
if (forcefield == 1) {
if (no_oop_types > 0) {
fprintf(DatF,"Improper Coeffs\n\n");
for (i=0; i < no_oop_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
- fprintf(DatF, "%10.4f ", ooptypes[i].params[j]);
+ // Modified on 10/05/2010 by STLM to match with lammps reading in integers for the all but the first coefficients
+ if (j == 0)
+ fprintf(DatF, "%10.4f ", ooptypes[i].params[j]);
+ else fprintf(DatF, "%10.0f ", ooptypes[i].params[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
}
else if (forcefield == 2) {
if ((no_oop_types + no_angleangle_types) > 0) {
fprintf(DatF,"Improper Coeffs\n\n");
for (i=0; i < no_oop_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 2; j++)
fprintf(DatF, "%10.4f ", ooptypes[i].params[j]);
fprintf(DatF, "\n");
}
for (i=0; i < no_angleangle_types; i++) {
fprintf(DatF, "%3i ", i+no_oop_types+1);
for ( j = 0; j < 2; j++)
fprintf(DatF, "%10.4f ", 0.0);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
}
if (forcefield == 2) {
if (no_angle_types > 0) {
fprintf(DatF,"BondBond Coeffs\n\n");
for (i=0; i < no_angle_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
fprintf(DatF, "%10.4f ", angletypes[i].bondbond_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"BondAngle Coeffs\n\n");
for (i=0; i < no_angle_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 4; j++)
fprintf(DatF, "%10.4f ",angletypes[i].bondangle_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
if ((no_oop_types+no_angleangle_types) > 0) {
fprintf(DatF,"AngleAngle Coeffs\n\n");
for (i=0; i < no_oop_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 6; j++)
fprintf(DatF, "%10.4f ", ooptypes[i].angleangle_params[j]);
fprintf(DatF, "\n");
}
for (i=0; i < no_angleangle_types; i++) {
fprintf(DatF, "%3i ", i+no_oop_types+1);
for ( j = 0; j < 6; j++)
fprintf(DatF, "%10.4f ", angleangletypes[i].params[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
if (no_dihedral_types > 0) {
fprintf(DatF,"AngleAngleTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
fprintf(DatF,"%10.4f ",
dihedraltypes[i].angleangledihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"EndBondTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%i ", i+1);
for ( j = 0; j < 8; j++)
fprintf(DatF, "%10.4f ",
dihedraltypes[i].endbonddihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"MiddleBondTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 4; j++)
fprintf(DatF,"%10.4f ",
dihedraltypes[i].midbonddihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"BondBond13 Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 3; j++)
fprintf(DatF, "%10.4f ",
dihedraltypes[i].bond13_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
fprintf(DatF,"AngleTorsion Coeffs\n\n");
for (i=0; i < no_dihedral_types; i++) {
fprintf(DatF, "%3i ", i+1);
for ( j = 0; j < 8; j++)
fprintf(DatF, "%10.4f ",
dihedraltypes[i].angledihedral_cross_term[j]);
fprintf(DatF, "\n");
}
fprintf(DatF, "\n");
}
}
/*--------------------------------------------------------------------*/
/* ATOMS */
fprintf(DatF, "Atoms\n\n");
for(k=0; k < total_no_atoms; k++) {
fprintf(DatF, " %6i %6i %3i %9.6f %15.9f %15.9f %15.9f\n",
k+1,
atoms[k].molecule,
atoms[k].type+1,
atoms[k].q,
atoms[k].x[0],
atoms[k].x[1],
atoms[k].x[2]);
}
fprintf(DatF, "\n");
/***** BONDS *****/
if (total_no_bonds > 0) {
fprintf(DatF, "Bonds\n\n");
for(k=0; k < total_no_bonds; k++)
fprintf(DatF, "%6i %3i %6i %6i\n",k+1,
bonds[k].type+1,
bonds[k].members[0]+1,
bonds[k].members[1]+1);
fprintf(DatF,"\n");
}
/***** ANGLES *****/
if (total_no_angles > 0) {
fprintf(DatF, "Angles\n\n");
for(k=0; k < total_no_angles; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i\n",k+1,
angles[k].type+1,
angles[k].members[0]+1,
angles[k].members[1]+1,
angles[k].members[2]+1);
fprintf(DatF, "\n");
}
/***** TORSIONS *****/
if (total_no_dihedrals > 0) {
fprintf(DatF,"Dihedrals\n\n");
for(k=0; k < total_no_dihedrals; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i %6i\n",k+1,
dihedrals[k].type+1,
dihedrals[k].members[0]+1,
dihedrals[k].members[1]+1,
dihedrals[k].members[2]+1,
dihedrals[k].members[3]+1);
fprintf(DatF, "\n");
}
/***** OUT-OF-PLANES *****/
if (total_no_oops+total_no_angle_angles > 0) {
fprintf(DatF,"Impropers\n\n");
for (k=0; k < total_no_oops; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i %6i \n", k+1,
oops[k].type+1,
oops[k].members[0]+1,
oops[k].members[1]+1,
oops[k].members[2]+1,
oops[k].members[3]+1);
if (forcefield == 2) {
for (k=0; k < total_no_angle_angles; k++)
fprintf(DatF, "%6i %3i %6i %6i %6i %6i \n",k+total_no_oops+1,
angleangles[k].type+no_oop_types+1,
angleangles[k].members[0]+1,
angleangles[k].members[1]+1,
angleangles[k].members[2]+1,
angleangles[k].members[3]+1);
}
fprintf(DatF, "\n");
}
/* Close data file */
if (fclose(DatF) !=0) {
fprintf(stderr,"Error closing %s.lammps05\n", rootname);
exit(1);
}
}
diff --git a/tools/msi2lmp/src/msi2lmp.c b/tools/msi2lmp/src/msi2lmp.c
index 1a7508a1b..af687d0de 100644
--- a/tools/msi2lmp/src/msi2lmp.c
+++ b/tools/msi2lmp/src/msi2lmp.c
@@ -1,275 +1,278 @@
/*
*
* msi2lmp.exe V3.6
*
* v3.6 KLA - Changes to output to either lammps 2001 (F90 version) or to
* lammps 2005 (C++ version)
*
* v3.4 JEC - a number of minor changes due to way newline and EOF are generated
* on Materials Studio generated .car and .mdf files as well as odd
* behavior out of newer Linux IO libraries. ReadMdfFile was restructured
* in the process.
*
* v3.1 JEC - changed IO interface to standard in/out, forcefield file
* location can be indicated by environmental variable; added
* printing options, consistency checks and forcefield
* parameter versions sensitivity (highest one used)
*
* v3.0 JEC - program substantially rewritten to reduce execution time
* and be 98 % dynamic in memory use (still fixed limits on
* number of parameter types for different internal coordinate
* sets)
*
* v2.0 MDP - got internal coordinate information from mdf file and
* forcefield parameters from frc file thus eliminating
* need for Discover
*
* V1.0 SL - original version. Used .car file and internal coordinate
* information from Discover to produce LAMMPS data file.
*
* This program uses the .car and .mdf files from MSI/Biosyms's INSIGHT
* program to produce a LAMMPS data file.
*
* The program is started by supplying information at the command prompt
* according to the usage described below.
*
* USAGE: msi2lmp3 ROOTNAME {-print #} {-class #} {-frc FRC_FILE} -2001
*
* -- msi2lmp3 is the name of the executable
* -- ROOTNAME is the base name of the .car and .mdf files
*
* -- -print
* # is the print level: 0 - silent except for errors
* 1 - minimal (default)
* 2 - more verbose
* -- -class
* # is the class of forcefield to use (I = Class I e.g., CVFF)
* (II = Class II e.g., CFFx )
* default is -class I
*
* -- -frc - specifies name of the forcefield file (e.g., cff91)
*
* If the name includes a hard wired directory (i.e., if the name
* starts with . or /), then the name is used alone. Otherwise,
* the program looks for the forcefield file in $BIOSYM_LIBRARY.
* If $BIOSYM_LIBRARY is not set, then the current directory is
* used.
*
* If the file name does not include a dot after the first
* character, then .frc is appended to the name.
*
* For example, -frc cvff (assumes cvff.frc is in $BIOSYM_LIBRARY
* or .)
*
* -frc cff/cff91 (assumes cff91.frc is in
* $BIOSYM_LIBRARY/cff or ./cff)
*
* -frc /usr/local/biosym/forcefields/cff95 (absolute
* location)
*
* By default, the program uses $BIOSYM_LIBRARY/cvff.frc
*
* -- -2001 will output a data file for the FORTRAN 90 version of LAMMPS (2001)
* By default, the program will output for the C++ version of LAMMPS.
*
* -- output is written to a file called ROOTNAME.lammps{01/05}
*
*
****************************************************************
*
* Msi2lmp3
*
* This is the third version of a program that generates a LAMMPS
* data file based on the information in a MSI car file (atom
* coordinates) and mdf file (molecular topology). A key part of
* the program looks up forcefield parameters from an MSI frc file.
*
* The first version was written by Steve Lustig at Dupont, but
* required using Discover to derive internal coordinates and
* forcefield parameters
*
* The second version was written by Michael Peachey while an
* in intern in the Cray Chemistry Applications Group managed
* by John Carpenter. This version derived internal coordinates
* from the mdf file and looked up parameters in the frc file
* thus eliminating the need for Discover.
*
* The third version was written by John Carpenter to optimize
* the performance of the program for large molecular systems
* (the original code for deriving atom numbers was quadratic in time)
* and to make the program fully dynamic. The second version used
* fixed dimension arrays for the internal coordinates.
*
* John Carpenter can be contacted by sending email to
* jec374@earthlink.net
*
* November 2000
*/
#define MAIN
#include "Msi2LMP2.h"
int main (int argc, char *argv[])
{
int n,i,found_dot; /* Counter */
int outv;
char *string;
char *frc_dir_name;
char *frc_file_name;
FILE *DatF;
/* Functions called from within main */
/* All code is located in .c file with function name */
extern void FrcMenu();
extern void ReadCarFile();
extern void ReadMdfFile();
extern void ReadFrcFile();
extern void MakeLists();
extern void GetParameters(int);
extern void CheckLists();
extern void WriteDataFile(FILE *,char *,int);
-
+
outv = 2005;
pflag = 1;
forcefield = 1; /* Variable that identifies forcefield to use */
frc_file_name = (char *) calloc(160,sizeof(char));
frc_dir_name = (char *) calloc(160,sizeof(char));
frc_dir_name = getenv("BIOSYM_LIBRARY");
-
+
if (frc_dir_name == NULL) {
- frc_file_name = strcpy(frc_file_name,"./cvff.frc");
+ frc_file_name = strcpy(frc_file_name,"../biosym_frc_files/clayff.frc");
}
else {
for (i=0; i < strlen(frc_dir_name); i++)
frc_file_name[i] = frc_dir_name[i];
frc_file_name = strcat(frc_file_name,"/cvff.frc");
}
+
+
if (argc < 2) { /* If no rootname was supplied, prompt for it */
fprintf(stderr,"The rootname of the .car and .mdf files must be entered\n");
}
else /* rootname was supplied as first argument, copy to rootname */
sprintf(rootname,"%s",argv[1]);
-
+
n = 2;
while (n < argc) {
if (strcmp(argv[n],"-class") == 0) {
if (strcmp(argv[n+1],"I") == 0) {
forcefield = 1;
n++;
}
else if (strcmp(argv[n+1],"II") == 0) {
forcefield = 2;
n++;
}
else {
fprintf(stderr,"Unrecognized Forcefield class: %s\n",
argv[n+1]);
n++;
}
}
else if (strcmp(argv[n],"-2001") == 0) {
outv = 2001;
n++;
}
else if (strcmp(argv[n],"-frc") == 0) {
if ((frc_dir_name != NULL) && (argv[n+1][0] != '.')) {
for (i=0; i < strlen(frc_dir_name); i++) {
frc_file_name[i] = frc_dir_name[i];
}
frc_file_name[strlen(frc_dir_name)] = '\0';
frc_file_name = strcat(frc_file_name,"/");
frc_file_name = strcat(frc_file_name,argv[n+1]);
}
else {
frc_file_name = strcpy(frc_file_name,argv[n+1]);
}
found_dot = 0;
for (i=1; i < strlen(frc_file_name); i++) {
if (frc_file_name[i] == '.') found_dot = 1;
}
if (found_dot == 0)
frc_file_name = strcat(frc_file_name,".frc");
n++;
}
else if (strstr(argv[n],"-p") != NULL) {
pflag = atoi(argv[n+1]);
n++;
}
else {
fprintf(stderr,"Unrecognized option: %s\n",argv[n]);
}
n++;
}
for (i=0; i < strlen(frc_file_name); i++)
FrcFileName[i] = frc_file_name[i];
free(frc_file_name);
if (pflag > 0) {
fprintf(stderr,"\nRunning Msi2lmp.....\n\n");
fprintf(stderr," Forcefield file name: %s\n",FrcFileName);
fprintf(stderr," Forcefield class: %d\n\n",forcefield);
}
if (((forcefield == 1) && (strstr(FrcFileName,"cff") != NULL) ||
(forcefield == 2) && (strstr(FrcFileName,"cvff") != NULL))) {
fprintf(stderr," WARNING - forcefield name and class appear to\n");
fprintf(stderr," be inconsistent - Errors may result\n\n");
}
/* Read in .car file */
-
+ printf("I am before read car file\n");
ReadCarFile();
-
+ printf("I am after read car file\n");
/*Read in .mdf file */
ReadMdfFile();
-
+ printf("I am after read mdf file\n");
/* Define bonds, angles, etc...*/
if (pflag > 0) fprintf(stderr,"\n Building internal coordinate lists \n");
MakeLists();
/* Read .frc file into memory */
-
+
+ // Commented out to create conversion file suitable for non-orthogonal boxes Sept 13, 2010 SLTM
if (pflag > 0) fprintf(stderr,"\n Reading forcefield file \n");
ReadFrcFile();
/* Get forcefield parameters */
if (pflag > 0) fprintf(stderr,"\n Get parameters for this molecular system\n");
GetParameters(forcefield);
/* Do internal check of internal coordinate lists */
if (pflag > 0) fprintf(stderr,"\n Check parameters for internal consistency\n");
CheckLists();
if (outv == 2001) { fprintf(stderr,"\n Writing LAMMPS 2001 data file\n");
WriteDataFile01(rootname,forcefield);
}
else if (outv == 2005) {fprintf(stderr,"\n Writing LAMMPS 2005 data file\n");
WriteDataFile05(rootname,forcefield);
}
if (pflag > 0) fprintf(stderr,"\nNormal program termination\n");
}
#include <ctype.h>
int blank_line(char *line)
{
int i,n;
for (i=0,n=0; i < strlen(line); i++) {
if (isalnum((unsigned char)line[i])) n++;
}
if (n > 0) {
return(0);
}
else {
return(1);
}
}

Event Timeline