lammps/doc/Section_modify.html

523 lines
24 KiB
HTML

<HTML>
<CENTER><A HREF = "Section_tools.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_errors.html">Next
Section</A>
</CENTER>
<HR>
<H3>8. Modifying & extending LAMMPS
</H3>
<P>LAMMPS is designed in a modular fashion so as to be easy to modify and
extend with new functionality. In fact, about 75% if its source code
is files added in this fashion.
</P>
<P>In this section, changes and additions users can make are listed along
with minimal instructions. The best way to add a new feature is to
find a similar feature in LAMMPS and look at the corresponding source
and header files to figure out what it does. You will need some
knowledge of C++ to be able to understand the hi-level structure of
LAMMPS and its class organization, but functions (class methods) that
do actual computations are written in vanilla C-style code and operate
on simple C-style data structures (vectors and arrays).
</P>
<P>Most of the new features described in this section require you to
write a new C++ derived class (except for exceptions described below,
where you can make small edits to existing files). Creating a new
class requires 2 files, a source code file (*.cpp) and a header file
(*.h). The derived class must provide certain methods to work as a
new option. Depending on how different your new feature is compared
to existing features, you can either derive from the base class
itself, or from a derived class that already exists. Enabling LAMMPS
to invoke the new class is as simple as adding two lines to the
style_user.h file, in the same syntax as other LAMMPS classes are
specified in the style.h file.
</P>
<P>The advantage of C++ and its object-orientation is that all the code
and variables needed to define the new feature are in the 2 files you
write, and thus shouldn't make the rest of LAMMPS more complex or
cause side-effect bugs.
</P>
<P>Here is a concrete example. Suppose you write 2 files pair_foo.cpp
and pair_foo.h that define a new class PairFoo that computes pairwise
potentials described in the classic 1997 <A HREF = "#Foo">paper</A> by Foo, et al.
If you wish to invoke those potentials in a LAMMPS input script with a
command like
</P>
<PRE>pair_style foo 0.1 3.5
</PRE>
<P>you put your 2 files in the LAMMPS src directory, add 2 lines to the
style_user.h file, and re-make the code.
</P>
<P>The first line added to style_user.h would be
</P>
<PRE>PairStyle(foo,PairFoo)
</PRE>
<P>in the #ifdef PairClass section, where "foo" is the style keyword in
the pair_style command, and PairFoo is the class name in your C++
files.
</P>
<P>The 2nd line added to style_user.h would be
</P>
<PRE>#include "pair_foo.h"
</PRE>
<P>in the #ifdef PairInclude section, where pair_foo.h is the name of
your new include file.
</P>
<P>When you re-make LAMMPS, your new pairwise potential becomes part of
the executable and can be invoked with a pair_style command like the
example above. Arguments like 0.1 and 3.5 can be defined and
processed by your new class.
</P>
<P>Here is a list of the new features that can be added in this way:
</P>
<UL><LI><A HREF = "#atom">Atom styles</A>
<LI><A HREF = "#bond">Bond, angle, dihedral, improper potentials</A>
<LI><A HREF = "#compute">Compute styles</A>
<LI><A HREF = "#dump">Dump styles</A>
<LI><A HREF = "#fix">Fix styles</A> which include integrators, temperature and pressure control, force constraints, boundary conditions, diagnostic output, etc
<LI><A HREF = "#command">Input script commands</A>
<LI><A HREF = "#kspace">Kspace computations</A>
<LI><A HREF = "#min">Minimization solvers</A>
<LI><A HREF = "#pair">Pairwise potentials</A>
<LI><A HREF = "#region">Region styles</A>
</UL>
<P>As illustrated by the pairwise example, these options are referred to
in the LAMMPS documentation as the "style" of a particular command.
</P>
<P>The instructions below give the header file for the base class that
these styles are derived from. Public variables in that file are ones
used and set by the derived classes which are also used by the base
class. Sometimes they are also used by the rest of LAMMPS. Virtual
functions in the base class header file which are set = 0 are ones you
must define in your new derived class to give it the functionality
LAMMPS expects. Virtual functions that are not set to 0 are functions
you can optionally define.
</P>
<P>Additionally, new output options can be added directly to the
thermo.cpp, dump_custom.cpp, and variable.cpp files as explained in
these sections:
</P>
<UL><LI><A HREF = "#dump_custom">Dump custom output options</A>
<LI><A HREF = "#thermo">Thermodynamic output options</A>
<LI><A HREF = "#variable">Variable options</A>
</UL>
<HR>
<P>Here are additional guidelines for modifying LAMMPS and adding new
functionality:
</P>
<UL><LI>Think about whether what you want to do would be better as a pre- or
post-processing step. Many computations are more easily and more
quickly done that way.
<LI>Don't do anything within the timestepping of a run that isn't
parallel. E.g. don't accumulate a bunch of data on a single processor
and analyze it. You run the risk of seriously degrading the parallel
efficiency.
<LI>If your new feature reads arguments or writes output, make sure you
follow the unit conventions discussed by the <A HREF = "units.html">units</A>
command.
<LI>If you add something you think is truly useful and doesn't impact
LAMMPS performance when it isn't used, send an email to the
<A HREF = "http://lammps.sandia.gov/authors.html">developers</A>. We might be
interested in adding it to the LAMMPS distribution.
</UL>
<HR>
<HR>
<A NAME = "atom"></A><H4>Atom styles
</H4>
<P>Classes that define an atom style are derived from the Atom class.
The atom style determines what quantities are associated with an atom.
A new atom style can be created if one of the existing atom styles
does not define all the arrays you need to store and communicate with
atoms.
</P>
<P>Atom_vec_atomic.cpp is a simple example of an atom style.
</P>
<P>Here is a brief description of methods you define in your new derived
class. See atom.h for details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >grow</TD><TD > re-allocate atom arrays to longer lengths</TD></TR>
<TR><TD >copy</TD><TD > copy info for one atom to another atom's array locations</TD></TR>
<TR><TD >pack_comm</TD><TD > store an atom's info in a buffer communicated every timestep</TD></TR>
<TR><TD >unpack_comm</TD><TD > retrieve an atom's info from the buffer</TD></TR>
<TR><TD >pack_reverse</TD><TD > store an atom's info in a buffer communicating partial forces</TD></TR>
<TR><TD >unpack_reverse</TD><TD > retrieve an atom's info from the buffer</TD></TR>
<TR><TD >pack_border</TD><TD > store an atom's info in a buffer communicated on neighbor re-builds</TD></TR>
<TR><TD >unpack_border</TD><TD > retrieve an atom's info from the buffer</TD></TR>
<TR><TD >pack_exchange</TD><TD > store all an atom's info to migrate to another processor</TD></TR>
<TR><TD >unpack_exchange</TD><TD > retrieve an atom's info from the buffer</TD></TR>
<TR><TD >size_restart</TD><TD > number of restart quantities associated with proc's atoms</TD></TR>
<TR><TD >pack_restart</TD><TD > pack atom quantities into a buffer</TD></TR>
<TR><TD >unpack_restart</TD><TD > unpack atom quantities from a buffer</TD></TR>
<TR><TD >create_atom</TD><TD > create an individual atom of this style</TD></TR>
<TR><TD >data_atom</TD><TD > parse an atom line from the data file</TD></TR>
<TR><TD >memory_usage</TD><TD > tally memory allocated by atom arrays
</TD></TR></TABLE></DIV>
<P>The constructor of the derived class sets values for several variables
that you must set when defining a new atom style. The atom arrays
themselves are defined in atom.cpp. Search for the word "customize"
and you will find locations you will need to modify.
</P>
<HR>
<A NAME = "bond"></A><H4>Bond, angle, dihedral, improper potentials
</H4>
<P>Classes that compute molecular interactions are derived from the Bond,
Angle, Dihedral, and Improper classes. New styles can be created to
add new potentials to LAMMPS.
</P>
<P>Bond_harmonic.cpp is the simplest example of a bond style. Ditto for
the harmonic forms of the angle, dihedral, and improper style
commands.
</P>
<P>Here is a brief description of methods you define in your new derived
bond class. See bond.h, angle.h, dihedral.h, and improper.h for
details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >compute</TD><TD > compute the molecular interactions</TD></TR>
<TR><TD >coeff</TD><TD > set coefficients for one bond type</TD></TR>
<TR><TD >equilibrium_distance</TD><TD > length of bond, used by SHAKE</TD></TR>
<TR><TD >write & read_restart</TD><TD > writes/reads coeffs to restart files</TD></TR>
<TR><TD >single</TD><TD > force and energy of a single bond
</TD></TR></TABLE></DIV>
<HR>
<A NAME = "compute"></A><H4>Compute styles
</H4>
<P>Classes that compute scalar and vector quantities like temperature
and the pressure tensor, as well as classes that compute per-atom
quantities like kinetic energy and the centro-symmetry parameter
are derived from the Compute class. New styles can be created
to add new calculations to LAMMPS.
</P>
<P>Compute_temp.cpp is a simple example of computing a scalar
temperature. Compute_ke_atom.cpp is a simple example of computing
per-atom kinetic energy.
</P>
<P>Here is a brief description of methods you define in your new derived
class. See compute.h for details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >compute_scalar</TD><TD > compute a scalar quantity</TD></TR>
<TR><TD >compute_vector</TD><TD > compute a vector of quantities</TD></TR>
<TR><TD >compute_peratom</TD><TD > compute one or more quantities per atom</TD></TR>
<TR><TD >pack_comm</TD><TD > pack a buffer with items to communicate</TD></TR>
<TR><TD >unpack_comm</TD><TD > unpack the buffer</TD></TR>
<TR><TD >pack_reverse</TD><TD > pack a buffer with items to reverse communicate</TD></TR>
<TR><TD >unpack_reverse</TD><TD > unpack the buffer</TD></TR>
<TR><TD >memory_usage</TD><TD > tally memory usage
</TD></TR></TABLE></DIV>
<HR>
<A NAME = "dump"></A><H4>Dump styles
</H4>
<A NAME = "dump_custom"></A><H4>Dump custom output options
</H4>
<P>Classes that dump per-atom info to files are derived from the Dump
class. To dump new quantities or in a new format, a new derived dump
class can be added, but it is typically simpler to modify the
DumpCustom class contained in the dump_custom.cpp file.
</P>
<P>Dump_atom.cpp is a simple example of a derived dump class.
</P>
<P>Here is a brief description of methods you define in your new derived
class. See dump.h for details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >write_header</TD><TD > write the header section of a snapshot of atoms</TD></TR>
<TR><TD >count</TD><TD > count the number of lines a processor will output</TD></TR>
<TR><TD >pack</TD><TD > pack a proc's output data into a buffer</TD></TR>
<TR><TD >write_data</TD><TD > write a proc's data to a file
</TD></TR></TABLE></DIV>
<P>See the <A HREF = "dump.html">dump</A> command and its <I>custom</I> style for a list of
keywords for atom information that can already be dumped by
DumpCustom. It includes options to dump per-atom info from Compute
classes, so adding a new derived Compute class is one way to calculate
new quantities to dump.
</P>
<P>Alternatively, you can add new keywords to the dump custom command.
Search for the word "customize" in dump_custom.cpp to see the
half-dozen or so locations where code will need to be added.
</P>
<HR>
<A NAME = "fix"></A><H4>Fix styles
</H4>
<P>In LAMMPS, a "fix" is any operation that is computed during
timestepping that alters some property of the system. Essentially
everything that happens during a simulation besides force computation,
neighbor list construction, and output, is a "fix". This includes
time integration (update of coordinates and velocities), force
constraints or boundary conditions (SHAKE or walls), and diagnostics
(compute a diffusion coefficient). New styles can be created to add
new options to LAMMPS.
</P>
<P>Fix_setforce.cpp is a simple example of setting forces on atoms to
prescribed values. There are dozens of fix options already in LAMMPS;
choose one as a template that is similar to what you want to
implement.
</P>
<P>Here is a brief description of methods you can define in your new
derived class. See fix.h for details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >setmask</TD><TD > determines when the fix is called during the timestep</TD></TR>
<TR><TD >init</TD><TD > initialization before a run</TD></TR>
<TR><TD >setup</TD><TD > called immediately before the 1st timestep</TD></TR>
<TR><TD >initial_integrate</TD><TD > called at very beginning of each timestep</TD></TR>
<TR><TD >pre_exchange</TD><TD > called before atom exchange on re-neighboring steps</TD></TR>
<TR><TD >pre_neighbor</TD><TD > called before neighbor list build</TD></TR>
<TR><TD >post_force</TD><TD > called after pair & molecular forces are computed</TD></TR>
<TR><TD >final_integrate</TD><TD > called at end of each timestep</TD></TR>
<TR><TD >end_of_step</TD><TD > called at very end of timestep</TD></TR>
<TR><TD >write_restart</TD><TD > dumps fix info to restart file</TD></TR>
<TR><TD >restart</TD><TD > uses info from restart file to re-initialize the fix</TD></TR>
<TR><TD >grow_arrays</TD><TD > allocate memory for atom-based arrays used by fix</TD></TR>
<TR><TD >copy_arrays</TD><TD > copy atom info when an atom migrates to a new processor</TD></TR>
<TR><TD >memory_usage</TD><TD > report memory used by fix</TD></TR>
<TR><TD >pack_exchange</TD><TD > store atom's data in a buffer</TD></TR>
<TR><TD >unpack_exchange</TD><TD > retrieve atom's data from a buffer</TD></TR>
<TR><TD >pack_restart</TD><TD > store atom's data for writing to restart file</TD></TR>
<TR><TD >unpack_restart</TD><TD > retrieve atom's data from a restart file buffer</TD></TR>
<TR><TD >size_restart</TD><TD > size of atom's data</TD></TR>
<TR><TD >maxsize_restart</TD><TD > max size of atom's data</TD></TR>
<TR><TD >initial_integrate_respa</TD><TD > same as initial_integrate, but for rRESPA</TD></TR>
<TR><TD >post_force_respa</TD><TD > same as post_force, but for rRESPA</TD></TR>
<TR><TD >final_integrate_respa</TD><TD > same as final_integrate, but for rRESPA</TD></TR>
<TR><TD >pack_comm</TD><TD > pack a buffer to communicate a per-atom quantity</TD></TR>
<TR><TD >unpack_comm</TD><TD > unpack a buffer to communicate a per-atom quantity</TD></TR>
<TR><TD >pack_reverse_comm</TD><TD > pack a buffer to reverse communicate a per-atom quantity</TD></TR>
<TR><TD >unpack_reverse_comm</TD><TD > unpack a buffer to reverse communicate a per-atom quantity</TD></TR>
<TR><TD >thermo</TD><TD > compute quantities for thermodynamic output
</TD></TR></TABLE></DIV>
<P>Typically, only a small fraction of these methods are defined for a
particular fix. Setmask is mandatory, as it determines when the fix
will be invoked during the timestep. Fixes that perform time
integration (<I>nve</I>, <I>nvt</I>, <I>npt</I>) implement initial_integrate and
final_integrate to perform velocity Verlet updates. Fixes that
constrain forces implement post_force. Fixes that perform diagnostics
typically implement end_of_step. For an end_of_step fix, one of your
fix arguments must be the variable "nevery" which is used to determine
when to call the fix. By convention, this is the first argument the
fix defines (after the ID, group-ID, style).
</P>
<P>If the fix needs to store information for each atom that persists from
timestep to timestep, it can manage that memory and migrate the info
with the atoms as they move from processors to processor by
implementing the grow_arrays, copy_arrays, pack_exchange, and
unpack_exchange methods. Similarly, the pack_restart and
unpack_restart methods can be implemented to store information about
the fix in restart files. If you wish an integrator or force
constraint fix to work with rRESPA (see the <A HREF = "run_style.html">run_style</A>
command), the initial_integrate, post_force_integrate, and
final_integrate_respa methods can be implemented. The thermo method
enables a fix to contribute values to thermodynamic output, as printed
quantities and/or to be summed to the potential energy of the system.
</P>
<HR>
<A NAME = "command"></A><H4>Input script commands
</H4>
<P>New commands can be added to LAMMPS input scripts by adding new
classes that have a "command" method and are listed in the Command
sections of style.h (or style_user.h). For example, the create_atoms,
read_data, velocity, and run commands are all implemented in this
fashion. When such a command is encountered in the LAMMPS input
script, LAMMPS simply creates a class with the corresponding name,
invokes the "command" method of the class, and passes it the arguments
from the input script. The command method can perform whatever
operations it wishes on LAMMPS data structures.
</P>
<P>The single method your new class must define is as follows:
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >command</TD><TD > operations performed by the new command
</TD></TR></TABLE></DIV>
<P>Of course, the new class can define other methods and variables as
needed.
</P>
<HR>
<A NAME = "kspace"></A><H4>Kspace computations
</H4>
<P>Classes that compute long-range Coulombic interactions via K-space
represenations (Ewald, PPPM) are derived from the KSpace class. New
styles can be created to add new K-space options to LAMMPS.
</P>
<P>Ewald.cpp is an example of computing K-space interactions.
</P>
<P>Here is a brief description of methods you define in your new derived
class. See kspace.h for details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >init</TD><TD > initialize the calculation before a run</TD></TR>
<TR><TD >setup</TD><TD > computation before the 1st timestep of a run</TD></TR>
<TR><TD >compute</TD><TD > every-timestep computation</TD></TR>
<TR><TD >memory_usage</TD><TD > tally of memory usage
</TD></TR></TABLE></DIV>
<HR>
<A NAME = "min"></A><H4>Minimization solvers
</H4>
<P>Classes that perform energy minimization derived from the Min class.
New styles can be created to add new minimization algorithms to
LAMMPS.
</P>
<P>Min_cg.cpp is an example of conjugate gradient minimization.
</P>
<P>Here is a brief description of methods you define in your new derived
class. See min.h for details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >init</TD><TD > initialize the minimization before a run</TD></TR>
<TR><TD >run</TD><TD > perform the minimization</TD></TR>
<TR><TD >memory_usage</TD><TD > tally of memory usage
</TD></TR></TABLE></DIV>
<HR>
<A NAME = "pair"></A><H4>Pairwise potentials
</H4>
<P>Classes that compute pairwise interactions are derived from the Pair
class. In LAMMPS, pairwise calculation include manybody potentials
such as EAM or Tersoff where particles interact without a static bond
topology. New styles can be created to add new pair potentials to
LAMMPS.
</P>
<P>Pair_lj_cut.cpp is a simple example of a Pair class, though it
includes some optional methods to enable its use with rRESPA.
</P>
<P>Here is a brief description of the class methods in pair.h:
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >compute</TD><TD > workhorse routine that computes pairwise interactions</TD></TR>
<TR><TD >settings</TD><TD > reads the input script line with arguments you define</TD></TR>
<TR><TD >coeff</TD><TD > set coefficients for one i,j type pair</TD></TR>
<TR><TD >init_one</TD><TD > perform initialization for one i,j type pair</TD></TR>
<TR><TD >init_style</TD><TD > initialization specific to this pair style</TD></TR>
<TR><TD >write & read_restart</TD><TD > write/read i,j pair coeffs to restart files</TD></TR>
<TR><TD >write & read_restart_settings</TD><TD > write/read global settings to restart files</TD></TR>
<TR><TD >single</TD><TD > force and energy of a single pairwise interaction between 2 atoms</TD></TR>
<TR><TD >compute_inner/middle/outer</TD><TD > versions of compute used by rRESPA
</TD></TR></TABLE></DIV>
<P>The inner/middle/outer routines are optional.
</P>
<HR>
<A NAME = "region"></A><H4>Region styles
</H4>
<P>Classes that define geometric regions are derived from the Region
class. Regions are used elsewhere in LAMMPS to group atoms, delete
atoms to create a void, insert atoms in a specified region, etc. New
styles can be created to add new region shapes to LAMMPS.
</P>
<P>Region_sphere.cpp is an example of a spherical region.
</P>
<P>Here is a brief description of methods you define in your new derived
class. See region.h for details.
</P>
<DIV ALIGN=center><TABLE WIDTH="0%" BORDER=1 >
<TR><TD >match</TD><TD > determine whether a point is in the region
</TD></TR></TABLE></DIV>
<HR>
<A NAME = "thermo"></A><H4>Thermodynamic output options
</H4>
<P>There is one class that computes and prints thermodynamic information
to the screen and log file; see the file thermo.cpp.
</P>
<P>There are several styles defined in thermo.cpp: "one", "multi",
"granular", etc. There is also a flexible "custom" style which allows
the user to explicitly list keywords for quantities to print when
thermodynamic info is output. See the
<A HREF = "thermo_style.html">thermo_style</A> command for a list of defined
quantities.
</P>
<P>The thermo styles (one, multi, etc) are simply lists of keywords.
Adding a new style thus only requies defining a new list of keywords.
Search for the word "customize" with references to "thermo style" in
thermo.cpp to see the two locations where code will need to be added.
</P>
<P>New keywords can also be added to thermo.cpp to compute new quantities
for output. Search for the word "customize" with references to
"keyword" in thermo.cpp to see the several locations where code will
need to be added.
</P>
<P>Note that the <A HREF = "thermo.html">thermo_style custom</A> command already allows
for thermo output of quantities calculated by <A HREF = "fix.html">fixes</A>,
<A HREF = "compute.html">computes</A>, and <A HREF = "variable.html">variables</A>. Thus, it may
be simpler to compute what you wish via one of those constructs, than
by adding a new keyword to the thermo command.
</P>
<HR>
<A NAME = "variable"></A><H4>Variable options
</H4>
<P>There is one class that computes and stores <A HREF = "variable.html">variable</A>
information in LAMMPS; see the file variable.cpp. The value
associated with a variable can be periodically printed to the screen
via the <A HREF = "print.html">print</A>, <A HREF = "fix_print.html">fix print</A>, or
<A HREF = "thermo_style.html">thermo_style custom</A> commands. Variables of style
"equal" can compute complex equations that involve the following types
of arguments:
</P>
<P>thermo keywords = ke, vol, atoms, ...
other variables = v_a, v_myvar, ...
math functions = div(x,y), mult(x,y), add(x,y), ...
group functions = mass(group), xcm(group,x), ...
atom values = x<B>123</B>, y<B>3</B>, vx<B>34</B>, ...
compute values = c_mytemp<B>0</B>, c_thermo_press<B>3</B>, ...
</P>
<P>Adding keywords for the <A HREF = "themo_style.html">thermo_style custom</A> command
(which can then be accessed by variables) was discussed
<A HREF = "Section_modify.html#thermo">here</A> on this page.
</P>
<P>Adding a new math function of one or two arguments can be done by
editing one section of the Variable::evaulate() method. Search for
the word "customize" to find the appropriate location.
</P>
<P>Adding a new group function can be done by editing one section of the
Variable::evaulate() method. Search for the word "customize" to find
the appropriate location. You may need to add a new method to the
Group class as well (see the group.cpp file).
</P>
<P>Accessing a new atom-based vector can be done by editing one section
of the Variable::evaulate() method. Search for the word "customize"
to find the appropriate location.
</P>
<P>Adding new <A HREF = "compute.html">compute styles</A> (whose calculated values can
then be accessed by variables) was discussed
<A HREF = "Section_modify.html#compute">here</A> on this page.
</P>
<HR>
<HR>
<A NAME = "Foo"></A>
<P><B>(Foo)</B> Foo, Morefoo, and Maxfoo, J of Classic Potentials, 75, 345 (1997).
</P>
</HTML>