Page MenuHomec4science

Section_modify.txt
No OneTemporary

File Metadata

Created
Thu, Jul 25, 01:49

Section_modify.txt

"Previous Section"_Section_tools.html - "LAMMPS WWW Site"_lws -
"LAMMPS Documentation"_ld - "LAMMPS Commands"_lc - "Next
Section"_Section_errors.html :c
:link(lws,http://lammps.sandia.gov)
:link(ld,Manual.html)
:link(lc,Section_commands.html#comm)
:line
8. Modifying & extending LAMMPS :h3
LAMMPS is designed in a modular fashion so as to be easy to modify and
extend with new functionality. In this section, changes and additions
users can make are listed along with some minimal instructions.
Realistically, 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).
Most of the new features described in this section require you to
write a new C++ class (except for dump, thermo, and variable options,
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). Their contents are briefly discussed below.
Enabling LAMMPS to invoke the new class is as simple as adding two
definition lines to the style_user.h file, in the same syntax as the
existing LAMMPS classes are defined in the style.h file.
The power of C++ and its object-orientation is that usually, all the
code and variables needed to define the new feature are contained in
the 2 files you write, and thus shouldn't make the rest of the code
more complex or cause side-effect bugs.
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 "paper"_#Foo by Foo, et. al.
If you wish to invoke those potentials in a LAMMPS input script with a
command like
pair_style foo 0.1 3.5 :pre
you simply need to put your 2 files in the LAMMPS src directory, add 2
lines to the style_user.h file, and re-make the code.
The first line added to style_user.h would be
PairStyle(foo,PairFoo) :pre
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.
The 2nd line added to style_user.h would be
#include "pair_foo.h" :pre
in the #ifdef PairInclude section, where pair_foo.h is the name of
your new include file.
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.
Note that if you are using Makefile.list instead of Makefile to build
LAMMPS, you will need to explicitly add the names of your new .cpp and
.h file to Makefile.list.
Here is a list of the kinds of new features that can be added in this
way. The dump and thermo options do not typically require new styles;
LAMMPS can simply be recompiled after new code is added to
dump_custom.cpp or thermo_custom.cpp.
"Pairwise potentials"_#pair
"Bond, angle, dihedral, improper potentials"_#bond
"Dump options"_#dump
"Thermodynamic output options"_#thermo
"Temperature computation options"_#temp
"Region geometry options"_#region
"Fix options"_#fix which include integrators, \
temperature and pressure control, force constraints, \
boundary conditions, diagnostic output, etc
"Atom options"_#atom
"Variable options"_#variable
"New top-level commands"_#command :ul
As illustrated by the pairwise example, these options are
referred to in the LAMMPS documentation as the "style" of a particular
command.
The instructions below for each category will list the header file for
the parent class that these styles are sub-classes of. Public
variables in that file are ones used and set by the sub-classes which
are also used by the parent class. Sometimes they are also used by
the rest of LAMMPS. Virtual functions in the header file which are
set = 0 are ones you must define in your new class to give it the
functionality LAMMPS expects. Virtual functions that are not set to 0
are functions you can optionally define.
Here are some additional guidelines for modifying LAMMPS and adding
new functionality:
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.
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.
If your new feature reads arguments or writes output, make sure you
follow the unit conventions discussed by the "units"_units.html
command.
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
developers. We might be interested in adding it to the LAMMPS
distribution.
:line
Pairwise potentials :link(pair),h4
All classes that compute pairwise interactions are sub-classes of the
Pair class. See the pair.h file for a list of methods this class
defines.
Pair_lj_cut.cpp and pair_lj_cut.h are the simplest example of a Pair
class. They implement the {lj/cut} style of the
"pair_style"_pair_style.html command.
Here is a brief description of the class methods in pair.h:
compute: the workhorse routine that computes the pairwise interactions
settings: reads the input script line with any arguments you define
coeff: set coefficients for one i,j type pair
init_one: perform initialization for one i,j type pair
write & read_restart: write/read i,j pair coeffs to restart files
write & read_restart_settings: write/read global settings to restart files
single: force and energy of a single pairwise interaction between 2 atoms
compute_inner/middle/outer: versions of compute used by rRESPA :tb(s=:)
The inner/middle/outer routines are optional. Only a few of the
pairwise potentials use these in conjunction with rRESPA as set by the
"run_style"_run_style.html command.
:line
Bond, angle, dihedral, improper potentials :link(bond),h4
All classes that compute molecular interactions are sub-classes of the
Bond, Angle, Dihedral, and Improper classes. See the bond.h, angle.h,
dihedral.h, and improper.h file for a list of methods these classes
defines.
Bond_harmonic.cpp and bond_harmonic.h are the simplest example of a
Bond class. Ditto for the harmonic forms of the angle, dihedral, and
improper style commands. The bond_harmonic files implement the
{harmonic} style of the "bond_style"_bond_style.html command.
Here is a brief description of the class methods in bond.h, angle.h,
etc:
compute: the workhorse routine that computes the molecular interactions
coeff: set coefficients for one bond type
equilibrium_distance: length of bond, used by SHAKE
write & read_restart: writes/reads coeffs to restart files
single: force and energy of a single bond :tb(s=:)
:line
Dump options :link(dump),h4
There are several classes that print dump files (snapshots of atoms)
that are sub-classes of the Dump class. These include the
dump_atom.cpp, dump_bond.cpp, and dump_custom.cpp files.
New dump classes can be added, but it is typically simpler to modify
the DumpCustom class contained in the dump_custom.cpp file. See the
"dump"_dump.html command and its {custom} style for a list of what
atom information can already be dumped by DumpCustom. If the
attribute you want to dump is not in the list, or if you define a "new
atom style"_#atom with new attributes (e.g. atoms that store their own
magnetic moment), here is how to dump it out in a snapshot file:
Search the dump_custom.cpp and dump_custom.h files for the word
"customize". It appears in roughly half a dozen locations. In each
of the locations you can add a bit of code that will extend the
DumpCustom class to enable it to dump a new quantity. E.g. you will
add a keyword, add an if test, add a new small method that packs the
requested data into a buffer, etc. For the latter, you can perform a
modest amount of computation in this method; see the pack_xs()
function for an example.
If desired, a dump custom option can also compute more complicated
quantities by invoking a fix that computed quantities at the end of a
timestep (should be the same timestep the dump is invoked on). See
the ENERGY, CENTRO, and stress options (SXX, SYY, etc) in
dump_custom.cpp for examples.
When you re-make LAMMPS, your new option should now be useable via the
dump custom command.
:line
Thermodynamic output options :link(thermo),h4
There is only one class that computes and prints thermodynamic
information to the screen and log file, although the
"thermo_style"_thermo_style.html command treats its options as styles.
There are several styles defined in thermo.cpp: "one", "multi", and
"granular". There is also a flexible "custom" style which allows you
to specify what quantities will be printed each timestep where
thermodynamics is computed. See the "thermo_style"_thermo_style.html
command for a list of pre-defined quantities.
Here is how you can extend the thermo output capabilities. Search the
thermo.cpp and thermo.h files for the word "customize" which will tell
you where to make these additions. Note that fixes can also print-out
thermodynamic quantities via the "fix_modify"_fix_modify.html command,
so you do not need to modify thermo.cpp to print fix information.
If you want to create a new style (like "one" or "granular") that
prints a collection of pre-defined quantities, you add a few lines
that define the new style to thermo.cpp. First, add a #DEFINE line at
the top of the file which lists the quantities to print. Then add the
style name you have chosen to the if test in the constructor to copy
the defined string to the line[] variable.
You can also add new quantities to the custom list. Add your new
keyword to the if test in the parse_fields() function where the call
to addfield() specifies the text string (8 character max) that will be
printed with the quantity, the function that will compute it, and the
data type (INT,FLOAT) of the quantity. Then at the bottom of the
file, add a function compute_*() which computes the quantity you wish
to print. The function assigns the quantity to the variable "dvalue"
if it is a floating-point quantity, or to "ivalue" if it is an
integer. See the other compute_*() functions for examples of how
various quantities can be accessed, computed, summed across
processors, normalized as per-atom values, etc. Also, if it makes
sense to allow the quantity to be stored in a variable in the input
script, add a couple of lines to the compute_value() function that is
called when a variable is evaluated. Finally, add a prototype for
your new compute method to thermo.h.
:line
Temperature computation options :link(temp),h4
All classes that compute the temperature of the system are sub-classes
of the Temperature class. See the temperature.h file for a list of
methods these classes defines. Temperatures are computed by LAMMPS
when velocities are set, when thermodynamics are computed, and when
temperature is controlled by various thermostats like the "fix
nvt"_fix_nvt.html of "fix langevin"_fix_langevin.html commands.
Temp_full.cpp and temp_full.h are the simplest example of a
Temperature class. They implement the {full} style of the
"temperature"_temperature.html command.
Here is a brief description of the class methods in temperature.h:
init: setup the temperature computation
compute: compute and return temperature :tb(s=:)
:line
Region geometry options :link(region),h4
All classes that define geometric regions are sub-classes of the
Region class. See the region.h file for a list of methods these
classes defines. Regions are used elsewhere in LAMMPS to group atoms,
delete atoms to create a void, insert atoms in a specified region,
etc.
Region_sphere.cpp and region_sphere.h are the simplest example of a
Region class. They implement the {sphere} style of the
"region"_region.html command.
Here is a brief description of the single class method required:
match: determine whether a point is in the region :tb(s=:)
:line
Fix options :link(fix),h4
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 manipulation, and output, is a "fix". This includes
time integration (update of velocity and coordinates), force
constraints (SHAKE or walls), and diagnostics (compute a diffusion
coefficient). See the fix.h file for a list of methods these classes
defines.
There are dozens of fix options in LAMMPS; choose one as a template
that is similar to what you want to implement. They can be as simple
as zeroing out forces (see "fix enforce2d"_fix_enforce2d.html which
corresponds to the {enforce2d} style) or as complicated as applying
SHAKE constraints on bonds and angles (see "fix shake"_fix_shake.html
which corresponds to the {shake} style) which involves many extra
computations.
Here is a brief description of the class methods in fix.h:
setmask: determines when the fix is called during the timestep
init: initialization before a run
setup: called immediately before the 1st timestep
initial_integrate: called at very beginning of each timestep
pre_exchange: called before atom exchange on re-neighboring steps
pre_neighbor: called before neighbor list build
post_force: called after pair & molecular forces are computed
final_integrate: called at end of each timestep
end_of_step: called at very end of timestep
write_restart: dumps fix info to restart file
restart: uses info from restart file to re-initialize the fix
grow_arrays: allocate memory for atom-based arrays used by fix
copy_arrays: copy atom info when an atom migrates to a new processor
memory_usage: report memory used by fix
pack_exchange: store atom's data in a buffer
unpack_exchange: retrieve atom's data from a buffer
pack_restart: store atom's data for writing to restart file
unpack_restart: retrieve atom's data from a restart file buffer
size_restart: size of atom's data
maxsize_restart: max size of atom's data
initial_integrate_respa: same as initial_integrate, but for rRESPA
post_force_respa: same as post_force, but for rRESPA
final_integrate_respa: same as final_integrate, but for rRESPA
pack_comm: pack a buffer to communicate a per-atom quantity
unpack_comm: unpack a buffer to communicate a per-atom quantity
pack_reverse_comm: pack a buffer to reverse communicate a per-atom quantity
unpack_reverse_comm: unpack a buffer to reverse communicate a per-atom quantity
thermo_fields: define quantities for thermodynamic output
thermo_compute: compute thermodynamic quantities :tb(s=:)
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 ({nve}, {nvt}, {npt}) 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).
If the fix needs to store information for each atom that persists from
timestep to timestep, it can manage that memory and migrate it with
the atoms as they move from processors to processor by implementing
the grow_arrays, copy_arrays, pack_exchange, and unpack_exchange
methods. Similary, the pack_restart and unpack_restart methods can be
implemented to store information about the fix in restart files. If
you wish a integrator or force constraint fix to work with rRESPA (see
the "run_style"_run_style.html command), the initial_integrate,
post_force_integrate, and final_integrate_respa methods can be
implemented. The thermo_fields and thermo_compute methods enable a
fix to contribute values to thermodynamic output, as printed
quantities and/or to be summed to the potential energy of the system.
:line
Atom options :link(atom),h4
All classes that define an atom style are sub-classes of the Atom
class. See the atom.h file for a list of methods these classes
defines. The atom style determines what quantities are associated
with an atom in a LAMMPS simulation. If one of the existing atom
styles does not define all the arrays you need to store with an atom,
then a new atom class can be created.
Atom_atomic.cpp and atom_atomic.h are the simplest example of an Atom
class. They implement the {atomic} style of the
"atom_style"_atom_style.html command.
Here is a brief description of the class methods in atom.h:
copy: copy info for one atom to another atom's array location
pack_comm: store an atom's info in a buffer communicated every timestep
unpack_comm: retrieve an atom's info from the buffer
pack_reverse: store an atom's info in a buffer communicating partial forces
unpack_reverse: retrieve an atom's info from the buffer
pack_border: store an atom's info in a buffer communicated on neighbor re-builds
unpack_border: retrieve an atom's info from the buffer
pack_exchange: store all an atom's info to migrate to another processor
unpack_exchange: retrieve an atom's info from the buffer
:tb(s=:)
There are also several methods in atom.cpp you will need to augment
with information about your new atom class, following the patterns of
the other atom styles. These routines are so similar for all classes,
that it was simpler to just have one master routine for all classes.
constructor: create style variable and atom array ptrs to NULL
destructor: free memory for atom arrays
set_style: set style variable
check_style: check for pure style vs hybrid style
style2arg: convert style variables to keywords
grow: re-allocate atom arrays to longer lengths
unpack_data: parse atom lines from data file
create_one: create an individual atom of this style
size_restart: number of restart quantities associated with proc's atoms
pack_restart: pack atom quantities into a buffer
unpack_restart: unpack atom quantities from a buffer
memory_usage: memory allocated by atom arrays
:tb(s=:)
:line
Variable options :link(variable),h4
The variable class stores and evaluates input script variables $a, $b,
... $z, as described in "this section"_Section_commands.html#3_2.
{Equal}-style variables are defined by an equation that is evaulated
each time the variable is used. The equation can include functions,
vectors, keywords, and numbers as described in the
"variable"_variable.html command. The list of valid functions,
vectors, and keywords, can be extended by adding a few lines of code
to the evaluate() method at the end of the variable.cpp file. Search
for the word "customize" to find the correct locations for adding
code.
A new function (e.g. foo(arg1,arg2,...)) can be added in the section
that starts with the comment
// customize by adding function to this list and to if statement :pre
A new vector (e.g. q[]) can be added in the section that starts with
the comment
// customize by adding vector to this list and to if statement :pre
A new keyword (e.g. mysum) can be added in the section that starts with
the comment
// customize by adding keyword to this list and to if statement :pre
Note that keywords supported by the "thermo_style
custom"_themo_style.html command are evaluated by the thermo routines,
so do not need to be added to variable.cpp.
:line
New top-level commands :link(command),h4
It is possible to add a new command to a LAMMPS input script as
opposed to adding a new style to an existing command (atom_style,
pair_style, fix, etc). For example the create_atoms, read_data,
velocity, and run commands are all top-level LAMMPS commands that are
listed in the Command section of style.h. When such a command is
encountered in the LAMMPS input script, the topmost level of LAMMPS
(lammps.cpp) 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 the LAMMPS data structures.
Thus to add a new command, you simply need to add a *.cpp and *.h file
containing a single class:
command: operations performed by the new command :tb(s=:)
Of course, the new class can define other methods and variables that
it uses internally.
:line
:link(Foo)
[(Foo)] Foo, Morefoo, and Maxfoo, J of Classic Potentials, 75, 345 (1997).

Event Timeline