forked from lijiext/lammps
Merge pull request #2312 from akohlmey/developer-guide
Integrate text from developer.tex file to the manual
This commit is contained in:
commit
ded657120d
16
doc/Makefile
16
doc/Makefile
|
@ -54,7 +54,7 @@ DOXYFILES = $(shell sed -n -e 's/\#.*$$//' -e '/^ *INPUT \+=/,/^[A-Z_]\+ \+
|
|||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html create HTML doc pages in html dir"
|
||||
@echo " pdf create Developer.pdf and Manual.pdf in this dir"
|
||||
@echo " pdf create Manual.pdf in this dir"
|
||||
@echo " fetch fetch HTML and PDF files from LAMMPS web site"
|
||||
@echo " epub create ePUB format manual for e-book readers"
|
||||
@echo " mobi convert ePUB to MOBI format manual for e-book readers (e.g. Kindle)"
|
||||
|
@ -69,7 +69,7 @@ help:
|
|||
# ------------------------------------------
|
||||
|
||||
clean-all: clean
|
||||
rm -rf $(BUILDDIR)/docenv $(MATHJAX) $(BUILDDIR)/LAMMPS.mobi $(BUILDDIR)/LAMMPS.epub $(BUILDDIR)/Manual.pdf $(BUILDDIR)/Developer.pdf
|
||||
rm -rf $(BUILDDIR)/docenv $(MATHJAX) $(BUILDDIR)/LAMMPS.mobi $(BUILDDIR)/LAMMPS.epub $(BUILDDIR)/Manual.pdf
|
||||
|
||||
clean: clean-spelling
|
||||
rm -rf $(BUILDDIR)/html $(BUILDDIR)/epub $(BUILDDIR)/latex $(BUILDDIR)/doctrees $(BUILDDIR)/doxygen/xml $(BUILDDIR)/doxygen-warn.log $(BUILDDIR)/doxygen/Doxyfile $(SPHINXCONFIG)/conf.py
|
||||
|
@ -139,13 +139,6 @@ mobi: epub
|
|||
pdf: xmlgen $(VENV) $(SPHINXCONFIG)/conf.py $(ANCHORCHECK)
|
||||
@$(MAKE) $(MFLAGS) -C graphviz all
|
||||
@if [ "$(HAS_PDFLATEX)" == "NO" ] ; then echo "PDFLaTeX was not found! Please check README.md for further instructions" 1>&2; exit 1; fi
|
||||
@(\
|
||||
cd src/Developer; \
|
||||
pdflatex developer; \
|
||||
pdflatex developer; \
|
||||
mv developer.pdf ../../Developer.pdf; \
|
||||
cd ../../; \
|
||||
)
|
||||
@(\
|
||||
. $(VENV)/bin/activate ; env PYTHONWARNINGS= \
|
||||
sphinx-build $(SPHINXEXTRA) -b latex -c $(SPHINXCONFIG) -d $(BUILDDIR)/doctrees $(RSTDIR) latex ;\
|
||||
|
@ -175,12 +168,11 @@ pdf: xmlgen $(VENV) $(SPHINXCONFIG)/conf.py $(ANCHORCHECK)
|
|||
@rm -rf latex/USER
|
||||
@cp -r src/PDF latex/PDF
|
||||
@rm -rf latex/PDF/.[sg]*
|
||||
@echo "Build finished. Manual.pdf and Developer.pdf are in this directory."
|
||||
@echo "Build finished. Manual.pdf is in this directory."
|
||||
|
||||
fetch:
|
||||
@rm -rf html_www Manual_www.pdf Developer_www.pdf
|
||||
@rm -rf html_www Manual_www.pdf
|
||||
@curl -s -o Manual_www.pdf http://lammps.sandia.gov/doc/Manual.pdf
|
||||
@curl -s -o Developer_www.pdf http://lammps.sandia.gov/doc/Developer.pdf
|
||||
@curl -s -o lammps-doc.tar.gz http://lammps.sandia.gov/tars/lammps-doc.tar.gz
|
||||
@tar xzf lammps-doc.tar.gz
|
||||
@rm -f lammps-doc.tar.gz
|
||||
|
|
|
@ -471,7 +471,7 @@ LAMMPS source distribution.
|
|||
.. code-block:: bash
|
||||
|
||||
make html # create HTML doc pages in html directory
|
||||
make pdf # create Developer.pdf and Manual.pdf in this directory
|
||||
make pdf # create Manual.pdf in this directory
|
||||
make fetch # fetch HTML and PDF files from LAMMPS web site
|
||||
make clean # remove all intermediate files
|
||||
make clean-all # reset the entire doc build environment
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
/developer.aux
|
||||
/developer.log
|
||||
/developer.toc
|
|
@ -1,198 +0,0 @@
|
|||
#FIG 3.2 Produced by xfig version 3.2.5a
|
||||
Portrait
|
||||
Center
|
||||
Inches
|
||||
Letter
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2232 1170 3540 1170 3540 1505 2232 1505 2232 1170
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2220 1830 3015 1830 3015 2219 2220 2219 2220 1830
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2226 3285 3300 3285 3300 3665 2226 3665 2226 3285
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2223 5190 3225 5190 3225 5525 2223 5525 2223 5190
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2232 7125 3090 7125 3090 7478 2232 7478 2232 7125
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2226 10230 3300 10230 3300 10565 2226 10565 2226 10230
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4026 10305 4980 10305 4980 10592 4026 10592 4026 10305
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4029 9900 5205 9900 5205 10250 4029 10250 4029 9900
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4038 9315 5370 9315 5370 9659 4038 9659 4038 9315
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4023 8955 4530 8955 4530 9278 4023 9278 4023 8955
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4029 8475 5190 8475 5190 8762 4029 8762 4029 8475
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4008 8115 5430 8115 5430 8408 4008 8408 4008 8115
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4026 7425 4995 7425 4995 7712 4026 7712 4026 7425
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4035 6720 4650 6720 4650 7025 4035 7025 4035 6720
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4044 7080 4830 7080 4830 7358 4044 7358 4044 7080
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4032 6105 5205 6105 5205 6419 4032 6419 4032 6105
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4026 5715 5115 5715 5115 6062 4026 6062 4026 5715
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4023 3585 4605 3585 4605 3872 4023 3872 4023 3585
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
3954 1680 5175 1680 5175 1997 3954 1997 3954 1680
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
1620 5235 2100 615
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
1605 5445 2070 10695
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3120 1935 3855 1800
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3150 2115 3765 2250
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3135 7230 3945 6840
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3150 7335 3945 8610
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
5265 8610 6195 8400
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
5280 8655 6180 8820
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3345 10290 3930 10020
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3360 10395 3930 10425
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3360 10455 3930 10755
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2193 360 3435 360 3435 647 2193 647 2193 360
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3398 3472 3923 3307
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3413 3601 3923 3721
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3285 2806 3870 2802
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3315 5372 3900 5368
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
6354 2280 7470 2280 7470 2585 6354 2585 6354 2280
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
6348 1875 7320 1875 7320 2222 6348 2222 6348 1875
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
3954 2070 5505 2070 5505 2372 3954 2372 3954 2070
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
5634 2137 6230 2045
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
5670 2310 6265 2418
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
3900 2640 5400 2640 5400 2975 3900 2975 3900 2640
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4038 3165 5385 3165 5385 3497 4038 3497 4038 3165
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4245 4110 5730 4110 5730 4499 4245 4499 4245 4110
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4233 4545 6390 4545 6390 4862 4233 4862 4233 4545
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4026 5190 5385 5190 5385 5525 4026 5525 4026 5190
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4038 7755 5310 7755 5310 8075 4038 8075 4038 7755
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
6270 8250 7365 8250 7365 8610 6270 8610 6270 8250
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
6273 8655 7380 8655 7380 8978 6273 8978 6273 8655
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
4041 10620 5985 10620 5985 10943 4041 10943 4041 10620
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2217 10830 3135 10830 3135 11156 2217 11156 2217 10830
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2229 9780 3240 9780 3240 10118 2229 10118 2229 9780
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2214 9015 3285 9015 3285 9362 2214 9362 2214 9015
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2208 5850 3420 5850 3420 6209 2208 6209 2208 5850
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2217 4275 3615 4275 3615 4634 2217 4634 2217 4275
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2235 2655 3150 2655 3150 3000 2235 3000 2235 2655
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
60 5115 1500 5115 1500 5610 60 5610 60 5115
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3486 6018 4011 5853
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3486 6129 3996 6249
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3361 9291 3991 9531
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3345 9129 4005 9099
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3691 4412 4216 4277
|
||||
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
|
||||
1 1 2.00 120.00 240.00
|
||||
3695 4561 4175 4711
|
||||
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
|
||||
2220 735 3129 735 3129 1043 2220 1043 2220 735
|
||||
4 0 1 50 -1 18 18 0.0000 4 225 1275 2265 1455 Universe\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 285 735 2265 2175 Input\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 225 780 2265 2925 Atom\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 285 1020 2265 3600 Update\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 285 1320 2265 4575 Neighbor\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 225 945 2265 5475 Comm\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 225 1110 2265 6150 Domain\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 225 810 2265 7425 Force\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 285 975 2265 9300 Modify\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 285 900 2265 10050 Group\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 285 990 2265 10500 Output\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 225 825 2265 11100 Timer\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 225 1170 3990 1950 Variable\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 225 1470 3990 2325 Command\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 285 1275 4065 3450 Integrate\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 225 525 4065 3825 Min\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 285 1230 4065 5475 Irregular\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 285 1020 4065 6000 Region\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 225 975 4065 6375 Lattice\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 225 435 4065 9225 Fix\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 285 1305 4065 9600 Compute\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 225 570 4065 6975 Pair\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 285 840 4065 7665 Angle\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 225 1215 4065 8010 Dihedral\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 285 1305 4065 8355 Improper\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 285 1095 4065 8700 KSpace\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 285 855 4065 10545 Dump\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 225 1815 4065 10890 WriteRestart\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 225 930 6315 8550 FFT3D\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 285 1005 6315 8925 Remap\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 225 885 6390 2175 Finish\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 285 1050 6390 2550 Special\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 225 1305 3990 2925 AtomVec\001
|
||||
4 0 4 50 -1 18 18 0.0000 4 225 765 4065 7320 Bond\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 225 1095 4065 10200 Thermo\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 285 1380 4305 4425 NeighList\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 285 2025 4305 4800 NeighRequest\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 285 1155 2250 600 Memory\001
|
||||
4 0 0 50 -1 18 18 0.0000 4 225 1305 120 5475 LAMMPS\001
|
||||
4 0 1 50 -1 18 18 0.0000 4 225 735 2265 1005 Error\001
|
Binary file not shown.
|
@ -1,699 +0,0 @@
|
|||
\documentclass{article}
|
||||
\usepackage{graphicx}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\centerline{\Large \bf LAMMPS Developer Guide}
|
||||
\centerline{\bf 23 Aug 2011}
|
||||
|
||||
\vspace{0.5in}
|
||||
|
||||
This document is a developer guide to the LAMMPS molecular dynamics
|
||||
package, whose WWW site is at lammps.sandia.gov. It describes the
|
||||
internal structure and algorithms of the code. Sections will be added
|
||||
as we have time, and in response to requests from developers and
|
||||
users.
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\pagebreak
|
||||
\section{LAMMPS source files}
|
||||
|
||||
LAMMPS source files are in two directories of the distribution
|
||||
tarball. The src directory has the majority of them, all of which are
|
||||
C++ files (*.cpp and *.h). Many of these files are in the src
|
||||
directory itself. There are also dozens of ``packages'', which can be
|
||||
included or excluded when LAMMPS is built. See the
|
||||
doc/Section\_build.html section of the manual for more information
|
||||
about packages, or type ``make'' from within the src directory, which
|
||||
lists package-related commands, such as ``make package-status''. The
|
||||
source files for each package are in an all-uppercase sub-directory of
|
||||
src, like src/MOLECULE or src/USER-CUDA. If the package is currently
|
||||
installed, copies of the package source files will also exist in the
|
||||
src directory itself. The src/STUBS sub-directory is not a package
|
||||
but contains a dummy version of the MPI library, used when building a
|
||||
serial version of the code.
|
||||
|
||||
The lib directory also contains source code for external libraries,
|
||||
used by a few of the packages. Each sub-directory, like meam or gpu,
|
||||
contains the source files, some of which are in different languages
|
||||
such as Fortran. The files are compiled into libraries from within
|
||||
each sub-directory, e.g. performing a ``make'' in the lib/meam directory
|
||||
creates a libmeam.a file. These libraries are linked to during a
|
||||
LAMMPS build, if the corresponding package is installed.
|
||||
|
||||
LAMMPS C++ source files almost always come in pairs, such as run.cpp
|
||||
and run.h. The pair of files defines a C++ class, the Run class in
|
||||
this case, which contains the code invoked by the ``run'' command in a
|
||||
LAMMPS input script. As this example illustrates, source file and
|
||||
class names often have a one-to-one correspondence with a command used
|
||||
in a LAMMPS input script. Some source files and classes do not have a
|
||||
corresponding input script command, e.g. ``force.cpp'' and the Force
|
||||
class. They are discussed in the next section.
|
||||
|
||||
\pagebreak
|
||||
\section{Class hierarchy of LAMMPS}
|
||||
|
||||
Though LAMMPS has a lot of source files and classes, its class
|
||||
hierarchy is quite simple, as outlined in Fig \ref{fig:classes}. Each
|
||||
boxed name refers to a class and has a pair of associated source files
|
||||
in lammps/src, e.g. ``memory.cpp'' and ``memory.h''. More details on the
|
||||
class and its methods and data structures can be found by examining
|
||||
its *.h file.
|
||||
|
||||
LAMMPS (lammps.cpp/h) is the top-level class for the entire code. It
|
||||
holds an ``instance'' of LAMMPS and can be instantiated one or more
|
||||
times by a calling code. For example, the file src/main.cpp simply
|
||||
instantiates one instance of LAMMPS and passes it the input script.
|
||||
|
||||
The file src/library.cpp contains a C-style library interface to the
|
||||
LAMMPS class. See the lammps/couple and lammps/python directories for
|
||||
examples of simple programs that use LAMMPS through its library
|
||||
interface. A driver program can instantiate the LAMMPS class multiple
|
||||
times, e.g. to embed several atomistic simulation regions within a
|
||||
mesoscale or continuum simulation domain.
|
||||
|
||||
There are a dozen or so top-level classes within the LAMMPS class that
|
||||
are visible everywhere in the code. They are shaded blue in Fig
|
||||
\ref{fig:classes}. Thus any class can refer to the y-coordinate of
|
||||
local atom $I$ as atom$\rightarrow$x[i][1]. This visibility is
|
||||
enabled by a bit of cleverness in the Pointers class (see
|
||||
src/pointers.h) which every class inherits from.
|
||||
|
||||
There are a handful of virtual parent classes in LAMMPS that define
|
||||
what LAMMPS calls ``styles''. They are shaded red in Fig
|
||||
\ref{fig:classes}. Each of these are parents of a number of child
|
||||
classes that implement the interface defined by the parent class. For
|
||||
example, the fix style has around 100 child classes. They are the
|
||||
possible fixes that can be specified by the fix command in an input
|
||||
script, e.g. fix nve, fix shake, fix ave/time, etc. The corresponding
|
||||
classes are Fix (for the parent class), FixNVE, FixShake, FixAveTime,
|
||||
etc. The source files for these classes are easy to identify in the
|
||||
src directory, since they begin with the word ``fix'', e,g,
|
||||
fix\_nve.cpp, fix\_shake,cpp, fix\_ave\_time.cpp, etc.
|
||||
|
||||
The one exception is child class files for the ``command'' style. These
|
||||
implement specific commands in the input script that can be invoked
|
||||
before/after/between runs or which launch a simulation. Examples are
|
||||
the create\_box, minimize, run, and velocity commands which encode the
|
||||
CreateBox, Minimize, Run, and Velocity classes. The corresponding
|
||||
files are create\_box,cpp, minimize.cpp, run.cpp, and velocity.cpp.
|
||||
The list of command style files can be found by typing ``grep
|
||||
COMMAND\_CLASS *.h'' from within the src directory, since that word in
|
||||
the header file identifies the class as an input script command.
|
||||
Similar words can be grepped to list files for the other LAMMPS
|
||||
styles. E.g. ATOM\_CLASS, PAIR\_CLASS, BOND\_CLASS, REGION\_CLASS,
|
||||
FIX\_CLASS, COMPUTE\_CLASS, DUMP\_CLASS, etc.
|
||||
|
||||
\begin{figure}[htb]
|
||||
\begin{center}
|
||||
\includegraphics[height=4in]{classes.pdf}
|
||||
\end{center}
|
||||
\caption{Class hierarchy within LAMMPS source code.}
|
||||
\label{fig:classes}
|
||||
\end{figure}
|
||||
|
||||
More details on individual classes in Fig \ref{fig:classes} are as
|
||||
follows:
|
||||
|
||||
\begin{itemize}
|
||||
|
||||
\item The Memory class handles allocation of all large vectors and
|
||||
arrays.
|
||||
|
||||
\item The Error class prints all error and warning messages.
|
||||
|
||||
\item The Universe class sets up partitions of processors so that
|
||||
multiple simulations can be run, each on a subset of the processors
|
||||
allocated for a run, e.g. by the mpirun command.
|
||||
|
||||
\item The Input class reads an input script, stores variables, and
|
||||
invokes stand-alone commands that are child classes of the Command
|
||||
class.
|
||||
|
||||
\item As discussed above, the Command class is a parent class for
|
||||
certain input script commands that perform a one-time operation
|
||||
before/after/between simulations or which invoke a simulation. They
|
||||
are instantiated from within the Input class, invoked, then
|
||||
immediately destructed.
|
||||
|
||||
\item The Finish class is instantiated to print statistics to the
|
||||
screen after a simulation is performed, by commands like run and
|
||||
minimize.
|
||||
|
||||
\item The Special class walks the bond topology of a molecular system
|
||||
to find first, second, third neighbors of each atom. It is invoked by
|
||||
several commands, like read\_data, read\_restart, and replicate.
|
||||
|
||||
\item The Atom class stores all per-atom arrays. More precisely, they
|
||||
are allocated and stored by the AtomVec class, and the Atom class
|
||||
simply stores a pointer to them. The AtomVec class is a parent
|
||||
class for atom styles, defined by the atom\_style command.
|
||||
|
||||
\item The Update class holds an integrator and a minimizer. The
|
||||
Integrate class is a parent style for the Verlet and rRESPA time
|
||||
integrators, as defined by the run\_style input command. The Min
|
||||
class is a parent style for various energy minimizers.
|
||||
|
||||
\item The Neighbor class builds and stores neighbor lists. The
|
||||
NeighList class stores a single list (for all atoms). The
|
||||
NeighRequest class is called by pair, fix, or compute styles when
|
||||
they need a particular kind of neighbor list.
|
||||
|
||||
\item The Comm class performs interprocessor communication, typically
|
||||
of ghost atom information. This usually involves MPI message
|
||||
exchanges with 6 neighboring processors in the 3d logical grid of
|
||||
processors mapped to the simulation box. Sometimes the Irregular
|
||||
class is used, when atoms may migrate to arbitrary processors.
|
||||
|
||||
\item The Domain class stores the simulation box geometry, as well as
|
||||
geometric Regions and any user definition of a Lattice. The latter
|
||||
are defined by region and lattice commands in an input script.
|
||||
|
||||
\item The Force class computes various forces between atoms. The Pair
|
||||
parent class is for non-bonded or pair-wise forces, which in LAMMPS
|
||||
lingo includes many-body forces such as the Tersoff 3-body
|
||||
potential. The Bond, Angle, Dihedral, Improper parent classes are
|
||||
styles for bonded interactions within a static molecular topology.
|
||||
The KSpace parent class is for computing long-range Coulombic
|
||||
interactions. One of its child classes, PPPM, uses the FFT3D and
|
||||
Remap classes to communicate grid-based information with neighboring
|
||||
processors.
|
||||
|
||||
\item The Modify class stores lists of Fix and Compute classes, both
|
||||
of which are parent styles.
|
||||
|
||||
\item The Group class manipulates groups that atoms are assigned to
|
||||
via the group command. It also computes various attributes of
|
||||
groups of atoms.
|
||||
|
||||
\item The Output class is used to generate 3 kinds of output from a
|
||||
LAMMPS simulation: thermodynamic information printed to the screen
|
||||
and log file, dump file snapshots, and restart files. These
|
||||
correspond to the Thermo, Dump, and WriteRestart classes
|
||||
respectively. The Dump class is a parent style.
|
||||
|
||||
\item The Timer class logs MPI timing information, output at the end
|
||||
of a run.
|
||||
|
||||
\end{itemize}
|
||||
|
||||
%%\pagebreak
|
||||
%%\section{Spatial decomposition and parallel operations}
|
||||
%%distributed memory
|
||||
%%Ref to JCP paper
|
||||
%%diagram of 3d grid of procs and spatial decomp
|
||||
%%6-way comm
|
||||
%%ghost atoms, PBC added when comm (in atom class)
|
||||
|
||||
%%\pagebreak
|
||||
%%\section{Fixes, computes, variables}
|
||||
%%fixes intercolate in timestep, store per-atom info
|
||||
%%computes based on current snapshot
|
||||
%%equal- and atom-style variables
|
||||
%%output they produce - see write-up in HowTo
|
||||
|
||||
\pagebreak
|
||||
\section{How a timestep works}
|
||||
|
||||
The first and most fundamental operation within LAMMPS to understand
|
||||
is how a timestep is structured. Timestepping is performed by the
|
||||
Integrate class within the Update class. Since Integrate is a parent
|
||||
class, corresponding to the run\_style input script command, it has
|
||||
child classes. In this section, the timestep implemented by the
|
||||
Verlet child class is described. A similar timestep is implemented by
|
||||
the Respa child class, for the rRESPA hierarchical timestepping
|
||||
method. The Min parent class performs energy minimization, so does
|
||||
not perform a literal timestep. But it has logic similar to what is
|
||||
described here, to compute forces and invoke fixes at each iteration
|
||||
of a minimization. Differences between time integration and
|
||||
minimization are highlighted at the end of this section.
|
||||
|
||||
The Verlet class is encoded in the src/verlet.cpp and verlet.h files.
|
||||
It implements the velocity-Verlet timestepping algorithm. The
|
||||
workhorse method is Verlet::run(), but first we highlight several
|
||||
other methods in the class.
|
||||
|
||||
\begin{itemize}
|
||||
|
||||
\item The init() method is called at the beginning of each dynamics
|
||||
run. It simply sets some internal flags, based on user settings in
|
||||
other parts of the code.
|
||||
|
||||
\item The setup() or setup\_minimal() methods are also called before
|
||||
each run. The velocity-Verlet method requires current forces be
|
||||
calculated before the first timestep, so these routines compute
|
||||
forces due to all atomic interactions, using the same logic that
|
||||
appears in the timestepping described next. A few fixes are also
|
||||
invoked, using the mechanism described in the next section. Various
|
||||
counters are also initialized before the run begins. The
|
||||
setup\_minimal() method is a variant that has a flag for performing
|
||||
less setup. This is used when runs are continued and information
|
||||
from the previous run is still valid. For example, if repeated
|
||||
short LAMMPS runs are being invoked, interleaved by other commands,
|
||||
via the ``pre no'' and ``every'' options of the run command, the
|
||||
setup\_minimal() method is used.
|
||||
|
||||
\item The force\_clear() method initializes force and other arrays to
|
||||
zero before each timestep, so that forces (torques, etc) can be
|
||||
accumulated.
|
||||
|
||||
\end{itemize}
|
||||
|
||||
Now for the Verlet::run() method. Its structure in hi-level pseudo
|
||||
code is shown in Fig \ref{fig:verlet}. In the actual code in
|
||||
src/verlet.cpp some of these operations are conditionally invoked.
|
||||
|
||||
\begin{figure}[htb]
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
loop over N timesteps:
|
||||
ev_set()
|
||||
|
||||
fix->initial_integrate()
|
||||
fix->post_integrate()
|
||||
|
||||
nflag = neighbor->decide()
|
||||
if nflag:
|
||||
fix->pre_exchange()
|
||||
domain->pbc()
|
||||
domain->reset_box()
|
||||
comm->setup()
|
||||
neighbor->setup_bins()
|
||||
comm->exchange()
|
||||
comm->borders()
|
||||
fix->pre_neighbor()
|
||||
neighbor->build()
|
||||
else
|
||||
comm->forward_comm()
|
||||
|
||||
force_clear()
|
||||
fix->pre_force()
|
||||
|
||||
pair->compute()
|
||||
bond->compute()
|
||||
angle->compute()
|
||||
dihedral->compute()
|
||||
improper->compute()
|
||||
kspace->compute()
|
||||
|
||||
comm->reverse_comm()
|
||||
|
||||
fix->post_force()
|
||||
fix->final_integrate()
|
||||
fix->end_of_step()
|
||||
|
||||
if any output on this step: output->write()
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
\caption{Pseudo-code for the Verlet::run() method.}
|
||||
\label{fig:verlet}
|
||||
\end{figure}
|
||||
|
||||
The ev\_set() method (in the parent Integrate class), sets two flags
|
||||
({\em eflag} and {\em vflag}) for energy and virial computation. Each
|
||||
flag encodes whether global and/or per-atom energy and virial should
|
||||
be calculated on this timestep, because some fix or variable or output
|
||||
will need it. These flags are passed to the various methods that
|
||||
compute particle interactions, so that they can skip the extra
|
||||
calculations if the energy and virial are not needed. See the
|
||||
comments with the Integrate::ev\_set() method which document the flag
|
||||
values.
|
||||
|
||||
At various points of the timestep, fixes are invoked,
|
||||
e.g. fix$\rightarrow$initial\_integrate(). In the code, this is
|
||||
actually done via the Modify class which stores all the Fix objects
|
||||
and lists of which should be invoked at what point in the timestep.
|
||||
Fixes are the LAMMPS mechanism for tailoring the operations of a
|
||||
timestep for a particular simulation. As described elsewhere
|
||||
(unwritten section), each fix has one or more methods, each of which
|
||||
is invoked at a specific stage of the timestep, as in Fig
|
||||
\ref{fig:verlet}. All the fixes defined in an input script with an
|
||||
initial\_integrate() method are invoked at the beginning of each
|
||||
timestep. Fix nve, nvt, npt are examples, since they perform the
|
||||
start-of-timestep velocity-Verlet integration to update velocities by
|
||||
a half-step, and coordinates by a full step. The post\_integrate()
|
||||
method is next. Only a few fixes use this, e.g. to reflect particles
|
||||
off box boundaries in the FixWallReflect class.
|
||||
|
||||
The decide() method in the Neighbor class determines whether neighbor
|
||||
lists need to be rebuilt on the current timestep. If not, coordinates
|
||||
of ghost atoms are acquired by each processor via the forward\_comm()
|
||||
method of the Comm class. If neighbor lists need to be built, several
|
||||
operations within the inner if clause of Fig \ref{fig:verlet} are
|
||||
first invoked. The pre\_exchange() method of any defined fixes is
|
||||
invoked first. Typically this inserts or deletes particles from the
|
||||
system.
|
||||
|
||||
Periodic boundary conditions are then applied by the Domain class via
|
||||
its pbc() method to remap particles that have moved outside the
|
||||
simulation box back into the box. Note that this is not done every
|
||||
timestep. but only when neighbor lists are rebuilt. This is so that
|
||||
each processor's sub-domain will have consistent (nearby) atom
|
||||
coordinates for its owned and ghost atoms. It is also why dumped atom
|
||||
coordinates can be slightly outside the simulation box.
|
||||
|
||||
The box boundaries are then reset (if needed) via the reset\_box()
|
||||
method of the Domain class, e.g. if box boundaries are shrink-wrapped
|
||||
to current particle coordinates. A change in the box size or shape
|
||||
requires internal information for communicating ghost atoms (Comm
|
||||
class) and neighbor list bins (Neighbor class) be updated. The
|
||||
setup() method of the Comm class and setup\_bins() method of the
|
||||
Neighbor class perform the update.
|
||||
|
||||
The code is now ready to migrate atoms that have left a processor's
|
||||
geometric sub-domain to new processors. The exchange() method of the
|
||||
Comm class performs this operation. The borders() method of the Comm
|
||||
class then identifies ghost atoms surrounding each processor's
|
||||
sub-domain and communicates ghost atom information to neighboring
|
||||
processors. It does this by looping over all the atoms owned by a
|
||||
processor to make lists of those to send to each neighbor processor.
|
||||
On subsequent timesteps, the lists are used by the
|
||||
Comm::forward\_comm() method.
|
||||
|
||||
Fixes with a pre\_neighbor() method are then called. These typically
|
||||
re-build some data structure stored by the fix that depends on the
|
||||
current atoms owned by each processor.
|
||||
|
||||
Now that each processor has a current list of its owned and ghost
|
||||
atoms, LAMMPS is ready to rebuild neighbor lists via the build()
|
||||
method of the Neighbor class. This is typically done by binning all
|
||||
owned and ghost atoms, and scanning a stencil of bins around each
|
||||
owned atom's bin to make a Verlet list of neighboring atoms within the
|
||||
force cutoff plus neighbor skin distance.
|
||||
|
||||
In the next portion of the timestep, all interaction forces between
|
||||
particles are computed, after zeroing the per-atom force vector via
|
||||
the force\_clear() method. If the newton flag is set to ``on'' by the
|
||||
newton command, forces on both owned and ghost atoms are calculated.
|
||||
|
||||
Pairwise forces are calculated first, which enables the global virial
|
||||
(if requested) to be calculated cheaply (at the end of the
|
||||
Pair::compute() method), by a dot product of atom coordinates and
|
||||
forces. By including owned and ghost atoms in the dot product, the
|
||||
effect of periodic boundary conditions is correctly accounted for.
|
||||
Molecular topology interactions (bonds, angles, dihedrals, impropers)
|
||||
are calculated next. The final contribution is from long-range
|
||||
Coulombic interactions, invoked by the KSpace class.
|
||||
|
||||
If the newton flag is on, forces on ghost atoms are communicated and
|
||||
summed back to their corresponding owned atoms. The reverse\_comm()
|
||||
method of the Comm class performs this operation, which is essentially
|
||||
the inverse operation of sending copies of owned atom coordinates to
|
||||
other processor's ghost atoms.
|
||||
|
||||
At this point in the timestep, the total force on each atom is known.
|
||||
Additional force constraints (external forces, SHAKE, etc) are applied
|
||||
by Fixes that have a post\_force() method. The second half of the
|
||||
velocity-Verlet integration is then performed (another half-step
|
||||
update of the velocities) via fixes like nve, nvt, npt.
|
||||
|
||||
At the end of the timestep, fixes that define an end\_of\_step()
|
||||
method are invoked. These typically perform a diagnostic calculation,
|
||||
e.g. the ave/time and ave/spatial fixes. The final operation of the
|
||||
timestep is to perform any requested output, via the write() method of
|
||||
the Output class. There are 3 kinds of LAMMPS output: thermodynamic
|
||||
output to the screen and log file, snapshots of atom data to a dump
|
||||
file, and restart files. See the thermo\_style, dump, and restart
|
||||
commands for more details.
|
||||
|
||||
The iteration performed by an energy minimization is similar to the
|
||||
dynamics timestep of Fig \ref{fig:verlet}. Forces are computed,
|
||||
neighbor lists are built as needed, atoms migrate to new processors,
|
||||
and atom coordinates and forces are communicated to neighboring
|
||||
processors. The only difference is what Fix class operations are
|
||||
invoked when. Only a subset of LAMMPS fixes are useful during energy
|
||||
minimization, as explained in their individual doc pages. The
|
||||
relevant Fix class methods are min\_pre\_exchange(),
|
||||
min\_pre\_force(), and min\_post\_force(). Each is invoked at the
|
||||
appropriate place within the minimization iteration. For example, the
|
||||
min\_post\_force() method is analogous to the post\_force() method for
|
||||
dynamics; it is used to alter or constrain forces on each atom, which
|
||||
affects the minimization procedure.
|
||||
|
||||
\pagebreak
|
||||
\section{Extending LAMMPS}
|
||||
|
||||
The Section\_modify.html file in the doc directory of
|
||||
the LAMMPS distribution gives an overview of how LAMMPS can
|
||||
be extended by writing new classes that derive from existing
|
||||
parent classes in LAMMPS. Here, some specific coding
|
||||
details are provided for writing a new fix.
|
||||
|
||||
\subsection{New fixes}
|
||||
|
||||
(this section provided by Kirill Lykov)
|
||||
\vspace{0.25cm}
|
||||
|
||||
Writing fixes is a flexible way of extending LAMMPS. Users can
|
||||
implement many things using fixes:
|
||||
|
||||
\begin{itemize}
|
||||
\item changing particles attributes (positions, velocities, forces, etc.).
|
||||
Example: FixFreeze.
|
||||
\item reading/writing data. Example: FixRestart.
|
||||
\item implementing boundary conditions. Example: FixWall.
|
||||
\item saving information about particles for future use (previous positions,
|
||||
for instance). Example: FixStoreState.
|
||||
\end{itemize}
|
||||
|
||||
All fixes are derived from class Fix and must have constructor with the
|
||||
signature: FixMine(class LAMMPS *, int, char **).
|
||||
|
||||
Every fix must be registered in LAMMPS by writing the following lines
|
||||
of code in the header before include guards:
|
||||
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
#ifdef FIX_CLASS
|
||||
FixStyle(your/fix/name,FixMine)
|
||||
#else
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
|
||||
Where ``your/fix/name'' is a name of your fix in the script and FixMine
|
||||
is the name of the class. This code allows LAMMPS to find your fix
|
||||
when it parses input script. In addition, your fix header must be
|
||||
included in the file ``style\_fix.h''. In case if you use LAMMPS make,
|
||||
this file is generated automatically - all files starting with prefix
|
||||
fix\_ are included, so call your header the same way. Otherwise, don't
|
||||
forget to add your include into ``style\_fix.h''.
|
||||
|
||||
Let's write a simple fix which will print average velocity at the end
|
||||
of each timestep. First of all, implement a constructor:
|
||||
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
FixPrintVel::FixPrintVel(LAMMPS *lmp, int narg, char **arg)
|
||||
: Fix(lmp, narg, arg)
|
||||
{
|
||||
if (narg < 4)
|
||||
error->all(FLERR,"Illegal fix print command");
|
||||
|
||||
nevery = atoi(arg[3]);
|
||||
if (nevery <= 0)
|
||||
error->all(FLERR,"Illegal fix print command");
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
|
||||
In the constructor you should parse your fix arguments which are
|
||||
specified in the script. All fixes have pretty the same syntax: fix
|
||||
[fix\_identifier] [group\_name] [fix\_name] [fix\_arguments]. The
|
||||
first 3 parameters are parsed by Fix class constructor, while
|
||||
[fix\_arguments] should be parsed by you. In our case, we need to
|
||||
specify how often we want to print an average velocity. For instance,
|
||||
once in 50 timesteps: fix 1 print/vel 50. There is a special variable
|
||||
in Fix class called nevery which specifies how often method
|
||||
end\_of\_step() is called. Thus all we need to do is just set it up.
|
||||
|
||||
The next method we need to implement is setmask():
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
int FixPrintVel::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= FixConst::END_OF_STEP;
|
||||
return mask;
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
|
||||
Here user specifies which methods of your fix should be called during
|
||||
the execution. For instance, END\_OF\_STEP corresponds to the
|
||||
end\_of\_step() method. Overall, there are 8 most important methods,
|
||||
methods are called in predefined order during the execution of the
|
||||
verlet algorithm as was mentioned in the Section 3:
|
||||
|
||||
\begin{itemize}
|
||||
\item initial\_integrate()
|
||||
\item post\_integrate()
|
||||
\item pre\_exchange()
|
||||
\item pre\_neighbor()
|
||||
\item pre\_force()
|
||||
\item post\_force()
|
||||
\item final\_integrate()
|
||||
\item end\_of\_step()
|
||||
\end{itemize}
|
||||
|
||||
Fix developer must understand when he wants to execute his code. In
|
||||
case if we want to write FixPrintVel, we need only end\_of\_step():
|
||||
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
void FixPrintVel::end_of_step()
|
||||
{
|
||||
// for add3, scale3
|
||||
using namespace MathExtra;
|
||||
|
||||
double** v = atom->v;
|
||||
int nlocal = atom->nlocal;
|
||||
double localAvgVel[4]; // 4th element for particles count
|
||||
memset(localAvgVel, 0, 4 * sizeof(double));
|
||||
for (int particleInd = 0; particleInd < nlocal; ++particleInd) {
|
||||
add3(localAvgVel, v[particleInd], localAvgVel);
|
||||
}
|
||||
localAvgVel[3] = nlocal;
|
||||
double globalAvgVel[4];
|
||||
memset(globalAvgVel, 0, 4 * sizeof(double));
|
||||
MPI_Allreduce(localAvgVel, globalAvgVel, 4, MPI_DOUBLE, MPI_SUM, world);
|
||||
scale3(1.0 / globalAvgVel[3], globalAvgVel);
|
||||
if (comm->me == 0) {
|
||||
printf("\%e, \%e, \%e\n",
|
||||
globalAvgVel[0], globalAvgVel[1], globalAvgVel[2]);
|
||||
}
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
|
||||
In the code above, we use MathExtra routines defined in
|
||||
``math\_extra.h''. There are bunch of math functions to work with
|
||||
arrays of doubles as with math vectors.
|
||||
|
||||
In this code we use an instance of Atom class. This object is stored
|
||||
in the Pointers class (see ``pointers.h''). This object contains all
|
||||
global information about the simulation system. Data from Pointers
|
||||
class available to all classes inherited from it using protected
|
||||
inheritance. Hence when you write you own class, which is going to use
|
||||
LAMMPS data, don't forget to inherit from Pointers. When writing
|
||||
fixes we inherit from class Fix which is inherited from Pointers so
|
||||
there is no need to inherit from it directly.
|
||||
|
||||
The code above computes average velocity for all particles in the
|
||||
simulation. Yet you have one unused parameter in fix call from the
|
||||
script - [group\_name]. This parameter specifies the group of atoms
|
||||
used in the fix. So we should compute average for all particles in the
|
||||
simulation if group\_name == all, but it can be any group. The group
|
||||
information is specified by groupbit which is defined in class Fix:
|
||||
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
for (int particleInd = 0; particleInd < nlocal; ++particleInd) {
|
||||
if (atom->mask[particleInd] & groupbit) {
|
||||
//Do all job here
|
||||
}
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
|
||||
Class Atom encapsulates atoms positions, velocities, forces, etc. User
|
||||
can access them using particle index. Note, that particle indexes are
|
||||
usually changed every timestep because of sorting.
|
||||
|
||||
Lets consider another Fix example. We want to have a fix which stores
|
||||
atoms position from previous time step in your fix. The local atoms
|
||||
indexes will not be valid on the next iteration. In order to handle
|
||||
this situation there are several methods which should be implemented:
|
||||
|
||||
\begin{itemize}
|
||||
\item \verb|double memory_usage| - return how much memory fix uses
|
||||
\item \verb|void grow_arrays(int)| - do reallocation of the per particle arrays
|
||||
in your fix
|
||||
\item \verb|void copy_arrays(int i, int j, int delflag)| - copy i-th per-particle
|
||||
information to j-th. Used when atoms sorting is performed. if delflag is set
|
||||
and atom j owns a body, move the body information to atom i.
|
||||
\item \verb|void set_arrays(int i)| - sets i-th particle related information to zero
|
||||
\end{itemize}
|
||||
|
||||
Note, that if your class implements these methods, it must call add calls of
|
||||
add\_callback and delete\_callback to constructor and destructor:
|
||||
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
FixSavePos::FixSavePos(LAMMPS *lmp, int narg, char **arg) {
|
||||
//...
|
||||
atom->add_callback(0);
|
||||
}
|
||||
|
||||
FixSavePos::~FixSavePos() {
|
||||
atom->delete_callback(id, 0);
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
|
||||
Since we want to store positions of atoms from previous timestep, we
|
||||
need to add double** x to the header file. Than add allocation code to
|
||||
constructor:
|
||||
|
||||
\verb|memory->create(this->x, atom->nmax, 3, "FixSavePos:x");|. Free memory
|
||||
at destructor: \verb|memory->destroy(x);|
|
||||
|
||||
Finally, implement mentioned methods:
|
||||
|
||||
\begin{center}
|
||||
\begin{verbatim}
|
||||
double FixSavePos::memory_usage()
|
||||
{
|
||||
int nmax = atom->nmax;
|
||||
double bytes = 0.0;
|
||||
bytes += nmax * 3 * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void FixSavePos::grow_arrays(int nmax)
|
||||
{
|
||||
memory->grow(this->x, nmax, 3, "FixSavePos:x");
|
||||
}
|
||||
|
||||
void FixSavePos::copy_arrays(int i, int j, int delflag)
|
||||
{
|
||||
memcpy(this->x[j], this->x[i], sizeof(double) * 3);
|
||||
}
|
||||
|
||||
void FixSavePos::set_arrays(int i)
|
||||
{
|
||||
memset(this->x[i], 0, sizeof(double) * 3);
|
||||
}
|
||||
|
||||
int FixSavePos::pack_exchange(int i, double *buf)
|
||||
{
|
||||
int m = 0;
|
||||
buf[m++] = x[i][0];
|
||||
buf[m++] = x[i][1];
|
||||
buf[m++] = x[i][2];
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
int FixSavePos::unpack_exchange(int nlocal, double *buf)
|
||||
{
|
||||
int m = 0;
|
||||
x[nlocal][0] = buf[m++];
|
||||
x[nlocal][1] = buf[m++];
|
||||
x[nlocal][2] = buf[m++];
|
||||
|
||||
return m;
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{center}
|
||||
|
||||
Now, a little bit about memory allocation. We used Memory class which
|
||||
is just a bunch of template functions for allocating 1D and 2D
|
||||
arrays. So you need to add include ``memory.h'' to have access to them.
|
||||
|
||||
Finally, if you need to write/read some global information used in
|
||||
your fix to the restart file, you might do it by setting flag
|
||||
restart\_global = 1 in the constructor and implementing methods void
|
||||
write\_restart(FILE *fp) and void restart(char *buf).
|
||||
|
||||
\end{document}
|
|
@ -23,7 +23,6 @@ this Intr are included in this list.
|
|||
* `Mail list <https://lammps.sandia.gov/mail.html>`_
|
||||
* `Workshops <https://lammps.sandia.gov/workshops.html>`_
|
||||
* `Tutorials <https://lammps.sandia.gov/tutorials.html>`_
|
||||
* `Developer guide <https://lammps.sandia.gov/Developer.pdf>`_
|
||||
|
||||
* `Pre- and post-processing tools for LAMMPS <https://lammps.sandia.gov/prepost.html>`_
|
||||
* `Other software usable with LAMMPS <https://lammps.sandia.gov/offsite.html>`_
|
||||
|
|
|
@ -27,8 +27,7 @@ all LAMMPS development is coordinated.
|
|||
The content for this manual is part of the LAMMPS distribution. You
|
||||
can build a local copy of the Manual as HTML pages or a PDF file, by
|
||||
following the steps on the :doc:`Manual build <Manual_build>` doc page.
|
||||
There is also a `Developer.pdf <Developer.pdf>`_ document which gives
|
||||
a brief description of the basic code structure of LAMMPS.
|
||||
The manual is split into two parts: 1) User documentation and 2) Programmer documentation.
|
||||
|
||||
----------
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ files. Here is a list with descriptions:
|
|||
lammps.1 # man page for the lammps command
|
||||
msi2lmp.1 # man page for the msi2lmp command
|
||||
Manual.pdf # large PDF version of entire manual
|
||||
Developer.pdf # small PDF with info about how LAMMPS is structured
|
||||
LAMMPS.epub # Manual in ePUB e-book format
|
||||
LAMMPS.mobi # Manual in MOBI e-book format
|
||||
docenv # virtualenv folder for processing the manual sources
|
||||
|
@ -35,7 +34,7 @@ of two ways:
|
|||
|
||||
a. You can "fetch" the current HTML and PDF files from the LAMMPS web
|
||||
site. Just type ``make fetch``. This should download a html_www
|
||||
directory and Manual_www.pdf/Developer_www.pdf files. Note that if
|
||||
directory and a Manual_www.pdf file. Note that if
|
||||
new LAMMPS features have been added more recently than the date of
|
||||
your LAMMPS version, the fetched documentation will include those
|
||||
changes (but your source code will not, unless you update your local
|
||||
|
@ -49,6 +48,11 @@ b. You can build the HTML or PDF files yourself, by typing ``make html``
|
|||
only once, unless you type ``make clean-all``. After that, viewing and
|
||||
processing of the documentation can be done without internet access.
|
||||
|
||||
A current version of the manual (latest patch release, aka unstable branch)
|
||||
is is available online at: `https://lammps.sandia.gov/doc/Manual.html <https://lammps.sandia.gov/doc/Manual.html>`_
|
||||
A version of the manual corresponding to the ongoing development
|
||||
(aka master branch) is available online at: `https://doc.lammps.org/ <https://doc.lammps.org/>`_
|
||||
|
||||
----------
|
||||
|
||||
The generation of all documentation is managed by the Makefile in the
|
||||
|
@ -58,10 +62,9 @@ available:
|
|||
.. code-block:: bash
|
||||
|
||||
make html # generate HTML in html dir using Sphinx
|
||||
make pdf # generate 2 PDF files (Manual.pdf,Developer.pdf)
|
||||
# in doc dir via htmldoc and pdflatex
|
||||
make fetch # fetch HTML doc pages and 2 PDF files from web site
|
||||
# as a tarball and unpack into html dir and 2 PDFs
|
||||
make pdf # generate PDF as Manual.pdf using Sphinx and pdflatex
|
||||
make fetch # fetch HTML doc pages and PDF file from web site
|
||||
# as a tarball and unpack into html dir and PDF
|
||||
make epub # generate LAMMPS.epub in ePUB format using Sphinx
|
||||
make mobi # generate LAMMPS.mobi in MOBI format using ebook-convert
|
||||
|
||||
|
|
|
@ -113,8 +113,630 @@ care has to be taken, that suitable communicators are used to not
|
|||
create conflicts between different instances.
|
||||
|
||||
The LAMMPS class currently holds instances of 19 classes representing
|
||||
different core functionalities
|
||||
There are a handful of virtual parent classes in LAMMPS that define
|
||||
what LAMMPS calls ``styles``. They are shaded red in Fig
|
||||
\ref{fig:classes}. Each of these are parents of a number of child
|
||||
classes that implement the interface defined by the parent class.
|
||||
different core functionalities There are a handful of virtual parent
|
||||
classes in LAMMPS that define what LAMMPS calls ``styles``. They are
|
||||
shaded red in the :ref:`class-topology` figure. Each of these are
|
||||
parents of a number of child classes that implement the interface
|
||||
defined by the parent class. There are two main categories of these
|
||||
``styles``: some may only have one instance active at a time (e.g. atom,
|
||||
pair, bond, angle, dihedral, improper, kspace, comm) and there is a
|
||||
dedicated pointer variable in the composite class that manages them.
|
||||
Setups that require a mix of different such styles have to use a
|
||||
*hybrid* class that manages and forwards calls to the corresponding
|
||||
sub-styles for the designated subset of atoms or data. or the composite
|
||||
class may have lists of class instances, e.g. Modify handles lists of
|
||||
compute and fix styles, while Output handles dumps class instances.
|
||||
|
||||
The exception to this scheme are the ``command`` style classes. These
|
||||
implement specific commands that can be invoked before, after, or between
|
||||
runs or are commands which launch a simulation. For these an instance
|
||||
of the class is created, its command() method called and then, after
|
||||
completion, the class instance deleted. Examples for this are the
|
||||
create_box, create_atoms, minimize, run, or velocity command styles.
|
||||
|
||||
For all those ``styles`` certain naming conventions are employed: for
|
||||
the fix nve command the class is called FixNVE and the files are
|
||||
``fix_nve.h`` and ``fix_nve.cpp``. Similarly for fix ave/time we have
|
||||
FixAveTime and ``fix_ave_time.h`` and ``fix_ave_time.cpp``. Style names
|
||||
are lower case and without spaces or special characters. A suffix or
|
||||
multiple appended with a forward slash '/' denotes a variant of the
|
||||
corresponding class without the suffix. To connect the style name and
|
||||
the class name, LAMMPS uses macros like the following ATOM\_CLASS,
|
||||
PAIR\_CLASS, BOND\_CLASS, REGION\_CLASS, FIX\_CLASS, COMPUTE\_CLASS,
|
||||
or DUMP\_CLASS in the corresponding header file. During compilation
|
||||
files with the pattern ``style_name.h`` are created that contain include
|
||||
statements including all headers of all styles of a given type that
|
||||
are currently active (or "installed).
|
||||
|
||||
|
||||
More details on individual classes in the :ref:`class-topology` are as
|
||||
follows:
|
||||
|
||||
- The Memory class handles allocation of all large vectors and arrays.
|
||||
|
||||
- The Error class prints all error and warning messages.
|
||||
|
||||
- The Universe class sets up partitions of processors so that multiple
|
||||
simulations can be run, each on a subset of the processors allocated
|
||||
for a run, e.g. by the mpirun command.
|
||||
|
||||
- The Input class reads and processes input input strings and files,
|
||||
stores variables, and invokes :doc:`commands <Commands_all>`.
|
||||
|
||||
- As discussed above, command style classes are directly derived from
|
||||
the Pointers class. They provide input script commands that perform
|
||||
one-time operations before/after/between simulations or which invoke a
|
||||
simulation. They are instantiated from within the Input class,
|
||||
invoked, then immediately destructed.
|
||||
|
||||
- The Finish class is instantiated to print statistics to the screen
|
||||
after a simulation is performed, by commands like run and minimize.
|
||||
|
||||
- The Special class walks the bond topology of a molecular system to
|
||||
find first, second, third neighbors of each atom. It is invoked by
|
||||
several commands, like :doc:`read_data <read_data>`,
|
||||
:doc:`read_restart <read_restart>`, or :doc:`replicate <replicate>`.
|
||||
|
||||
- The Atom class stores per-atom properties associated with atom styles.
|
||||
More precisely, they are allocated and managed by a class derived from
|
||||
the AtomVec class, and the Atom class simply stores pointers to them.
|
||||
The classes derived from AtomVec represent the different atom styles
|
||||
and they are instantiated through the :doc:`atom_style <atom_style>`
|
||||
command.
|
||||
|
||||
- The Update class holds instances of an integrator and a minimizer
|
||||
class. The Integrate class is a parent style for the Verlet and
|
||||
r-RESPA time integrators, as defined by the :doc:`run_style
|
||||
<run_style>` command. The Min class is a parent style for various
|
||||
energy minimizers.
|
||||
|
||||
- The Neighbor class builds and stores neighbor lists. The NeighList
|
||||
class stores a single list (for all atoms). A NeighRequest class
|
||||
instance is created by pair, fix, or compute styles when they need a
|
||||
particular kind of neighbor list and use the NeighRequest properties
|
||||
to select the neighbor list settings for the given request. There can
|
||||
be multiple instances of the NeighRequest class and the Neighbor class
|
||||
will try to optimize how they are computed by creating copies or
|
||||
sub-lists where possible.
|
||||
|
||||
- The Comm class performs inter-processor communication, typically of
|
||||
ghost atom information. This usually involves MPI message exchanges
|
||||
with 6 neighboring processors in the 3d logical grid of processors
|
||||
mapped to the simulation box. There are two :doc:`communication styles
|
||||
<comm_style>` enabling different ways to do the domain decomposition.
|
||||
Sometimes the Irregular class is used, when atoms may migrate to
|
||||
arbitrary processors.
|
||||
|
||||
- The Domain class stores the simulation box geometry, as well as
|
||||
geometric Regions and any user definition of a Lattice. The latter
|
||||
are defined by the :doc:`region <region>` and :doc:`lattice <lattice>`
|
||||
commands in an input script.
|
||||
|
||||
- The Force class computes various forces between atoms. The Pair
|
||||
parent class is for non-bonded or pair-wise forces, which in LAMMPS
|
||||
also includes many-body forces such as the Tersoff 3-body potential if
|
||||
those are computed by walking pairwise neighbor lists. The Bond,
|
||||
Angle, Dihedral, Improper parent classes are styles for bonded
|
||||
interactions within a static molecular topology. The KSpace parent
|
||||
class is for computing long-range Coulombic interactions. One of its
|
||||
child classes, PPPM, uses the FFT3D and Remap classes to redistribute
|
||||
and communicate grid-based information across the parallel processors.
|
||||
|
||||
- The Modify class stores lists of class instances derived from the
|
||||
:doc:`Fix <fix>` and :doc:`Compute <compute>` base classes.
|
||||
|
||||
- The Group class manipulates groups that atoms are assigned to via the
|
||||
:doc:`group <group>` command. It also has functions to compute
|
||||
various attributes of groups of atoms.
|
||||
|
||||
- The Output class is used to generate 3 kinds of output from a LAMMPS
|
||||
simulation: thermodynamic information printed to the screen and log
|
||||
file, dump file snapshots, and restart files. These correspond to the
|
||||
:doc:`Thermo <thermo_style>`, :doc:`Dump <dump>`, and
|
||||
:doc:`WriteRestart <write_restart>` classes respectively. The Dump
|
||||
class is a base class with several derived classes implementing
|
||||
various dump style variants.
|
||||
|
||||
- The Timer class logs timing information, output at the end
|
||||
of a run.
|
||||
|
||||
.. TODO section on "Spatial decomposition and parallel operations"
|
||||
.. diagram of 3d processor grid, brick vs. tiled. local vs. ghost
|
||||
.. atoms, 6-way communication with pack/unpack functions,
|
||||
.. PBC as part of the communication
|
||||
|
||||
.. TODO section on "Fixes, Computes, and Variables"
|
||||
.. how and when data is computed and provided and how it is
|
||||
.. referenced. flags in Fix/Compute/Variable classes tell
|
||||
.. style and amount of available data.
|
||||
|
||||
|
||||
How a timestep works
|
||||
====================
|
||||
|
||||
The first and most fundamental operation within LAMMPS to understand is
|
||||
how a timestep is structured. Timestepping is performed by calling
|
||||
methods of the Integrate class instance within the Update class. Since
|
||||
Integrate is a base class, it will point to an instance of a derived
|
||||
class corresponding to what is selected by the :doc:`run_style
|
||||
<run_style>` input script command.
|
||||
|
||||
In this section, the timestep implemented by the Verlet class is
|
||||
described. A similar timestep protocol is implemented by the Respa
|
||||
class, for the r-RESPA hierarchical timestepping method.
|
||||
|
||||
The Min base class performs energy minimization, so does not perform a
|
||||
literal timestep. But it has logic similar to what is described here,
|
||||
to compute forces and invoke fixes at each iteration of a minimization.
|
||||
Differences between time integration and minimization are highlighted at
|
||||
the end of this section.
|
||||
|
||||
The Verlet class is encoded in the ``src/verlet.cpp`` and ``verlet.h``
|
||||
files. It implements the velocity-Verlet timestepping algorithm. The
|
||||
workhorse method is ``Verlet::run()``, but first we highlight several
|
||||
other methods in the class.
|
||||
|
||||
- The ``init()`` method is called at the beginning of each dynamics
|
||||
run. It simply sets some internal flags, based on user settings in
|
||||
other parts of the code.
|
||||
|
||||
- The ``setup()`` or ``setup_minimal()`` methods are also called before
|
||||
each run. The velocity-Verlet method requires current forces be
|
||||
calculated before the first timestep, so these routines compute
|
||||
forces due to all atomic interactions, using the same logic that
|
||||
appears in the timestepping described next. A few fixes are also
|
||||
invoked, using the mechanism described in the next section. Various
|
||||
counters are also initialized before the run begins. The
|
||||
``setup_minimal()`` method is a variant that has a flag for performing
|
||||
less setup. This is used when runs are continued and information
|
||||
from the previous run is still valid. For example, if repeated
|
||||
short LAMMPS runs are being invoked, interleaved by other commands,
|
||||
via the *pre no* and *every* options of the run command, the
|
||||
``setup_minimal()`` method is used.
|
||||
|
||||
- The ``force_clear()`` method initializes force and other arrays to
|
||||
zero before each timestep, so that forces (torques, etc) can be
|
||||
accumulated.
|
||||
|
||||
Now for the ``Verlet::run()`` method. Its basic structure in hi-level pseudo
|
||||
code is shown below. In the actual code in ``src/verlet.cpp`` some of
|
||||
these operations are conditionally invoked.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
loop over N timesteps:
|
||||
if timeout condition: break
|
||||
ev_set()
|
||||
|
||||
fix->initial_integrate()
|
||||
fix->post_integrate()
|
||||
|
||||
nflag = neighbor->decide()
|
||||
if nflag:
|
||||
fix->pre_exchange()
|
||||
domain->pbc()
|
||||
domain->reset_box()
|
||||
comm->setup()
|
||||
neighbor->setup_bins()
|
||||
comm->exchange()
|
||||
comm->borders()
|
||||
fix->pre_neighbor()
|
||||
neighbor->build()
|
||||
fix->post_neighbor()
|
||||
else:
|
||||
comm->forward_comm()
|
||||
|
||||
force_clear()
|
||||
fix->pre_force()
|
||||
|
||||
pair->compute()
|
||||
bond->compute()
|
||||
angle->compute()
|
||||
dihedral->compute()
|
||||
improper->compute()
|
||||
kspace->compute()
|
||||
|
||||
fix->pre_reverse()
|
||||
comm->reverse_comm()
|
||||
|
||||
fix->post_force()
|
||||
fix->final_integrate()
|
||||
fix->end_of_step()
|
||||
|
||||
if any output on this step:
|
||||
output->write()
|
||||
|
||||
# after loop
|
||||
fix->post_run()
|
||||
|
||||
|
||||
The ``ev_set()`` method (in the parent Integrate class), sets two flags
|
||||
(*eflag* and *vflag*) for energy and virial computation. Each flag
|
||||
encodes whether global and/or per-atom energy and virial should be
|
||||
calculated on this timestep, because some fix or variable or output will
|
||||
need it. These flags are passed to the various methods that compute
|
||||
particle interactions, so that they either compute and tally the
|
||||
corresponding data or can skip the extra calculations if the energy and
|
||||
virial are not needed. See the comments for the ``Integrate::ev_set()``
|
||||
method which document the flag values.
|
||||
|
||||
At various points of the timestep, fixes are invoked,
|
||||
e.g. ``fix->initial_integrate()``. In the code, this is actually done
|
||||
via the Modify class which stores all the Fix objects and lists of which
|
||||
should be invoked at what point in the timestep. Fixes are the LAMMPS
|
||||
mechanism for tailoring the operations of a timestep for a particular
|
||||
simulation. As described elsewhere, each fix has one or more methods,
|
||||
each of which is invoked at a specific stage of the timestep, as show in
|
||||
the timestep pseudo-code. All the active fixes defined in an input
|
||||
script, that are flagged to have an ``initial_integrate()`` method are
|
||||
invoked at the beginning of each timestep. Examples are :doc:`fix nve
|
||||
<fix_nve>` or :doc:`fix nvt or fix npt <fix_nh>` which perform the
|
||||
start-of-timestep velocity-Verlet integration operations to update
|
||||
velocities by a half-step, and coordinates by a full step. The
|
||||
``post_integrate()`` method is next for operations that need to happen
|
||||
immediately after those updates. Only a few fixes use this, e.g. to
|
||||
reflect particles off box boundaries in the :doc:`FixWallReflect class
|
||||
<fix_wall_reflect>`.
|
||||
|
||||
The ``decide()`` method in the Neighbor class determines whether
|
||||
neighbor lists need to be rebuilt on the current timestep (conditions
|
||||
can be changed using the :doc:`neigh_modify every/delay/check
|
||||
<neigh_modify>` command. If not, coordinates of ghost atoms are
|
||||
acquired by each processor via the ``forward_comm()`` method of the Comm
|
||||
class. If neighbor lists need to be built, several operations within
|
||||
the inner if clause of the pseudo-code are first invoked. The
|
||||
``pre_exchange()`` method of any defined fixes is invoked first.
|
||||
Typically this inserts or deletes particles from the system.
|
||||
|
||||
Periodic boundary conditions are then applied by the Domain class via
|
||||
its ``pbc()`` method to remap particles that have moved outside the
|
||||
simulation box back into the box. Note that this is not done every
|
||||
timestep, but only when neighbor lists are rebuilt. This is so that
|
||||
each processor's sub-domain will have consistent (nearby) atom
|
||||
coordinates for its owned and ghost atoms. It is also why dumped atom
|
||||
coordinates may be slightly outside the simulation box if not dumped
|
||||
on a step where the neighbor lists are rebuilt.
|
||||
|
||||
The box boundaries are then reset (if needed) via the ``reset_box()``
|
||||
method of the Domain class, e.g. if box boundaries are shrink-wrapped to
|
||||
current particle coordinates. A change in the box size or shape
|
||||
requires internal information for communicating ghost atoms (Comm class)
|
||||
and neighbor list bins (Neighbor class) be updated. The ``setup()``
|
||||
method of the Comm class and ``setup_bins()`` method of the Neighbor
|
||||
class perform the update.
|
||||
|
||||
The code is now ready to migrate atoms that have left a processor's
|
||||
geometric sub-domain to new processors. The ``exchange()`` method of
|
||||
the Comm class performs this operation. The ``borders()`` method of the
|
||||
Comm class then identifies ghost atoms surrounding each processor's
|
||||
sub-domain and communicates ghost atom information to neighboring
|
||||
processors. It does this by looping over all the atoms owned by a
|
||||
processor to make lists of those to send to each neighbor processor. On
|
||||
subsequent timesteps, the lists are used by the ``Comm::forward_comm()``
|
||||
method.
|
||||
|
||||
Fixes with a ``pre_neighbor()`` method are then called. These typically
|
||||
re-build some data structure stored by the fix that depends on the
|
||||
current atoms owned by each processor.
|
||||
|
||||
Now that each processor has a current list of its owned and ghost
|
||||
atoms, LAMMPS is ready to rebuild neighbor lists via the ``build()``
|
||||
method of the Neighbor class. This is typically done by binning all
|
||||
owned and ghost atoms, and scanning a stencil of bins around each
|
||||
owned atom's bin to make a Verlet list of neighboring atoms within the
|
||||
force cutoff plus neighbor skin distance.
|
||||
|
||||
In the next portion of the timestep, all interaction forces between
|
||||
particles are computed, after zeroing the per-atom force vector via the
|
||||
``force_clear()`` method. If the newton flag is set to *on* by the
|
||||
newton command, forces are added to both owned and ghost atoms, otherwise
|
||||
only to owned (aka local) atoms.
|
||||
|
||||
Pairwise forces are calculated first, which enables the global virial
|
||||
(if requested) to be calculated cheaply (at O(N) cost instead of O(N**2)
|
||||
at the end of the ``Pair::compute()`` method), by a dot product of atom
|
||||
coordinates and forces. By including owned and ghost atoms in the dot
|
||||
product, the effect of periodic boundary conditions is correctly
|
||||
accounted for. Molecular topology interactions (bonds, angles,
|
||||
dihedrals, impropers) are calculated next (if supported by the current
|
||||
atom style). The final contribution is from long-range Coulombic
|
||||
interactions, invoked by the KSpace class.
|
||||
|
||||
The ``pre_reverse()`` method in fixes is used for operations that have to
|
||||
be done *before* the upcoming reverse communication (e.g. to perform
|
||||
additional data transfers or reductions for data computed during the
|
||||
force computation and stored with ghost atoms).
|
||||
|
||||
If the newton flag is on, forces on ghost atoms are communicated and
|
||||
summed back to their corresponding owned atoms. The ``reverse_comm()``
|
||||
method of the Comm class performs this operation, which is essentially
|
||||
the inverse operation of sending copies of owned atom coordinates to
|
||||
other processor's ghost atoms.
|
||||
|
||||
At this point in the timestep, the total force on each (local) atom is
|
||||
known. Additional force constraints (external forces, SHAKE, etc) are
|
||||
applied by Fixes that have a ``post_force()`` method. The second half
|
||||
of the velocity-Verlet integration, ``final_integrate()`` is then
|
||||
performed (another half-step update of the velocities) via fixes like
|
||||
nve, nvt, npt.
|
||||
|
||||
At the end of the timestep, fixes that contain an ``end_of_step()``
|
||||
method are invoked. These typically perform a diagnostic calculation,
|
||||
e.g. the ave/time and ave/spatial fixes. The final operation of the
|
||||
timestep is to perform any requested output, via the ``write()`` method
|
||||
of the Output class. There are 3 kinds of LAMMPS output: thermodynamic
|
||||
output to the screen and log file, snapshots of atom data to a dump
|
||||
file, and restart files. See the :doc:`thermo_style <thermo_style>`,
|
||||
:doc:`dump <dump>`, and :doc:`restart <restart>` commands for more
|
||||
details.
|
||||
|
||||
The the flow of control during energy minimization iterations is
|
||||
similar to that of a molecular dynamics timestep. Forces are computed,
|
||||
neighbor lists are built as needed, atoms migrate to new processors, and
|
||||
atom coordinates and forces are communicated to neighboring processors.
|
||||
The only difference is what Fix class operations are invoked when. Only
|
||||
a subset of LAMMPS fixes are useful during energy minimization, as
|
||||
explained in their individual doc pages. The relevant Fix class methods
|
||||
are ``min_pre_exchange()``, ``min_pre_force()``, and ``min_post_force()``.
|
||||
Each fix is invoked at the appropriate place within the minimization
|
||||
iteration. For example, the ``min_post_force()`` method is analogous to
|
||||
the ``post_force()`` method for dynamics; it is used to alter or constrain
|
||||
forces on each atom, which affects the minimization procedure.
|
||||
|
||||
After all iterations are completed there is a ``cleanup`` step which
|
||||
calls the ``post_run()`` method of fixes to perform operations only required
|
||||
at the end of a calculations (like freeing temporary storage or creating
|
||||
final outputs).
|
||||
|
||||
Modifying and extending LAMMPS
|
||||
==============================
|
||||
|
||||
The :doc:`Modify` section of the manual gives an overview of how LAMMPS can
|
||||
be extended by writing new classes that derive from existing
|
||||
parent classes in LAMMPS. Here, some specific coding
|
||||
details are provided for writing code for LAMMPS.
|
||||
|
||||
Writing a new fix style
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Writing fixes is a flexible way of extending LAMMPS. Users can
|
||||
implement many things using fixes:
|
||||
|
||||
- changing particles attributes (positions, velocities, forces, etc.). Examples: FixNVE, FixFreeze.
|
||||
- reading/writing data. Example: FixRestart.
|
||||
- adding or modifying properties due to geometry. Example: FixWall.
|
||||
- interacting with other subsystems or external code: Examples: FixTTM, FixExternal, FixLATTE
|
||||
- saving information for analysis or future use (previous positions,
|
||||
for instance). Examples: Fix AveTime, FixStoreState.
|
||||
|
||||
|
||||
All fixes are derived from the Fix base class and must have a
|
||||
constructor with the signature: ``FixPrintVel(class LAMMPS *, int, char **)``.
|
||||
|
||||
Every fix must be registered in LAMMPS by writing the following lines
|
||||
of code in the header before include guards:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
FixStyle(print/vel,FixPrintVel)
|
||||
#else
|
||||
/* the definition of the FixPrintVel class comes here */
|
||||
...
|
||||
#endif
|
||||
|
||||
Where ``print/vel`` is the style name of your fix in the input script and
|
||||
``FixPrintVel`` is the name of the class. The header file would be called
|
||||
``fix_print_vel.h`` and the implementation file ``fix_print_vel.cpp``.
|
||||
These conventions allow LAMMPS to automatically integrate it into the
|
||||
executable when compiling and associate your new fix class with the designated
|
||||
keyword when it parses the input script.
|
||||
|
||||
Let's write a simple fix which will print the average velocity at the end
|
||||
of each timestep. First of all, implement a constructor:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
FixPrintVel::FixPrintVel(LAMMPS *lmp, int narg, char **arg)
|
||||
: Fix(lmp, narg, arg)
|
||||
{
|
||||
if (narg < 4)
|
||||
error->all(FLERR,"Illegal fix print/vel command");
|
||||
|
||||
nevery = force->inumeric(FLERR,arg[3]);
|
||||
if (nevery <= 0)
|
||||
error->all(FLERR,"Illegal fix print/vel command");
|
||||
}
|
||||
|
||||
In the constructor you should parse your fix arguments which are
|
||||
specified in the script. All fixes have pretty the same syntax:
|
||||
``fix <fix-ID> <fix group> <fix name> <fix arguments ...>``. The
|
||||
first 3 parameters are parsed by Fix base class constructor, while
|
||||
``<fix arguments>`` should be parsed by you. In our case, we need to
|
||||
specify how often we want to print an average velocity. For instance,
|
||||
once in 50 timesteps: ``fix 1 print/vel 50``. There is a special variable
|
||||
in the Fix class called ``nevery`` which specifies how often the method
|
||||
``end_of_step()`` is called. Thus all we need to do is just set it up.
|
||||
|
||||
The next method we need to implement is ``setmask()``:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
int FixPrintVel::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= FixConst::END_OF_STEP;
|
||||
return mask;
|
||||
}
|
||||
|
||||
Here the user specifies which methods of your fix should be called
|
||||
during execution. The constant ``END_OF_STEP`` corresponds to the
|
||||
``end_of_step()`` method. The most important available methods that
|
||||
are called during a timestep and the order in which they are called
|
||||
are shown in the previous section.
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
void FixPrintVel::end_of_step()
|
||||
{
|
||||
// for add3, scale3
|
||||
using namespace MathExtra;
|
||||
|
||||
double** v = atom->v;
|
||||
int nlocal = atom->nlocal;
|
||||
double localAvgVel[4]; // 4th element for particles count
|
||||
memset(localAvgVel, 0, 4 * sizeof(double));
|
||||
for (int particleInd = 0; particleInd < nlocal; ++particleInd) {
|
||||
add3(localAvgVel, v[particleInd], localAvgVel);
|
||||
}
|
||||
localAvgVel[3] = nlocal;
|
||||
double globalAvgVel[4];
|
||||
memset(globalAvgVel, 0, 4 * sizeof(double));
|
||||
MPI_Allreduce(localAvgVel, globalAvgVel, 4, MPI_DOUBLE, MPI_SUM, world);
|
||||
scale3(1.0 / globalAvgVel[3], globalAvgVel);
|
||||
if ((comm->me == 0) && screen) {
|
||||
fmt::print(screen,"{}, {}, {}\n",
|
||||
globalAvgVel[0], globalAvgVel[1], globalAvgVel[2]);
|
||||
}
|
||||
}
|
||||
|
||||
In the code above, we use MathExtra routines defined in
|
||||
``math_extra.h``. There are bunch of math functions to work with
|
||||
arrays of doubles as with math vectors. It is also important to note
|
||||
that LAMMPS code should always assume to be run in parallel and that
|
||||
atom data is thus distributed across the MPI ranks. Thus you can
|
||||
only process data from local atoms directly and need to use MPI library
|
||||
calls to combine or exchange data. For serial execution, LAMMPS
|
||||
comes bundled with the MPI STUBS library that contains the MPI library
|
||||
function calls in dummy versions that only work for a single MPI rank.
|
||||
|
||||
In this code we use an instance of Atom class. This object is stored
|
||||
in the Pointers class (see ``pointers.h``) which is the base class of
|
||||
the Fix base class. This object contains references to various class
|
||||
instances (the original instances are created and held by the LAMMPS
|
||||
class) with all global information about the simulation system.
|
||||
Data from the Pointers class is available to all classes inherited from
|
||||
it using protected inheritance. Hence when you write you own class,
|
||||
which is going to use LAMMPS data, don't forget to inherit from Pointers
|
||||
or pass an Pointer to it to all functions that need access. When writing
|
||||
fixes we inherit from class Fix which is inherited from Pointers so
|
||||
there is no need to inherit from it directly.
|
||||
|
||||
The code above computes average velocity for all particles in the
|
||||
simulation. Yet you have one unused parameter in fix call from the
|
||||
script: ``group_name``. This parameter specifies the group of atoms
|
||||
used in the fix. So we should compute average for all particles in the
|
||||
simulation only if ``group_name == "all"``, but it can be any group.
|
||||
The group membership information of an atom is contained in the *mask*
|
||||
property of and atom and the bit corresponding to a given group is
|
||||
stored in the groupbit variable which is defined in Fix base class:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
for (int i = 0; i < nlocal; ++i) {
|
||||
if (atom->mask[i] & groupbit) {
|
||||
// Do all job here
|
||||
}
|
||||
}
|
||||
|
||||
Class Atom encapsulates atoms positions, velocities, forces, etc. User
|
||||
can access them using particle index. Note, that particle indexes are
|
||||
usually changed every few timesteps because of neighbor list rebuilds
|
||||
and spatial sorting (to improve cache efficiency).
|
||||
|
||||
Let us consider another Fix example: We want to have a fix which stores
|
||||
atoms position from previous time step in your fix. The local atoms
|
||||
indexes may not be valid on the next iteration. In order to handle
|
||||
this situation there are several methods which should be implemented:
|
||||
|
||||
- ``double memory_usage()``: return how much memory the fix uses (optional)
|
||||
- ``void grow_arrays(int)``: do reallocation of the per particle arrays in your fix
|
||||
- ``void copy_arrays(int i, int j, int delflag)``: copy i-th per-particle
|
||||
information to j-th. Used when atom sorting is performed. if delflag is set
|
||||
and atom j owns a body, move the body information to atom i.
|
||||
- ``void set_arrays(int i)``: sets i-th particle related information to zero
|
||||
|
||||
Note, that if your class implements these methods, it must call add calls of
|
||||
add_callback and delete_callback to constructor and destructor. Since we want
|
||||
to store positions of atoms from previous timestep, we need to add
|
||||
``double** xold`` to the header file. Than add allocation code
|
||||
to the constructor:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
FixSavePos::FixSavePos(LAMMPS *lmp, int narg, char **arg), xold(nullptr)
|
||||
{
|
||||
//...
|
||||
memory->create(xold, atom->nmax, 3, "FixSavePos:x");
|
||||
atom->add_callback(0);
|
||||
}
|
||||
|
||||
FixSavePos::~FixSavePos() {
|
||||
atom->delete_callback(id, 0);
|
||||
memory->destroy(xold);
|
||||
}
|
||||
|
||||
Implement the aforementioned methods:
|
||||
|
||||
.. code-block:: C++
|
||||
|
||||
double FixSavePos::memory_usage()
|
||||
{
|
||||
int nmax = atom->nmax;
|
||||
double bytes = 0.0;
|
||||
bytes += nmax * 3 * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void FixSavePos::grow_arrays(int nmax)
|
||||
{
|
||||
memory->grow(xold, nmax, 3, "FixSavePos:xold");
|
||||
}
|
||||
|
||||
void FixSavePos::copy_arrays(int i, int j, int delflag)
|
||||
{
|
||||
memcpy(xold[j], xold[i], sizeof(double) * 3);
|
||||
}
|
||||
|
||||
void FixSavePos::set_arrays(int i)
|
||||
{
|
||||
memset(xold[i], 0, sizeof(double) * 3);
|
||||
}
|
||||
|
||||
int FixSavePos::pack_exchange(int i, double *buf)
|
||||
{
|
||||
int m = 0;
|
||||
buf[m++] = xold[i][0];
|
||||
buf[m++] = xold[i][1];
|
||||
buf[m++] = xold[i][2];
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
int FixSavePos::unpack_exchange(int nlocal, double *buf)
|
||||
{
|
||||
int m = 0;
|
||||
xold[nlocal][0] = buf[m++];
|
||||
xold[nlocal][1] = buf[m++];
|
||||
xold[nlocal][2] = buf[m++];
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
Now, a little bit about memory allocation. We use the Memory class which
|
||||
is just a bunch of template functions for allocating 1D and 2D
|
||||
arrays. So you need to add include ``memory.h`` to have access to them.
|
||||
|
||||
Finally, if you need to write/read some global information used in
|
||||
your fix to the restart file, you might do it by setting flag
|
||||
``restart_global = 1`` in the constructor and implementing methods void
|
||||
``write_restart(FILE *fp)`` and ``void restart(char *buf)``.
|
||||
If, in addition, you want to write the per-atom property to restart
|
||||
files additional settings and functions are needed:
|
||||
|
||||
- a fix flag indicating this needs to be set ``restart_peratom = 1;``
|
||||
- ``atom->add_callback()`` and ``atom->delete_callback()`` must be called
|
||||
a second time with the final argument set to 1 instead of 0 (indicating
|
||||
restart processing instead of per-atom data memory management).
|
||||
- the functions ``void pack_restart(int i, double *buf)`` and
|
||||
``void unpack_restart(int nlocal, int nth)`` need to be implemented
|
||||
|
|
|
@ -586,6 +586,7 @@ del
|
|||
delaystep
|
||||
DeleteIDs
|
||||
deleteIDs
|
||||
delflag
|
||||
Dellago
|
||||
delocalization
|
||||
delocalized
|
||||
|
@ -1104,6 +1105,7 @@ gromos
|
|||
Gronbech
|
||||
Groot
|
||||
groupbig
|
||||
groupbit
|
||||
grp
|
||||
Grueneisen
|
||||
gsmooth
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
/pair_kim.cpp
|
||||
/pair_kim.h
|
||||
|
||||
/superpose3d.h
|
||||
/math_eigen.h
|
||||
|
||||
/kokkos.cpp
|
||||
/kokkos.h
|
||||
/kokkos_type.h
|
||||
|
|
Loading…
Reference in New Issue