diff --git a/doc/Manual.html b/doc/Manual.html
index 84a071a6d..ac4f3e1af 100644
--- a/doc/Manual.html
+++ b/doc/Manual.html
@@ -1,435 +1,435 @@
 <HTML>
 <HEAD>
 <TITLE>LAMMPS-ICMS Users Manual</TITLE>
 <META NAME="docnumber" CONTENT="24 Jan 2013 version">
 <META NAME="author" CONTENT="http://lammps.sandia.gov - Sandia National Laboratories">
 <META NAME="copyright" CONTENT="Copyright (2003) Sandia Corporation.  This software and manual is distributed under the GNU General Public License.">
 </HEAD>
 
 <BODY>
 
 <CENTER><A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> - <A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> 
 </CENTER>
 
 
 
 
 
 
 <HR>
 
 <H1></H1>
 
 <CENTER><H3>LAMMPS-ICMS Documentation 
 </H3></CENTER>
-<CENTER><H4>14 May 2013 version 
+<CENTER><H4>24 May 2013 version 
 </H4></CENTER>
 <H4>Version info: 
 </H4>
 <P>The LAMMPS "version" is the date when it was released, such as 1 May
 2010. LAMMPS is updated continuously.  Whenever we fix a bug or add a
 feature, we release it immediately, and post a notice on <A HREF = "http://lammps.sandia.gov/bug.html">this page of
 the WWW site</A>.  Each dated copy of LAMMPS contains all the
 features and bug-fixes up to and including that version date. The
 version date is printed to the screen and logfile every time you run
 LAMMPS. It is also in the file src/version.h and in the LAMMPS
 directory name created when you unpack a tarball, and at the top of
 the first page of the manual (this page).
 </P>
 <P>LAMMPS-ICMS is an experimental variant of LAMMPS with additional
 features made available for testing before they will be submitted
 for inclusion into the official LAMMPS tree. The source code is 
 based on the official LAMMPS svn repository mirror at the Institute
 for Computational Molecular Science at Temple University and generally
 kept up-to-date as much as possible. Sometimes, e.g. when additional
 development work is needed to adapt the upstream changes into
 LAMMPS-ICMS it can take longer until synchronization; and occasionally,
 e.g. in case of the rewrite of the multi-threading support, the
 development will be halted except for important bugfixes until
 all features of LAMMPS-ICMS fully compatible with the upstream
 version or replaced by alternate implementations.
 </P>
 <UL><LI>If you browse the HTML doc pages on the LAMMPS WWW site, they always
 describe the most current version of upstream LAMMPS, but may be
 missing some new features in LAMMPS-ICMS. 
 
 <LI>If you browse the HTML doc pages included in your tarball, they
 describe the version you have, however, not all new features in
 LAMMPS-ICMS are documented immediately. 
 
 <LI>The <A HREF = "Manual.pdf">PDF file</A> on the WWW site or in the tarball is updated
 about once per month.  This is because it is large, and we don't want
 it to be part of every patch. 
 
 <LI>There is also a <A HREF = "Developer.pdf">Developer.pdf</A> file in the doc
 directory, which describes the internal structure and algorithms of
 LAMMPS.  
 </UL>
 <P>LAMMPS stands for Large-scale Atomic/Molecular Massively Parallel
 Simulator.
 </P>
 <P>LAMMPS is a classical molecular dynamics simulation code designed to
 run efficiently on parallel computers.  It was developed at Sandia
 National Laboratories, a US Department of Energy facility, with
 funding from the DOE.  It is an open-source code, distributed freely
 under the terms of the GNU Public License (GPL).
 </P>
 <P>The primary developers of LAMMPS are <A HREF = "http://www.sandia.gov/~sjplimp">Steve Plimpton</A>, Aidan
 Thompson, and Paul Crozier who can be contacted at
 sjplimp,athomps,pscrozi at sandia.gov.  The <A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> at
 http://lammps.sandia.gov has more information about the code and its
 uses.
 </P>
 
 
 
 
 <HR>
 
 <P>The LAMMPS documentation is organized into the following sections.  If
 you find errors or omissions in this manual or have suggestions for
 useful information to add, please send an email to the developers so
 we can improve the LAMMPS documentation.
 </P>
 <P>Once you are familiar with LAMMPS, you may want to bookmark <A HREF = "Section_commands.html#comm">this
 page</A> at Section_commands.html#comm since
 it gives quick access to documentation for all LAMMPS commands.
 </P>
 <P><A HREF = "Manual.pdf">PDF file</A> of the entire manual, generated by
 <A HREF = "http://www.easysw.com/htmldoc">htmldoc</A>
 </P>
 <OL><LI><A HREF = "Section_intro.html">Introduction</A> 
 
 <UL>  1.1 <A HREF = "Section_intro.html#intro_1">What is LAMMPS</A> 
 <BR>
   1.2 <A HREF = "Section_intro.html#intro_2">LAMMPS features</A> 
 <BR>
   1.3 <A HREF = "Section_intro.html#intro_3">LAMMPS non-features</A> 
 <BR>
   1.4 <A HREF = "Section_intro.html#intro_4">Open source distribution</A> 
 <BR>
   1.5 <A HREF = "Section_intro.html#intro_5">Acknowledgments and citations</A> 
 <BR></UL>
 <LI><A HREF = "Section_start.html">Getting started</A> 
 
 <UL>  2.1 <A HREF = "Section_start.html#start_1">What's in the LAMMPS distribution</A> 
 <BR>
   2.2 <A HREF = "Section_start.html#start_2">Making LAMMPS</A> 
 <BR>
   2.3 <A HREF = "Section_start.html#start_3">Making LAMMPS with optional packages</A> 
 <BR>
   2.4 <A HREF = "Section_start.html#start_4">Building LAMMPS via the Make.py script</A> 
 <BR>
   2.5 <A HREF = "Section_start.html#start_5">Building LAMMPS as a library</A> 
 <BR>
   2.6 <A HREF = "Section_start.html#start_6">Running LAMMPS</A> 
 <BR>
   2.7 <A HREF = "Section_start.html#start_7">Command-line options</A> 
 <BR>
   2.8 <A HREF = "Section_start.html#start_8">Screen output</A> 
 <BR>
   2.9 <A HREF = "Section_start.html#start_9">Tips for users of previous versions</A> 
 <BR></UL>
 <LI><A HREF = "Section_commands.html">Commands</A> 
 
 <UL>  3.1 <A HREF = "Section_commands.html#cmd_1">LAMMPS input script</A> 
 <BR>
   3.2 <A HREF = "Section_commands.html#cmd_2">Parsing rules</A> 
 <BR>
   3.3 <A HREF = "Section_commands.html#cmd_3">Input script structure</A> 
 <BR>
   3.4 <A HREF = "Section_commands.html#cmd_4">Commands listed by category</A> 
 <BR>
   3.5 <A HREF = "Section_commands.html#cmd_5">Commands listed alphabetically</A> 
 <BR></UL>
 <LI><A HREF = "Section_packages.html">Packages</A> 
 
 <UL>  4.1 <A HREF = "Section_packages.html#pkg_1">Standard packages</A> 
 <BR>
   4.2 <A HREF = "Section_packages.html#pkg_2">User packages</A> 
 <BR></UL>
 <LI><A HREF = "Section_accelerate.html">Accelerating LAMMPS performance</A> 
 
 <UL>  5.1 <A HREF = "Section_accelerate.html#acc_1">Measuring performance</A> 
 <BR>
   5.2 <A HREF = "Section_accelerate.html#acc_2">General strategies</A> 
 <BR>
   5.3 <A HREF = "Section_accelerate.html#acc_3">Packages with optimized styles</A> 
 <BR>
   5.4 <A HREF = "Section_accelerate.html#acc_4">OPT package</A> 
 <BR>
   5.5 <A HREF = "Section_accelerate.html#acc_5">USER-OMP package</A> 
 <BR>
   5.6 <A HREF = "Section_accelerate.html#acc_6">GPU package</A> 
 <BR>
   5.7 <A HREF = "Section_accelerate.html#acc_7">USER-CUDA package</A> 
 <BR>
   5.8 <A HREF = "Section_accelerate.html#acc_8">Comparison of GPU and USER-CUDA packages</A> 
 <BR></UL>
 <LI><A HREF = "Section_howto.html">How-to discussions</A> 
 
 <UL>  6.1 <A HREF = "Section_howto.html#howto_1">Restarting a simulation</A> 
 <BR>
   6.2 <A HREF = "Section_howto.html#howto_2">2d simulations</A> 
 <BR>
   6.3 <A HREF = "Section_howto.html#howto_3">CHARMM and AMBER force fields</A> 
 <BR>
   6.4 <A HREF = "Section_howto.html#howto_4">Running multiple simulations from one input script</A> 
 <BR>
   6.5 <A HREF = "Section_howto.html#howto_5">Multi-replica simulations</A> 
 <BR>
   6.6 <A HREF = "Section_howto.html#howto_6">Granular models</A> 
 <BR>
   6.7 <A HREF = "Section_howto.html#howto_7">TIP3P water model</A> 
 <BR>
   6.8 <A HREF = "Section_howto.html#howto_8">TIP4P water model</A> 
 <BR>
   6.9 <A HREF = "Section_howto.html#howto_9">SPC water model</A> 
 <BR>
   6.10 <A HREF = "Section_howto.html#howto_10">Coupling LAMMPS to other codes</A> 
 <BR>
   6.11 <A HREF = "Section_howto.html#howto_11">Visualizing LAMMPS snapshots</A> 
 <BR>
   6.12 <A HREF = "Section_howto.html#howto_12">Triclinic (non-orthogonal) simulation boxes</A> 
 <BR>
   6.13 <A HREF = "Section_howto.html#howto_13">NEMD simulations</A> 
 <BR>
   6.14 <A HREF = "Section_howto.html#howto_14">Finite-size spherical and aspherical particles</A> 
 <BR>
   6.15 <A HREF = "Section_howto.html#howto_15">Output from LAMMPS (thermo, dumps, computes, fixes, variables)</A> 
 <BR>
   6.16 <A HREF = "Section_howto.html#howto_16">Thermostatting, barostatting, and compute temperature</A> 
 <BR>
   6.17 <A HREF = "Section_howto.html#howto_17">Walls</A> 
 <BR>
   6.18 <A HREF = "Section_howto.html#howto_18">Elastic constants</A> 
 <BR>
   6.19 <A HREF = "Section_howto.html#howto_19">Library interface to LAMMPS</A> 
 <BR>
   6.20 <A HREF = "Section_howto.html#howto_20">Calculating thermal conductivity</A> 
 <BR>
   6.21 <A HREF = "Section_howto.html#howto_21">Calculating viscosity</A> 
 <BR></UL>
 <LI><A HREF = "Section_example.html">Example problems</A> 
 
 <LI><A HREF = "Section_perf.html">Performance & scalability</A> 
 
 <LI><A HREF = "Section_tools.html">Additional tools</A> 
 
 <LI><A HREF = "Section_modify.html">Modifying & extending LAMMPS</A> 
 
 <UL>  10.1 <A HREF = "Section_modify.html#mod_1">Atom styles</A> 
 <BR>
   10.2 <A HREF = "Section_modify.html#mod_2">Bond, angle, dihedral, improper potentials</A> 
 <BR>
   10.3 <A HREF = "Section_modify.html#mod_3">Compute styles</A> 
 <BR>
   10.4 <A HREF = "Section_modify.html#mod_4">Dump styles</A> 
 <BR>
   10.5 <A HREF = "Section_modify.html#mod_5">Dump custom output options</A> 
 <BR>
   10.6 <A HREF = "Section_modify.html#mod_6">Fix styles</A> 
 <BR>
   10.7 <A HREF = "Section_modify.html#mod_7">Input script commands</A> 
 <BR>
   10.8 <A HREF = "Section_modify.html#mod_8">Kspace computations</A> 
 <BR>
   10.9 <A HREF = "Section_modify.html#mod_9">Minimization styles</A> 
 <BR>
   10.10 <A HREF = "Section_modify.html#mod_10">Pairwise potentials</A> 
 <BR>
   10.11 <A HREF = "Section_modify.html#mod_11">Region styles</A> 
 <BR>
   10.12 <A HREF = "Section_modify.html#mod_12">Body styles</A> 
 <BR>
   10.13 <A HREF = "Section_modify.html#mod_13">Thermodynamic output options</A> 
 <BR>
   10.14 <A HREF = "Section_modify.html#mod_14">Variable options</A> 
 <BR>
   10.15 <A HREF = "Section_modify.html#mod_15">Submitting new features for inclusion in LAMMPS</A> 
 <BR></UL>
 <LI><A HREF = "Section_python.html">Python interface</A> 
 
 <UL>  11.1 <A HREF = "Section_python.html#py_1">Building LAMMPS as a shared library</A> 
 <BR>
   11.2 <A HREF = "Section_python.html#py_2">Installing the Python wrapper into Python</A> 
 <BR>
   11.3 <A HREF = "Section_python.html#py_3">Extending Python with MPI to run in parallel</A> 
 <BR>
   11.4 <A HREF = "Section_python.html#py_4">Testing the Python-LAMMPS interface</A> 
 <BR>
   11.5 <A HREF = "Section_python.html#py_5">Using LAMMPS from Python</A> 
 <BR>
   11.6 <A HREF = "Section_python.html#py_6">Example Python scripts that use LAMMPS</A> 
 <BR></UL>
 <LI><A HREF = "Section_errors.html">Errors</A> 
 
 <UL>  12.1 <A HREF = "Section_errors.html#err_1">Common problems</A> 
 <BR>
   12.2 <A HREF = "Section_errors.html#err_2">Reporting bugs</A> 
 <BR>
   12.3 <A HREF = "Section_errors.html#err_3">Error & warning messages</A> 
 <BR></UL>
 <LI><A HREF = "Section_history.html">Future and history</A> 
 
 <UL>  13.1 <A HREF = "Section_history.html#hist_1">Coming attractions</A> 
 <BR>
   13.2 <A HREF = "Section_history.html#hist_2">Past versions</A> 
 <BR></UL>
 
 </OL>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 </BODY>
 
 </HTML>
diff --git a/doc/Manual.txt b/doc/Manual.txt
index 38f1f4c5d..8e0aa5aa1 100644
--- a/doc/Manual.txt
+++ b/doc/Manual.txt
@@ -1,273 +1,273 @@
 <HEAD>
 <TITLE>LAMMPS-ICMS Users Manual</TITLE>
 <META NAME="docnumber" CONTENT="24 Jan 2013 version">
 <META NAME="author" CONTENT="http://lammps.sandia.gov - Sandia National Laboratories">
 <META NAME="copyright" CONTENT="Copyright (2003) Sandia Corporation.  This software and manual is distributed under the GNU General Public License.">
 </HEAD>
 
 <BODY>
 
 "LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
 
 :link(lws,http://lammps.sandia.gov)
 :link(ld,Manual.html)
 :link(lc,Section_commands.html#comm)
 
 :line
 
 <H1></H1>
 
 LAMMPS-ICMS Documentation :c,h3
-14 May 2013 version :c,h4
+24 May 2013 version :c,h4
 
 Version info: :h4
 
 The LAMMPS "version" is the date when it was released, such as 1 May
 2010. LAMMPS is updated continuously.  Whenever we fix a bug or add a
 feature, we release it immediately, and post a notice on "this page of
 the WWW site"_bug.  Each dated copy of LAMMPS contains all the
 features and bug-fixes up to and including that version date. The
 version date is printed to the screen and logfile every time you run
 LAMMPS. It is also in the file src/version.h and in the LAMMPS
 directory name created when you unpack a tarball, and at the top of
 the first page of the manual (this page).
 
 LAMMPS-ICMS is an experimental variant of LAMMPS with additional
 features made available for testing before they will be submitted
 for inclusion into the official LAMMPS tree. The source code is 
 based on the official LAMMPS svn repository mirror at the Institute
 for Computational Molecular Science at Temple University and generally
 kept up-to-date as much as possible. Sometimes, e.g. when additional
 development work is needed to adapt the upstream changes into
 LAMMPS-ICMS it can take longer until synchronization; and occasionally,
 e.g. in case of the rewrite of the multi-threading support, the
 development will be halted except for important bugfixes until
 all features of LAMMPS-ICMS fully compatible with the upstream
 version or replaced by alternate implementations.
 
 If you browse the HTML doc pages on the LAMMPS WWW site, they always
 describe the most current version of upstream LAMMPS, but may be
 missing some new features in LAMMPS-ICMS. :ulb,l
 
 If you browse the HTML doc pages included in your tarball, they
 describe the version you have, however, not all new features in
 LAMMPS-ICMS are documented immediately. :l
 
 The "PDF file"_Manual.pdf on the WWW site or in the tarball is updated
 about once per month.  This is because it is large, and we don't want
 it to be part of every patch. :l
 
 There is also a "Developer.pdf"_Developer.pdf file in the doc
 directory, which describes the internal structure and algorithms of
 LAMMPS.  :ule,l
 
 LAMMPS stands for Large-scale Atomic/Molecular Massively Parallel
 Simulator.
 
 LAMMPS is a classical molecular dynamics simulation code designed to
 run efficiently on parallel computers.  It was developed at Sandia
 National Laboratories, a US Department of Energy facility, with
 funding from the DOE.  It is an open-source code, distributed freely
 under the terms of the GNU Public License (GPL).
 
 The primary developers of LAMMPS are "Steve Plimpton"_sjp, Aidan
 Thompson, and Paul Crozier who can be contacted at
 sjplimp,athomps,pscrozi at sandia.gov.  The "LAMMPS WWW Site"_lws at
 http://lammps.sandia.gov has more information about the code and its
 uses.
 
 :link(bug,http://lammps.sandia.gov/bug.html)
 :link(sjp,http://www.sandia.gov/~sjplimp)
 
 :line
 
 The LAMMPS documentation is organized into the following sections.  If
 you find errors or omissions in this manual or have suggestions for
 useful information to add, please send an email to the developers so
 we can improve the LAMMPS documentation.
 
 Once you are familiar with LAMMPS, you may want to bookmark "this
 page"_Section_commands.html#comm at Section_commands.html#comm since
 it gives quick access to documentation for all LAMMPS commands.
 
 "PDF file"_Manual.pdf of the entire manual, generated by
 "htmldoc"_http://www.easysw.com/htmldoc
 
 "Introduction"_Section_intro.html :olb,l
   1.1 "What is LAMMPS"_intro_1 :ulb,b
   1.2 "LAMMPS features"_intro_2 :b
   1.3 "LAMMPS non-features"_intro_3 :b
   1.4 "Open source distribution"_intro_4 :b
   1.5 "Acknowledgments and citations"_intro_5 :ule,b
 "Getting started"_Section_start.html :l
   2.1 "What's in the LAMMPS distribution"_start_1 :ulb,b
   2.2 "Making LAMMPS"_start_2 :b
   2.3 "Making LAMMPS with optional packages"_start_3 :b
   2.4 "Building LAMMPS via the Make.py script"_start_4 :b
   2.5 "Building LAMMPS as a library"_start_5 :b
   2.6 "Running LAMMPS"_start_6 :b
   2.7 "Command-line options"_start_7 :b
   2.8 "Screen output"_start_8 :b
   2.9 "Tips for users of previous versions"_start_9 :ule,b
 "Commands"_Section_commands.html :l
   3.1 "LAMMPS input script"_cmd_1 :ulb,b
   3.2 "Parsing rules"_cmd_2 :b
   3.3 "Input script structure"_cmd_3 :b
   3.4 "Commands listed by category"_cmd_4 :b
   3.5 "Commands listed alphabetically"_cmd_5 :ule,b
 "Packages"_Section_packages.html :l
   4.1 "Standard packages"_pkg_1 :ulb,b
   4.2 "User packages"_pkg_2 :ule,b
 "Accelerating LAMMPS performance"_Section_accelerate.html :l
   5.1 "Measuring performance"_acc_1 :ulb,b
   5.2 "General strategies"_acc_2 :b
   5.3 "Packages with optimized styles"_acc_3 :b
   5.4 "OPT package"_acc_4 :b
   5.5 "USER-OMP package"_acc_5 :b
   5.6 "GPU package"_acc_6 :b
   5.7 "USER-CUDA package"_acc_7 :b
   5.8 "Comparison of GPU and USER-CUDA packages"_acc_8 :ule,b
 "How-to discussions"_Section_howto.html :l
   6.1 "Restarting a simulation"_howto_1 :ulb,b
   6.2 "2d simulations"_howto_2 :b
   6.3 "CHARMM and AMBER force fields"_howto_3 :b
   6.4 "Running multiple simulations from one input script"_howto_4 :b
   6.5 "Multi-replica simulations"_howto_5 :b
   6.6 "Granular models"_howto_6 :b
   6.7 "TIP3P water model"_howto_7 :b
   6.8 "TIP4P water model"_howto_8 :b
   6.9 "SPC water model"_howto_9 :b
   6.10 "Coupling LAMMPS to other codes"_howto_10 :b
   6.11 "Visualizing LAMMPS snapshots"_howto_11 :b
   6.12 "Triclinic (non-orthogonal) simulation boxes"_howto_12 :b
   6.13 "NEMD simulations"_howto_13 :b
   6.14 "Finite-size spherical and aspherical particles"_howto_14 :b
   6.15 "Output from LAMMPS (thermo, dumps, computes, fixes, variables)"_howto_15 :b
   6.16 "Thermostatting, barostatting, and compute temperature"_howto_16 :b
   6.17 "Walls"_howto_17 :b
   6.18 "Elastic constants"_howto_18 :b
   6.19 "Library interface to LAMMPS"_howto_19 :b
   6.20 "Calculating thermal conductivity"_howto_20 :b
   6.21 "Calculating viscosity"_howto_21 :ule,b
 "Example problems"_Section_example.html :l
 "Performance & scalability"_Section_perf.html :l
 "Additional tools"_Section_tools.html :l
 "Modifying & extending LAMMPS"_Section_modify.html :l
   10.1 "Atom styles"_mod_1 :ulb,b
   10.2 "Bond, angle, dihedral, improper potentials"_mod_2 :b
   10.3 "Compute styles"_mod_3 :b
   10.4 "Dump styles"_mod_4 :b
   10.5 "Dump custom output options"_mod_5 :b
   10.6 "Fix styles"_mod_6 :b
   10.7 "Input script commands"_mod_7 :b
   10.8 "Kspace computations"_mod_8 :b
   10.9 "Minimization styles"_mod_9 :b
   10.10 "Pairwise potentials"_mod_10 :b
   10.11 "Region styles"_mod_11 :b
   10.12 "Body styles"_mod_12 :b
   10.13 "Thermodynamic output options"_mod_13 :b
   10.14 "Variable options"_mod_14 :b
   10.15 "Submitting new features for inclusion in LAMMPS"_mod_15 :ule,b
 "Python interface"_Section_python.html :l
   11.1 "Building LAMMPS as a shared library"_py_1 :ulb,b
   11.2 "Installing the Python wrapper into Python"_py_2 :b
   11.3 "Extending Python with MPI to run in parallel"_py_3 :b
   11.4 "Testing the Python-LAMMPS interface"_py_4 :b
   11.5 "Using LAMMPS from Python"_py_5 :b
   11.6 "Example Python scripts that use LAMMPS"_py_6 :ule,b
 "Errors"_Section_errors.html :l
   12.1 "Common problems"_err_1 :ulb,b
   12.2 "Reporting bugs"_err_2 :b
   12.3 "Error & warning messages"_err_3 :ule,b
 "Future and history"_Section_history.html :l
   13.1 "Coming attractions"_hist_1 :ulb,b
   13.2 "Past versions"_hist_2 :ule,b
 :ole
 
 :link(intro_1,Section_intro.html#intro_1)
 :link(intro_2,Section_intro.html#intro_2)
 :link(intro_3,Section_intro.html#intro_3)
 :link(intro_4,Section_intro.html#intro_4)
 :link(intro_5,Section_intro.html#intro_5)
 
 :link(start_1,Section_start.html#start_1)
 :link(start_2,Section_start.html#start_2)
 :link(start_3,Section_start.html#start_3)
 :link(start_4,Section_start.html#start_4)
 :link(start_5,Section_start.html#start_5)
 :link(start_6,Section_start.html#start_6)
 :link(start_7,Section_start.html#start_7)
 :link(start_8,Section_start.html#start_8)
 :link(start_9,Section_start.html#start_9)
 
 :link(cmd_1,Section_commands.html#cmd_1)
 :link(cmd_2,Section_commands.html#cmd_2)
 :link(cmd_3,Section_commands.html#cmd_3)
 :link(cmd_4,Section_commands.html#cmd_4)
 :link(cmd_5,Section_commands.html#cmd_5)
 
 :link(pkg_1,Section_packages.html#pkg_1)
 :link(pkg_2,Section_packages.html#pkg_2)
 
 :link(acc_1,Section_accelerate.html#acc_1)
 :link(acc_2,Section_accelerate.html#acc_2)
 :link(acc_3,Section_accelerate.html#acc_3)
 :link(acc_4,Section_accelerate.html#acc_4)
 :link(acc_5,Section_accelerate.html#acc_5)
 :link(acc_6,Section_accelerate.html#acc_6)
 :link(acc_7,Section_accelerate.html#acc_7)
 :link(acc_8,Section_accelerate.html#acc_8)
 
 :link(howto_1,Section_howto.html#howto_1)
 :link(howto_2,Section_howto.html#howto_2)
 :link(howto_3,Section_howto.html#howto_3)
 :link(howto_4,Section_howto.html#howto_4)
 :link(howto_5,Section_howto.html#howto_5)
 :link(howto_6,Section_howto.html#howto_6)
 :link(howto_7,Section_howto.html#howto_7)
 :link(howto_8,Section_howto.html#howto_8)
 :link(howto_9,Section_howto.html#howto_9)
 :link(howto_10,Section_howto.html#howto_10)
 :link(howto_11,Section_howto.html#howto_11)
 :link(howto_12,Section_howto.html#howto_12)
 :link(howto_13,Section_howto.html#howto_13)
 :link(howto_14,Section_howto.html#howto_14)
 :link(howto_15,Section_howto.html#howto_15)
 :link(howto_16,Section_howto.html#howto_16)
 :link(howto_17,Section_howto.html#howto_17)
 :link(howto_18,Section_howto.html#howto_18)
 :link(howto_19,Section_howto.html#howto_19)
 :link(howto_20,Section_howto.html#howto_20)
 :link(howto_21,Section_howto.html#howto_21)
 
 :link(mod_1,Section_modify.html#mod_1)
 :link(mod_2,Section_modify.html#mod_2)
 :link(mod_3,Section_modify.html#mod_3)
 :link(mod_4,Section_modify.html#mod_4)
 :link(mod_5,Section_modify.html#mod_5)
 :link(mod_6,Section_modify.html#mod_6)
 :link(mod_7,Section_modify.html#mod_7)
 :link(mod_8,Section_modify.html#mod_8)
 :link(mod_9,Section_modify.html#mod_9)
 :link(mod_10,Section_modify.html#mod_10)
 :link(mod_11,Section_modify.html#mod_11)
 :link(mod_12,Section_modify.html#mod_12)
 :link(mod_13,Section_modify.html#mod_13)
 :link(mod_14,Section_modify.html#mod_14)
 :link(mod_15,Section_modify.html#mod_15)
 
 :link(py_1,Section_python.html#py_1)
 :link(py_2,Section_python.html#py_2)
 :link(py_3,Section_python.html#py_3)
 :link(py_4,Section_python.html#py_4)
 :link(py_5,Section_python.html#py_5)
 :link(py_6,Section_python.html#py_6)
 
 :link(err_1,Section_errors.html#err_1)
 :link(err_2,Section_errors.html#err_2)
 :link(err_3,Section_errors.html#err_3)
 
 :link(hist_1,Section_history.html#hist_1)
 :link(hist_2,Section_history.html#hist_2)
 
 </BODY>
diff --git a/doc/delete_atoms.html b/doc/delete_atoms.html
index 02cc1e272..3ea9f9d36 100644
--- a/doc/delete_atoms.html
+++ b/doc/delete_atoms.html
@@ -1,113 +1,123 @@
 <HTML>
 <CENTER><A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> - <A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> 
 </CENTER>
 
 
 
 
 
 
 <HR>
 
 <H3>delete_atoms command 
 </H3>
 <P><B>Syntax:</B>
 </P>
 <PRE>delete_atoms style args keyword value ... 
 </PRE>
 <UL><LI>style = <I>group</I> or <I>region</I> or <I>overlap</I> or <I>porosity</I> 
 
 <PRE>  <I>group</I> args = group-ID
   <I>region</I> args = region-ID
   <I>overlap</I> args = cutoff group1-ID group2-ID
     cutoff = delete one atom from pairs of atoms within the cutoff (distance units)
     group1-ID = one atom in pair must be in this group
     group2-ID = other atom in pair must be in this group
   <I>porosity</I> args = region-ID fraction seed
     region-ID = region within which to perform deletions
     fraction = delete this fraction of atoms
     seed = random number seed (positive integer) 
 </PRE>
 <LI>zero or more keyword/value pairs may be appended 
 
-<LI>keyword = <I>compress</I> 
+<LI>keyword = <I>compress</I> or <I>mol</I> 
 
-<PRE>  <I>compress</I> value = <I>no</I> or <I>yes</I> 
+<PRE>  <I>compress</I> value = <I>no</I> or <I>yes</I>
+  <I>mol</I> value = <I>no</I> or <I>yes</I> 
 </PRE>
 
 </UL>
 <P><B>Examples:</B>
 </P>
 <PRE>delete_atoms group edge
 delete_atoms region sphere compress no
 delete_atoms overlap 0.3 all all
 delete_atoms overlap 0.5 solvent colloid
 delete_atoms porosity cube 0.1 482793 
 </PRE>
 <P><B>Description:</B>
 </P>
 <P>Delete the specified atoms.  This command can be used to carve out
 voids from a block of material or to delete created atoms that are too
 close to each other (e.g. at a grain boundary).
 </P>
 <P>For style <I>group</I>, all atoms belonging to the group are deleted.
 </P>
 <P>For style <I>region</I>, all atoms in the region volume are deleted.
+Additional atoms can be deleted if they are in a molecule for which
+one or more atoms were deleted within the region; see the <I>mol</I>
+keyword discussion below.
 </P>
 <P>For style <I>overlap</I> pairs of atoms whose distance of separation is
 within the specified cutoff distance are searched for, and one of the
 2 atoms is deleted.  Only pairs where one of the two atoms is in the
 first group specified and the other atom is in the second group are
 considered.  The atom that is in the first group is the one that is
 deleted.
 </P>
 <P>Note that it is OK for the two group IDs to be the same (e.g. group
 <I>all</I>), or for some atoms to be members of both groups.  In these
 cases, either atom in the pair may be deleted.  Also note that if
 there are atoms which are members of both groups, the only guarantee
 is that at the end of the deletion operation, enough deletions will
 have occurred that no atom pairs within the cutoff will remain
 (subject to the group restriction).  There is no guarantee that the
 minimum number of atoms will be deleted, or that the same atoms will
 be deleted when running on different numbers of processors.
 </P>
 <P>For style <I>porosity</I> a specified <I>fraction</I> of atoms are deleted
 within the specified region.  For example, if fraction is 0.1, then
 10% of the atoms will be deleted.  The atoms to delete are chosen
 randomly.  There is no guarantee that the exact fraction of atoms will
 be deleted, or that the same atoms will be deleted when running on
 different numbers of processors.
 </P>
 <P>If the <I>compress</I> keyword is set to <I>yes</I>, then after atoms are
 deleted, then atom IDs are re-assigned so that they run from 1 to the
 number of atoms in the system.  This is not done for molecular systems
 (see the <A HREF = "atom_style.html">atom_style</A> command), regardless of the
 <I>compress</I> setting, since it would foul up the bond connectivity that
 has already been assigned.
 </P>
+<P>It the <I>mol</I> keyword is set to <I>yes</I>, then for every atom that is
+deleted, all other atoms in the same molecule will also be deleted.
+This keyword is only used by the <I>region</I> style.  It is a way to
+insure that entire molecules are deleted instead of only a subset of
+atoms in a bond or angle or dihedral interaction.
+</P>
 <P><B>Restrictions:</B>
 </P>
 <P>The <I>overlap</I> styles requires inter-processor communication to acquire
 ghost atoms and build a neighbor list.  This means that your system
 must be ready to perform a simulation before using this command (force
 fields setup, atom masses set, etc).  Since a neighbor list is used to
 find overlapping atom pairs, it also means that you must define a
 <A HREF = "pair_style.html">pair style</A> with force cutoffs greater than or equal
 to the desired overlap cutoff between pairs of relevant atom types,
 even though the pair potential will not be evaluated.
 </P>
 <P>If the <A HREF = "special_bonds.html">special_bonds</A> command is used with a
 setting of 0, then a pair of bonded atoms (1-2, 1-3, or 1-4) will not
 appear in the neighbor list, and thus will not be considered for
 deletion by the <I>overlap</I> styles.  You probably don't want to be
 deleting one atom in a bonded pair anyway.
 </P>
 <P><B>Related commands:</B>
 </P>
 <P><A HREF = "create_atoms.html">create_atoms</A>
 </P>
 <P><B>Default:</B>
 </P>
-<P>The option defaults are compress = yes.
+<P>The option defaults are compress = yes and mol = no.
 </P>
 </HTML>
diff --git a/doc/delete_atoms.txt b/doc/delete_atoms.txt
index 5a613a352..7c4bd2bcf 100644
--- a/doc/delete_atoms.txt
+++ b/doc/delete_atoms.txt
@@ -1,103 +1,113 @@
 "LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
 
 :link(lws,http://lammps.sandia.gov)
 :link(ld,Manual.html)
 :link(lc,Section_commands.html#comm)
 
 :line
 
 delete_atoms command :h3
 
 [Syntax:]
 
 delete_atoms style args keyword value ... :pre
 
 style = {group} or {region} or {overlap} or {porosity} :ulb,l
   {group} args = group-ID
   {region} args = region-ID
   {overlap} args = cutoff group1-ID group2-ID
     cutoff = delete one atom from pairs of atoms within the cutoff (distance units)
     group1-ID = one atom in pair must be in this group
     group2-ID = other atom in pair must be in this group
   {porosity} args = region-ID fraction seed
     region-ID = region within which to perform deletions
     fraction = delete this fraction of atoms
     seed = random number seed (positive integer) :pre
 zero or more keyword/value pairs may be appended :l
-keyword = {compress} :l
-  {compress} value = {no} or {yes} :pre
+keyword = {compress} or {mol} :l
+  {compress} value = {no} or {yes}
+  {mol} value = {no} or {yes} :pre
 :ule
 
 [Examples:]
 
 delete_atoms group edge
 delete_atoms region sphere compress no
 delete_atoms overlap 0.3 all all
 delete_atoms overlap 0.5 solvent colloid
 delete_atoms porosity cube 0.1 482793 :pre
 
 [Description:]
 
 Delete the specified atoms.  This command can be used to carve out
 voids from a block of material or to delete created atoms that are too
 close to each other (e.g. at a grain boundary).
 
 For style {group}, all atoms belonging to the group are deleted.
 
 For style {region}, all atoms in the region volume are deleted.
+Additional atoms can be deleted if they are in a molecule for which
+one or more atoms were deleted within the region; see the {mol}
+keyword discussion below.
 
 For style {overlap} pairs of atoms whose distance of separation is
 within the specified cutoff distance are searched for, and one of the
 2 atoms is deleted.  Only pairs where one of the two atoms is in the
 first group specified and the other atom is in the second group are
 considered.  The atom that is in the first group is the one that is
 deleted.
 
 Note that it is OK for the two group IDs to be the same (e.g. group
 {all}), or for some atoms to be members of both groups.  In these
 cases, either atom in the pair may be deleted.  Also note that if
 there are atoms which are members of both groups, the only guarantee
 is that at the end of the deletion operation, enough deletions will
 have occurred that no atom pairs within the cutoff will remain
 (subject to the group restriction).  There is no guarantee that the
 minimum number of atoms will be deleted, or that the same atoms will
 be deleted when running on different numbers of processors.
 
 For style {porosity} a specified {fraction} of atoms are deleted
 within the specified region.  For example, if fraction is 0.1, then
 10% of the atoms will be deleted.  The atoms to delete are chosen
 randomly.  There is no guarantee that the exact fraction of atoms will
 be deleted, or that the same atoms will be deleted when running on
 different numbers of processors.
 
 If the {compress} keyword is set to {yes}, then after atoms are
 deleted, then atom IDs are re-assigned so that they run from 1 to the
 number of atoms in the system.  This is not done for molecular systems
 (see the "atom_style"_atom_style.html command), regardless of the
 {compress} setting, since it would foul up the bond connectivity that
 has already been assigned.
 
+It the {mol} keyword is set to {yes}, then for every atom that is
+deleted, all other atoms in the same molecule will also be deleted.
+This keyword is only used by the {region} style.  It is a way to
+insure that entire molecules are deleted instead of only a subset of
+atoms in a bond or angle or dihedral interaction.
+
 [Restrictions:]
 
 The {overlap} styles requires inter-processor communication to acquire
 ghost atoms and build a neighbor list.  This means that your system
 must be ready to perform a simulation before using this command (force
 fields setup, atom masses set, etc).  Since a neighbor list is used to
 find overlapping atom pairs, it also means that you must define a
 "pair style"_pair_style.html with force cutoffs greater than or equal
 to the desired overlap cutoff between pairs of relevant atom types,
 even though the pair potential will not be evaluated.
 
 If the "special_bonds"_special_bonds.html command is used with a
 setting of 0, then a pair of bonded atoms (1-2, 1-3, or 1-4) will not
 appear in the neighbor list, and thus will not be considered for
 deletion by the {overlap} styles.  You probably don't want to be
 deleting one atom in a bonded pair anyway.
 
 [Related commands:]
 
 "create_atoms"_create_atoms.html
 
 [Default:]
 
-The option defaults are compress = yes.
+The option defaults are compress = yes and mol = no.
diff --git a/doc/fix_gcmc.html b/doc/fix_gcmc.html
index c8a38e812..4be3248a4 100644
--- a/doc/fix_gcmc.html
+++ b/doc/fix_gcmc.html
@@ -1,259 +1,259 @@
 <HTML>
 <CENTER><A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> - <A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> 
 </CENTER>
 
 
 
 
 
 
 <HR>
 
 <H3>fix gcmc command 
 </H3>
 <P><B>Syntax:</B>
 </P>
 <PRE>fix ID group-ID gcmc N X M type seed T mu displace keyword values ... 
 </PRE>
 <UL><LI>ID, group-ID are documented in <A HREF = "fix.html">fix</A> command 
 
 <LI>gcmc = style name of this fix command 
 
 <LI>N = invoke this fix every N steps 
 
 <LI>X = number of exchanges to attempt every N steps 
 
 <LI>M = number of MC displacements to attempt every N steps 
 
 <LI>type = atom type or molecule ID of exchanged gas 
 
 <LI>seed = random # seed (positive integer) 
 
 <LI>T = temperature of the ideal gas reservoir (temperature units) 
 
 <LI>mu = chemical potential of the ideal gas reservoir (energy units) 
 
 <LI>displace = maximum Monte Carlo displacement distance (length units) 
 
 <LI>zero or more keyword/value pairs may be appended to args 
 
 <LI>keyword = <I>molecule</I>, <I>region</I>, <I>maxangle</I>, <I>pressure</I>, or <I>fugacity_coeff</I> 
 
 <PRE>  <I>molecule</I> value = <I>no</I> or <I>yes</I>
   <I>region</I> value = region-ID
     region-ID = ID of region to use as an exchange/move volume 
   <I>maxangle</I> value = maximum molecular rotation angle (degrees) 
   <I>pressure</I> value = pressue of the gas reservoir (pressure units)
   <I>fugacity_coeff</I> value = fugacity coefficient of the gas reservoir (unitless) 
 </PRE>
 
 </UL>
 <P><B>Examples:</B>
 </P>
 <PRE>fix 2 gas gcmc 10 1000 1000 2 29494 298.0 -0.5 0.01
-fix 3 Kr gcmc 10 100 100 1 3456543 3.0 -2.5 0.1 molecule yes maxrot 180
+fix 3 Kr gcmc 10 100 100 1 3456543 3.0 -2.5 0.1 molecule yes maxangle 180
 fix 4 my_gas gcmc 1 10 10 1 123456543 300.0 -12.5 1.0 region disk 
 </PRE>
 <P><B>Description:</B>
 </P>
 <P>This fix performs grand canonical Monte Carlo (GCMC) exchanges of
 atoms or molecules of the given type with an imaginary ideal gas reservoir at
 the specified T and chemical potential (mu) as discussed in
 <A HREF = "#Frenkel">(Frenkel)</A>. If used with the <A HREF = "fix_nh.html">fix nvt</A> command,
 simulations in the grand canonical enemble (muVT, constant chemical
 potential, constant volume, and constant temperature) can be
 performed.  Specific uses include computing isotherms in microporous
 materials, or computing vapor-liquid coexistence curves.
 </P>
 <P>Perform up to X exchanges of gas atoms or molecules of the given type 
 between the simulation domain and the imaginary reservoir every N 
 timesteps. Also perform M Monte Carlo displacements or rotations 
 (for molecules) of gas of the given type within the simulation domain.
 M should typically be chosen to be approximately equal to the expected
 number of gas atoms or molecules of the given type within the domain, 
 which will result in roughly one MC translation per atom or molecule 
 per MC cycle.
 </P>
 <P>For MC moves of molecular gasses, rotations and translations are each 
 attempted with 50% probability. For MC moves of atomic gasses, 
 translations are attempted 100% of the time. For MC exchanges of either
 molecular or atomic gasses, deletions and insertions are each attempted
 with 50% probability.
 </P>
 <P>This fix cannot be used to perform MC insertions of gas atoms or
 molecules other than the exchanged type, but MC deletions, translations,
 and rotations can be performed on any atom/molecule in the fix group. 
 All atoms in the simulation domain can be moved using regular time 
 integration displacements, e.g. via <A HREF = "fix_nvt.html">fix_nvt</A>, resulting
 in a hybrid GCMC+MD simulation. A smaller-than-usual timestep size 
 may be needed when running such a hybrid simulation, especially if 
 the inserted molecules are not well equilibrated.
 </P>
 <P>This command may optionally use the <I>region</I> keyword to define an 
 exchange and move volume.  The specified region must have been 
 previously defined with a <A HREF = "region.html">region</A> command.  It must be 
 defined with side = <I>in</I>.  Insertion attempts occur only within the 
 specified region. Move and deletion attempt candidates are selected 
 from gas atoms or molecules within the region. If no candidate can be 
 found within the specified region after randomly selecting candidates 
 1000 times, the move or deletion attempt is considered a failure. Moves 
 must start within the specified region, but may move the atom or molecule
 slightly outside of the region.
 </P>
 <P>If used with <A HREF = "fix_nvt.html">fix_nvt</A>, the temperature of the imaginary
 reservoir, T, should be set to be equivalent to the target temperature
 used in <A HREF = "fix_nvt.html">fix_nvt</A>. Otherwise, the imaginary reservoir
 will not be in thermal equilibrium with the simulation domain.
 </P>
 <P>Note that neighbor lists are re-built every timestep that this fix is
 invoked, so you should not set N to be too small.  However, periodic
 rebuilds are necessary in order to avoid dangerous rebuilds and missed
 interactions. Specifically, avoid performing so many MC displacements
 per timestep that atoms can move beyond the neighbor list skin
 distance. See the <A HREF = "neighbor.html">neighbor</A> command for details.
 </P>
 <P>When an atom or molecule is to be inserted, its center-of-mass 
 coordinates are chosen as a random position within the current 
 simulation domain, and new atom velocities are randomly chosen 
 from the specified temperature distribution given by T.  Relative 
 coordinates for atoms in a molecule are taken from the template
 molecule provided by the user. A random initial rotation is used in the
 case of molecule insertions.
 </P>
 <P>If the setting for the <I>molecule</I> keyword is <I>no</I>, then only single
 atoms are exchanged.  In this case, you should ensure you do not
 delete only a portion of a molecule (only some of its atoms), or
 LAMMPS will soon generate an error when it tries to find those atoms.
 LAMMPS will warn you if any of the atoms eligible for deletion have a
 non-zero molecule ID, but does not check for this at the time of
 deletion.
 </P>
 <P>If the setting for the <I>molecule</I> keyword is <I>yes</I>, entire molecules
 are exchanged. The user must supply a model molecule in the data
 file to use as a template for exchanges, and that molecule's number
 must be given in the fix GCMC command as the "type" of the exchanged
 gas. Note that the model molecule must be present whenever the fix 
 is initialized. This is a limitation that will likely be remedied
 in the not-to-distant future.
 </P>
 <P>Optionally, users may specify the maximum rotation angle for 
 molecular rotations using the <I>maxangle</I> keyword and specifying
 the angle in degrees. The specified angle will apply to all three 
 Euler angles used internally to define the rotation matrix for
 molecular rotations. The max angle can be set to zero, but rotations
 will be pointless. Note that the default is ten degrees for each 
 Euler angle.
 </P>
 <P>For atomic gasses, inserted atoms have the specified atom type, but
 deleted atoms are any atoms that have been inserted or that belong 
 to the user-specified fix group. For molecular gasses, exchanged 
 molecules use the same atom types as in the template molecule 
 supplied by the user.  In both cases, exchanged
 atoms/molecules are assigned to two groups: the default group "all"
 and the group specified in the fix gcmc command (which can also be 
 "all"). 
 </P>
 <P>The gas reservoir pressure can be specified using the <I>pressure</I> 
 keyword, in which case the user-specified chemical potential is 
 ignored. For non-ideal gas reservoirs, the user may also specify the 
 fugacity coefficient using the <I>fugacity_coeff</I> keyword.
 </P>
 <P>Use of this fix typically will cause the number of atoms to fluctuate,
 therefore, you will want to use the
 <A HREF = "compute_modify.html">compute_modify</A> command to insure that the
 current number of atoms is used as a normalizing factor each time
 temperature is computed.  Here is the necessary command:
 </P>
 <PRE>compute_modify thermo_temp dynamic yes 
 </PRE>
 <P>If LJ units are used, note that a value of 0.18292026 is used by this
 fix as the reduced value for Planck's constant.  This value was
 derived from LJ paramters for argon, where h* = h/sqrt(sigma^2 *
 epsilon * mass), sigma = 3.429 angstroms, epsilon/k = 121.85 K, and
 mass = 39.948 amu.
 </P>
 <P><B>Restart, fix_modify, output, run start/stop, minimize info:</B>
 </P>
 <P>This fix writes the state of the deposition to <A HREF = "restart.html">binary restart
 files</A>.  This includes information about the random
 number generator seed, the next timestep for MC exchanges, etc.  See
 the <A HREF = "read_restart.html">read_restart</A> command for info on how to
 re-specify a fix in an input script that reads a restart file, so that
 the operation of the fix continues in an uninterrupted fashion.
 </P>
 <P>None of the <A HREF = "fix_modify.html">fix_modify</A> options are relevant to this
 fix.
 </P>
 <P>This fix computes a global vector of length 6, which can be accessed
 by various <A HREF = "Section_howto.html#howto_15">output commands</A>.  The vector
 values are the following global cummulative quantities:
 </P>
 <UL><LI>1 = displacement attempts
 <LI>2 = displacement successes
 <LI>3 = insertion attempts
 <LI>4 = insertion successes 
 <LI>5 = deletion attempts
 <LI>6 = deletion successes
 <LI>7 = rotation attempts
 <LI>8 = rotation successes 
 </UL>
 <P>The vector values calculated by this fix are "extensive".
 </P>
 <P>No parameter of this fix can be used with the <I>start/stop</I> keywords of
 the <A HREF = "run.html">run</A> command.  This fix is not invoked during <A HREF = "minimize.html">energy
 minimization</A>.
 </P>
 <P><B>Restrictions:</B>
 </P>
 <P>This fix is part of the MC package.  It is only enabled if LAMMPS was
 built with that package.  See the <A HREF = "Section_start.html#start_3">Making
 LAMMPS</A> section for more info.
 </P>
 <P>Do not set "neigh_modify once yes" or else this fix will never be
 called.  Reneighboring is required.
 </P>
 <P>Only pairwise interactions, as defined by the
 <A HREF = "pair_style.html">pair_style</A> command, are included in this
 calculation.  Long-range interactions due to a
 <A HREF = "kspace_style.html">kspace_style</A> command are not included.  Not all
 pair potentials can be evaluated in a pairwise mode as required by
 this fix.  For example, 3-body potentials, such as
 <A HREF = "pair_tersoff.html">Tersoff</A> and <A HREF = "pair_sw.html">Stillinger-Weber</A> cannot
 be used.  <A HREF = "pair_eam.html">EAM</A> potentials for metals only include the
 pair potential portion of the EAM interaction, not the embedding term.
 </P>
 <P>Can be run in parallel, but aspects of the GCMC part will not scale 
 well in parallel. Only usable for 3D simulations with orthogonal 
 simulation cells.
 </P>
 <P>Note that very lengthy simulations involving insertions/deletions of
 billions of gas molecules may run out of atom or molecule IDs and
 trigger an error, so it is better to run multiple shorter-duration 
 simulations. Likewise, very large molecules have not been tested
 and may turn out to be problematic.
 </P>
 <P>Use of multiple fix gcmc commands in the same input script can be 
 problematic if using a template molecule. The issue is that the 
 user-referenced template molecule in the second fix gcmc command
 may no longer exist since it might have been deleted by the first
 fix gcmc command. An existing template molecule will need to be
 referenced by the user for each subsequent fix gcmc command.
 </P>
 <P><B>Related commands:</B>
 </P>
 <P><A HREF = "fix_nvt.html">fix_nvt</A>, <A HREF = "neighbor.html">neighbor</A>, 
 <A HREF = "fix_deposit.html">fix_deposit</A>, <A HREF = "fix_evaporate.html">fix_evaporate</A>,
 <A HREF = "delete_atoms.html">delete_atoms</A>
 </P>
 <P><B>Default:</B>
 </P>
 <P>The option defaults are molecule = no, maxangle = 10.
 </P>
 <HR>
 
 <A NAME = "Frenkel"></A>
 
 <P><B>(Frenkel)</B> Frenkel and Smit, Understanding Molecular Simulation, 
 Academic Press, London, 2002.
 </P>
 </HTML>
diff --git a/doc/fix_gcmc.txt b/doc/fix_gcmc.txt
index 02f879105..1f7af8d7a 100644
--- a/doc/fix_gcmc.txt
+++ b/doc/fix_gcmc.txt
@@ -1,240 +1,240 @@
 "LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
 
 :link(lws,http://lammps.sandia.gov)
 :link(ld,Manual.html)
 :link(lc,Section_commands.html#comm)
 
 :line
 
 fix gcmc command :h3
 
 [Syntax:]
 
 fix ID group-ID gcmc N X M type seed T mu displace keyword values ... :pre
 
 ID, group-ID are documented in "fix"_fix.html command :ulb,l
 gcmc = style name of this fix command :l
 N = invoke this fix every N steps :l
 X = number of exchanges to attempt every N steps :l
 M = number of MC displacements to attempt every N steps :l
 type = atom type or molecule ID of exchanged gas :l
 seed = random # seed (positive integer) :l
 T = temperature of the ideal gas reservoir (temperature units) :l
 mu = chemical potential of the ideal gas reservoir (energy units) :l
 displace = maximum Monte Carlo displacement distance (length units) :l
 zero or more keyword/value pairs may be appended to args :l
 keyword = {molecule}, {region}, {maxangle}, {pressure}, or {fugacity_coeff} :l
   {molecule} value = {no} or {yes}
   {region} value = region-ID
     region-ID = ID of region to use as an exchange/move volume 
   {maxangle} value = maximum molecular rotation angle (degrees) 
   {pressure} value = pressue of the gas reservoir (pressure units)
   {fugacity_coeff} value = fugacity coefficient of the gas reservoir (unitless) :pre
 :ule
 
 [Examples:]
 
 fix 2 gas gcmc 10 1000 1000 2 29494 298.0 -0.5 0.01
-fix 3 Kr gcmc 10 100 100 1 3456543 3.0 -2.5 0.1 molecule yes maxrot 180
+fix 3 Kr gcmc 10 100 100 1 3456543 3.0 -2.5 0.1 molecule yes maxangle 180
 fix 4 my_gas gcmc 1 10 10 1 123456543 300.0 -12.5 1.0 region disk :pre
 
 [Description:]
 
 This fix performs grand canonical Monte Carlo (GCMC) exchanges of
 atoms or molecules of the given type with an imaginary ideal gas reservoir at
 the specified T and chemical potential (mu) as discussed in
 "(Frenkel)"_#Frenkel. If used with the "fix nvt"_fix_nh.html command,
 simulations in the grand canonical enemble (muVT, constant chemical
 potential, constant volume, and constant temperature) can be
 performed.  Specific uses include computing isotherms in microporous
 materials, or computing vapor-liquid coexistence curves.
 
 Perform up to X exchanges of gas atoms or molecules of the given type 
 between the simulation domain and the imaginary reservoir every N 
 timesteps. Also perform M Monte Carlo displacements or rotations 
 (for molecules) of gas of the given type within the simulation domain.
 M should typically be chosen to be approximately equal to the expected
 number of gas atoms or molecules of the given type within the domain, 
 which will result in roughly one MC translation per atom or molecule 
 per MC cycle.
 
 For MC moves of molecular gasses, rotations and translations are each 
 attempted with 50% probability. For MC moves of atomic gasses, 
 translations are attempted 100% of the time. For MC exchanges of either
 molecular or atomic gasses, deletions and insertions are each attempted
 with 50% probability.
 
 This fix cannot be used to perform MC insertions of gas atoms or
 molecules other than the exchanged type, but MC deletions, translations,
 and rotations can be performed on any atom/molecule in the fix group. 
 All atoms in the simulation domain can be moved using regular time 
 integration displacements, e.g. via "fix_nvt"_fix_nvt.html, resulting
 in a hybrid GCMC+MD simulation. A smaller-than-usual timestep size 
 may be needed when running such a hybrid simulation, especially if 
 the inserted molecules are not well equilibrated.
 
 This command may optionally use the {region} keyword to define an 
 exchange and move volume.  The specified region must have been 
 previously defined with a "region"_region.html command.  It must be 
 defined with side = {in}.  Insertion attempts occur only within the 
 specified region. Move and deletion attempt candidates are selected 
 from gas atoms or molecules within the region. If no candidate can be 
 found within the specified region after randomly selecting candidates 
 1000 times, the move or deletion attempt is considered a failure. Moves 
 must start within the specified region, but may move the atom or molecule
 slightly outside of the region.
 
 If used with "fix_nvt"_fix_nvt.html, the temperature of the imaginary
 reservoir, T, should be set to be equivalent to the target temperature
 used in "fix_nvt"_fix_nvt.html. Otherwise, the imaginary reservoir
 will not be in thermal equilibrium with the simulation domain.
 
 Note that neighbor lists are re-built every timestep that this fix is
 invoked, so you should not set N to be too small.  However, periodic
 rebuilds are necessary in order to avoid dangerous rebuilds and missed
 interactions. Specifically, avoid performing so many MC displacements
 per timestep that atoms can move beyond the neighbor list skin
 distance. See the "neighbor"_neighbor.html command for details.
 
 When an atom or molecule is to be inserted, its center-of-mass 
 coordinates are chosen as a random position within the current 
 simulation domain, and new atom velocities are randomly chosen 
 from the specified temperature distribution given by T.  Relative 
 coordinates for atoms in a molecule are taken from the template
 molecule provided by the user. A random initial rotation is used in the
 case of molecule insertions.
 
 If the setting for the {molecule} keyword is {no}, then only single
 atoms are exchanged.  In this case, you should ensure you do not
 delete only a portion of a molecule (only some of its atoms), or
 LAMMPS will soon generate an error when it tries to find those atoms.
 LAMMPS will warn you if any of the atoms eligible for deletion have a
 non-zero molecule ID, but does not check for this at the time of
 deletion.
 
 If the setting for the {molecule} keyword is {yes}, entire molecules
 are exchanged. The user must supply a model molecule in the data
 file to use as a template for exchanges, and that molecule's number
 must be given in the fix GCMC command as the "type" of the exchanged
 gas. Note that the model molecule must be present whenever the fix 
 is initialized. This is a limitation that will likely be remedied
 in the not-to-distant future.
 
 Optionally, users may specify the maximum rotation angle for 
 molecular rotations using the {maxangle} keyword and specifying
 the angle in degrees. The specified angle will apply to all three 
 Euler angles used internally to define the rotation matrix for
 molecular rotations. The max angle can be set to zero, but rotations
 will be pointless. Note that the default is ten degrees for each 
 Euler angle.
 
 For atomic gasses, inserted atoms have the specified atom type, but
 deleted atoms are any atoms that have been inserted or that belong 
 to the user-specified fix group. For molecular gasses, exchanged 
 molecules use the same atom types as in the template molecule 
 supplied by the user.  In both cases, exchanged
 atoms/molecules are assigned to two groups: the default group "all"
 and the group specified in the fix gcmc command (which can also be 
 "all"). 
 
 The gas reservoir pressure can be specified using the {pressure} 
 keyword, in which case the user-specified chemical potential is 
 ignored. For non-ideal gas reservoirs, the user may also specify the 
 fugacity coefficient using the {fugacity_coeff} keyword.
 
 Use of this fix typically will cause the number of atoms to fluctuate,
 therefore, you will want to use the
 "compute_modify"_compute_modify.html command to insure that the
 current number of atoms is used as a normalizing factor each time
 temperature is computed.  Here is the necessary command:
 
 compute_modify thermo_temp dynamic yes :pre
 
 If LJ units are used, note that a value of 0.18292026 is used by this
 fix as the reduced value for Planck's constant.  This value was
 derived from LJ paramters for argon, where h* = h/sqrt(sigma^2 *
 epsilon * mass), sigma = 3.429 angstroms, epsilon/k = 121.85 K, and
 mass = 39.948 amu.
 
 [Restart, fix_modify, output, run start/stop, minimize info:]
 
 This fix writes the state of the deposition to "binary restart
 files"_restart.html.  This includes information about the random
 number generator seed, the next timestep for MC exchanges, etc.  See
 the "read_restart"_read_restart.html command for info on how to
 re-specify a fix in an input script that reads a restart file, so that
 the operation of the fix continues in an uninterrupted fashion.
 
 None of the "fix_modify"_fix_modify.html options are relevant to this
 fix.
 
 This fix computes a global vector of length 6, which can be accessed
 by various "output commands"_Section_howto.html#howto_15.  The vector
 values are the following global cummulative quantities:
 
 1 = displacement attempts
 2 = displacement successes
 3 = insertion attempts
 4 = insertion successes 
 5 = deletion attempts
 6 = deletion successes
 7 = rotation attempts
 8 = rotation successes :ul
 
 The vector values calculated by this fix are "extensive".
 
 No parameter of this fix can be used with the {start/stop} keywords of
 the "run"_run.html command.  This fix is not invoked during "energy
 minimization"_minimize.html.
 
 [Restrictions:]
 
 This fix is part of the MC package.  It is only enabled if LAMMPS was
 built with that package.  See the "Making
 LAMMPS"_Section_start.html#start_3 section for more info.
 
 Do not set "neigh_modify once yes" or else this fix will never be
 called.  Reneighboring is required.
 
 Only pairwise interactions, as defined by the
 "pair_style"_pair_style.html command, are included in this
 calculation.  Long-range interactions due to a
 "kspace_style"_kspace_style.html command are not included.  Not all
 pair potentials can be evaluated in a pairwise mode as required by
 this fix.  For example, 3-body potentials, such as
 "Tersoff"_pair_tersoff.html and "Stillinger-Weber"_pair_sw.html cannot
 be used.  "EAM"_pair_eam.html potentials for metals only include the
 pair potential portion of the EAM interaction, not the embedding term.
 
 Can be run in parallel, but aspects of the GCMC part will not scale 
 well in parallel. Only usable for 3D simulations with orthogonal 
 simulation cells.
 
 Note that very lengthy simulations involving insertions/deletions of
 billions of gas molecules may run out of atom or molecule IDs and
 trigger an error, so it is better to run multiple shorter-duration 
 simulations. Likewise, very large molecules have not been tested
 and may turn out to be problematic.
 
 Use of multiple fix gcmc commands in the same input script can be 
 problematic if using a template molecule. The issue is that the 
 user-referenced template molecule in the second fix gcmc command
 may no longer exist since it might have been deleted by the first
 fix gcmc command. An existing template molecule will need to be
 referenced by the user for each subsequent fix gcmc command.
 
 [Related commands:]
 
 "fix_nvt"_fix_nvt.html, "neighbor"_neighbor.html, 
 "fix_deposit"_fix_deposit.html, "fix_evaporate"_fix_evaporate.html,
 "delete_atoms"_delete_atoms.html
 
 [Default:]
 
 The option defaults are molecule = no, maxangle = 10.
 
 :line
 
 :link(Frenkel)
 [(Frenkel)] Frenkel and Smit, Understanding Molecular Simulation, 
 Academic Press, London, 2002.
diff --git a/doc/fix_reax_bonds.html b/doc/fix_reax_bonds.html
index b7c8e3659..dd25932e9 100644
--- a/doc/fix_reax_bonds.html
+++ b/doc/fix_reax_bonds.html
@@ -1,73 +1,73 @@
 <HTML>
 <CENTER><A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> - <A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> 
 </CENTER>
 
 
 
 
 
 
 <HR>
 
 <H3>fix reax/bonds command 
 </H3>
 <H3>fix reax/c/bonds command 
 </H3>
 <P><B>Syntax:</B>
 </P>
 <PRE>fix ID group-ID reax/bonds Nevery filename 
 </PRE>
 <UL><LI>ID, group-ID are documented in <A HREF = "fix.html">fix</A> command
 <LI>reax/bonds = style name of this fix command
 <LI>Nevery = output interval in timesteps
 <LI>filename = name of output file 
 </UL>
 <P><B>Examples:</B>
 </P>
 <PRE>fix 1 all reax/bonds 100 bonds.tatb
 fix 1 all reax/c/bonds 100 bonds.reaxc 
 </PRE>
 <P><B>Description:</B>
 </P>
 <P>Write out the bond information computed by the ReaxFF potential
-specified by <A HREF = "pair_reax.html">pair_style reax</A> or 
-<A HREF = "pair_reax_c.html">pair_style reax/c</A> in the exact same format as 
-the stand-alone ReaxFF code.  The bond information
-is written to <I>filename</I> on timesteps that are multiples of <I>Nevery</I>,
-including timestep 0.  For time-averaged chemical species analysis, 
+specified by <A HREF = "pair_reax.html">pair_style reax</A> or <A HREF = "pair_reax_c.html">pair_style
+reax/c</A> in the exact same format as the original
+stand-alone ReaxFF code of Adri van Duin.  The bond information is
+written to <I>filename</I> on timesteps that are multiples of <I>Nevery</I>,
+including timestep 0.  For time-averaged chemical species analysis,
 please see the <A HREF = "fix_species.html">fix species</A> command.
 </P>
 <P>The format of the output file should be self-explantory.
 </P>
 <HR>
 
 <P><B>Restart, fix_modify, output, run start/stop, minimize info:</B>
 </P>
 <P>No information about this fix is written to <A HREF = "restart.html">binary restart
 files</A>.  None of the <A HREF = "fix_modify.html">fix_modify</A> options
 are relevant to this fix.  No global or per-atom quantities are stored
 by this fix for access by various <A HREF = "Section_howto.html#howto_15">output
 commands</A>.  No parameter of this fix can
 be used with the <I>start/stop</I> keywords of the <A HREF = "run.html">run</A> command.
 This fix is not invoked during <A HREF = "minimize.html">energy minimization</A>.
 </P>
 <P><B>Restrictions:</B>
 </P>
 <P>The fix reax/bonds command requires that the <A HREF = "pair_reax.html">pair_style
 reax</A> be invoked.  This fix is part of the REAX
 package.  It is only enabled if LAMMPS was built with that package,
 which also requires the REAX library be built and linked with LAMMPS.
 The fix reax/c/bonds command requires that the <A HREF = "pair_reax_c.html">pair_style
-reax/c</A> be invoked.  This fix is part of the USER-REAXC
-package.  It is only enabled if LAMMPS was built with that package.
-See the <A HREF = "Section_start.html#start_3">Making LAMMPS</A> section for more
-info.
+reax/c</A> be invoked.  This fix is part of the
+USER-REAXC package.  It is only enabled if LAMMPS was built with that
+package.  See the <A HREF = "Section_start.html#start_3">Making LAMMPS</A> section
+for more info.
 </P>
 <P><B>Related commands:</B>
 </P>
 <P><A HREF = "pair_reax.html">pair_style reax</A>, <A HREF = "pair_reax_c.html">pair_style
 reax/c</A>, <A HREF = "fix_reaxc_species.html">fix reax/c/species</A>
 </P>
 <P><B>Default:</B> none
 </P>
 </HTML>
diff --git a/doc/fix_reax_bonds.txt b/doc/fix_reax_bonds.txt
index d51e08ef5..cc8966db6 100644
--- a/doc/fix_reax_bonds.txt
+++ b/doc/fix_reax_bonds.txt
@@ -1,67 +1,67 @@
 "LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
 
 :link(lws,http://lammps.sandia.gov)
 :link(ld,Manual.html)
 :link(lc,Section_commands.html#comm)
 
 :line
 
 fix reax/bonds command :h3
 fix reax/c/bonds command :h3
 
 [Syntax:]
 
 fix ID group-ID reax/bonds Nevery filename :pre
 
 ID, group-ID are documented in "fix"_fix.html command
 reax/bonds = style name of this fix command
 Nevery = output interval in timesteps
 filename = name of output file :ul
 
 [Examples:]
 
 fix 1 all reax/bonds 100 bonds.tatb
 fix 1 all reax/c/bonds 100 bonds.reaxc :pre
 
 [Description:]
 
 Write out the bond information computed by the ReaxFF potential
-specified by "pair_style reax"_pair_reax.html or 
-"pair_style reax/c"_pair_reax_c.html in the exact same format as 
-the stand-alone ReaxFF code.  The bond information
-is written to {filename} on timesteps that are multiples of {Nevery},
-including timestep 0.  For time-averaged chemical species analysis, 
+specified by "pair_style reax"_pair_reax.html or "pair_style
+reax/c"_pair_reax_c.html in the exact same format as the original
+stand-alone ReaxFF code of Adri van Duin.  The bond information is
+written to {filename} on timesteps that are multiples of {Nevery},
+including timestep 0.  For time-averaged chemical species analysis,
 please see the "fix species"_fix_species.html command.
 
 The format of the output file should be self-explantory.
 
 :line
 
 [Restart, fix_modify, output, run start/stop, minimize info:]
 
 No information about this fix is written to "binary restart
 files"_restart.html.  None of the "fix_modify"_fix_modify.html options
 are relevant to this fix.  No global or per-atom quantities are stored
 by this fix for access by various "output
 commands"_Section_howto.html#howto_15.  No parameter of this fix can
 be used with the {start/stop} keywords of the "run"_run.html command.
 This fix is not invoked during "energy minimization"_minimize.html.
 
 [Restrictions:]
 
 The fix reax/bonds command requires that the "pair_style
 reax"_pair_reax.html be invoked.  This fix is part of the REAX
 package.  It is only enabled if LAMMPS was built with that package,
 which also requires the REAX library be built and linked with LAMMPS.
 The fix reax/c/bonds command requires that the "pair_style
-reax/c"_pair_reax_c.html be invoked.  This fix is part of the USER-REAXC
-package.  It is only enabled if LAMMPS was built with that package.
-See the "Making LAMMPS"_Section_start.html#start_3 section for more
-info.
+reax/c"_pair_reax_c.html be invoked.  This fix is part of the
+USER-REAXC package.  It is only enabled if LAMMPS was built with that
+package.  See the "Making LAMMPS"_Section_start.html#start_3 section
+for more info.
 
 [Related commands:]
 
 "pair_style reax"_pair_reax.html, "pair_style
 reax/c"_pair_reax_c.html, "fix reax/c/species"_fix_reaxc_species.html
 
 [Default:] none
diff --git a/doc/fix_reaxc_species.html b/doc/fix_reaxc_species.html
new file mode 100644
index 000000000..e1af71daa
--- /dev/null
+++ b/doc/fix_reaxc_species.html
@@ -0,0 +1,143 @@
+<HTML>
+<CENTER><A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> - <A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> 
+</CENTER>
+
+
+
+
+
+
+<HR>
+
+<H3>fix reax/c/species command 
+</H3>
+<P><B>Syntax:</B>
+</P>
+<PRE>fix ID group-ID reax/c/species Nevery Nrepeat Nfreq filename keyword value ... 
+</PRE>
+<UL><LI>ID, group-ID are documented in <A HREF = "fix.html">fix</A> command 
+
+<LI>reax/c/species = style name of this command 
+
+<LI>Nevery = sample bond-order every this many timesteps 
+
+<LI>Nrepeat = # of bond-order samples used for calculating averages 
+
+<LI>Nfreq = calculate average bond-order every this many timesteps 
+
+<LI>filename = name of output file 
+
+<LI>zero or more keyword/value pairs may be appended 
+
+<LI>keyword = <I>cutoff</I> or <I>element</I> or <I>position</I> 
+
+<PRE>  <I>cutoff</I> value = I J Cutoff
+    I, J = atom types
+    Cutoff = Bond-order cutoff value for this pair of atom types
+  <I>element</I> value = Element1, Element2, ... 
+  <I>position</I> value = posfreq filepos
+    posfreq = write position files every this many timestep
+    filepos = name of position output file 
+</PRE>
+
+</UL>
+<P><B>Examples:</B>
+</P>
+<PRE>fix 1 all species 10 10 100 species.out
+fix 1 all species 1 2 20 species.out cutoff 1 1 0.40 cutoff 1 2 0.55
+fix 1 all species 1 100 100 species.out element Au O H position 1000 AuOH.pos 
+</PRE>
+<P><B>Description:</B>
+</P>
+<P>Write out the chemical species information computed by the ReaxFF potential
+specified by <A HREF = "pair_reax_c.html">pair_style reax/c</A>.  Bond-order values 
+(either averaged or instantaneous, depending on value of <I>Nrepeat</I>) 
+are used to determine chemical bonds. Every <I>Nfreq</I> timesteps,
+chemical species  information is written to <I>filename</I> as a two line output.
+The first line is a header containing labels. The second line consists 
+of the following: timestep, total number of molecules, 
+total number of distinct species, number of molecules of each species.
+The chemical formula of each species is given in the first line.
+</P>
+<P>Optional keyword <I>cutoff</I> can be assigned to change the minimum bond-order values 
+used in identifying chemical bonds between pairs of atoms.  Bond-order cutoffs 
+should be carefully chosen, as bond-order cutoffs that are too small may include 
+too many bonds (which will result in an error), while too-large cutoffs will 
+result in fragmented molecules.  The default cutoff of 0.3 usually gives good 
+estimate. 
+</P>
+<P>Optional keyword <I>element</I> can be used to specify the chemical symbol printed for
+each LAMMPS atom type. The number of symbols must match the number of LAMMPS atom types
+and each symbol must consist of 1 or 2 alphanumeric characters. Normally, these
+symbols should be chosen to match the chemical identity of each LAMMPS atom type,
+as specified using the <A HREF = "pair_reax_c.html">reax/c pair_coeff</A> command and 
+the ReaxFF force field file. 
+</P>
+<P>Optional keyword <I>position</I> writes center-of-mass positions of each identified 
+molecules to file <I>filepos</I> every <I>posfreq</I> timesteps.  The first line contains
+information on timestep, total number of molecules, total number of distinct 
+species, and box dimensions.  The second line is a header containing labels.
+From the third line downward, each molecule writes a line of output containing 
+the following information: molecule ID, number of atoms in this molecule, chemical 
+formula, total charge, and center-of-mass xyz positions of this molecule.  The xyz
+positions are in fractional coordinates relative to the box dimensions.  
+</P>
+<P>Keyword <I>position</I> output file <I>filepos</I> can contain the wildcard character "*".  
+If the "*" character appears in <I>filepos</I>, then one file per snapshot is written 
+at <I>posfreq</I> and the "*" character is replaced with the timestep value.  
+For example, AuO.pos.* becomes AuO.pos.0, AuO.pos.1000, etc.
+</P>
+<HR>
+
+<P>The <I>Nevery</I>, <I>Nrepeat</I>, and <I>Nfreq</I> arguments specify on what
+timesteps the bond-order values are sampled to get the average bond
+order.  The species analysis is performed using the average bond-order
+on timesteps
+that are a multiple of <I>Nfreq</I>.  The average is over <I>Nrepeat</I>
+bond-order samples, computed in the preceding portion of the simulation every
+<I>Nevery</I> timesteps.  <I>Nfreq</I> must be a multiple of <I>Nevery</I> and
+<I>Nevery</I> must be non-zero even if <I>Nrepeat</I> is 1.  Also, the timesteps
+contributing to the average bond-order cannot overlap, i.e. Nfreq >
+(Nrepeat-1)*Nevery is required.
+</P>
+<P>For example, if Nevery=2, Nrepeat=6, and Nfreq=100, then bond-order values on
+timesteps 90,92,94,96,98,100 will be used to compute the average bond-order
+ for the species analysis output on timestep 100.  
+</P>
+<HR>
+
+<P><B>Restart, fix_modify, output, run start/stop, minimize info:</B>
+</P>
+<P>No information about this fix is written to <A HREF = "restart.html">binary restart
+files</A>.  None of the <A HREF = "fix_modify.html">fix_modify</A> options
+are relevant to this fix.  No global or per-atom quantities are stored
+by this fix for access by various <A HREF = "Section_howto.html#howto_15">output
+commands</A>.  No parameter of this fix can
+be used with the <I>start/stop</I> keywords of the <A HREF = "run.html">run</A> command.
+This fix is not invoked during <A HREF = "minimize.html">energy minimization</A>.
+</P>
+<P><B>Restrictions:</B>
+</P>
+<P>The fix species currently only works with 
+<A HREF = "pair_reax_c.html">pair_style reax/c</A> and it requires that the <A HREF = "pair_reax_c.html">pair_style
+reax/c</A> be invoked.  This fix is part of the
+USER-REAXC package.  It is only enabled if LAMMPS was built with that
+package.  See the <A HREF = "Section_start.html#start_3">Making LAMMPS</A> section
+for more info.
+</P>
+<P>It should be possible to extend it to other reactive pair_styles (such as 
+<A HREF = "pair_airebo.html">rebo</A>, <A HREF = "pair_airebo.html">airebo</A>, 
+<A HREF = "pair_comb.html">comb</A>, and <A HREF = "pair_bop.html">bop</A>), but this has not yet been done.
+</P>
+<P><B>Related commands:</B>
+</P>
+<P><A HREF = "pair_reax_c.html">pair_style reax/c</A>, <A HREF = "fix_reax_bonds.html">fix
+reax/bonds</A>
+</P>
+<P><B>Default:</B> 
+</P>
+<P>The default values for bond-order cutoffs are 0.3 for all I-J pairs.  The
+default element symbols are C, H, O, N.  Position files are not written 
+by default.
+</P>
+</HTML>
diff --git a/doc/thermo_style.html b/doc/thermo_style.html
index 8641eb138..78bcc3038 100644
--- a/doc/thermo_style.html
+++ b/doc/thermo_style.html
@@ -1,324 +1,334 @@
 <HTML>
 <CENTER><A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> - <A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> 
 </CENTER>
 
 
 
 
 
 
 <HR>
 
 <H3>thermo_style command 
 </H3>
 <P><B>Syntax:</B>
 </P>
 <PRE>thermo_style style args 
 </PRE>
 <UL><LI>style = <I>one</I> or <I>multi</I> or <I>custom</I> 
 
 <LI>args = list of arguments for a particular style 
 
 <PRE>  <I>one</I> args = none
   <I>multi</I> args = none
   <I>custom</I> args = list of attributes
-    possible attributes = step, elapsed, elaplong, dt, cpu, tpcpu, spcpu,
+    possible attributes = step, elapsed, elaplong, dt, time, cpu, tpcpu, spcpu,
                           atoms, temp, press, pe, ke, etotal, enthalpy,
                           evdwl, ecoul, epair, ebond, eangle, edihed, eimp,
                           emol, elong, etail,
                           vol, lx, ly, lz, xlo, xhi, ylo, yhi, zlo, zhi,
 			  xy, xz, yz, xlat, ylat, zlat,
 			  pxx, pyy, pzz, pxy, pxz, pyz,
 			  fmax, fnorm,
 			  cella, cellb, cellc, cellalpha, cellbeta, cellgamma,
 			  c_ID, c_ID[I], c_ID[I][J],
                           f_ID, f_ID[I], f_ID[I][J],
                           v_name
       step = timestep
       elapsed = timesteps since start of this run
       elaplong = timesteps since start of initial run in a series of runs
       dt = timestep size
+      time = simulation time
       cpu = elapsed CPU time in seconds
       tpcpu = time per CPU second
       spcpu = timesteps per CPU second
       atoms = # of atoms
       temp = temperature
       press = pressure
       pe = total potential energy
       ke = kinetic energy
       etotal = total energy (pe + ke)
       enthalpy = enthalpy (etotal + press*vol)
       evdwl = VanderWaal pairwise energy
       ecoul = Coulombic pairwise energy
       epair = pairwise energy (evdwl + ecoul + elong + etail)
       ebond = bond energy
       eangle = angle energy
       edihed = dihedral energy
       eimp = improper energy
       emol = molecular energy (ebond + eangle + edihed + eimp)
       elong = long-range kspace energy
       etail = VanderWaal energy long-range tail correction
       vol = volume
       lx,ly,lz = box lengths in x,y,z
       xlo,xhi,ylo,yhi,zlo,zhi = box boundaries
       xy,xz,yz = box tilt for triclinic (non-orthogonal) simulation boxes
       xlat,ylat,zlat = lattice spacings as calculated by <A HREF = "lattice.html">lattice</A> command
       pxx,pyy,pzz,pxy,pxz,pyz = 6 components of pressure tensor
       fmax = max component of force on any atom in any dimension
       fnorm = length of force vector for all atoms
       cella,cellb,cellc = periodic cell lattice constants a,b,c 
       cellalpha, cellbeta, cellgamma = periodic cell angles alpha,beta,gamma
       c_ID = global scalar value calculated by a compute with ID
       c_ID[I] = Ith component of global vector calculated by a compute with ID
       c_ID[I][J] = I,J component of global array calculated by a compute with ID
       f_ID = global scalar value calculated by a fix with ID
       f_ID[I] = Ith component of global vector calculated by a fix with ID
       f_ID[I][J] = I,J component of global array calculated by a fix with ID
       v_name = scalar value calculated by an equal-style variable with name 
 </PRE>
 
 </UL>
 <P><B>Examples:</B>
 </P>
 <PRE>thermo_style multi
 thermo_style custom step temp pe etotal press vol
 thermo_style custom step temp etotal c_myTemp v_abc 
 </PRE>
 <P><B>Description:</B>
 </P>
 <P>Set the style and content for printing thermodynamic data to the
 screen and log file.
 </P>
 <P>Style <I>one</I> prints a one-line summary of thermodynamic info that is
 the equivalent of "thermo_style custom step temp epair emol etotal
 press".  The line contains only numeric values.
 </P>
 <P>Style <I>multi</I> prints a multiple-line listing of thermodynamic info
 that is the equivalent of "thermo_style custom etotal ke temp pe ebond
 eangle edihed eimp evdwl ecoul elong press".  The listing contains
 numeric values and a string ID for each quantity.
 </P>
 <P>Style <I>custom</I> is the most general setting and allows you to specify
 which of the keywords listed above you want printed on each
 thermodynamic timestep.  Note that the keywords c_ID, f_ID, v_name are
 references to <A HREF = "compute.html">computes</A>, <A HREF = "fix.html">fixes</A>, and
 equal-style <A HREF = "variable.html"">variables</A> that have been defined
 elsewhere in the input script or can even be new styles which users
 have added to LAMMPS (see the <A HREF = "Section_modify.html">Section_modify</A>
 section of the documentation).  Thus the <I>custom</I> style provides a
 flexible means of outputting essentially any desired quantity as a
 simulation proceeds.
 </P>
 <P>All styles except <I>custom</I> have <I>vol</I> appended to their list of
 outputs if the simulation box volume changes during the simulation.
 </P>
 <P>The values printed by the various keywords are instantaneous values,
 calculated on the current timestep.  Time-averaged quantities, which
 include values from previous timesteps, can be output by using the
 f_ID keyword and accessing a fix that does time-averaging such as the
 <A HREF = "fix_ave_time.html">fix ave/time</A> command.
 </P>
 <P>Options invoked by the <A HREF = "thermo_modify.html">thermo_modify</A> command can
 be used to set the one- or multi-line format of the print-out, the
 normalization of thermodynamic output (total values versus per-atom
 values for extensive quantities (ones which scale with the number of
 atoms in the system), and the numeric precision of each printed value.
 </P>
 <P>IMPORTANT NOTE: When you use a "thermo_style" command, all
 thermodynamic settings are restored to their default values, including
 those previously set by a <A HREF = "thermo_modify.html">thermo_modify</A> command.
 Thus if your input script specifies a thermo_style command, you should
 use the thermo_modify command after it.
 </P>
 <HR>
 
 <P>Several of the thermodynamic quantities require a temperature to be
 computed: "temp", "press", "ke", "etotal", "enthalpy", "pxx", etc.  By
 default this is done by using a <I>temperature</I> compute which is created
 when LAMMPS starts up, as if this command had been issued:
 </P>
 <PRE>compute thermo_temp all temp 
 </PRE>
 <P>See the <A HREF = "compute_temp.html">compute temp</A> command for details.  Note
 that the ID of this compute is <I>thermo_temp</I> and the group is <I>all</I>.
 You can change the attributes of this temperature (e.g. its
 degrees-of-freedom) via the <A HREF = "compute_modify.html">compute_modify</A>
 command.  Alternatively, you can directly assign a new compute (that
 calculates temperature) which you have defined, to be used for
 calculating any thermodynamic quantity that requires a temperature.
 This is done via the <A HREF = "thermo_modify.html">thermo_modify</A> command.
 </P>
 <P>Several of the thermodynamic quantities require a pressure to be
 computed: "press", "enthalpy", "pxx", etc.  By default this is done by
 using a <I>pressure</I> compute which is created when LAMMPS starts up, as
 if this command had been issued:
 </P>
 <PRE>compute thermo_press all pressure thermo_temp 
 </PRE>
 <P>See the <A HREF = "compute_pressure.html">compute pressure</A> command for details.
 Note that the ID of this compute is <I>thermo_press</I> and the group is
 <I>all</I>.  You can change the attributes of this pressure via the
 <A HREF = "compute_modify.html">compute_modify</A> command.  Alternatively, you can
 directly assign a new compute (that calculates pressure) which you
 have defined, to be used for calculating any thermodynamic quantity
 that requires a pressure.  This is done via the
 <A HREF = "thermo_modify.html">thermo_modify</A> command.
 </P>
 <P>Several of the thermodynamic quantities require a potential energy to
 be computed: "pe", "etotal", "ebond", etc.  This is done by using a
 <I>pe</I> compute which is created when LAMMPS starts up, as if this
 command had been issued:
 </P>
 <PRE>compute thermo_pe all pe 
 </PRE>
 <P>See the <A HREF = "compute_pe.html">compute pe</A> command for details.  Note that
 the ID of this compute is <I>thermo_pe</I> and the group is <I>all</I>.  You can
 change the attributes of this potential energy via the
 <A HREF = "compute_modify.html">compute_modify</A> command.
 </P>
 <HR>
 
 <P>The kinetic energy of the system <I>ke</I> is inferred from the temperature
 of the system with 1/2 Kb T of energy for each degree of freedom.
 Thus, using different <A HREF = "compute.html">compute commands</A> for calculating
 temperature, via the <A HREF = "thermo_modify.html">thermo_modify temp</A> command,
 may yield different kinetic energies, since different computes that
 calculate temperature can subtract out different non-thermal
 components of velocity and/or include different degrees of freedom
 (translational, rotational, etc).
 </P>
 <P>The potential energy of the system <I>pe</I> will include contributions
 from fixes if the <A HREF = "fix_modify.html">fix_modify thermo</A> option is set
 for a fix that calculates such a contribution.  For example, the <A HREF = "fix_wall.html">fix
 wall/lj93</A> fix calculates the energy of atoms
 interacting with the wall.  See the doc pages for "individual fixes"
 to see which ones contribute.
 </P>
 <P>A long-range tail correction <I>etail</I> for the VanderWaal pairwise
 energy will be non-zero only if the <A HREF = "pair_modify.html">pair_modify
 tail</A> option is turned on.  The <I>etail</I> contribution
 is included in <I>evdwl</I>, <I>pe</I>, and <I>etotal</I>, and the corresponding tail
 correction to the pressure is included in <I>press</I> and <I>pxx</I>, <I>pyy</I>,
 etc.
 </P>
 <HR>
 
 <P>The <I>step</I>, <I>elapsed</I>, and <I>elaplong</I> keywords refer to timestep
 count.  <I>Step</I> is the current timestep, or iteration count when a
 <A HREF = "minimize.html">minimization</A> is being performed.  <I>Elapsed</I> is the
 number of timesteps elapsed since the beginning of this run.
 <I>Elaplong</I> is the number of timesteps elapsed since the beginning of
 an initial run in a series of runs.  See the <I>start</I> and <I>stop</I>
 keywords for the <A HREF = "run.html">run</A> for info on how to invoke a series of
 runs that keep track of an initial starting time.  If these keywords
 are not used, then <I>elapsed</I> and <I>elaplong</I> are the same value.
 </P>
+<P>The <I>dt</I> keyword is the current timestep size in time
+<A HREF = "units.html">units</A>.  The <I>time</I> keyword is the current elapsed
+simulation time, also in time <A HREF = "units.html">units</A>, which is simply
+(step*dt) if the timestep size has not changed and the timestep has
+not been reset.  If the timestep has changed (e.g. via <A HREF = "fix_dt_reset.html">fix
+dt/reset</A>) or the timestep has been reset (e.g. via
+the "reset_timestep" command), then the simulation time is effectively
+a cummulative value up to the current point.
+</P>
 <P>The <I>cpu</I> keyword is elapsed CPU seconds since the beginning of this
 run.  The <I>tpcpu</I> and <I>spcpu</I> keywords are measures of how fast your
 simulation is currently running.  The <I>tpcpu</I> keyword is simulation
 time per CPU second, where simulation time is in time
 <A HREF = "units.html">units</A>.  E.g. for metal units, the <I>tpcpu</I> value would be
 picoseconds per CPU second.  The <I>spcpu</I> keyword is the number of
 timesteps per CPU second.  Both quantities are on-the-fly metrics,
 measured relative to the last time they were invoked.  Thus if you are
 printing out thermodyamic output every 100 timesteps, the two keywords
 will continually output the time and timestep rate for the last 100
 steps.  The <I>tpcpu</I> keyword does not attempt to track any changes in
 timestep size, e.g. due to using the <A HREF = "fix_dt_reset.html">fix dt/reset</A>
 command.
 </P>
 <P>The <I>fmax</I> and <I>fnorm</I> keywords are useful for monitoring the progress
 of an <A HREF = "minimize.html">energy minimization</A>.  The <I>fmax</I> keyword
 calculates the maximum force in any dimension on any atom in the
 system, or the infinity-norm of the force vector for the system.  The
 <I>fnorm</I> keyword calculates the 2-norm or length of the force vector.
 </P>
 <P>The keywords <I>cella</I>, <I>cellb</I>, <I>cellc</I>, <I>cellalpha</I>, <I>cellbeta</I>,
 <I>cellgamma</I>, correspond to the usual crystallographic quantities that
 define the periodic unit cell of a crystal.  See <A HREF = "Section_howto.html#howto_12">this
 section</A> of the doc pages for a geometric
 description of triclinic periodic cells, including a precise defintion
 of these quantities in terms of the internal LAMMPS cell dimensions
 <I>lx</I>, <I>ly</I>, <I>lz</I>, <I>yz</I>, <I>xz</I>, <I>xy</I>,
 </P>
 <HR>
 
 <P>The <I>c_ID</I> and <I>c_ID[I]</I> and <I>c_ID[I][J]</I> keywords allow global
 values calculated by a compute to be output.  As discussed on the
 <A HREF = "compute.html">compute</A> doc page, computes can calculate global,
 per-atom, or local values.  Only global values can be referenced by
 this command.  However, per-atom compute values can be referenced in a
 <A HREF = "variable.html">variable</A> and the variable referenced by thermo_style
 custom, as discussed below.
 </P>
 <P>The ID in the keyword should be replaced by the actual ID of a compute
 that has been defined elsewhere in the input script.  See the
 <A HREF = "compute.html">compute</A> command for details.  If the compute calculates
 a global scalar, vector, or array, then the keyword formats with 0, 1,
 or 2 brackets will reference a scalar value from the compute.
 </P>
 <P>Note that some computes calculate "intensive" global quantities like
 temperature; others calculate "extensive" global quantities like
 kinetic energy that are summed over all atoms in the compute group.
 Intensive quantities are printed directly without normalization by
 thermo_style custom.  Extensive quantities may be normalized by the
 total number of atoms in the simulation (NOT the number of atoms in
 the compute group) when output, depending on the <A HREF = "thermo_modify.html">thermo_modify
 norm</A> option being used.
 </P>
 <P>The <I>f_ID</I> and <I>f_ID[I]</I> and <I>f_ID[I][J]</I> keywords allow global
 values calculated by a fix to be output.  As discussed on the
 <A HREF = "fix.html">fix</A> doc page, fixes can calculate global, per-atom, or
 local values.  Only global values can be referenced by this command.
 However, per-atom fix values can be referenced in a
 <A HREF = "variable.html">variable</A> and the variable referenced by thermo_style
 custom, as discussed below.
 </P>
 <P>The ID in the keyword should be replaced by the actual ID of a fix
 that has been defined elsewhere in the input script.  See the
 <A HREF = "fix.html">fix</A> command for details.  If the fix calculates a global
 scalar, vector, or array, then the keyword formats with 0, 1, or 2
 brackets will reference a scalar value from the fix.
 </P>
 <P>Note that some fixes calculate "intensive" global quantities like
 timestep size; others calculate "extensive" global quantities like
 energy that are summed over all atoms in the fix group.  Intensive
 quantities are printed directly without normalization by thermo_style
 custom.  Extensive quantities may be normalized by the total number of
 atoms in the simulation (NOT the number of atoms in the fix group)
 when output, depending on the <A HREF = "thermo_modify.html">thermo_modify norm</A>
 option being used.
 </P>
 <P>The <I>v_name</I> keyword allow the current value of a variable to be
 output.  The name in the keyword should be replaced by the variable
 name that has been defined elsewhere in the input script.  Only
 equal-style variables can be referenced.  See the
 <A HREF = "variable.html">variable</A> command for details.  Variables of style
 <I>equal</I> can reference per-atom properties or thermodynamic keywords,
 or they can invoke other computes, fixes, or variables when evaluated,
 so this is a very general means of creating thermodynamic output.
 </P>
 <P>See <A HREF = "Section_modify.html">Section_modify</A> for information on how to add
 new compute and fix styles to LAMMPS to calculate quantities that can
 then be referenced with these keywords to generate thermodynamic
 output.
 </P>
 <HR>
 
 <P><B>Restrictions:</B>
 </P>
 <P>This command must come after the simulation box is defined by a
 <A HREF = "read_data.html">read_data</A>, <A HREF = "read_restart.html">read_restart</A>, or
 <A HREF = "create_box.html">create_box</A> command.
 </P>
 <P><B>Related commands:</B>
 </P>
 <P><A HREF = "thermo.html">thermo</A>, <A HREF = "thermo_modify.html">thermo_modify</A>,
 <A HREF = "fix_modify.html">fix_modify</A>, <A HREF = "compute_temp.html">compute temp</A>,
 <A HREF = "compute_pressure.html">compute pressure</A>
 </P>
 <P><B>Default:</B>
 </P>
 <PRE>thermo_style one 
 </PRE>
 </HTML>
diff --git a/doc/thermo_style.txt b/doc/thermo_style.txt
index 0e77cb728..29acefe6a 100644
--- a/doc/thermo_style.txt
+++ b/doc/thermo_style.txt
@@ -1,316 +1,326 @@
 "LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
 
 :link(lws,http://lammps.sandia.gov)
 :link(ld,Manual.html)
 :link(lc,Section_commands.html#comm)
 
 :line
 
 thermo_style command :h3
 
 [Syntax:]
 
 thermo_style style args :pre
 
 style = {one} or {multi} or {custom} :ulb,l
 args = list of arguments for a particular style :l
   {one} args = none
   {multi} args = none
   {custom} args = list of attributes
-    possible attributes = step, elapsed, elaplong, dt, cpu, tpcpu, spcpu,
+    possible attributes = step, elapsed, elaplong, dt, time, cpu, tpcpu, spcpu,
                           atoms, temp, press, pe, ke, etotal, enthalpy,
                           evdwl, ecoul, epair, ebond, eangle, edihed, eimp,
                           emol, elong, etail,
                           vol, lx, ly, lz, xlo, xhi, ylo, yhi, zlo, zhi,
 			  xy, xz, yz, xlat, ylat, zlat,
 			  pxx, pyy, pzz, pxy, pxz, pyz,
 			  fmax, fnorm,
 			  cella, cellb, cellc, cellalpha, cellbeta, cellgamma,
 			  c_ID, c_ID\[I\], c_ID\[I\]\[J\],
                           f_ID, f_ID\[I\], f_ID\[I\]\[J\],
                           v_name
       step = timestep
       elapsed = timesteps since start of this run
       elaplong = timesteps since start of initial run in a series of runs
       dt = timestep size
+      time = simulation time
       cpu = elapsed CPU time in seconds
       tpcpu = time per CPU second
       spcpu = timesteps per CPU second
       atoms = # of atoms
       temp = temperature
       press = pressure
       pe = total potential energy
       ke = kinetic energy
       etotal = total energy (pe + ke)
       enthalpy = enthalpy (etotal + press*vol)
       evdwl = VanderWaal pairwise energy
       ecoul = Coulombic pairwise energy
       epair = pairwise energy (evdwl + ecoul + elong + etail)
       ebond = bond energy
       eangle = angle energy
       edihed = dihedral energy
       eimp = improper energy
       emol = molecular energy (ebond + eangle + edihed + eimp)
       elong = long-range kspace energy
       etail = VanderWaal energy long-range tail correction
       vol = volume
       lx,ly,lz = box lengths in x,y,z
       xlo,xhi,ylo,yhi,zlo,zhi = box boundaries
       xy,xz,yz = box tilt for triclinic (non-orthogonal) simulation boxes
       xlat,ylat,zlat = lattice spacings as calculated by "lattice"_lattice.html command
       pxx,pyy,pzz,pxy,pxz,pyz = 6 components of pressure tensor
       fmax = max component of force on any atom in any dimension
       fnorm = length of force vector for all atoms
       cella,cellb,cellc = periodic cell lattice constants a,b,c 
       cellalpha, cellbeta, cellgamma = periodic cell angles alpha,beta,gamma
       c_ID = global scalar value calculated by a compute with ID
       c_ID\[I\] = Ith component of global vector calculated by a compute with ID
       c_ID\[I\]\[J\] = I,J component of global array calculated by a compute with ID
       f_ID = global scalar value calculated by a fix with ID
       f_ID\[I\] = Ith component of global vector calculated by a fix with ID
       f_ID\[I\]\[J\] = I,J component of global array calculated by a fix with ID
       v_name = scalar value calculated by an equal-style variable with name :pre
 :ule
 
 [Examples:]
 
 thermo_style multi
 thermo_style custom step temp pe etotal press vol
 thermo_style custom step temp etotal c_myTemp v_abc :pre
 
 [Description:]
 
 Set the style and content for printing thermodynamic data to the
 screen and log file.
 
 Style {one} prints a one-line summary of thermodynamic info that is
 the equivalent of "thermo_style custom step temp epair emol etotal
 press".  The line contains only numeric values.
 
 Style {multi} prints a multiple-line listing of thermodynamic info
 that is the equivalent of "thermo_style custom etotal ke temp pe ebond
 eangle edihed eimp evdwl ecoul elong press".  The listing contains
 numeric values and a string ID for each quantity.
 
 Style {custom} is the most general setting and allows you to specify
 which of the keywords listed above you want printed on each
 thermodynamic timestep.  Note that the keywords c_ID, f_ID, v_name are
 references to "computes"_compute.html, "fixes"_fix.html, and
 equal-style "variables"_variable.html" that have been defined
 elsewhere in the input script or can even be new styles which users
 have added to LAMMPS (see the "Section_modify"_Section_modify.html
 section of the documentation).  Thus the {custom} style provides a
 flexible means of outputting essentially any desired quantity as a
 simulation proceeds.
 
 All styles except {custom} have {vol} appended to their list of
 outputs if the simulation box volume changes during the simulation.
 
 The values printed by the various keywords are instantaneous values,
 calculated on the current timestep.  Time-averaged quantities, which
 include values from previous timesteps, can be output by using the
 f_ID keyword and accessing a fix that does time-averaging such as the
 "fix ave/time"_fix_ave_time.html command.
 
 Options invoked by the "thermo_modify"_thermo_modify.html command can
 be used to set the one- or multi-line format of the print-out, the
 normalization of thermodynamic output (total values versus per-atom
 values for extensive quantities (ones which scale with the number of
 atoms in the system), and the numeric precision of each printed value.
 
 IMPORTANT NOTE: When you use a "thermo_style" command, all
 thermodynamic settings are restored to their default values, including
 those previously set by a "thermo_modify"_thermo_modify.html command.
 Thus if your input script specifies a thermo_style command, you should
 use the thermo_modify command after it.
 
 :line
 
 Several of the thermodynamic quantities require a temperature to be
 computed: "temp", "press", "ke", "etotal", "enthalpy", "pxx", etc.  By
 default this is done by using a {temperature} compute which is created
 when LAMMPS starts up, as if this command had been issued:
 
 compute thermo_temp all temp :pre
 
 See the "compute temp"_compute_temp.html command for details.  Note
 that the ID of this compute is {thermo_temp} and the group is {all}.
 You can change the attributes of this temperature (e.g. its
 degrees-of-freedom) via the "compute_modify"_compute_modify.html
 command.  Alternatively, you can directly assign a new compute (that
 calculates temperature) which you have defined, to be used for
 calculating any thermodynamic quantity that requires a temperature.
 This is done via the "thermo_modify"_thermo_modify.html command.
 
 Several of the thermodynamic quantities require a pressure to be
 computed: "press", "enthalpy", "pxx", etc.  By default this is done by
 using a {pressure} compute which is created when LAMMPS starts up, as
 if this command had been issued:
 
 compute thermo_press all pressure thermo_temp :pre
 
 See the "compute pressure"_compute_pressure.html command for details.
 Note that the ID of this compute is {thermo_press} and the group is
 {all}.  You can change the attributes of this pressure via the
 "compute_modify"_compute_modify.html command.  Alternatively, you can
 directly assign a new compute (that calculates pressure) which you
 have defined, to be used for calculating any thermodynamic quantity
 that requires a pressure.  This is done via the
 "thermo_modify"_thermo_modify.html command.
 
 Several of the thermodynamic quantities require a potential energy to
 be computed: "pe", "etotal", "ebond", etc.  This is done by using a
 {pe} compute which is created when LAMMPS starts up, as if this
 command had been issued:
 
 compute thermo_pe all pe :pre
 
 See the "compute pe"_compute_pe.html command for details.  Note that
 the ID of this compute is {thermo_pe} and the group is {all}.  You can
 change the attributes of this potential energy via the
 "compute_modify"_compute_modify.html command.
 
 :line
 
 The kinetic energy of the system {ke} is inferred from the temperature
 of the system with 1/2 Kb T of energy for each degree of freedom.
 Thus, using different "compute commands"_compute.html for calculating
 temperature, via the "thermo_modify temp"_thermo_modify.html command,
 may yield different kinetic energies, since different computes that
 calculate temperature can subtract out different non-thermal
 components of velocity and/or include different degrees of freedom
 (translational, rotational, etc).
 
 The potential energy of the system {pe} will include contributions
 from fixes if the "fix_modify thermo"_fix_modify.html option is set
 for a fix that calculates such a contribution.  For example, the "fix
 wall/lj93"_fix_wall.html fix calculates the energy of atoms
 interacting with the wall.  See the doc pages for "individual fixes"
 to see which ones contribute.
 
 A long-range tail correction {etail} for the VanderWaal pairwise
 energy will be non-zero only if the "pair_modify
 tail"_pair_modify.html option is turned on.  The {etail} contribution
 is included in {evdwl}, {pe}, and {etotal}, and the corresponding tail
 correction to the pressure is included in {press} and {pxx}, {pyy},
 etc.
 
 :line
 
 The {step}, {elapsed}, and {elaplong} keywords refer to timestep
 count.  {Step} is the current timestep, or iteration count when a
 "minimization"_minimize.html is being performed.  {Elapsed} is the
 number of timesteps elapsed since the beginning of this run.
 {Elaplong} is the number of timesteps elapsed since the beginning of
 an initial run in a series of runs.  See the {start} and {stop}
 keywords for the "run"_run.html for info on how to invoke a series of
 runs that keep track of an initial starting time.  If these keywords
 are not used, then {elapsed} and {elaplong} are the same value.
 
+The {dt} keyword is the current timestep size in time
+"units"_units.html.  The {time} keyword is the current elapsed
+simulation time, also in time "units"_units.html, which is simply
+(step*dt) if the timestep size has not changed and the timestep has
+not been reset.  If the timestep has changed (e.g. via "fix
+dt/reset"_fix_dt_reset.html) or the timestep has been reset (e.g. via
+the "reset_timestep" command), then the simulation time is effectively
+a cummulative value up to the current point.
+
 The {cpu} keyword is elapsed CPU seconds since the beginning of this
 run.  The {tpcpu} and {spcpu} keywords are measures of how fast your
 simulation is currently running.  The {tpcpu} keyword is simulation
 time per CPU second, where simulation time is in time
 "units"_units.html.  E.g. for metal units, the {tpcpu} value would be
 picoseconds per CPU second.  The {spcpu} keyword is the number of
 timesteps per CPU second.  Both quantities are on-the-fly metrics,
 measured relative to the last time they were invoked.  Thus if you are
 printing out thermodyamic output every 100 timesteps, the two keywords
 will continually output the time and timestep rate for the last 100
 steps.  The {tpcpu} keyword does not attempt to track any changes in
 timestep size, e.g. due to using the "fix dt/reset"_fix_dt_reset.html
 command.
 
 The {fmax} and {fnorm} keywords are useful for monitoring the progress
 of an "energy minimization"_minimize.html.  The {fmax} keyword
 calculates the maximum force in any dimension on any atom in the
 system, or the infinity-norm of the force vector for the system.  The
 {fnorm} keyword calculates the 2-norm or length of the force vector.
 
 The keywords {cella}, {cellb}, {cellc}, {cellalpha}, {cellbeta},
 {cellgamma}, correspond to the usual crystallographic quantities that
 define the periodic unit cell of a crystal.  See "this
 section"_Section_howto.html#howto_12 of the doc pages for a geometric
 description of triclinic periodic cells, including a precise defintion
 of these quantities in terms of the internal LAMMPS cell dimensions
 {lx}, {ly}, {lz}, {yz}, {xz}, {xy},
 
 :line
 
 The {c_ID} and {c_ID\[I\]} and {c_ID\[I\]\[J\]} keywords allow global
 values calculated by a compute to be output.  As discussed on the
 "compute"_compute.html doc page, computes can calculate global,
 per-atom, or local values.  Only global values can be referenced by
 this command.  However, per-atom compute values can be referenced in a
 "variable"_variable.html and the variable referenced by thermo_style
 custom, as discussed below.
 
 The ID in the keyword should be replaced by the actual ID of a compute
 that has been defined elsewhere in the input script.  See the
 "compute"_compute.html command for details.  If the compute calculates
 a global scalar, vector, or array, then the keyword formats with 0, 1,
 or 2 brackets will reference a scalar value from the compute.
 
 Note that some computes calculate "intensive" global quantities like
 temperature; others calculate "extensive" global quantities like
 kinetic energy that are summed over all atoms in the compute group.
 Intensive quantities are printed directly without normalization by
 thermo_style custom.  Extensive quantities may be normalized by the
 total number of atoms in the simulation (NOT the number of atoms in
 the compute group) when output, depending on the "thermo_modify
 norm"_thermo_modify.html option being used.
 
 The {f_ID} and {f_ID\[I\]} and {f_ID\[I\]\[J\]} keywords allow global
 values calculated by a fix to be output.  As discussed on the
 "fix"_fix.html doc page, fixes can calculate global, per-atom, or
 local values.  Only global values can be referenced by this command.
 However, per-atom fix values can be referenced in a
 "variable"_variable.html and the variable referenced by thermo_style
 custom, as discussed below.
 
 The ID in the keyword should be replaced by the actual ID of a fix
 that has been defined elsewhere in the input script.  See the
 "fix"_fix.html command for details.  If the fix calculates a global
 scalar, vector, or array, then the keyword formats with 0, 1, or 2
 brackets will reference a scalar value from the fix.
 
 Note that some fixes calculate "intensive" global quantities like
 timestep size; others calculate "extensive" global quantities like
 energy that are summed over all atoms in the fix group.  Intensive
 quantities are printed directly without normalization by thermo_style
 custom.  Extensive quantities may be normalized by the total number of
 atoms in the simulation (NOT the number of atoms in the fix group)
 when output, depending on the "thermo_modify norm"_thermo_modify.html
 option being used.
 
 The {v_name} keyword allow the current value of a variable to be
 output.  The name in the keyword should be replaced by the variable
 name that has been defined elsewhere in the input script.  Only
 equal-style variables can be referenced.  See the
 "variable"_variable.html command for details.  Variables of style
 {equal} can reference per-atom properties or thermodynamic keywords,
 or they can invoke other computes, fixes, or variables when evaluated,
 so this is a very general means of creating thermodynamic output.
 
 See "Section_modify"_Section_modify.html for information on how to add
 new compute and fix styles to LAMMPS to calculate quantities that can
 then be referenced with these keywords to generate thermodynamic
 output.
 
 :line
 
 [Restrictions:]
 
 This command must come after the simulation box is defined by a
 "read_data"_read_data.html, "read_restart"_read_restart.html, or
 "create_box"_create_box.html command.
 
 [Related commands:]
 
 "thermo"_thermo.html, "thermo_modify"_thermo_modify.html,
 "fix_modify"_fix_modify.html, "compute temp"_compute_temp.html,
 "compute pressure"_compute_pressure.html
 
 [Default:]
 
 thermo_style one :pre
diff --git a/src/MAKE/Makefile.mingw b/src/MAKE/Makefile.mingw
deleted file mode 100644
index d322bc47a..000000000
--- a/src/MAKE/Makefile.mingw
+++ /dev/null
@@ -1,113 +0,0 @@
-# mingw = Windows 32bit, cross-compiled on Linux, gcc-4.4.1, MinGW x-compiler 
-
-SHELL = /bin/sh
-
-# ---------------------------------------------------------------------
-# compiler/linker settings
-# specify flags and libraries needed for your compiler
-
-CC =		i686-pc-mingw32-g++
-CCFLAGS =	-O3 -march=i686 -mtune=generic -mfpmath=387 -mpc64 \
-	 -ffast-math -funroll-loops -fstrict-aliasing -Wall -W -Wno-uninitialized 
-SHFLAGS =	-fPIC
-DEPFLAGS =	-M
-
-LINK =		i686-pc-mingw32-g++
-LINKFLAGS =	-O 
-LIB =         -lwsock32  # -lwsock32 is needed for USER-IMD which uses tcp/ip sockets.
-SIZE =		i686-pc-mingw32-size
-
-ARCHIVE =	ar
-ARFLAGS =	-rcsv
-SHLIBFLAGS =	-shared
-
-# ---------------------------------------------------------------------
-# LAMMPS-specific settings
-# specify settings for LAMMPS features you will use
-# if you change any -D setting, do full re-compile after "make clean"
-
-# LAMMPS ifdef settings, OPTIONAL
-# see possible settings in doc/Section_start.html#2_2 (step 4)
-
-LMP_INC = -DLAMMPS_XDR # -DLAMMPS_GZIP -DMALLOC_MEMALIGN=64
-
-# MPI library, REQUIRED
-# see discussion in doc/Section_start.html#2_2 (step 5)
-# can point to dummy MPI library in src/STUBS as in Makefile.serial
-# INC = path for mpi.h, MPI compiler settings
-# PATH = path for MPI library
-# LIB = name of MPI library
-
-MPI_INC =    -I../STUBS 
-MPI_PATH = 
-MPI_LIB =    mpi.o	
-
-# FFT library, OPTIONAL
-# see discussion in doc/Section_start.html#2_2 (step 6)
-# can be left blank to use provided KISS FFT library
-# INC = -DFFT setting, e.g. -DFFT_FFTW, FFT compiler settings
-# PATH = path for FFT library
-# LIB = name of FFT library
-
-FFT_INC =   -DFFT_NONE #-DFFT_SINGLE
-FFT_PATH = 
-FFT_LIB =	#-lfftw
-
-# JPEG library, OPTIONAL
-# see discussion in doc/Section_start.html#2_2 (step 7)
-# only needed if -DLAMMPS_JPEG listed with LMP_INC
-# INC = path for jpeglib.h
-# PATH = path for JPEG library
-# LIB = name of JPEG library
-
-JPG_INC =       
-JPG_PATH = 	
-JPG_LIB =	
-
-# ---------------------------------------------------------------------
-# build rules and dependencies
-# no need to edit this section
-
-include	Makefile.package.settings
-include	Makefile.package
-
-EXTRA_INC = $(LMP_INC) $(PKG_INC) $(MPI_INC) $(FFT_INC) $(JPG_INC) $(PKG_SYSINC)
-EXTRA_PATH = $(PKG_PATH) $(MPI_PATH) $(FFT_PATH) $(JPG_PATH) $(PKG_SYSPATH)
-EXTRA_LIB = $(PKG_LIB) $(MPI_LIB) $(FFT_LIB) $(JPG_LIB) $(PKG_SYSLIB)
-
-# Path to src files
-
-vpath %.cpp ..
-vpath %.h ..
-
-# Link target
-
-$(EXE):	$(EXE).exe ../MAKE/mingw_cross.nsis
-	makensis ../MAKE/mingw_cross.nsis
-	(cd ..; zip -0 lammps-icms-win.zip lammps-icms-win.exe)
-	touch $(EXE)
-
-$(EXE).exe: $(OBJ) mpi.o
-	$(LINK) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(EXTRA_LIB) $(LIB) -o $(EXE).exe
-	$(SIZE) $(EXE).exe
-
-# Library target
-
-lib:	$(OBJ)
-	$(ARCHIVE) $(ARFLAGS) $(EXE) $(OBJ)
-
-# Compilation rules
-
-%.o:%.cpp
-	$(CC) $(CCFLAGS) $(EXTRA_INC) -c $<
-
-%.d:%.cpp
-	$(CC) $(CCFLAGS) $(EXTRA_INC) $(DEPFLAGS) $< > $@
-
-# Individual dependencies
-
-mpi.o:  ../STUBS/mpi.c ../STUBS/mpi.h
-	$(CC) $(CCFLAGS) $(EXTRA_INC) -c $<
-
-DEPENDS = $(OBJ:.o=.d)
-sinclude $(DEPENDS)
diff --git a/src/atom_vec_sphere.cpp b/src/atom_vec_sphere.cpp
index a757d8975..5d331953c 100644
--- a/src/atom_vec_sphere.cpp
+++ b/src/atom_vec_sphere.cpp
@@ -1,1171 +1,1170 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #include "math.h"
 #include "stdlib.h"
 #include "string.h"
 #include "atom_vec_sphere.h"
 #include "atom.h"
 #include "comm.h"
 #include "domain.h"
 #include "modify.h"
 #include "force.h"
 #include "fix.h"
 #include "fix_adapt.h"
 #include "math_const.h"
 #include "memory.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
 using namespace MathConst;
 
 #define DELTA 10000
 
 /* ---------------------------------------------------------------------- */
 
 AtomVecSphere::AtomVecSphere(LAMMPS *lmp) : AtomVec(lmp)
 {
   molecular = 0;
 
   comm_x_only = 1;
   comm_f_only = 0;
   size_forward = 3;
   size_reverse = 6;
   size_border = 8;
   size_velocity = 6;
   size_data_atom = 7;
   size_data_vel = 7;
   xcol_data = 5;
 
   atom->sphere_flag = 1;
   atom->radius_flag = atom->rmass_flag = atom->omega_flag =
     atom->torque_flag = 1;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void AtomVecSphere::init()
 {
   AtomVec::init();
 
   // set radvary if particle diameters are time-varying due to fix adapt
 
   radvary = 0;
   comm_x_only = 1;
   size_forward = 3;
 
   for (int i = 0; i < modify->nfix; i++)
     if (strcmp(modify->fix[i]->style,"adapt") == 0) {
       FixAdapt *fix = (FixAdapt *) modify->fix[i];
       if (fix->diamflag) {
         radvary = 1;
         comm_x_only = 0;
         size_forward = 5;
       }
     }
 }
 
 /* ----------------------------------------------------------------------
    grow atom arrays
    n = 0 grows arrays by DELTA
    n > 0 allocates arrays to size n
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::grow(int n)
 {
   if (n == 0) nmax += DELTA;
   else nmax = n;
   atom->nmax = nmax;
   if (nmax < 0 || nmax > MAXSMALLINT)
     error->one(FLERR,"Per-processor system is too big");
 
   tag = memory->grow(atom->tag,nmax,"atom:tag");
   type = memory->grow(atom->type,nmax,"atom:type");
   mask = memory->grow(atom->mask,nmax,"atom:mask");
   image = memory->grow(atom->image,nmax,"atom:image");
   x = memory->grow(atom->x,nmax+1,3,"atom:x");
   v = memory->grow(atom->v,nmax,3,"atom:v");
   f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
 
   radius = memory->grow(atom->radius,nmax,"atom:radius");
   rmass = memory->grow(atom->rmass,nmax,"atom:rmass");
   omega = memory->grow(atom->omega,nmax,3,"atom:omega");
   torque = memory->grow(atom->torque,nmax*comm->nthreads,3,"atom:torque");
 
   if (atom->nextra_grow)
     for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
       modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
 }
 
 /* ----------------------------------------------------------------------
    reset local array ptrs
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::grow_reset()
 {
   tag = atom->tag; type = atom->type;
   mask = atom->mask; image = atom->image;
   x = atom->x; v = atom->v; f = atom->f;
   radius = atom->radius; rmass = atom->rmass;
   omega = atom->omega; torque = atom->torque;
 }
 
 /* ----------------------------------------------------------------------
    copy atom I info to atom J
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::copy(int i, int j, int delflag)
 {
   tag[j] = tag[i];
   type[j] = type[i];
   mask[j] = mask[i];
   image[j] = image[i];
   x[j][0] = x[i][0];
   x[j][1] = x[i][1];
   x[j][2] = x[i][2];
   v[j][0] = v[i][0];
   v[j][1] = v[i][1];
   v[j][2] = v[i][2];
 
   radius[j] = radius[i];
   rmass[j] = rmass[i];
   omega[j][0] = omega[i][0];
   omega[j][1] = omega[i][1];
   omega[j][2] = omega[i][2];
 
   if (atom->nextra_grow)
     for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
       modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j,delflag);
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_comm(int n, int *list, double *buf,
                                int pbc_flag, int *pbc)
 {
   int i,j,m;
   double dx,dy,dz;
 
   if (radvary == 0) {
     m = 0;
     if (pbc_flag == 0) {
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0];
         buf[m++] = x[j][1];
         buf[m++] = x[j][2];
       }
     } else {
       if (domain->triclinic == 0) {
         dx = pbc[0]*domain->xprd;
         dy = pbc[1]*domain->yprd;
         dz = pbc[2]*domain->zprd;
       } else {
         dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
         dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
         dz = pbc[2]*domain->zprd;
       }
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0] + dx;
         buf[m++] = x[j][1] + dy;
         buf[m++] = x[j][2] + dz;
       }
     }
 
   } else {
     m = 0;
     if (pbc_flag == 0) {
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0];
         buf[m++] = x[j][1];
         buf[m++] = x[j][2];
         buf[m++] = radius[j];
         buf[m++] = rmass[j];
       }
     } else {
       if (domain->triclinic == 0) {
         dx = pbc[0]*domain->xprd;
         dy = pbc[1]*domain->yprd;
         dz = pbc[2]*domain->zprd;
       } else {
         dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
         dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
         dz = pbc[2]*domain->zprd;
       }
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0] + dx;
         buf[m++] = x[j][1] + dy;
         buf[m++] = x[j][2] + dz;
         buf[m++] = radius[j];
         buf[m++] = rmass[j];
       }
     }
   }
 
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_comm_vel(int n, int *list, double *buf,
                                    int pbc_flag, int *pbc)
 {
   int i,j,m;
   double dx,dy,dz,dvx,dvy,dvz;
 
   if (radvary == 0) {
     m = 0;
     if (pbc_flag == 0) {
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0];
         buf[m++] = x[j][1];
         buf[m++] = x[j][2];
         buf[m++] = v[j][0];
         buf[m++] = v[j][1];
         buf[m++] = v[j][2];
         buf[m++] = omega[j][0];
         buf[m++] = omega[j][1];
         buf[m++] = omega[j][2];
       }
     } else {
       if (domain->triclinic == 0) {
         dx = pbc[0]*domain->xprd;
         dy = pbc[1]*domain->yprd;
         dz = pbc[2]*domain->zprd;
       } else {
         dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
         dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
         dz = pbc[2]*domain->zprd;
       }
       if (!deform_vremap) {
         for (i = 0; i < n; i++) {
           j = list[i];
           buf[m++] = x[j][0] + dx;
           buf[m++] = x[j][1] + dy;
           buf[m++] = x[j][2] + dz;
           buf[m++] = v[j][0];
           buf[m++] = v[j][1];
           buf[m++] = v[j][2];
           buf[m++] = omega[j][0];
           buf[m++] = omega[j][1];
           buf[m++] = omega[j][2];
         }
       } else {
         dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
         dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
         dvz = pbc[2]*h_rate[2];
         for (i = 0; i < n; i++) {
           j = list[i];
           buf[m++] = x[j][0] + dx;
           buf[m++] = x[j][1] + dy;
           buf[m++] = x[j][2] + dz;
           if (mask[i] & deform_groupbit) {
             buf[m++] = v[j][0] + dvx;
             buf[m++] = v[j][1] + dvy;
             buf[m++] = v[j][2] + dvz;
           } else {
             buf[m++] = v[j][0];
             buf[m++] = v[j][1];
             buf[m++] = v[j][2];
           }
           buf[m++] = omega[j][0];
           buf[m++] = omega[j][1];
           buf[m++] = omega[j][2];
         }
       }
     }
 
   } else {
     m = 0;
     if (pbc_flag == 0) {
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0];
         buf[m++] = x[j][1];
         buf[m++] = x[j][2];
         buf[m++] = radius[j];
         buf[m++] = rmass[j];
         buf[m++] = v[j][0];
         buf[m++] = v[j][1];
         buf[m++] = v[j][2];
         buf[m++] = omega[j][0];
         buf[m++] = omega[j][1];
         buf[m++] = omega[j][2];
       }
     } else {
       if (domain->triclinic == 0) {
         dx = pbc[0]*domain->xprd;
         dy = pbc[1]*domain->yprd;
         dz = pbc[2]*domain->zprd;
       } else {
         dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
         dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
         dz = pbc[2]*domain->zprd;
       }
       if (!deform_vremap) {
         for (i = 0; i < n; i++) {
           j = list[i];
           buf[m++] = x[j][0] + dx;
           buf[m++] = x[j][1] + dy;
           buf[m++] = x[j][2] + dz;
           buf[m++] = radius[j];
           buf[m++] = rmass[j];
           buf[m++] = v[j][0];
           buf[m++] = v[j][1];
           buf[m++] = v[j][2];
           buf[m++] = omega[j][0];
           buf[m++] = omega[j][1];
           buf[m++] = omega[j][2];
         }
       } else {
         dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
         dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
         dvz = pbc[2]*h_rate[2];
         for (i = 0; i < n; i++) {
           j = list[i];
           buf[m++] = x[j][0] + dx;
           buf[m++] = x[j][1] + dy;
           buf[m++] = x[j][2] + dz;
           buf[m++] = radius[j];
           buf[m++] = rmass[j];
           if (mask[i] & deform_groupbit) {
             buf[m++] = v[j][0] + dvx;
             buf[m++] = v[j][1] + dvy;
             buf[m++] = v[j][2] + dvz;
           } else {
             buf[m++] = v[j][0];
             buf[m++] = v[j][1];
             buf[m++] = v[j][2];
           }
           buf[m++] = omega[j][0];
           buf[m++] = omega[j][1];
           buf[m++] = omega[j][2];
         }
       }
     }
   }
 
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_comm_hybrid(int n, int *list, double *buf)
 {
   int i,j,m;
 
   if (radvary == 0) return 0;
 
   m = 0;
   for (i = 0; i < n; i++) {
     j = list[i];
     buf[m++] = radius[j];
     buf[m++] = rmass[j];
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void AtomVecSphere::unpack_comm(int n, int first, double *buf)
 {
   int i,m,last;
 
   if (radvary == 0) {
     m = 0;
     last = first + n;
     for (i = first; i < last; i++) {
       x[i][0] = buf[m++];
       x[i][1] = buf[m++];
       x[i][2] = buf[m++];
     }
   } else {
     m = 0;
     last = first + n;
     for (i = first; i < last; i++) {
       x[i][0] = buf[m++];
       x[i][1] = buf[m++];
       x[i][2] = buf[m++];
       radius[i] = buf[m++];
       rmass[i] = buf[m++];
     }
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void AtomVecSphere::unpack_comm_vel(int n, int first, double *buf)
 {
   int i,m,last;
 
   if (radvary == 0) {
     m = 0;
     last = first + n;
     for (i = first; i < last; i++) {
       x[i][0] = buf[m++];
       x[i][1] = buf[m++];
       x[i][2] = buf[m++];
       v[i][0] = buf[m++];
       v[i][1] = buf[m++];
       v[i][2] = buf[m++];
       omega[i][0] = buf[m++];
       omega[i][1] = buf[m++];
       omega[i][2] = buf[m++];
     }
   } else {
     m = 0;
     last = first + n;
     for (i = first; i < last; i++) {
       x[i][0] = buf[m++];
       x[i][1] = buf[m++];
       x[i][2] = buf[m++];
       radius[i] = buf[m++];
       rmass[i] = buf[m++];
       v[i][0] = buf[m++];
       v[i][1] = buf[m++];
       v[i][2] = buf[m++];
       omega[i][0] = buf[m++];
       omega[i][1] = buf[m++];
       omega[i][2] = buf[m++];
     }
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::unpack_comm_hybrid(int n, int first, double *buf)
 {
   int i,m,last;
 
   if (radvary == 0) return 0;
 
   m = 0;
   last = first + n;
   for (i = first; i < last; i++) {
     radius[i] = buf[m++];
     rmass[i] = buf[m++];
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_reverse(int n, int first, double *buf)
 {
   int i,m,last;
 
   m = 0;
   last = first + n;
   for (i = first; i < last; i++) {
     buf[m++] = f[i][0];
     buf[m++] = f[i][1];
     buf[m++] = f[i][2];
     buf[m++] = torque[i][0];
     buf[m++] = torque[i][1];
     buf[m++] = torque[i][2];
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_reverse_hybrid(int n, int first, double *buf)
 {
   int i,m,last;
 
   m = 0;
   last = first + n;
   for (i = first; i < last; i++) {
     buf[m++] = torque[i][0];
     buf[m++] = torque[i][1];
     buf[m++] = torque[i][2];
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void AtomVecSphere::unpack_reverse(int n, int *list, double *buf)
 {
   int i,j,m;
 
   m = 0;
   for (i = 0; i < n; i++) {
     j = list[i];
     f[j][0] += buf[m++];
     f[j][1] += buf[m++];
     f[j][2] += buf[m++];
     torque[j][0] += buf[m++];
     torque[j][1] += buf[m++];
     torque[j][2] += buf[m++];
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::unpack_reverse_hybrid(int n, int *list, double *buf)
 {
   int i,j,m;
 
   m = 0;
   for (i = 0; i < n; i++) {
     j = list[i];
     torque[j][0] += buf[m++];
     torque[j][1] += buf[m++];
     torque[j][2] += buf[m++];
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_border(int n, int *list, double *buf,
                                  int pbc_flag, int *pbc)
 {
   int i,j,m;
   double dx,dy,dz;
 
   m = 0;
   if (pbc_flag == 0) {
     for (i = 0; i < n; i++) {
       j = list[i];
       buf[m++] = x[j][0];
       buf[m++] = x[j][1];
       buf[m++] = x[j][2];
       buf[m++] = tag[j];
       buf[m++] = type[j];
       buf[m++] = mask[j];
       buf[m++] = radius[j];
       buf[m++] = rmass[j];
     }
   } else {
     if (domain->triclinic == 0) {
       dx = pbc[0]*domain->xprd;
       dy = pbc[1]*domain->yprd;
       dz = pbc[2]*domain->zprd;
     } else {
       dx = pbc[0];
       dy = pbc[1];
       dz = pbc[2];
     }
     for (i = 0; i < n; i++) {
       j = list[i];
       buf[m++] = x[j][0] + dx;
       buf[m++] = x[j][1] + dy;
       buf[m++] = x[j][2] + dz;
       buf[m++] = tag[j];
       buf[m++] = type[j];
       buf[m++] = mask[j];
       buf[m++] = radius[j];
       buf[m++] = rmass[j];
     }
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_border_vel(int n, int *list, double *buf,
                                      int pbc_flag, int *pbc)
 {
   int i,j,m;
   double dx,dy,dz,dvx,dvy,dvz;
 
   m = 0;
   if (pbc_flag == 0) {
     for (i = 0; i < n; i++) {
       j = list[i];
       buf[m++] = x[j][0];
       buf[m++] = x[j][1];
       buf[m++] = x[j][2];
       buf[m++] = tag[j];
       buf[m++] = type[j];
       buf[m++] = mask[j];
       buf[m++] = radius[j];
       buf[m++] = rmass[j];
       buf[m++] = v[j][0];
       buf[m++] = v[j][1];
       buf[m++] = v[j][2];
       buf[m++] = omega[j][0];
       buf[m++] = omega[j][1];
       buf[m++] = omega[j][2];
     }
   } else {
     if (domain->triclinic == 0) {
       dx = pbc[0]*domain->xprd;
       dy = pbc[1]*domain->yprd;
       dz = pbc[2]*domain->zprd;
     } else {
       dx = pbc[0];
       dy = pbc[1];
       dz = pbc[2];
     }
     if (!deform_vremap) {
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0] + dx;
         buf[m++] = x[j][1] + dy;
         buf[m++] = x[j][2] + dz;
         buf[m++] = tag[j];
         buf[m++] = type[j];
         buf[m++] = mask[j];
         buf[m++] = radius[j];
         buf[m++] = rmass[j];
         buf[m++] = v[j][0];
         buf[m++] = v[j][1];
         buf[m++] = v[j][2];
         buf[m++] = omega[j][0];
         buf[m++] = omega[j][1];
         buf[m++] = omega[j][2];
       }
     } else {
       dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
       dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
       dvz = pbc[2]*h_rate[2];
       for (i = 0; i < n; i++) {
         j = list[i];
         buf[m++] = x[j][0] + dx;
         buf[m++] = x[j][1] + dy;
         buf[m++] = x[j][2] + dz;
         buf[m++] = tag[j];
         buf[m++] = type[j];
         buf[m++] = mask[j];
         buf[m++] = radius[j];
         buf[m++] = rmass[j];
         if (mask[i] & deform_groupbit) {
           buf[m++] = v[j][0] + dvx;
           buf[m++] = v[j][1] + dvy;
           buf[m++] = v[j][2] + dvz;
         } else {
           buf[m++] = v[j][0];
           buf[m++] = v[j][1];
           buf[m++] = v[j][2];
         }
         buf[m++] = omega[j][0];
         buf[m++] = omega[j][1];
         buf[m++] = omega[j][2];
       }
     }
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_border_hybrid(int n, int *list, double *buf)
 {
   int i,j,m;
 
   m = 0;
   for (i = 0; i < n; i++) {
     j = list[i];
     buf[m++] = radius[j];
     buf[m++] = rmass[j];
   }
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void AtomVecSphere::unpack_border(int n, int first, double *buf)
 {
   int i,m,last;
 
   m = 0;
   last = first + n;
   for (i = first; i < last; i++) {
     if (i == nmax) grow(0);
     x[i][0] = buf[m++];
     x[i][1] = buf[m++];
     x[i][2] = buf[m++];
     tag[i] = static_cast<int> (buf[m++]);
     type[i] = static_cast<int> (buf[m++]);
     mask[i] = static_cast<int> (buf[m++]);
     radius[i] = buf[m++];
     rmass[i] = buf[m++];
   }
 }
 
 
 /* ---------------------------------------------------------------------- */
 
 void AtomVecSphere::unpack_border_vel(int n, int first, double *buf)
 {
   int i,m,last;
 
   m = 0;
   last = first + n;
   for (i = first; i < last; i++) {
     if (i == nmax) grow(0);
     x[i][0] = buf[m++];
     x[i][1] = buf[m++];
     x[i][2] = buf[m++];
     tag[i] = static_cast<int> (buf[m++]);
     type[i] = static_cast<int> (buf[m++]);
     mask[i] = static_cast<int> (buf[m++]);
     radius[i] = buf[m++];
     rmass[i] = buf[m++];
     v[i][0] = buf[m++];
     v[i][1] = buf[m++];
     v[i][2] = buf[m++];
     omega[i][0] = buf[m++];
     omega[i][1] = buf[m++];
     omega[i][2] = buf[m++];
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::unpack_border_hybrid(int n, int first, double *buf)
 {
   int i,m,last;
 
   m = 0;
   last = first + n;
   for (i = first; i < last; i++) {
     radius[i] = buf[m++];
     rmass[i] = buf[m++];
   }
   return m;
 }
 
 /* ----------------------------------------------------------------------
    pack data for atom I for sending to another proc
    xyz must be 1st 3 values, so comm::exchange() can test on them
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_exchange(int i, double *buf)
 {
   int m = 1;
   buf[m++] = x[i][0];
   buf[m++] = x[i][1];
   buf[m++] = x[i][2];
   buf[m++] = v[i][0];
   buf[m++] = v[i][1];
   buf[m++] = v[i][2];
   buf[m++] = tag[i];
   buf[m++] = type[i];
   buf[m++] = mask[i];
   *((tagint *) &buf[m++]) = image[i];
 
   buf[m++] = radius[i];
   buf[m++] = rmass[i];
   buf[m++] = omega[i][0];
   buf[m++] = omega[i][1];
   buf[m++] = omega[i][2];
 
   if (atom->nextra_grow)
     for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
       m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
 
   buf[0] = m;
   return m;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int AtomVecSphere::unpack_exchange(double *buf)
 {
   int nlocal = atom->nlocal;
   if (nlocal == nmax) grow(0);
 
   int m = 1;
   x[nlocal][0] = buf[m++];
   x[nlocal][1] = buf[m++];
   x[nlocal][2] = buf[m++];
   v[nlocal][0] = buf[m++];
   v[nlocal][1] = buf[m++];
   v[nlocal][2] = buf[m++];
   tag[nlocal] = static_cast<int> (buf[m++]);
   type[nlocal] = static_cast<int> (buf[m++]);
   mask[nlocal] = static_cast<int> (buf[m++]);
   image[nlocal] = *((tagint *) &buf[m++]);
 
   radius[nlocal] = buf[m++];
   rmass[nlocal] = buf[m++];
   omega[nlocal][0] = buf[m++];
   omega[nlocal][1] = buf[m++];
   omega[nlocal][2] = buf[m++];
 
   if (atom->nextra_grow)
     for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
       m += modify->fix[atom->extra_grow[iextra]]->
         unpack_exchange(nlocal,&buf[m]);
 
   atom->nlocal++;
   return m;
 }
 
 /* ----------------------------------------------------------------------
    size of restart data for all atoms owned by this proc
    include extra data stored by fixes
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::size_restart()
 {
   int i;
 
   int nlocal = atom->nlocal;
   int n = 16 * nlocal;
 
   if (atom->nextra_restart)
     for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
       for (i = 0; i < nlocal; i++)
         n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
 
   return n;
 }
 
 /* ----------------------------------------------------------------------
    pack atom I's data for restart file including extra quantities
    xyz must be 1st 3 values, so that read_restart can test on them
    molecular types may be negative, but write as positive
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_restart(int i, double *buf)
 {
   int m = 1;
   buf[m++] = x[i][0];
   buf[m++] = x[i][1];
   buf[m++] = x[i][2];
   buf[m++] = tag[i];
   buf[m++] = type[i];
   buf[m++] = mask[i];
   *((tagint *) &buf[m++]) = image[i];
   buf[m++] = v[i][0];
   buf[m++] = v[i][1];
   buf[m++] = v[i][2];
 
   buf[m++] = radius[i];
   buf[m++] = rmass[i];
   buf[m++] = omega[i][0];
   buf[m++] = omega[i][1];
   buf[m++] = omega[i][2];
 
   if (atom->nextra_restart)
     for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
       m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
 
   buf[0] = m;
   return m;
 }
 
 /* ----------------------------------------------------------------------
    unpack data for one atom from restart file including extra quantities
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::unpack_restart(double *buf)
 {
   int nlocal = atom->nlocal;
   if (nlocal == nmax) {
     grow(0);
     if (atom->nextra_store)
       memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
   }
 
   int m = 1;
   x[nlocal][0] = buf[m++];
   x[nlocal][1] = buf[m++];
   x[nlocal][2] = buf[m++];
   tag[nlocal] = static_cast<int> (buf[m++]);
   type[nlocal] = static_cast<int> (buf[m++]);
   mask[nlocal] = static_cast<int> (buf[m++]);
   image[nlocal] = *((tagint *) &buf[m++]);
   v[nlocal][0] = buf[m++];
   v[nlocal][1] = buf[m++];
   v[nlocal][2] = buf[m++];
 
   radius[nlocal] = buf[m++];
   rmass[nlocal] = buf[m++];
   omega[nlocal][0] = buf[m++];
   omega[nlocal][1] = buf[m++];
   omega[nlocal][2] = buf[m++];
 
   double **extra = atom->extra;
   if (atom->nextra_store) {
     int size = static_cast<int> (buf[0]) - m;
     for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
   }
 
   atom->nlocal++;
   return m;
 }
 
 /* ----------------------------------------------------------------------
    create one atom of itype at coord
    set other values to defaults
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::create_atom(int itype, double *coord)
 {
   int nlocal = atom->nlocal;
   if (nlocal == nmax) grow(0);
 
   tag[nlocal] = 0;
   type[nlocal] = itype;
   x[nlocal][0] = coord[0];
   x[nlocal][1] = coord[1];
   x[nlocal][2] = coord[2];
   mask[nlocal] = 1;
   image[nlocal] = ((tagint) IMGMAX << IMG2BITS) |
     ((tagint) IMGMAX << IMGBITS) | IMGMAX;
   v[nlocal][0] = 0.0;
   v[nlocal][1] = 0.0;
   v[nlocal][2] = 0.0;
 
   radius[nlocal] = 0.5;
   rmass[nlocal] = 4.0*MY_PI/3.0 * radius[nlocal]*radius[nlocal]*radius[nlocal];
   omega[nlocal][0] = 0.0;
   omega[nlocal][1] = 0.0;
   omega[nlocal][2] = 0.0;
 
   atom->nlocal++;
 }
 
 /* ----------------------------------------------------------------------
    unpack one line from Atoms section of data file
    initialize other atom quantities
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::data_atom(double *coord, tagint imagetmp, char **values)
 {
   int nlocal = atom->nlocal;
   if (nlocal == nmax) grow(0);
 
   tag[nlocal] = atoi(values[0]);
   if (tag[nlocal] <= 0)
     error->one(FLERR,"Invalid atom ID in Atoms section of data file");
 
   type[nlocal] = atoi(values[1]);
   if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
     error->one(FLERR,"Invalid atom type in Atoms section of data file");
 
   radius[nlocal] = 0.5 * atof(values[2]);
   if (radius[nlocal] < 0.0)
     error->one(FLERR,"Invalid radius in Atoms section of data file");
 
   double density = atof(values[3]);
   if (density <= 0.0)
     error->one(FLERR,"Invalid density in Atoms section of data file");
 
   if (radius[nlocal] == 0.0) rmass[nlocal] = density;
   else
     rmass[nlocal] = 4.0*MY_PI/3.0 *
       radius[nlocal]*radius[nlocal]*radius[nlocal] * density;
 
   x[nlocal][0] = coord[0];
   x[nlocal][1] = coord[1];
   x[nlocal][2] = coord[2];
 
   image[nlocal] = imagetmp;
 
   mask[nlocal] = 1;
   v[nlocal][0] = 0.0;
   v[nlocal][1] = 0.0;
   v[nlocal][2] = 0.0;
   omega[nlocal][0] = 0.0;
   omega[nlocal][1] = 0.0;
   omega[nlocal][2] = 0.0;
 
   atom->nlocal++;
 }
 
 /* ----------------------------------------------------------------------
    unpack hybrid quantities from one line in Atoms section of data file
    initialize other atom quantities for this sub-style
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::data_atom_hybrid(int nlocal, char **values)
 {
   radius[nlocal] = 0.5 * atof(values[0]);
   if (radius[nlocal] < 0.0)
     error->one(FLERR,"Invalid radius in Atoms section of data file");
 
   double density = atof(values[1]);
   if (density <= 0.0)
     error->one(FLERR,"Invalid density in Atoms section of data file");
 
   if (radius[nlocal] == 0.0) rmass[nlocal] = density;
   else
     rmass[nlocal] = 4.0*MY_PI/3.0 *
       radius[nlocal]*radius[nlocal]*radius[nlocal] * density;
 
   return 2;
 }
 
 /* ----------------------------------------------------------------------
    unpack one line from Velocities section of data file
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::data_vel(int m, char **values)
 {
   v[m][0] = atof(values[0]);
   v[m][1] = atof(values[1]);
   v[m][2] = atof(values[2]);
   omega[m][0] = atof(values[3]);
   omega[m][1] = atof(values[4]);
   omega[m][2] = atof(values[5]);
 }
 
 /* ----------------------------------------------------------------------
    unpack hybrid quantities from one line in Velocities section of data file
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::data_vel_hybrid(int m, char **values)
 {
   omega[m][0] = atof(values[0]);
   omega[m][1] = atof(values[1]);
   omega[m][2] = atof(values[2]);
   return 3;
 }
 
 /* ----------------------------------------------------------------------
    pack atom info for data file including 3 image flags
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::pack_data(double **buf)
 {
   int nlocal = atom->nlocal;
   for (int i = 0; i < nlocal; i++) {
     buf[i][0] = tag[i];
     buf[i][1] = type[i];
     buf[i][2] = 2.0*radius[i];
     if (radius[i] == 0.0) buf[i][3] = rmass[i];
     else 
       buf[i][3] = rmass[i] / (4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i]);
     buf[i][4] = x[i][0];
-    buf[i][5] = x[i][0];
-    buf[i][6] = x[i][1];
-    buf[i][7] = x[i][2];
-    buf[i][8] = (image[i] & IMGMASK) - IMGMAX;
-    buf[i][9] = (image[i] >> IMGBITS & IMGMASK) - IMGMAX;
-    buf[i][10] = (image[i] >> IMG2BITS) - IMGMAX;
+    buf[i][5] = x[i][1];
+    buf[i][6] = x[i][2];
+    buf[i][7] = (image[i] & IMGMASK) - IMGMAX;
+    buf[i][8] = (image[i] >> IMGBITS & IMGMASK) - IMGMAX;
+    buf[i][9] = (image[i] >> IMG2BITS) - IMGMAX;
   }
 }
 
 /* ----------------------------------------------------------------------
    pack hybrid atom info for data file
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_data_hybrid(int i, double *buf)
 {
   buf[0] = 2.0*radius[i];
   if (radius[i] == 0.0) buf[1] = rmass[i];
   else buf[1] = rmass[i] / (4.0*MY_PI/3.0 * radius[i]*radius[i]*radius[i]);
   return 2;
 }
 
 /* ----------------------------------------------------------------------
    write atom info to data file including 3 image flags
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::write_data(FILE *fp, int n, double **buf)
 {
   for (int i = 0; i < n; i++)
     fprintf(fp,"%d %d %-1.16e %-1.16e %-1.16e %-1.16e %-1.16e %d %d %d\n",
             (int) buf[i][0],(int) buf[i][1],
             buf[i][2],buf[i][3],
             buf[i][4],buf[i][5],buf[i][6],
             (int) buf[i][7],(int) buf[i][8],(int) buf[i][9]);
 }
 
 /* ----------------------------------------------------------------------
    write hybrid atom info to data file
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::write_data_hybrid(FILE *fp, double *buf)
 {
   fprintf(fp," %-1.16e %-1.16e",buf[0],buf[1]);
   return 2;
 }
 
 /* ----------------------------------------------------------------------
    pack velocity info for data file
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::pack_vel(double **buf)
 {
   int nlocal = atom->nlocal;
   for (int i = 0; i < nlocal; i++) {
     buf[i][0] = tag[i];
     buf[i][1] = v[i][0];
     buf[i][2] = v[i][1];
     buf[i][3] = v[i][2];
     buf[i][4] = omega[i][0];
     buf[i][5] = omega[i][1];
     buf[i][6] = omega[i][2];
   }
 }
 
 /* ----------------------------------------------------------------------
    pack hybrid velocity info for data file
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::pack_vel_hybrid(int i, double *buf)
 {
   buf[0] = omega[i][0];
   buf[1] = omega[i][1];
   buf[2] = omega[i][2];
   return 3;
 }
 
 /* ----------------------------------------------------------------------
    write velocity info to data file
 ------------------------------------------------------------------------- */
 
 void AtomVecSphere::write_vel(FILE *fp, int n, double **buf)
 {
   for (int i = 0; i < n; i++)
     fprintf(fp,"%d %-1.16e %-1.16e %-1.16e %-1.16e %-1.16e %-1.16e\n",
             (int) buf[i][0],buf[i][1],buf[i][2],buf[i][3],
             buf[i][4],buf[i][5],buf[i][6]);
 }
 
 /* ----------------------------------------------------------------------
    write hybrid velocity info to data file
 ------------------------------------------------------------------------- */
 
 int AtomVecSphere::write_vel_hybrid(FILE *fp, double *buf)
 {
   fprintf(fp," %-1.16e %-1.16e %-1.16e",buf[0],buf[1],buf[2]);
   return 3;
 }
 
 /* ----------------------------------------------------------------------
    return # of bytes of allocated memory
 ------------------------------------------------------------------------- */
 
 bigint AtomVecSphere::memory_usage()
 {
   bigint bytes = 0;
 
   if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
   if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
   if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
   if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
   if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
   if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
   if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
 
   if (atom->memcheck("radius")) bytes += memory->usage(radius,nmax);
   if (atom->memcheck("rmass")) bytes += memory->usage(rmass,nmax);
   if (atom->memcheck("omega")) bytes += memory->usage(omega,nmax,3);
   if (atom->memcheck("torque")) 
     bytes += memory->usage(torque,nmax*comm->nthreads,3);
 
   return bytes;
 }
diff --git a/src/comm.cpp b/src/comm.cpp
index 4f4dfe75f..b15fc5a28 100644
--- a/src/comm.cpp
+++ b/src/comm.cpp
@@ -1,1861 +1,1863 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 /* ----------------------------------------------------------------------
    Contributing author (triclinic) : Pieter in 't Veld (SNL)
 ------------------------------------------------------------------------- */
 
 #include "lmptype.h"
 #include "mpi.h"
 #include "math.h"
 #include "string.h"
 #include "stdio.h"
 #include "stdlib.h"
 #include "comm.h"
 #include "universe.h"
 #include "atom.h"
 #include "atom_vec.h"
 #include "force.h"
 #include "pair.h"
 #include "domain.h"
 #include "neighbor.h"
 #include "group.h"
 #include "modify.h"
 #include "fix.h"
 #include "compute.h"
 #include "output.h"
 #include "dump.h"
 #include "procmap.h"
 #include "math_extra.h"
 #include "error.h"
 #include "memory.h"
 
 #ifdef _OPENMP
 #include "omp.h"
 #endif
 
 using namespace LAMMPS_NS;
 
 #define BUFFACTOR 1.5
 #define BUFMIN 1000
 #define BUFEXTRA 1000
 #define BIG 1.0e20
 
 enum{SINGLE,MULTI};
 enum{MULTIPLE};                   // same as in ProcMap
 enum{ONELEVEL,TWOLEVEL,NUMA,CUSTOM};
 enum{CART,CARTREORDER,XYZ};
 
 /* ----------------------------------------------------------------------
    setup MPI and allocate buffer space
 ------------------------------------------------------------------------- */
 
 Comm::Comm(LAMMPS *lmp) : Pointers(lmp)
 {
   MPI_Comm_rank(world,&me);
   MPI_Comm_size(world,&nprocs);
 
   user_procgrid[0] = user_procgrid[1] = user_procgrid[2] = 0;
   coregrid[0] = coregrid[1] = coregrid[2] = 1;
   gridflag = ONELEVEL;
   mapflag = CART;
   customfile = NULL;
   recv_from_partition = send_to_partition = -1;
   otherflag = 0;
   outfile = NULL;
 
   grid2proc = NULL;
 
   bordergroup = 0;
   style = SINGLE;
   uniform = 1;
   xsplit = ysplit = zsplit = NULL;
   multilo = multihi = NULL;
   cutghostmulti = NULL;
   cutghostuser = 0.0;
   ghost_velocity = 0;
 
   // use of OpenMP threads
   // query OpenMP for number of threads/process set by user at run-time
   // if the OMP_NUM_THREADS environment variable is not set, we default
   // to using 1 thread. This follows the principle of the least surprise,
   // while practically all OpenMP implementations violate it by using
   // as many threads as there are (virtual) CPU cores by default.
 
   nthreads = 1;
 #ifdef _OPENMP
   if (getenv("OMP_NUM_THREADS") == NULL) {
     nthreads = 1;
     if (me == 0)
       error->warning(FLERR,"OMP_NUM_THREADS environment is not set.");
   } else {
     nthreads = omp_get_max_threads();
   }
 
   // enforce consistent number of threads across all MPI tasks
 
   MPI_Bcast(&nthreads,1,MPI_INT,0,world);
   omp_set_num_threads(nthreads);
 
   if (me == 0) {
     if (screen)
       fprintf(screen,"  using %d OpenMP thread(s) per MPI task\n",nthreads);
     if (logfile)
       fprintf(logfile,"  using %d OpenMP thread(s) per MPI task\n",nthreads);
   }
 #endif
 
   // initialize comm buffers & exchange memory
 
   maxsend = BUFMIN;
   memory->create(buf_send,maxsend+BUFEXTRA,"comm:buf_send");
   maxrecv = BUFMIN;
   memory->create(buf_recv,maxrecv,"comm:buf_recv");
 
   maxswap = 6;
   allocate_swap(maxswap);
 
   sendlist = (int **) memory->smalloc(maxswap*sizeof(int *),"comm:sendlist");
   memory->create(maxsendlist,maxswap,"comm:maxsendlist");
   for (int i = 0; i < maxswap; i++) {
     maxsendlist[i] = BUFMIN;
     memory->create(sendlist[i],BUFMIN,"comm:sendlist[i]");
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 Comm::~Comm()
 {
   memory->destroy(xsplit);
   memory->destroy(ysplit);
   memory->destroy(zsplit);
 
   delete [] customfile;
   delete [] outfile;
 
   memory->destroy(grid2proc);
 
   free_swap();
   if (style == MULTI) {
     free_multi();
     memory->destroy(cutghostmulti);
   }
 
   if (sendlist) for (int i = 0; i < maxswap; i++) memory->destroy(sendlist[i]);
   memory->sfree(sendlist);
   memory->destroy(maxsendlist);
 
   memory->destroy(buf_send);
   memory->destroy(buf_recv);
 }
 
 /* ----------------------------------------------------------------------
    create 3d grid of procs based on Nprocs and box size & shape
    map processors to grid, setup xyz split for a uniform grid
 ------------------------------------------------------------------------- */
 
 void Comm::set_proc_grid(int outflag)
 {
   // recv 3d proc grid of another partition if my 3d grid depends on it
 
   if (recv_from_partition >= 0) {
     MPI_Status status;
     if (me == 0) {
       MPI_Recv(other_procgrid,3,MPI_INT,
                universe->root_proc[recv_from_partition],0,
                universe->uworld,&status);
       MPI_Recv(other_coregrid,3,MPI_INT,
                universe->root_proc[recv_from_partition],0,
                universe->uworld,&status);
     }
     MPI_Bcast(other_procgrid,3,MPI_INT,0,world);
     MPI_Bcast(other_coregrid,3,MPI_INT,0,world);
   }
 
   // create ProcMap class to create 3d grid and map procs to it
 
   ProcMap *pmap = new ProcMap(lmp);
 
   // create 3d grid of processors
   // produces procgrid and coregrid (if relevant)
 
   if (gridflag == ONELEVEL) {
     pmap->onelevel_grid(nprocs,user_procgrid,procgrid,
                         otherflag,other_style,other_procgrid,other_coregrid);
 
   } else if (gridflag == TWOLEVEL) {
     pmap->twolevel_grid(nprocs,user_procgrid,procgrid,
                         ncores,user_coregrid,coregrid,
                         otherflag,other_style,other_procgrid,other_coregrid);
 
   } else if (gridflag == NUMA) {
     pmap->numa_grid(nprocs,user_procgrid,procgrid,coregrid);
 
   } else if (gridflag == CUSTOM) {
     pmap->custom_grid(customfile,nprocs,user_procgrid,procgrid);
   }
 
   // error check on procgrid
   // should not be necessary due to ProcMap
 
   if (procgrid[0]*procgrid[1]*procgrid[2] != nprocs)
     error->all(FLERR,"Bad grid of processors");
   if (domain->dimension == 2 && procgrid[2] != 1)
     error->all(FLERR,"Processor count in z must be 1 for 2d simulation");
 
   // grid2proc[i][j][k] = proc that owns i,j,k location in 3d grid
 
   if (grid2proc) memory->destroy(grid2proc);
   memory->create(grid2proc,procgrid[0],procgrid[1],procgrid[2],
                  "comm:grid2proc");
 
   // map processor IDs to 3d processor grid
   // produces myloc, procneigh, grid2proc
 
   if (gridflag == ONELEVEL) {
     if (mapflag == CART)
       pmap->cart_map(0,procgrid,myloc,procneigh,grid2proc);
     else if (mapflag == CARTREORDER)
       pmap->cart_map(1,procgrid,myloc,procneigh,grid2proc);
     else if (mapflag == XYZ)
       pmap->xyz_map(xyz,procgrid,myloc,procneigh,grid2proc);
 
   } else if (gridflag == TWOLEVEL) {
     if (mapflag == CART)
       pmap->cart_map(0,procgrid,ncores,coregrid,myloc,procneigh,grid2proc);
     else if (mapflag == CARTREORDER)
       pmap->cart_map(1,procgrid,ncores,coregrid,myloc,procneigh,grid2proc);
     else if (mapflag == XYZ)
       pmap->xyz_map(xyz,procgrid,ncores,coregrid,myloc,procneigh,grid2proc);
 
   } else if (gridflag == NUMA) {
     pmap->numa_map(0,coregrid,myloc,procneigh,grid2proc);
 
   } else if (gridflag == CUSTOM) {
     pmap->custom_map(procgrid,myloc,procneigh,grid2proc);
   }
 
   // print 3d grid info to screen and logfile
 
   if (outflag && me == 0) {
     if (screen) {
       fprintf(screen,"  %d by %d by %d MPI processor grid\n",
               procgrid[0],procgrid[1],procgrid[2]);
       if (gridflag == NUMA || gridflag == TWOLEVEL)
         fprintf(screen,"  %d by %d by %d core grid within node\n",
                 coregrid[0],coregrid[1],coregrid[2]);
     }
     if (logfile) {
       fprintf(logfile,"  %d by %d by %d MPI processor grid\n",
               procgrid[0],procgrid[1],procgrid[2]);
       if (gridflag == NUMA || gridflag == TWOLEVEL)
         fprintf(logfile,"  %d by %d by %d core grid within node\n",
                 coregrid[0],coregrid[1],coregrid[2]);
     }
   }
 
   // print 3d grid details to outfile
 
   if (outfile) pmap->output(outfile,procgrid,grid2proc);
 
   // free ProcMap class
 
   delete pmap;
 
   // set xsplit,ysplit,zsplit for uniform spacings
 
   memory->destroy(xsplit);
   memory->destroy(ysplit);
   memory->destroy(zsplit);
 
   memory->create(xsplit,procgrid[0]+1,"comm:xsplit");
   memory->create(ysplit,procgrid[1]+1,"comm:ysplit");
   memory->create(zsplit,procgrid[2]+1,"comm:zsplit");
 
   for (int i = 0; i < procgrid[0]; i++) xsplit[i] = i * 1.0/procgrid[0];
   for (int i = 0; i < procgrid[1]; i++) ysplit[i] = i * 1.0/procgrid[1];
   for (int i = 0; i < procgrid[2]; i++) zsplit[i] = i * 1.0/procgrid[2];
 
   xsplit[procgrid[0]] = ysplit[procgrid[1]] = zsplit[procgrid[2]] = 1.0;
 
   // set lamda box params after procs are assigned
   // only set once unless load-balancing occurs
 
   if (domain->triclinic) domain->set_lamda_box();
 
   // send my 3d proc grid to another partition if requested
 
   if (send_to_partition >= 0) {
     if (me == 0) {
       MPI_Send(procgrid,3,MPI_INT,
                universe->root_proc[send_to_partition],0,
                universe->uworld);
       MPI_Send(coregrid,3,MPI_INT,
                universe->root_proc[send_to_partition],0,
                universe->uworld);
     }
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Comm::init()
 {
   triclinic = domain->triclinic;
   map_style = atom->map_style;
 
   // comm_only = 1 if only x,f are exchanged in forward/reverse comm
   // comm_x_only = 0 if ghost_velocity since velocities are added
 
   comm_x_only = atom->avec->comm_x_only;
   comm_f_only = atom->avec->comm_f_only;
   if (ghost_velocity) comm_x_only = 0;
 
   // set per-atom sizes for forward/reverse/border comm
   // augment by velocity quantities if needed
 
   size_forward = atom->avec->size_forward;
   size_reverse = atom->avec->size_reverse;
   size_border = atom->avec->size_border;
 
   if (ghost_velocity) size_forward += atom->avec->size_velocity;
   if (ghost_velocity) size_border += atom->avec->size_velocity;
 
   // maxforward = # of datums in largest forward communication
   // maxreverse = # of datums in largest reverse communication
   // query pair,fix,compute,dump for their requirements
   // pair style can force reverse comm even if newton off
 
   maxforward = MAX(size_forward,size_border);
   maxreverse = size_reverse;
 
   if (force->pair) maxforward = MAX(maxforward,force->pair->comm_forward);
   if (force->pair) maxreverse = MAX(maxreverse,force->pair->comm_reverse);
 
   for (int i = 0; i < modify->nfix; i++) {
     maxforward = MAX(maxforward,modify->fix[i]->comm_forward);
     maxreverse = MAX(maxreverse,modify->fix[i]->comm_reverse);
   }
 
   for (int i = 0; i < modify->ncompute; i++) {
     maxforward = MAX(maxforward,modify->compute[i]->comm_forward);
     maxreverse = MAX(maxreverse,modify->compute[i]->comm_reverse);
   }
 
   for (int i = 0; i < output->ndump; i++) {
     maxforward = MAX(maxforward,output->dump[i]->comm_forward);
     maxreverse = MAX(maxreverse,output->dump[i]->comm_reverse);
   }
 
   if (force->newton == 0) maxreverse = 0;
   if (force->pair) maxreverse = MAX(maxreverse,force->pair->comm_reverse_off);
 
   // memory for multi-style communication
 
   if (style == MULTI && multilo == NULL) {
     allocate_multi(maxswap);
     memory->create(cutghostmulti,atom->ntypes+1,3,"comm:cutghostmulti");
   }
   if (style == SINGLE && multilo) {
     free_multi();
     memory->destroy(cutghostmulti);
   }
 }
 
 /* ----------------------------------------------------------------------
    setup spatial-decomposition communication patterns
    function of neighbor cutoff(s) & cutghostuser & current box size
    single style sets slab boundaries (slablo,slabhi) based on max cutoff
    multi style sets type-dependent slab boundaries (multilo,multihi)
 ------------------------------------------------------------------------- */
 
 void Comm::setup()
 {
   // cutghost[] = max distance at which ghost atoms need to be acquired
   // for orthogonal:
   //   cutghost is in box coords = neigh->cutghost in all 3 dims
   // for triclinic:
   //   neigh->cutghost = distance between tilted planes in box coords
   //   cutghost is in lamda coords = distance between those planes
   // for multi:
   //   cutghostmulti = same as cutghost, only for each atom type
 
   int i;
   int ntypes = atom->ntypes;
   double *prd,*sublo,*subhi;
 
   double cut = MAX(neighbor->cutneighmax,cutghostuser);
 
   if (triclinic == 0) {
     prd = domain->prd;
     sublo = domain->sublo;
     subhi = domain->subhi;
     cutghost[0] = cutghost[1] = cutghost[2] = cut;
 
     if (style == MULTI) {
       double *cuttype = neighbor->cuttype;
       for (i = 1; i <= ntypes; i++)
         cutghostmulti[i][0] = cutghostmulti[i][1] = cutghostmulti[i][2] =
           cuttype[i];
     }
 
   } else {
     prd = domain->prd_lamda;
     sublo = domain->sublo_lamda;
     subhi = domain->subhi_lamda;
     double *h_inv = domain->h_inv;
     double length0,length1,length2;
     length0 = sqrt(h_inv[0]*h_inv[0] + h_inv[5]*h_inv[5] + h_inv[4]*h_inv[4]);
     cutghost[0] = cut * length0;
     length1 = sqrt(h_inv[1]*h_inv[1] + h_inv[3]*h_inv[3]);
     cutghost[1] = cut * length1;
     length2 = h_inv[2];
     cutghost[2] = cut * length2;
 
     if (style == MULTI) {
       double *cuttype = neighbor->cuttype;
       for (i = 1; i <= ntypes; i++) {
         cutghostmulti[i][0] = cuttype[i] * length0;
         cutghostmulti[i][1] = cuttype[i] * length1;
         cutghostmulti[i][2] = cuttype[i] * length2;
       }
     }
   }
 
   // recvneed[idim][0/1] = # of procs away I recv atoms from, within cutghost
   //   0 = from left, 1 = from right
   //   do not cross non-periodic boundaries, need[2] = 0 for 2d
   // sendneed[idim][0/1] = # of procs away I send atoms to
   //   0 = to left, 1 = to right
   //   set equal to recvneed[idim][1/0] of neighbor proc
   // maxneed[idim] = max procs away any proc recvs atoms in either direction
   // uniform = 1 = uniform sized sub-domains:
   //   maxneed is directly computable from sub-domain size
   //     limit to procgrid-1 for non-PBC
   //   recvneed = maxneed except for procs near non-PBC
   //   sendneed = recvneed of neighbor on each side
   // uniform = 0 = non-uniform sized sub-domains:
   //   compute recvneed via updown() which accounts for non-PBC
   //   sendneed = recvneed of neighbor on each side
   //   maxneed via Allreduce() of recvneed
 
   int *periodicity = domain->periodicity;
   int left,right;
 
   if (uniform) {
     maxneed[0] = static_cast<int> (cutghost[0] * procgrid[0] / prd[0]) + 1;
     maxneed[1] = static_cast<int> (cutghost[1] * procgrid[1] / prd[1]) + 1;
     maxneed[2] = static_cast<int> (cutghost[2] * procgrid[2] / prd[2]) + 1;
     if (domain->dimension == 2) maxneed[2] = 0;
     if (!periodicity[0]) maxneed[0] = MIN(maxneed[0],procgrid[0]-1);
     if (!periodicity[1]) maxneed[1] = MIN(maxneed[1],procgrid[1]-1);
     if (!periodicity[2]) maxneed[2] = MIN(maxneed[2],procgrid[2]-1);
 
     if (!periodicity[0]) {
       recvneed[0][0] = MIN(maxneed[0],myloc[0]);
       recvneed[0][1] = MIN(maxneed[0],procgrid[0]-myloc[0]-1);
       left = myloc[0] - 1;
       if (left < 0) left = procgrid[0] - 1;
       sendneed[0][0] = MIN(maxneed[0],procgrid[0]-left-1);
       right = myloc[0] + 1;
       if (right == procgrid[0]) right = 0;
       sendneed[0][1] = MIN(maxneed[0],right);
     } else recvneed[0][0] = recvneed[0][1] =
              sendneed[0][0] = sendneed[0][1] = maxneed[0];
 
     if (!periodicity[1]) {
       recvneed[1][0] = MIN(maxneed[1],myloc[1]);
       recvneed[1][1] = MIN(maxneed[1],procgrid[1]-myloc[1]-1);
       left = myloc[1] - 1;
       if (left < 0) left = procgrid[1] - 1;
       sendneed[1][0] = MIN(maxneed[1],procgrid[1]-left-1);
       right = myloc[1] + 1;
       if (right == procgrid[1]) right = 0;
       sendneed[1][1] = MIN(maxneed[1],right);
     } else recvneed[1][0] = recvneed[1][1] =
              sendneed[1][0] = sendneed[1][1] = maxneed[1];
 
     if (!periodicity[2]) {
       recvneed[2][0] = MIN(maxneed[2],myloc[2]);
       recvneed[2][1] = MIN(maxneed[2],procgrid[2]-myloc[2]-1);
       left = myloc[2] - 1;
       if (left < 0) left = procgrid[2] - 1;
       sendneed[2][0] = MIN(maxneed[2],procgrid[2]-left-1);
       right = myloc[2] + 1;
       if (right == procgrid[2]) right = 0;
       sendneed[2][1] = MIN(maxneed[2],right);
     } else recvneed[2][0] = recvneed[2][1] =
              sendneed[2][0] = sendneed[2][1] = maxneed[2];
 
   } else {
     recvneed[0][0] = updown(0,0,myloc[0],prd[0],periodicity[0],xsplit);
     recvneed[0][1] = updown(0,1,myloc[0],prd[0],periodicity[0],xsplit);
     left = myloc[0] - 1;
     if (left < 0) left = procgrid[0] - 1;
     sendneed[0][0] = updown(0,1,left,prd[0],periodicity[0],xsplit);
     right = myloc[0] + 1;
     if (right == procgrid[0]) right = 0;
     sendneed[0][1] = updown(0,0,right,prd[0],periodicity[0],xsplit);
 
     recvneed[1][0] = updown(1,0,myloc[1],prd[1],periodicity[1],ysplit);
     recvneed[1][1] = updown(1,1,myloc[1],prd[1],periodicity[1],ysplit);
     left = myloc[1] - 1;
     if (left < 0) left = procgrid[1] - 1;
     sendneed[1][0] = updown(1,1,left,prd[1],periodicity[1],ysplit);
     right = myloc[1] + 1;
     if (right == procgrid[1]) right = 0;
     sendneed[1][1] = updown(1,0,right,prd[1],periodicity[1],ysplit);
 
     if (domain->dimension == 3) {
       recvneed[2][0] = updown(2,0,myloc[2],prd[2],periodicity[2],zsplit);
       recvneed[2][1] = updown(2,1,myloc[2],prd[2],periodicity[2],zsplit);
       left = myloc[2] - 1;
       if (left < 0) left = procgrid[2] - 1;
       sendneed[2][0] = updown(2,1,left,prd[2],periodicity[2],zsplit);
       right = myloc[2] + 1;
       if (right == procgrid[2]) right = 0;
       sendneed[2][1] = updown(2,0,right,prd[2],periodicity[2],zsplit);
     } else recvneed[2][0] = recvneed[2][1] =
              sendneed[2][0] = sendneed[2][1] = 0;
 
     int all[6];
     MPI_Allreduce(&recvneed[0][0],all,6,MPI_INT,MPI_MAX,world);
     maxneed[0] = MAX(all[0],all[1]);
     maxneed[1] = MAX(all[2],all[3]);
     maxneed[2] = MAX(all[4],all[5]);
-    // if (me == 0) printf("MAXNEED %d %d %d\n",maxneed[0],maxneed[1],maxneed[2]);
+    //if (me == 0) 
+    //printf("MAXNEED %d %d %d\n",maxneed[0],maxneed[1],maxneed[2]);
   }
 
   // allocate comm memory
 
   nswap = 2 * (maxneed[0]+maxneed[1]+maxneed[2]);
   if (nswap > maxswap) grow_swap(nswap);
 
   // setup parameters for each exchange:
   // sendproc = proc to send to at each swap
   // recvproc = proc to recv from at each swap
   // for style SINGLE:
   //   slablo/slabhi = boundaries for slab of atoms to send at each swap
   //   use -BIG/midpt/BIG to insure all atoms included even if round-off occurs
   //   if round-off, atoms recvd across PBC can be < or > than subbox boundary
   //   note that borders() only loops over subset of atoms during each swap
   //   treat all as PBC here, non-PBC is handled in borders() via r/s need[][]
   // for style MULTI:
   //   multilo/multihi is same, with slablo/slabhi for each atom type
   // pbc_flag: 0 = nothing across a boundary, 1 = something across a boundary
   // pbc = -1/0/1 for PBC factor in each of 3/6 orthogonal/triclinic dirs
   // for triclinic, slablo/hi and pbc_border will be used in lamda (0-1) coords
   // 1st part of if statement is sending to the west/south/down
   // 2nd part of if statement is sending to the east/north/up
 
   int dim,ineed;
 
   int iswap = 0;
   for (dim = 0; dim < 3; dim++) {
     for (ineed = 0; ineed < 2*maxneed[dim]; ineed++) {
       pbc_flag[iswap] = 0;
       pbc[iswap][0] = pbc[iswap][1] = pbc[iswap][2] =
         pbc[iswap][3] = pbc[iswap][4] = pbc[iswap][5] = 0;
 
       if (ineed % 2 == 0) {
         sendproc[iswap] = procneigh[dim][0];
         recvproc[iswap] = procneigh[dim][1];
         if (style == SINGLE) {
           if (ineed < 2) slablo[iswap] = -BIG;
           else slablo[iswap] = 0.5 * (sublo[dim] + subhi[dim]);
           slabhi[iswap] = sublo[dim] + cutghost[dim];
         } else {
           for (i = 1; i <= ntypes; i++) {
             if (ineed < 2) multilo[iswap][i] = -BIG;
             else multilo[iswap][i] = 0.5 * (sublo[dim] + subhi[dim]);
             multihi[iswap][i] = sublo[dim] + cutghostmulti[i][dim];
           }
         }
         if (myloc[dim] == 0) {
           pbc_flag[iswap] = 1;
           pbc[iswap][dim] = 1;
           if (triclinic) {
             if (dim == 1) pbc[iswap][5] = 1;
             else if (dim == 2) pbc[iswap][4] = pbc[iswap][3] = 1;
           }
         }
 
       } else {
         sendproc[iswap] = procneigh[dim][1];
         recvproc[iswap] = procneigh[dim][0];
         if (style == SINGLE) {
           slablo[iswap] = subhi[dim] - cutghost[dim];
           if (ineed < 2) slabhi[iswap] = BIG;
           else slabhi[iswap] = 0.5 * (sublo[dim] + subhi[dim]);
         } else {
           for (i = 1; i <= ntypes; i++) {
             multilo[iswap][i] = subhi[dim] - cutghostmulti[i][dim];
             if (ineed < 2) multihi[iswap][i] = BIG;
             else multihi[iswap][i] = 0.5 * (sublo[dim] + subhi[dim]);
           }
         }
         if (myloc[dim] == procgrid[dim]-1) {
           pbc_flag[iswap] = 1;
           pbc[iswap][dim] = -1;
           if (triclinic) {
             if (dim == 1) pbc[iswap][5] = -1;
             else if (dim == 2) pbc[iswap][4] = pbc[iswap][3] = -1;
           }
         }
       }
 
       iswap++;
     }
   }
 }
 
 /* ----------------------------------------------------------------------
    walk up/down the extent of nearby processors in dim and dir
    loc = myloc of proc to start at
    dir = 0/1 = walk to left/right
    do not cross non-periodic boundaries
    is not called for z dim in 2d
    return how many procs away are needed to encompass cutghost away from loc
 ------------------------------------------------------------------------- */
 
 int Comm::updown(int dim, int dir, int loc,
                  double prd, int periodicity, double *split)
 {
   int index,count;
   double frac,delta;
 
   if (dir == 0) {
     frac = cutghost[dim]/prd;
     index = loc - 1;
     delta = 0.0;
     count = 0;
     while (delta < frac) {
       if (index < 0) {
         if (!periodicity) break;
         index = procgrid[dim] - 1;
       }
       count++;
       delta += split[index+1] - split[index];
       index--;
     }
 
   } else {
     frac = cutghost[dim]/prd;
     index = loc + 1;
     delta = 0.0;
     count = 0;
     while (delta < frac) {
       if (index >= procgrid[dim]) {
         if (!periodicity) break;
         index = 0;
       }
       count++;
       delta += split[index+1] - split[index];
       index++;
     }
   }
 
   return count;
 }
 
 /* ----------------------------------------------------------------------
    forward communication of atom coords every timestep
    other per-atom attributes may also be sent via pack/unpack routines
 ------------------------------------------------------------------------- */
 
 void Comm::forward_comm(int dummy)
 {
   int n;
   MPI_Request request;
   MPI_Status status;
   AtomVec *avec = atom->avec;
   double **x = atom->x;
   double *buf;
 
   // exchange data with another proc
   // if other proc is self, just copy
   // if comm_x_only set, exchange or copy directly to x, don't unpack
 
   for (int iswap = 0; iswap < nswap; iswap++) {
     if (sendproc[iswap] != me) {
       if (comm_x_only) {
         if (size_forward_recv[iswap]) buf = x[firstrecv[iswap]];
         else buf = NULL;
         if (size_forward_recv[iswap])
           MPI_Irecv(buf,size_forward_recv[iswap],MPI_DOUBLE,
                     recvproc[iswap],0,world,&request);
         n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
                             buf_send,pbc_flag[iswap],pbc[iswap]);
         if (n) MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
         if (size_forward_recv[iswap]) MPI_Wait(&request,&status);
       } else if (ghost_velocity) {
         if (size_forward_recv[iswap])
           MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
                     recvproc[iswap],0,world,&request);
         n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
                                 buf_send,pbc_flag[iswap],pbc[iswap]);
         if (n) MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
         if (size_forward_recv[iswap]) MPI_Wait(&request,&status);
         avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_recv);
       } else {
         if (size_forward_recv[iswap])
           MPI_Irecv(buf_recv,size_forward_recv[iswap],MPI_DOUBLE,
                     recvproc[iswap],0,world,&request);
         n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
                             buf_send,pbc_flag[iswap],pbc[iswap]);
         if (n) MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
         if (size_forward_recv[iswap]) MPI_Wait(&request,&status);
         avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_recv);
       }
 
     } else {
       if (comm_x_only) {
         if (sendnum[iswap])
           n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
                               x[firstrecv[iswap]],pbc_flag[iswap],
                               pbc[iswap]);
       } else if (ghost_velocity) {
         n = avec->pack_comm_vel(sendnum[iswap],sendlist[iswap],
                                 buf_send,pbc_flag[iswap],pbc[iswap]);
         avec->unpack_comm_vel(recvnum[iswap],firstrecv[iswap],buf_send);
       } else {
         n = avec->pack_comm(sendnum[iswap],sendlist[iswap],
                             buf_send,pbc_flag[iswap],pbc[iswap]);
         avec->unpack_comm(recvnum[iswap],firstrecv[iswap],buf_send);
       }
     }
   }
 }
 
 /* ----------------------------------------------------------------------
    reverse communication of forces on atoms every timestep
    other per-atom attributes may also be sent via pack/unpack routines
 ------------------------------------------------------------------------- */
 
 void Comm::reverse_comm()
 {
   int n;
   MPI_Request request;
   MPI_Status status;
   AtomVec *avec = atom->avec;
   double **f = atom->f;
   double *buf;
 
   // exchange data with another proc
   // if other proc is self, just copy
   // if comm_f_only set, exchange or copy directly from f, don't pack
 
   for (int iswap = nswap-1; iswap >= 0; iswap--) {
     if (sendproc[iswap] != me) {
       if (comm_f_only) {
         if (size_reverse_recv[iswap])
           MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,
                     sendproc[iswap],0,world,&request);
         if (size_reverse_send[iswap]) buf = f[firstrecv[iswap]];
         else buf = NULL;
         if (size_reverse_send[iswap])
           MPI_Send(buf,size_reverse_send[iswap],MPI_DOUBLE,
                    recvproc[iswap],0,world);
         if (size_reverse_recv[iswap]) MPI_Wait(&request,&status);
       } else {
         if (size_reverse_recv[iswap])
           MPI_Irecv(buf_recv,size_reverse_recv[iswap],MPI_DOUBLE,
                     sendproc[iswap],0,world,&request);
         n = avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
         if (n) MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
         if (size_reverse_recv[iswap]) MPI_Wait(&request,&status);
       }
       avec->unpack_reverse(sendnum[iswap],sendlist[iswap],buf_recv);
 
     } else {
       if (comm_f_only) {
         if (sendnum[iswap])
             avec->unpack_reverse(sendnum[iswap],sendlist[iswap],
                                 f[firstrecv[iswap]]);
       } else {
         n = avec->pack_reverse(recvnum[iswap],firstrecv[iswap],buf_send);
         avec->unpack_reverse(sendnum[iswap],sendlist[iswap],buf_send);
       }
     }
   }
 }
 
 /* ----------------------------------------------------------------------
    exchange: move atoms to correct processors
    atoms exchanged with all 6 stencil neighbors
    send out atoms that have left my box, receive ones entering my box
    atoms will be lost if not inside some proc's box
      can happen if atom moves outside of non-periodic bounary
      or if atom moves more than one proc away
    this routine called before every reneighboring
    for triclinic, atoms must be in lamda coords (0-1) before exchange is called
 ------------------------------------------------------------------------- */
 
 void Comm::exchange()
 {
   int i,m,nsend,nrecv,nrecv1,nrecv2,nlocal;
   double lo,hi,value;
   double **x;
   double *sublo,*subhi,*buf;
   MPI_Request request;
   MPI_Status status;
   AtomVec *avec = atom->avec;
 
   // clear global->local map for owned and ghost atoms
   // b/c atoms migrate to new procs in exchange() and
   //   new ghosts are created in borders()
   // map_set() is done at end of borders()
   // clear ghost count and any ghost bonus data internal to AtomVec
 
   if (map_style) atom->map_clear();
   atom->nghost = 0;
   atom->avec->clear_bonus();
 
   // subbox bounds for orthogonal or triclinic
 
   if (triclinic == 0) {
     sublo = domain->sublo;
     subhi = domain->subhi;
   } else {
     sublo = domain->sublo_lamda;
     subhi = domain->subhi_lamda;
   }
 
   // loop over dimensions
 
   for (int dim = 0; dim < 3; dim++) {
 
     // fill buffer with atoms leaving my box, using < and >=
     // when atom is deleted, fill it in with last atom
 
     x = atom->x;
     lo = sublo[dim];
     hi = subhi[dim];
     nlocal = atom->nlocal;
     i = nsend = 0;
 
     while (i < nlocal) {
       if (x[i][dim] < lo || x[i][dim] >= hi) {
         if (nsend > maxsend) grow_send(nsend,1);
         nsend += avec->pack_exchange(i,&buf_send[nsend]);
         avec->copy(nlocal-1,i,1);
         nlocal--;
       } else i++;
     }
     atom->nlocal = nlocal;
 
     // send/recv atoms in both directions
     // if 1 proc in dimension, no send/recv, set recv buf to send buf
     // if 2 procs in dimension, single send/recv
     // if more than 2 procs in dimension, send/recv to both neighbors
 
     if (procgrid[dim] == 1) {
       nrecv = nsend;
       buf = buf_send;
 
     } else {
       MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][0],0,
                    &nrecv1,1,MPI_INT,procneigh[dim][1],0,world,&status);
       nrecv = nrecv1;
       if (procgrid[dim] > 2) {
         MPI_Sendrecv(&nsend,1,MPI_INT,procneigh[dim][1],0,
                      &nrecv2,1,MPI_INT,procneigh[dim][0],0,world,&status);
         nrecv += nrecv2;
       }
       if (nrecv > maxrecv) grow_recv(nrecv);
 
       MPI_Irecv(buf_recv,nrecv1,MPI_DOUBLE,procneigh[dim][1],0,
                 world,&request);
       MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][0],0,world);
       MPI_Wait(&request,&status);
 
       if (procgrid[dim] > 2) {
         MPI_Irecv(&buf_recv[nrecv1],nrecv2,MPI_DOUBLE,procneigh[dim][0],0,
                   world,&request);
         MPI_Send(buf_send,nsend,MPI_DOUBLE,procneigh[dim][1],0,world);
         MPI_Wait(&request,&status);
       }
 
       buf = buf_recv;
     }
 
     // check incoming atoms to see if they are in my box
     // if so, add to my list
 
     m = 0;
     while (m < nrecv) {
       value = buf[m+dim+1];
       if (value >= lo && value < hi) m += avec->unpack_exchange(&buf[m]);
       else m += static_cast<int> (buf[m]);
     }
   }
 
   if (atom->firstgroupname) atom->first_reorder();
 }
 
 /* ----------------------------------------------------------------------
    borders: list nearby atoms to send to neighboring procs at every timestep
    one list is created for every swap that will be made
    as list is made, actually do swaps
    this does equivalent of a communicate, so don't need to explicitly
      call communicate routine on reneighboring timestep
    this routine is called before every reneighboring
    for triclinic, atoms must be in lamda coords (0-1) before borders is called
 ------------------------------------------------------------------------- */
 
 void Comm::borders()
 {
   int i,n,itype,iswap,dim,ineed,twoneed,smax,rmax;
   int nsend,nrecv,sendflag,nfirst,nlast,ngroup;
   double lo,hi;
   int *type;
   double **x;
   double *buf,*mlo,*mhi;
   MPI_Request request;
   MPI_Status status;
   AtomVec *avec = atom->avec;
 
   // do swaps over all 3 dimensions
 
   iswap = 0;
   smax = rmax = 0;
 
   for (dim = 0; dim < 3; dim++) {
     nlast = 0;
     twoneed = 2*maxneed[dim];
     for (ineed = 0; ineed < twoneed; ineed++) {
 
       // find atoms within slab boundaries lo/hi using <= and >=
       // check atoms between nfirst and nlast
       //   for first swaps in a dim, check owned and ghost
       //   for later swaps in a dim, only check newly arrived ghosts
       // store sent atom indices in list for use in future timesteps
 
       x = atom->x;
       if (style == SINGLE) {
         lo = slablo[iswap];
         hi = slabhi[iswap];
       } else {
         type = atom->type;
         mlo = multilo[iswap];
         mhi = multihi[iswap];
       }
       if (ineed % 2 == 0) {
         nfirst = nlast;
         nlast = atom->nlocal + atom->nghost;
       }
 
       nsend = 0;
 
       // sendflag = 0 if I do not send on this swap
       // sendneed test indicates receiver no longer requires data
       // e.g. due to non-PBC or non-uniform sub-domains
 
       if (ineed/2 >= sendneed[dim][ineed % 2]) sendflag = 0;
       else sendflag = 1;
 
       // find send atoms according to SINGLE vs MULTI
       // all atoms eligible versus atoms in bordergroup
       // only need to limit loop to bordergroup for first sends (ineed < 2)
       // on these sends, break loop in two: owned (in group) and ghost
 
       if (sendflag) {
         if (!bordergroup || ineed >= 2) {
           if (style == SINGLE) {
             for (i = nfirst; i < nlast; i++)
               if (x[i][dim] >= lo && x[i][dim] <= hi) {
                 if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
                 sendlist[iswap][nsend++] = i;
               }
           } else {
             for (i = nfirst; i < nlast; i++) {
               itype = type[i];
               if (x[i][dim] >= mlo[itype] && x[i][dim] <= mhi[itype]) {
                 if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
                 sendlist[iswap][nsend++] = i;
               }
             }
           }
 
         } else {
           if (style == SINGLE) {
             ngroup = atom->nfirst;
             for (i = 0; i < ngroup; i++)
               if (x[i][dim] >= lo && x[i][dim] <= hi) {
                 if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
                 sendlist[iswap][nsend++] = i;
               }
             for (i = atom->nlocal; i < nlast; i++)
               if (x[i][dim] >= lo && x[i][dim] <= hi) {
                 if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
                 sendlist[iswap][nsend++] = i;
               }
           } else {
             ngroup = atom->nfirst;
             for (i = 0; i < ngroup; i++) {
               itype = type[i];
               if (x[i][dim] >= mlo[itype] && x[i][dim] <= mhi[itype]) {
                 if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
                 sendlist[iswap][nsend++] = i;
               }
             }
             for (i = atom->nlocal; i < nlast; i++) {
               itype = type[i];
               if (x[i][dim] >= mlo[itype] && x[i][dim] <= mhi[itype]) {
                 if (nsend == maxsendlist[iswap]) grow_list(iswap,nsend);
                 sendlist[iswap][nsend++] = i;
               }
             }
           }
         }
       }
 
       // pack up list of border atoms
 
       if (nsend*size_border > maxsend)
         grow_send(nsend*size_border,0);
       if (ghost_velocity)
         n = avec->pack_border_vel(nsend,sendlist[iswap],buf_send,
                                   pbc_flag[iswap],pbc[iswap]);
       else
         n = avec->pack_border(nsend,sendlist[iswap],buf_send,
                               pbc_flag[iswap],pbc[iswap]);
 
       // swap atoms with other proc
       // no MPI calls except SendRecv if nsend/nrecv = 0
       // put incoming ghosts at end of my atom arrays
       // if swapping with self, simply copy, no messages
 
       if (sendproc[iswap] != me) {
         MPI_Sendrecv(&nsend,1,MPI_INT,sendproc[iswap],0,
                      &nrecv,1,MPI_INT,recvproc[iswap],0,world,&status);
         if (nrecv*size_border > maxrecv) grow_recv(nrecv*size_border);
         if (nrecv) MPI_Irecv(buf_recv,nrecv*size_border,MPI_DOUBLE,
                              recvproc[iswap],0,world,&request);
         if (n) MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
         if (nrecv) MPI_Wait(&request,&status);
         buf = buf_recv;
       } else {
         nrecv = nsend;
         buf = buf_send;
       }
 
       // unpack buffer
 
       if (ghost_velocity)
         avec->unpack_border_vel(nrecv,atom->nlocal+atom->nghost,buf);
       else
         avec->unpack_border(nrecv,atom->nlocal+atom->nghost,buf);
 
       // set all pointers & counters
 
       smax = MAX(smax,nsend);
       rmax = MAX(rmax,nrecv);
       sendnum[iswap] = nsend;
       recvnum[iswap] = nrecv;
       size_forward_recv[iswap] = nrecv*size_forward;
       size_reverse_send[iswap] = nrecv*size_reverse;
       size_reverse_recv[iswap] = nsend*size_reverse;
       firstrecv[iswap] = atom->nlocal + atom->nghost;
       atom->nghost += nrecv;
       iswap++;
     }
   }
 
   // insure send/recv buffers are long enough for all forward & reverse comm
 
   int max = MAX(maxforward*smax,maxreverse*rmax);
   if (max > maxsend) grow_send(max,0);
   max = MAX(maxforward*rmax,maxreverse*smax);
   if (max > maxrecv) grow_recv(max);
 
   // reset global->local map
 
   if (map_style) atom->map_set();
 }
 
 /* ----------------------------------------------------------------------
    forward communication invoked by a Pair
 ------------------------------------------------------------------------- */
 
 void Comm::forward_comm_pair(Pair *pair)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = 0; iswap < nswap; iswap++) {
 
     // pack buffer
 
     n = pair->pack_comm(sendnum[iswap],sendlist[iswap],
                         buf_send,pbc_flag[iswap],pbc[iswap]);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (recvnum[iswap])
         MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
                   world,&request);
       if (sendnum[iswap])
         MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
       if (recvnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     pair->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    reverse communication invoked by a Pair
 ------------------------------------------------------------------------- */
 
 void Comm::reverse_comm_pair(Pair *pair)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = nswap-1; iswap >= 0; iswap--) {
 
     // pack buffer
 
     n = pair->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (sendnum[iswap])
         MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
                   world,&request);
       if (recvnum[iswap])
         MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
       if (sendnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     pair->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    forward communication invoked by a Fix
    n = constant number of datums per atom
 ------------------------------------------------------------------------- */
 
 void Comm::forward_comm_fix(Fix *fix)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = 0; iswap < nswap; iswap++) {
 
     // pack buffer
 
     n = fix->pack_comm(sendnum[iswap],sendlist[iswap],
                        buf_send,pbc_flag[iswap],pbc[iswap]);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (recvnum[iswap])
         MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
                   world,&request);
       if (sendnum[iswap])
         MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
       if (recvnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     fix->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    reverse communication invoked by a Fix
    n = constant number of datums per atom
 ------------------------------------------------------------------------- */
 
 void Comm::reverse_comm_fix(Fix *fix)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = nswap-1; iswap >= 0; iswap--) {
 
     // pack buffer
 
     n = fix->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (sendnum[iswap])
         MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
                   world,&request);
       if (recvnum[iswap])
         MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
       if (sendnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     fix->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    forward communication invoked by a Fix
    n = total datums for all atoms, allows for variable number/atom
 ------------------------------------------------------------------------- */
 
 void Comm::forward_comm_variable_fix(Fix *fix)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = 0; iswap < nswap; iswap++) {
 
     // pack buffer
 
     n = fix->pack_comm(sendnum[iswap],sendlist[iswap],
                        buf_send,pbc_flag[iswap],pbc[iswap]);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (recvnum[iswap])
         MPI_Irecv(buf_recv,maxrecv,MPI_DOUBLE,recvproc[iswap],0,
                   world,&request);
       if (sendnum[iswap])
         MPI_Send(buf_send,n,MPI_DOUBLE,sendproc[iswap],0,world);
       if (recvnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     fix->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    reverse communication invoked by a Fix
    n = total datums for all atoms, allows for variable number/atom
 ------------------------------------------------------------------------- */
 
 void Comm::reverse_comm_variable_fix(Fix *fix)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = nswap-1; iswap >= 0; iswap--) {
 
     // pack buffer
 
     n = fix->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (sendnum[iswap])
         MPI_Irecv(buf_recv,maxrecv,MPI_DOUBLE,sendproc[iswap],0,
                   world,&request);
       if (recvnum[iswap])
         MPI_Send(buf_send,n,MPI_DOUBLE,recvproc[iswap],0,world);
       if (sendnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     fix->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    forward communication invoked by a Compute
 ------------------------------------------------------------------------- */
 
 void Comm::forward_comm_compute(Compute *compute)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = 0; iswap < nswap; iswap++) {
 
     // pack buffer
 
     n = compute->pack_comm(sendnum[iswap],sendlist[iswap],
                            buf_send,pbc_flag[iswap],pbc[iswap]);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (recvnum[iswap])
         MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
                   world,&request);
       if (sendnum[iswap])
         MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
       if (recvnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     compute->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    reverse communication invoked by a Compute
 ------------------------------------------------------------------------- */
 
 void Comm::reverse_comm_compute(Compute *compute)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = nswap-1; iswap >= 0; iswap--) {
 
     // pack buffer
 
     n = compute->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (sendnum[iswap])
         MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
                   world,&request);
       if (recvnum[iswap])
         MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
       if (sendnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     compute->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    forward communication invoked by a Dump
 ------------------------------------------------------------------------- */
 
 void Comm::forward_comm_dump(Dump *dump)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = 0; iswap < nswap; iswap++) {
 
     // pack buffer
 
     n = dump->pack_comm(sendnum[iswap],sendlist[iswap],
                         buf_send,pbc_flag[iswap],pbc[iswap]);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (recvnum[iswap])
         MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
                   world,&request);
       if (sendnum[iswap])
         MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
       if (recvnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     dump->unpack_comm(recvnum[iswap],firstrecv[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    reverse communication invoked by a Dump
 ------------------------------------------------------------------------- */
 
 void Comm::reverse_comm_dump(Dump *dump)
 {
   int iswap,n;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   for (iswap = nswap-1; iswap >= 0; iswap--) {
 
     // pack buffer
 
     n = dump->pack_reverse_comm(recvnum[iswap],firstrecv[iswap],buf_send);
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (sendnum[iswap])
         MPI_Irecv(buf_recv,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,
                   world,&request);
       if (recvnum[iswap])
         MPI_Send(buf_send,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,world);
       if (sendnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     dump->unpack_reverse_comm(sendnum[iswap],sendlist[iswap],buf);
   }
 }
 
 /* ----------------------------------------------------------------------
    forward communication of N values in array
 ------------------------------------------------------------------------- */
 
 void Comm::forward_comm_array(int n, double **array)
 {
   int i,j,k,m,iswap,last;
   double *buf;
   MPI_Request request;
   MPI_Status status;
 
   // check that buf_send and buf_recv are big enough
 
 
 
 
   for (iswap = 0; iswap < nswap; iswap++) {
 
     // pack buffer
 
     m = 0;
     for (i = 0; i < sendnum[iswap]; i++) {
       j = sendlist[iswap][i];
       for (k = 0; k < n; k++)
         buf_send[m++] = array[j][k];
     }
 
     // exchange with another proc
     // if self, set recv buffer to send buffer
 
     if (sendproc[iswap] != me) {
       if (recvnum[iswap])
         MPI_Irecv(buf_recv,n*recvnum[iswap],MPI_DOUBLE,recvproc[iswap],0,
                   world,&request);
       if (sendnum[iswap])
         MPI_Send(buf_send,n*sendnum[iswap],MPI_DOUBLE,sendproc[iswap],0,world);
       if (recvnum[iswap]) MPI_Wait(&request,&status);
       buf = buf_recv;
     } else buf = buf_send;
 
     // unpack buffer
 
     m = 0;
     last = firstrecv[iswap] + recvnum[iswap];
     for (i = firstrecv[iswap]; i < last; i++)
       for (k = 0; k < n; k++)
         array[i][k] = buf[m++];
   }
 }
 
 /* ----------------------------------------------------------------------
    communicate inbuf around full ring of processors with messtag
    nbytes = size of inbuf = n datums * nper bytes
    callback() is invoked to allow caller to process/update each proc's inbuf
-   note that callback() is invoked on final iteration for original inbuf
+   if self=1 (default), then callback() is invoked on final iteration
+     using original inbuf, which may have been updated
    for non-NULL outbuf, final updated inbuf is copied to it
-   outbuf = inbuf is OK
+     outbuf = inbuf is OK
 ------------------------------------------------------------------------- */
 
 void Comm::ring(int n, int nper, void *inbuf, int messtag,
                 void (*callback)(int, char *), void *outbuf, int self)
 {
   MPI_Request request;
   MPI_Status status;
 
   int nbytes = n*nper;
   int maxbytes;
   MPI_Allreduce(&nbytes,&maxbytes,1,MPI_INT,MPI_MAX,world);
 
   char *buf,*bufcopy;
   memory->create(buf,maxbytes,"comm:buf");
   memory->create(bufcopy,maxbytes,"comm:bufcopy");
   memcpy(buf,inbuf,nbytes);
 
   int next = me + 1;
   int prev = me - 1;
   if (next == nprocs) next = 0;
   if (prev < 0) prev = nprocs - 1;
 
   for (int loop = 0; loop < nprocs; loop++) {
     if (me != next) {
       MPI_Irecv(bufcopy,maxbytes,MPI_CHAR,prev,messtag,world,&request);
       MPI_Send(buf,nbytes,MPI_CHAR,next,messtag,world);
       MPI_Wait(&request,&status);
       MPI_Get_count(&status,MPI_CHAR,&nbytes);
       memcpy(buf,bufcopy,nbytes);
     }
     if (self || loop < nprocs-1) callback(nbytes/nper,buf);
   }
 
   if (outbuf) memcpy(outbuf,buf,nbytes);
 
   memory->destroy(buf);
   memory->destroy(bufcopy);
 }
 
 /* ----------------------------------------------------------------------
    realloc the size of the send buffer as needed with BUFFACTOR & BUFEXTRA
    if flag = 1, realloc
    if flag = 0, don't need to realloc with copy, just free/malloc
 ------------------------------------------------------------------------- */
 
 void Comm::grow_send(int n, int flag)
 {
   maxsend = static_cast<int> (BUFFACTOR * n);
   if (flag)
     memory->grow(buf_send,(maxsend+BUFEXTRA),"comm:buf_send");
   else {
     memory->destroy(buf_send);
     memory->create(buf_send,maxsend+BUFEXTRA,"comm:buf_send");
   }
 }
 
 /* ----------------------------------------------------------------------
    free/malloc the size of the recv buffer as needed with BUFFACTOR
 ------------------------------------------------------------------------- */
 
 void Comm::grow_recv(int n)
 {
   maxrecv = static_cast<int> (BUFFACTOR * n);
   memory->destroy(buf_recv);
   memory->create(buf_recv,maxrecv,"comm:buf_recv");
 }
 
 /* ----------------------------------------------------------------------
    realloc the size of the iswap sendlist as needed with BUFFACTOR
 ------------------------------------------------------------------------- */
 
 void Comm::grow_list(int iswap, int n)
 {
   maxsendlist[iswap] = static_cast<int> (BUFFACTOR * n);
   memory->grow(sendlist[iswap],maxsendlist[iswap],"comm:sendlist[iswap]");
 }
 
 /* ----------------------------------------------------------------------
    realloc the buffers needed for swaps
 ------------------------------------------------------------------------- */
 
 void Comm::grow_swap(int n)
 {
   free_swap();
   allocate_swap(n);
   if (style == MULTI) {
     free_multi();
     allocate_multi(n);
   }
 
   sendlist = (int **)
     memory->srealloc(sendlist,n*sizeof(int *),"comm:sendlist");
   memory->grow(maxsendlist,n,"comm:maxsendlist");
   for (int i = maxswap; i < n; i++) {
     maxsendlist[i] = BUFMIN;
     memory->create(sendlist[i],BUFMIN,"comm:sendlist[i]");
   }
   maxswap = n;
 }
 
 /* ----------------------------------------------------------------------
    allocation of swap info
 ------------------------------------------------------------------------- */
 
 void Comm::allocate_swap(int n)
 {
   memory->create(sendnum,n,"comm:sendnum");
   memory->create(recvnum,n,"comm:recvnum");
   memory->create(sendproc,n,"comm:sendproc");
   memory->create(recvproc,n,"comm:recvproc");
   memory->create(size_forward_recv,n,"comm:size");
   memory->create(size_reverse_send,n,"comm:size");
   memory->create(size_reverse_recv,n,"comm:size");
   memory->create(slablo,n,"comm:slablo");
   memory->create(slabhi,n,"comm:slabhi");
   memory->create(firstrecv,n,"comm:firstrecv");
   memory->create(pbc_flag,n,"comm:pbc_flag");
   memory->create(pbc,n,6,"comm:pbc");
 }
 
 /* ----------------------------------------------------------------------
    allocation of multi-type swap info
 ------------------------------------------------------------------------- */
 
 void Comm::allocate_multi(int n)
 {
   multilo = memory->create(multilo,n,atom->ntypes+1,"comm:multilo");
   multihi = memory->create(multihi,n,atom->ntypes+1,"comm:multihi");
 }
 
 /* ----------------------------------------------------------------------
    free memory for swaps
 ------------------------------------------------------------------------- */
 
 void Comm::free_swap()
 {
   memory->destroy(sendnum);
   memory->destroy(recvnum);
   memory->destroy(sendproc);
   memory->destroy(recvproc);
   memory->destroy(size_forward_recv);
   memory->destroy(size_reverse_send);
   memory->destroy(size_reverse_recv);
   memory->destroy(slablo);
   memory->destroy(slabhi);
   memory->destroy(firstrecv);
   memory->destroy(pbc_flag);
   memory->destroy(pbc);
 }
 
 /* ----------------------------------------------------------------------
    free memory for multi-type swaps
 ------------------------------------------------------------------------- */
 
 void Comm::free_multi()
 {
   memory->destroy(multilo);
   memory->destroy(multihi);
 }
 
 /* ----------------------------------------------------------------------
    set communication style
    invoked from input script by communicate command
 ------------------------------------------------------------------------- */
 
 void Comm::set(int narg, char **arg)
 {
   if (narg < 1) error->all(FLERR,"Illegal communicate command");
 
   if (strcmp(arg[0],"single") == 0) style = SINGLE;
   else if (strcmp(arg[0],"multi") == 0) style = MULTI;
   else error->all(FLERR,"Illegal communicate command");
 
   int iarg = 1;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"group") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal communicate command");
       bordergroup = group->find(arg[iarg+1]);
       if (bordergroup < 0)
         error->all(FLERR,"Invalid group in communicate command");
       if (bordergroup && (atom->firstgroupname == NULL ||
                           strcmp(arg[iarg+1],atom->firstgroupname) != 0))
         error->all(FLERR,"Communicate group != atom_modify first group");
       iarg += 2;
     } else if (strcmp(arg[iarg],"cutoff") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal communicate command");
       cutghostuser = atof(arg[iarg+1]);
       if (cutghostuser < 0.0)
         error->all(FLERR,"Invalid cutoff in communicate command");
       iarg += 2;
     } else if (strcmp(arg[iarg],"vel") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal communicate command");
       if (strcmp(arg[iarg+1],"yes") == 0) ghost_velocity = 1;
       else if (strcmp(arg[iarg+1],"no") == 0) ghost_velocity = 0;
       else error->all(FLERR,"Illegal communicate command");
       iarg += 2;
     } else error->all(FLERR,"Illegal communicate command");
   }
 }
 
 /* ----------------------------------------------------------------------
    set dimensions for 3d grid of processors, and associated flags
    invoked from input script by processors command
 ------------------------------------------------------------------------- */
 
 void Comm::set_processors(int narg, char **arg)
 {
   if (narg < 3) error->all(FLERR,"Illegal processors command");
 
   if (strcmp(arg[0],"*") == 0) user_procgrid[0] = 0;
   else user_procgrid[0] = atoi(arg[0]);
   if (strcmp(arg[1],"*") == 0) user_procgrid[1] = 0;
   else user_procgrid[1] = atoi(arg[1]);
   if (strcmp(arg[2],"*") == 0) user_procgrid[2] = 0;
   else user_procgrid[2] = atoi(arg[2]);
 
   if (user_procgrid[0] < 0 || user_procgrid[1] < 0 || user_procgrid[2] < 0)
     error->all(FLERR,"Illegal processors command");
 
   int p = user_procgrid[0]*user_procgrid[1]*user_procgrid[2];
   if (p && p != nprocs)
     error->all(FLERR,"Specified processors != physical processors");
 
   int iarg = 3;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"grid") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal processors command");
 
       if (strcmp(arg[iarg+1],"onelevel") == 0) {
         gridflag = ONELEVEL;
 
       } else if (strcmp(arg[iarg+1],"twolevel") == 0) {
         if (iarg+6 > narg) error->all(FLERR,"Illegal processors command");
         gridflag = TWOLEVEL;
 
         ncores = atoi(arg[iarg+2]);
         if (strcmp(arg[iarg+3],"*") == 0) user_coregrid[0] = 0;
         else user_coregrid[0] = atoi(arg[iarg+3]);
         if (strcmp(arg[iarg+4],"*") == 0) user_coregrid[1] = 0;
         else user_coregrid[1] = atoi(arg[iarg+4]);
         if (strcmp(arg[iarg+5],"*") == 0) user_coregrid[2] = 0;
         else user_coregrid[2] = atoi(arg[iarg+5]);
 
         if (ncores <= 0 || user_coregrid[0] < 0 ||
             user_coregrid[1] < 0 || user_coregrid[2] < 0)
           error->all(FLERR,"Illegal processors command");
         iarg += 4;
 
       } else if (strcmp(arg[iarg+1],"numa") == 0) {
         gridflag = NUMA;
 
       } else if (strcmp(arg[iarg],"custom") == 0) {
         if (iarg+3 > narg) error->all(FLERR,"Illegal processors command");
         gridflag = CUSTOM;
         delete [] customfile;
         int n = strlen(arg[iarg+2]) + 1;
         customfile = new char[n];
         strcpy(customfile,arg[iarg+2]);
         iarg += 1;
 
       } else error->all(FLERR,"Illegal processors command");
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"map") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal processors command");
       if (strcmp(arg[iarg+1],"cart") == 0) mapflag = CART;
       else if (strcmp(arg[iarg+1],"cart/reorder") == 0) mapflag = CARTREORDER;
       else if (strcmp(arg[iarg+1],"xyz") == 0 ||
                strcmp(arg[iarg+1],"xzy") == 0 ||
                strcmp(arg[iarg+1],"yxz") == 0 ||
                strcmp(arg[iarg+1],"yzx") == 0 ||
                strcmp(arg[iarg+1],"zxy") == 0 ||
                strcmp(arg[iarg+1],"zyx") == 0) {
         mapflag = XYZ;
         strcpy(xyz,arg[iarg+1]);
       } else error->all(FLERR,"Illegal processors command");
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"part") == 0) {
       if (iarg+4 > narg) error->all(FLERR,"Illegal processors command");
       if (universe->nworlds == 1)
         error->all(FLERR,
                    "Cannot use processors part command "
                    "without using partitions");
       int isend = atoi(arg[iarg+1]);
       int irecv = atoi(arg[iarg+2]);
       if (isend < 1 || isend > universe->nworlds ||
           irecv < 1 || irecv > universe->nworlds || isend == irecv)
         error->all(FLERR,"Invalid partitions in processors part command");
       if (isend-1 == universe->iworld) {
         if (send_to_partition >= 0)
           error->all(FLERR,
                      "Sending partition in processors part command "
                      "is already a sender");
         send_to_partition = irecv-1;
       }
       if (irecv-1 == universe->iworld) {
         if (recv_from_partition >= 0)
           error->all(FLERR,
                      "Receiving partition in processors part command "
                      "is already a receiver");
         recv_from_partition = isend-1;
       }
 
       // only receiver has otherflag dependency
 
       if (strcmp(arg[iarg+3],"multiple") == 0) {
         if (universe->iworld == irecv-1) {
           otherflag = 1;
           other_style = MULTIPLE;
         }
       } else error->all(FLERR,"Illegal processors command");
       iarg += 4;
 
     } else if (strcmp(arg[iarg],"file") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal processors command");
       delete [] outfile;
       int n = strlen(arg[iarg+1]) + 1;
       outfile = new char[n];
       strcpy(outfile,arg[iarg+1]);
       iarg += 2;
 
     } else error->all(FLERR,"Illegal processors command");
   }
 
   // error checks
 
   if (gridflag == NUMA && mapflag != CART)
     error->all(FLERR,"Processors grid numa and map style are incompatible");
   if (otherflag && (gridflag == NUMA || gridflag == CUSTOM))
     error->all(FLERR,
                "Processors part option and grid style are incompatible");
 }
 
 /* ----------------------------------------------------------------------
    return # of bytes of allocated memory
 ------------------------------------------------------------------------- */
 
 bigint Comm::memory_usage()
 {
   bigint bytes = 0;
   bytes += nprocs * sizeof(int);    // grid2proc
   for (int i = 0; i < nswap; i++)
     bytes += memory->usage(sendlist[i],maxsendlist[i]);
   bytes += memory->usage(buf_send,maxsend+BUFEXTRA);
   bytes += memory->usage(buf_recv,maxrecv);
   return bytes;
 }
diff --git a/src/delete_atoms.cpp b/src/delete_atoms.cpp
index dc70d8557..d2fa42192 100644
--- a/src/delete_atoms.cpp
+++ b/src/delete_atoms.cpp
@@ -1,360 +1,422 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #include "stdlib.h"
 #include "string.h"
 #include "delete_atoms.h"
 #include "atom.h"
 #include "atom_vec.h"
 #include "comm.h"
 #include "domain.h"
 #include "force.h"
 #include "group.h"
 #include "region.h"
 #include "neighbor.h"
 #include "neigh_list.h"
 #include "neigh_request.h"
 #include "random_mars.h"
 #include "memory.h"
 #include "error.h"
 
+#include <map>
+
 using namespace LAMMPS_NS;
 
+// allocate space for static class variable
+
+DeleteAtoms *DeleteAtoms::cptr;
+
 /* ---------------------------------------------------------------------- */
 
 DeleteAtoms::DeleteAtoms(LAMMPS *lmp) : Pointers(lmp) {}
 
 /* ---------------------------------------------------------------------- */
 
 void DeleteAtoms::command(int narg, char **arg)
 {
   if (domain->box_exist == 0)
     error->all(FLERR,"Delete_atoms command before simulation box is defined");
   if (narg < 1) error->all(FLERR,"Illegal delete_atoms command");
   if (atom->tag_enable == 0)
     error->all(FLERR,"Cannot use delete_atoms unless atoms have IDs");
 
   // store state before delete
 
   bigint natoms_previous = atom->natoms;
 
   // delete the atoms
 
   if (strcmp(arg[0],"group") == 0) delete_group(narg,arg);
   else if (strcmp(arg[0],"region") == 0) delete_region(narg,arg);
   else if (strcmp(arg[0],"overlap") == 0) delete_overlap(narg,arg);
   else if (strcmp(arg[0],"porosity") == 0) delete_porosity(narg,arg);
   else error->all(FLERR,"Illegal delete_atoms command");
 
   // delete local atoms flagged in dlist
   // reset nlocal
 
   AtomVec *avec = atom->avec;
   int nlocal = atom->nlocal;
 
   int i = 0;
   while (i < nlocal) {
     if (dlist[i]) {
       avec->copy(nlocal-1,i,1);
       dlist[i] = dlist[nlocal-1];
       nlocal--;
     } else i++;
   }
 
   atom->nlocal = nlocal;
   memory->destroy(dlist);
 
   // if non-molecular system and compress flag set,
   // reset atom tags to be contiguous
   // set all atom IDs to 0, call tag_extend()
 
   if (atom->molecular == 0 && compress_flag) {
     int *tag = atom->tag;
     for (i = 0; i < nlocal; i++) tag[i] = 0;
     atom->tag_extend();
   }
 
   // reset atom->natoms
   // reset atom->map if it exists
   // set nghost to 0 so old ghosts of deleted atoms won't be mapped
 
   bigint nblocal = atom->nlocal;
   MPI_Allreduce(&nblocal,&atom->natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
   if (atom->map_style) {
     atom->nghost = 0;
     atom->map_init();
     atom->map_set();
   }
 
   // print before and after atom count
 
   bigint ndelete = natoms_previous - atom->natoms;
 
   if (comm->me == 0) {
     if (screen) fprintf(screen,"Deleted " BIGINT_FORMAT
                         " atoms, new total = " BIGINT_FORMAT "\n",
                         ndelete,atom->natoms);
     if (logfile) fprintf(logfile,"Deleted " BIGINT_FORMAT
                          " atoms, new total = " BIGINT_FORMAT "\n",
                          ndelete,atom->natoms);
   }
 }
 
 /* ----------------------------------------------------------------------
    delete all atoms in group
    group will still exist
 ------------------------------------------------------------------------- */
 
 void DeleteAtoms::delete_group(int narg, char **arg)
 {
   if (narg < 2) error->all(FLERR,"Illegal delete_atoms command");
 
   int igroup = group->find(arg[1]);
   if (igroup == -1) error->all(FLERR,"Could not find delete_atoms group ID");
   options(narg-2,&arg[2]);
 
   // allocate and initialize deletion list
 
   int nlocal = atom->nlocal;
   memory->create(dlist,nlocal,"delete_atoms:dlist");
   for (int i = 0; i < nlocal; i++) dlist[i] = 0;
 
   int *mask = atom->mask;
   int groupbit = group->bitmask[igroup];
 
   for (int i = 0; i < nlocal; i++)
     if (mask[i] & groupbit) dlist[i] = 1;
 }
 
 /* ----------------------------------------------------------------------
    delete all atoms in region
+   if mol_flag is set, also delete atoms in molecules with any deletions
 ------------------------------------------------------------------------- */
 
 void DeleteAtoms::delete_region(int narg, char **arg)
 {
   if (narg < 2) error->all(FLERR,"Illegal delete_atoms command");
 
   int iregion = domain->find_region(arg[1]);
   if (iregion == -1) error->all(FLERR,"Could not find delete_atoms region ID");
   options(narg-2,&arg[2]);
 
   // allocate and initialize deletion list
 
   int nlocal = atom->nlocal;
   memory->create(dlist,nlocal,"delete_atoms:dlist");
   for (int i = 0; i < nlocal; i++) dlist[i] = 0;
 
   double **x = atom->x;
 
   for (int i = 0; i < nlocal; i++)
     if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2])) dlist[i] = 1;
+
+  if (mol_flag == 0) return;
+
+  // delete entire molecules if any atom in molecule was deleted
+  // store list of molecule IDs I delete atoms from in list
+  // pass list from proc to proc via ring communication
+
+  hash = new std::map<int,int>();
+
+  int *molecule = atom->molecule;
+  for (int i = 0; i < nlocal; i++)
+    if (dlist[i] && hash->find(molecule[i]) == hash->end())
+      (*hash)[molecule[i]] = 1;
+
+  int n = hash->size();
+  int *list;
+  memory->create(list,n,"delete_atoms:list");
+
+  n = 0;
+  std::map<int,int>::iterator pos;
+  for (pos = hash->begin(); pos != hash->end(); ++pos) list[n++] = pos->first;
+
+  cptr = this;
+  comm->ring(n,sizeof(int),list,1,molring,NULL);
+
+  delete hash;
+  memory->destroy(list);
+}
+
+/* ----------------------------------------------------------------------
+   callback from comm->ring()
+   cbuf = list of N molecule IDs, put them in hash
+   loop over my atoms, if matches moleculed ID in hash, delete that atom
+------------------------------------------------------------------------- */
+
+void DeleteAtoms::molring(int n, char *cbuf)
+{
+  int *list = (int *) cbuf;
+  int *dlist = cptr->dlist;
+  std::map<int,int> *hash = cptr->hash;
+  int nlocal = cptr->atom->nlocal;
+  int *molecule = cptr->atom->molecule;
+
+  hash->clear();
+  for (int i = 0; i < n; i++) (*hash)[list[i]] = 1;
+
+  for (int i = 0; i < nlocal; i++)
+    if (hash->find(molecule[i]) != hash->end()) dlist[i] = 1;
 }
 
 /* ----------------------------------------------------------------------
    delete atoms so there are no pairs within cutoff
    which atoms are deleted depends on ordering of atoms within proc
    deletions can vary with processor count
    no guarantee that minimium number of atoms will be deleted
 ------------------------------------------------------------------------- */
 
 void DeleteAtoms::delete_overlap(int narg, char **arg)
 {
   if (narg < 4) error->all(FLERR,"Illegal delete_atoms command");
 
   // read args
 
   double cut = atof(arg[1]);
   double cutsq = cut*cut;
 
   int igroup1 = group->find(arg[2]);
   int igroup2 = group->find(arg[3]);
   if (igroup1 < 0 || igroup2 < 0)
     error->all(FLERR,"Could not find delete_atoms group ID");
   options(narg-4,&arg[4]);
 
   int group1bit = group->bitmask[igroup1];
   int group2bit = group->bitmask[igroup2];
 
   if (comm->me == 0 && screen)
     fprintf(screen,"System init for delete_atoms ...\n");
 
   // request a full neighbor list for use by this command
 
   int irequest = neighbor->request((void *) this);
   neighbor->requests[irequest]->pair = 0;
   neighbor->requests[irequest]->command = 1;
   neighbor->requests[irequest]->half = 0;
   neighbor->requests[irequest]->full = 1;
   neighbor->requests[irequest]->occasional = 1;
 
   // init entire system since comm->borders and neighbor->build is done
   // comm::init needs neighbor::init needs pair::init needs kspace::init, etc
 
   lmp->init();
 
   // error check on cutoff
   // if no pair style, neighbor list will be empty
 
   if (force->pair == NULL)
     error->all(FLERR,"Delete_atoms requires a pair style be defined");
   if (cut > neighbor->cutneighmax)
     error->all(FLERR,"Delete_atoms cutoff > neighbor cutoff");
 
   // setup domain, communication and neighboring
   // acquire ghosts
   // build neighbor list based on earlier request
 
   if (domain->triclinic) domain->x2lamda(atom->nlocal);
   domain->pbc();
   domain->reset_box();
   comm->setup();
   if (neighbor->style) neighbor->setup_bins();
   comm->exchange();
   comm->borders();
   if (domain->triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
 
   NeighList *list = neighbor->lists[irequest];
   neighbor->build_one(irequest);
 
   // allocate and initialize deletion list
   // must be after exchange potentially changes nlocal
 
   int nlocal = atom->nlocal;
   memory->create(dlist,nlocal,"delete_atoms:dlist");
   for (int i = 0; i < nlocal; i++) dlist[i] = 0;
 
   // double loop over owned atoms and their full neighbor list
   // at end of loop, there are no more overlaps
   // only ever delete owned atom I, never J even if owned
 
   int *tag = atom->tag;
   int *mask = atom->mask;
   double **x = atom->x;
   double *special_coul = force->special_coul;
   double *special_lj = force->special_lj;
 
   int i,j,ii,jj,inum,jnum;
   double xtmp,ytmp,ztmp,delx,dely,delz,rsq;
   int *ilist,*jlist,*numneigh,**firstneigh;
   double factor_lj,factor_coul;
 
   inum = list->inum;
   ilist = list->ilist;
   numneigh = list->numneigh;
   firstneigh = list->firstneigh;
 
   for (ii = 0; ii < inum; ii++) {
     i = ilist[ii];
     xtmp = x[i][0];
     ytmp = x[i][1];
     ztmp = x[i][2];
     jlist = firstneigh[i];
     jnum = numneigh[i];
 
     for (jj = 0; jj < jnum; jj++) {
       j = jlist[jj];
       factor_lj = special_lj[sbmask(j)];
       factor_coul = special_coul[sbmask(j)];
       j &= NEIGHMASK;
 
       // if both weighting factors are 0, skip this pair
       // could be 0 and still be in neigh list for long-range Coulombics
       // want consistency with non-charged pairs which wouldn't be in list
 
       if (factor_lj == 0.0 && factor_coul == 0.0) continue;
 
       // only consider deletion if I,J distance < cutoff
 
       delx = xtmp - x[j][0];
       dely = ytmp - x[j][1];
       delz = ztmp - x[j][2];
       rsq = delx*delx + dely*dely + delz*delz;
       if (rsq >= cutsq) continue;
 
       // only consider deletion if I,J are in groups 1,2 respectively
       // true whether J is owned or ghost atom
 
       if (!(mask[i] & group1bit)) continue;
       if (!(mask[j] & group2bit)) continue;
 
       // J is owned atom:
       //   delete atom I if atom J has not already been deleted
       // J is ghost atom:
       //   delete atom I if J,I is not a candidate deletion pair
       //     due to being in groups 1,2 respectively
       //   if they are candidate pair, then either:
       //      another proc owns J and could delete J
       //      J is a ghost of another of my owned atoms, and I could delete J
       //   test on tags of I,J insures that only I or J is deleted
 
       if (j < nlocal) {
         if (dlist[j]) continue;
       } else if ((mask[i] & group2bit) && (mask[j] & group1bit)) {
         if (tag[i] > tag[j]) continue;
       }
 
       dlist[i] = 1;
       break;
     }
   }
 }
 
 /* ----------------------------------------------------------------------
    create porosity by deleting atoms in a specified region
 ------------------------------------------------------------------------- */
 
 void DeleteAtoms::delete_porosity(int narg, char **arg)
 {
   if (narg < 4) error->all(FLERR,"Illegal delete_atoms command");
 
   int iregion = domain->find_region(arg[1]);
   if (iregion == -1) error->all(FLERR,"Could not find delete_atoms region ID");
 
   double porosity_fraction = atof(arg[2]);
   int seed = atoi(arg[3]);
   options(narg-4,&arg[4]);
 
   RanMars *random = new RanMars(lmp,seed + comm->me);
 
   // allocate and initialize deletion list
 
   int nlocal = atom->nlocal;
   memory->create(dlist,nlocal,"delete_atoms:dlist");
   for (int i = 0; i < nlocal; i++) dlist[i] = 0;
 
   double **x = atom->x;
 
   for (int i = 0; i < nlocal; i++)
     if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2]))
       if (random->uniform() <= porosity_fraction) dlist[i] = 1;
 }
 
 /* ----------------------------------------------------------------------
    process command options
 ------------------------------------------------------------------------- */
 
 void DeleteAtoms::options(int narg, char **arg)
 {
   compress_flag = 1;
+  mol_flag = 0;
 
   int iarg = 0;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"compress") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal delete_bonds command");
       if (strcmp(arg[iarg+1],"yes") == 0) compress_flag = 1;
       else if (strcmp(arg[iarg+1],"no") == 0) compress_flag = 0;
       else error->all(FLERR,"Illegal delete_bonds command");
       iarg += 2;
+    } else if (strcmp(arg[iarg],"mol") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal delete_bonds command");
+      if (strcmp(arg[iarg+1],"yes") == 0) mol_flag = 1;
+      else if (strcmp(arg[iarg+1],"no") == 0) mol_flag = 0;
+      else error->all(FLERR,"Illegal delete_bonds command");
+      iarg += 2;
     } else error->all(FLERR,"Illegal delete_bonds command");
   }
 }
diff --git a/src/delete_atoms.h b/src/delete_atoms.h
index aab02f41d..217401c97 100644
--- a/src/delete_atoms.h
+++ b/src/delete_atoms.h
@@ -1,87 +1,95 @@
 /* -*- c++ -*- ----------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #ifdef COMMAND_CLASS
 
 CommandStyle(delete_atoms,DeleteAtoms)
 
 #else
 
 #ifndef LMP_DELETE_ATOMS_H
 #define LMP_DELETE_ATOMS_H
 
 #include "pointers.h"
+#include <map>
 
 namespace LAMMPS_NS {
 
 class DeleteAtoms : protected Pointers {
  public:
   DeleteAtoms(class LAMMPS *);
   void command(int, char **);
 
  private:
   int *dlist;
-  int compress_flag;
+  int compress_flag,mol_flag;
+  std::map<int,int> *hash;
 
   void delete_group(int, char **);
   void delete_region(int, char **);
   void delete_overlap(int, char **);
   void delete_porosity(int, char **);
   void options(int, char **);
 
   inline int sbmask(int j) {
     return j >> SBBITS & 3;
   }
+
+  // static variable for ring communication callback to access class data
+  // callback functions for ring communication
+
+  static DeleteAtoms *cptr;
+  static void molring(int, char *);
 };
 
 }
 
 #endif
 #endif
 
 /* ERROR/WARNING messages:
 
 E: Delete_atoms command before simulation box is defined
 
 The delete_atoms command cannot be used before a read_data,
 read_restart, or create_box command.
 
 E: Illegal ... command
 
 Self-explanatory.  Check the input script syntax and compare to the
 documentation for the command.  You can use -echo screen as a
 command-line option when running LAMMPS to see the offending line.
 
 E: Cannot use delete_atoms unless atoms have IDs
 
 Your atoms do not have IDs, so the delete_atoms command cannot be
 used.
 
 E: Could not find delete_atoms group ID
 
 Group ID used in the delete_atoms command does not exist.
 
 E: Could not find delete_atoms region ID
 
 Region ID used in the delete_atoms command does not exist.
 
 E: Delete_atoms requires a pair style be defined
 
 This is because atom deletion within a cutoff uses a pairwise
 neighbor list.
 
 E: Delete_atoms cutoff > neighbor cutoff
 
 Cannot delete atoms further away than a processor knows about.
 
 */
diff --git a/src/fix_dt_reset.cpp b/src/fix_dt_reset.cpp
index 60e9e0b44..79e9441f6 100644
--- a/src/fix_dt_reset.cpp
+++ b/src/fix_dt_reset.cpp
@@ -1,215 +1,204 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #include "math.h"
 #include "stdlib.h"
 #include "string.h"
 #include "fix_dt_reset.h"
 #include "atom.h"
 #include "update.h"
 #include "integrate.h"
 #include "domain.h"
 #include "lattice.h"
 #include "force.h"
 #include "pair.h"
 #include "modify.h"
 #include "fix.h"
 #include "output.h"
 #include "dump.h"
 #include "comm.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
 using namespace FixConst;
 
 #define BIG 1.0e20
 
 /* ---------------------------------------------------------------------- */
 
 FixDtReset::FixDtReset(LAMMPS *lmp, int narg, char **arg) :
   Fix(lmp, narg, arg)
 {
   if (narg < 7) error->all(FLERR,"Illegal fix dt/reset command");
 
   // set time_depend, else elapsed time accumulation can be messed up
 
   time_depend = 1;
   scalar_flag = 1;
   vector_flag = 1;
-  size_vector = 2;
+  size_vector = 1;
   global_freq = 1;
   extscalar = 0;
   extvector = 0;
 
   nevery = atoi(arg[3]);
   if (nevery <= 0) error->all(FLERR,"Illegal fix dt/reset command");
 
   minbound = maxbound = 1;
   tmin = tmax = 0.0;
   if (strcmp(arg[4],"NULL") == 0) minbound = 0;
   else tmin = atof(arg[4]);
   if (strcmp(arg[5],"NULL") == 0) maxbound = 0;
   else tmax = atof(arg[5]);
   xmax = atof(arg[6]);
 
   if (minbound && tmin < 0.0) error->all(FLERR,"Illegal fix dt/reset command");
   if (maxbound && tmax < 0.0) error->all(FLERR,"Illegal fix dt/reset command");
   if (minbound && maxbound && tmin >= tmax)
     error->all(FLERR,"Illegal fix dt/reset command");
   if (xmax <= 0.0) error->all(FLERR,"Illegal fix dt/reset command");
 
   int scaleflag = 1;
 
   int iarg = 7;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"units") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal fix dt/reset command");
       if (strcmp(arg[iarg+1],"box") == 0) scaleflag = 0;
       else if (strcmp(arg[iarg+1],"lattice") == 0) scaleflag = 1;
       else error->all(FLERR,"Illegal fix dt/reset command");
       iarg += 2;
     } else error->all(FLERR,"Illegal fix dt/reset command");
   }
 
   // setup scaling, based on xlattice parameter
 
   if (scaleflag && domain->lattice == NULL)
     error->all(FLERR,"Use of fix dt/reset with undefined lattice");
   if (scaleflag) xmax *= domain->lattice->xlattice;
 
   // initializations
 
-  t_elapsed = t_laststep = 0.0;
+  t_laststep = 0.0;
   laststep = update->ntimestep;
 }
 
 /* ---------------------------------------------------------------------- */
 
 int FixDtReset::setmask()
 {
   int mask = 0;
-  mask |= INITIAL_INTEGRATE;
   mask |= END_OF_STEP;
   return mask;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void FixDtReset::init()
 {
   // set rRESPA flag
 
   respaflag = 0;
   if (strstr(update->integrate_style,"respa")) respaflag = 1;
 
   // check for DCD or XTC dumps
 
   for (int i = 0; i < output->ndump; i++)
     if ((strcmp(output->dump[i]->style,"dcd") == 0 ||
         strcmp(output->dump[i]->style,"xtc") == 0) && comm->me == 0)
       error->warning(FLERR,
                      "Dump dcd/xtc timestamp may be wrong with fix dt/reset");
 
   ftm2v = force->ftm2v;
   dt = update->dt;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void FixDtReset::setup(int vflag)
 {
   end_of_step();
 }
 
 /* ---------------------------------------------------------------------- */
 
-void FixDtReset::initial_integrate(int vflag)
-{
-  // calculate elapsed time based on previous reset timestep
-
-  t_elapsed = t_laststep + (update->ntimestep-laststep)*dt;
-}
-
-/* ---------------------------------------------------------------------- */
-
 void FixDtReset::end_of_step()
 {
   double dtv,dtf,dtsq;
   double vsq,fsq,massinv;
   double delx,dely,delz,delr;
 
   // compute vmax and amax of any atom in group
 
   double **v = atom->v;
   double **f = atom->f;
   double *mass = atom->mass;
   double *rmass = atom->rmass;
   int *type = atom->type;
   int *mask = atom->mask;
   int nlocal = atom->nlocal;
 
   double dtmin = BIG;
 
   for (int i = 0; i < nlocal; i++)
     if (mask[i] & groupbit) {
       if (rmass) massinv = 1.0/rmass[i];
       else massinv = 1.0/mass[type[i]];
       vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
       fsq = f[i][0]*f[i][0] + f[i][1]*f[i][1] + f[i][2]*f[i][2];
       dtv = dtf = BIG;
       if (vsq > 0.0) dtv = xmax/sqrt(vsq);
       if (fsq > 0.0) dtf = sqrt(2.0*xmax/(ftm2v*sqrt(fsq)*massinv));
       dt = MIN(dtv,dtf);
       dtsq = dt*dt;
       delx = dt*v[i][0] + 0.5*dtsq*massinv*f[i][0] * ftm2v;
       dely = dt*v[i][1] + 0.5*dtsq*massinv*f[i][1] * ftm2v;
       delz = dt*v[i][2] + 0.5*dtsq*massinv*f[i][2] * ftm2v;
       delr = sqrt(delx*delx + dely*dely + delz*delz);
       if (delr > xmax) dt *= xmax/delr;
       dtmin = MIN(dtmin,dt);
     }
 
   MPI_Allreduce(&dtmin,&dt,1,MPI_DOUBLE,MPI_MIN,world);
 
   if (minbound) dt = MAX(dt,tmin);
   if (maxbound) dt = MIN(dt,tmax);
 
   // if timestep didn't change, just return
   // else reset update->dt and other classes that depend on it
   // rRESPA, pair style, fixes
 
   if (dt == update->dt) return;
 
-  t_elapsed = t_laststep += (update->ntimestep-laststep)*update->dt;
   laststep = update->ntimestep;
 
+  update->update_time();
   update->dt = dt;
   if (respaflag) update->integrate->reset_dt();
   if (force->pair) force->pair->reset_dt();
   for (int i = 0; i < modify->nfix; i++) modify->fix[i]->reset_dt();
 }
 
 /* ---------------------------------------------------------------------- */
 
 double FixDtReset::compute_scalar()
 {
   return update->dt;
 }
 
 /* ---------------------------------------------------------------------- */
 
 double FixDtReset::compute_vector(int n)
 {
-  if (n == 0) return t_elapsed;
   return (double) laststep;
 }
diff --git a/src/fix_dt_reset.h b/src/fix_dt_reset.h
index de97d147d..7084b5993 100644
--- a/src/fix_dt_reset.h
+++ b/src/fix_dt_reset.h
@@ -1,71 +1,70 @@
 /* -*- c++ -*- ----------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #ifdef FIX_CLASS
 
 FixStyle(dt/reset,FixDtReset)
 
 #else
 
 #ifndef LMP_FIX_DT_RESET_H
 #define LMP_FIX_DT_RESET_H
 
 #include "fix.h"
 
 namespace LAMMPS_NS {
 
 class FixDtReset : public Fix {
  public:
   FixDtReset(class LAMMPS *, int, char **);
   ~FixDtReset() {}
   int setmask();
   void init();
   void setup(int);
-  void initial_integrate(int);
   void end_of_step();
   double compute_scalar();
   double compute_vector(int);
 
  private:
   bigint laststep;
   int minbound,maxbound;
   double tmin,tmax,xmax;
   double ftm2v;
-  double dt,t_elapsed,t_laststep;
+  double dt,t_laststep;
   int respaflag;
 };
 
 }
 
 #endif
 #endif
 
 /* ERROR/WARNING messages:
 
 E: Illegal ... command
 
 Self-explanatory.  Check the input script syntax and compare to the
 documentation for the command.  You can use -echo screen as a
 command-line option when running LAMMPS to see the offending line.
 
 E: Use of fix dt/reset with undefined lattice
 
 Must use lattice command with fix dt/reset command if units option is
 set to lattice.
 
 W: Dump dcd/xtc timestamp may be wrong with fix dt/reset
 
 If the fix changes the timestep, the dump dcd file will not
 reflect the change.
 
 */
diff --git a/src/respa.cpp b/src/respa.cpp
index 469b3d698..8e9288e35 100644
--- a/src/respa.cpp
+++ b/src/respa.cpp
@@ -1,720 +1,721 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 /* ----------------------------------------------------------------------
    Contributing authors: Mark Stevens (SNL), Paul Crozier (SNL)
 ------------------------------------------------------------------------- */
 
 #include "stdlib.h"
 #include "string.h"
 #include "respa.h"
 #include "neighbor.h"
 #include "atom.h"
 #include "domain.h"
 #include "comm.h"
 #include "force.h"
 #include "pair.h"
 #include "bond.h"
 #include "angle.h"
 #include "dihedral.h"
 #include "improper.h"
 #include "kspace.h"
 #include "output.h"
 #include "update.h"
 #include "modify.h"
 #include "compute.h"
 #include "fix_respa.h"
 #include "timer.h"
 #include "memory.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
 
 /* ---------------------------------------------------------------------- */
 
 Respa::Respa(LAMMPS *lmp, int narg, char **arg) : Integrate(lmp, narg, arg)
 {
   if (narg < 1) error->all(FLERR,"Illegal run_style respa command");
 
   nlevels = atoi(arg[0]);
   if (nlevels < 1) error->all(FLERR,"Respa levels must be >= 1");
 
   if (narg < nlevels) error->all(FLERR,"Illegal run_style respa command");
   loop = new int[nlevels];
   for (int iarg = 1; iarg < nlevels; iarg++) {
     loop[iarg-1] = atoi(arg[iarg]);
     if (loop[iarg-1] <= 0) error->all(FLERR,"Illegal run_style respa command");
   }
   loop[nlevels-1] = 1;
 
   // set level at which each force is computed
   // argument settings override defaults
 
   level_bond = level_angle = level_dihedral = level_improper = -1;
   level_pair = level_kspace = -1;
   level_inner = level_middle = level_outer = -1;
 
   int iarg = nlevels;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"bond") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_bond = atoi(arg[iarg+1]) - 1;
       iarg += 2;
     } else if (strcmp(arg[iarg],"angle") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_angle = atoi(arg[iarg+1]) - 1;
       iarg += 2;
     } else if (strcmp(arg[iarg],"dihedral") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_dihedral = atoi(arg[iarg+1]) - 1;
       iarg += 2;
     } else if (strcmp(arg[iarg],"improper") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_improper = atoi(arg[iarg+1]) - 1;
       iarg += 2;
     } else if (strcmp(arg[iarg],"pair") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_pair = atoi(arg[iarg+1]) - 1;
       iarg += 2;
     } else if (strcmp(arg[iarg],"inner") == 0) {
       if (iarg+4 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_inner = atoi(arg[iarg+1]) - 1;
       cutoff[0] = atof(arg[iarg+2]);
       cutoff[1] = atof(arg[iarg+3]);
       iarg += 4;
     } else if (strcmp(arg[iarg],"middle") == 0) {
       if (iarg+4 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_middle = atoi(arg[iarg+1]) - 1;
       cutoff[2] = atof(arg[iarg+2]);
       cutoff[3] = atof(arg[iarg+3]);
       iarg += 4;
     } else if (strcmp(arg[iarg],"outer") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_outer = atoi(arg[iarg+1]) - 1;
       iarg += 2;
     } else if (strcmp(arg[iarg],"kspace") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal run_style respa command");
       level_kspace = atoi(arg[iarg+1]) - 1;
       iarg += 2;
     } else error->all(FLERR,"Illegal run_style respa command");
   }
 
   // cannot specify both pair and inner/middle/outer
 
   if (level_pair >= 0 &&
       (level_inner >= 0 || level_middle >= 0 || level_outer >= 0))
     error->all(FLERR,"Cannot set both respa pair and inner/middle/outer");
 
   // if either inner and outer is specified, then both must be
 
   if ((level_inner >= 0 && level_outer == -1) ||
       (level_outer >= 0 && level_inner == -1))
     error->all(FLERR,"Must set both respa inner and outer");
 
   // middle cannot be set without inner/outer
 
   if (level_middle >= 0 && level_inner == -1)
     error->all(FLERR,"Cannot set respa middle without inner/outer");
 
   // set defaults if user did not specify level
   // bond to innermost level
   // angle same as bond, dihedral same as angle, improper same as dihedral
   // pair to outermost level if no inner/middle/outer
   // inner/middle/outer have no defaults
   // kspace same as pair or outer
 
   if (level_bond == -1) level_bond = 0;
   if (level_angle == -1) level_angle = level_bond;
   if (level_dihedral == -1) level_dihedral = level_angle;
   if (level_improper == -1) level_improper = level_dihedral;
   if (level_pair == -1 && level_inner == -1) level_pair = nlevels-1;
   if (level_kspace == -1 && level_pair >= 0) level_kspace = level_pair;
   if (level_kspace == -1 && level_pair == -1) level_kspace = level_outer;
 
   // print respa levels
 
   if (comm->me == 0) {
     if (screen) {
       fprintf(screen,"Respa levels:\n");
       for (int i = 0; i < nlevels; i++) {
         fprintf(screen,"  %d =",i+1);
         if (level_bond == i) fprintf(screen," bond");
         if (level_angle == i) fprintf(screen," angle");
         if (level_dihedral == i) fprintf(screen," dihedral");
         if (level_improper == i) fprintf(screen," improper");
         if (level_pair == i) fprintf(screen," pair");
         if (level_inner == i) fprintf(screen," pair-inner");
         if (level_middle == i) fprintf(screen," pair-middle");
         if (level_outer == i) fprintf(screen," pair-outer");
         if (level_kspace == i) fprintf(screen," kspace");
         fprintf(screen,"\n");
       }
     }
     if (logfile) {
       fprintf(logfile,"Respa levels:\n");
       for (int i = 0; i < nlevels; i++) {
         fprintf(logfile,"  %d =",i+1);
         if (level_bond == i) fprintf(logfile," bond");
         if (level_angle == i) fprintf(logfile," angle");
         if (level_dihedral == i) fprintf(logfile," dihedral");
         if (level_improper == i) fprintf(logfile," improper");
         if (level_pair == i) fprintf(logfile," pair");
         if (level_inner == i) fprintf(logfile," pair-inner");
         if (level_middle == i) fprintf(logfile," pair-middle");
         if (level_outer == i) fprintf(logfile," pair-outer");
         if (level_kspace == i) fprintf(logfile," kspace");
         fprintf(logfile,"\n");
       }
     }
   }
 
   // check that levels are in correct order
 
   if (level_angle < level_bond || level_dihedral < level_angle ||
       level_improper < level_dihedral)
     error->all(FLERR,"Invalid order of forces within respa levels");
   if (level_pair >= 0) {
     if (level_pair < level_improper || level_kspace < level_pair)
       error->all(FLERR,"Invalid order of forces within respa levels");
   }
   if (level_pair == -1 && level_middle == -1) {
     if (level_inner < level_improper || level_outer < level_inner ||
         level_kspace < level_outer)
       error->all(FLERR,"Invalid order of forces within respa levels");
   }
   if (level_pair == -1 && level_middle >= 0) {
     if (level_inner < level_improper || level_middle < level_inner ||
         level_outer < level_inner || level_kspace < level_outer)
       error->all(FLERR,"Invalid order of forces within respa levels");
   }
 
   // warn if any levels are devoid of forces
 
   int flag = 0;
   for (int i = 0; i < nlevels; i++)
     if (level_bond != i && level_angle != i && level_dihedral != i &&
         level_improper != i && level_pair != i && level_inner != i &&
         level_middle != i && level_outer != i && level_kspace != i) flag = 1;
   if (flag && comm->me == 0)
     error->warning(FLERR,"One or more respa levels compute no forces");
 
   // check cutoff consistency if inner/middle/outer are enabled
 
   if (level_inner >= 0 && cutoff[1] < cutoff[0])
     error->all(FLERR,"Respa inner cutoffs are invalid");
   if (level_middle >= 0 && (cutoff[3] < cutoff[2] || cutoff[2] < cutoff[1]))
     error->all(FLERR,"Respa middle cutoffs are invalid");
 
   // set outer pair of cutoffs to inner pair if middle is not enabled
 
   if (level_inner >= 0 && level_middle < 0) {
     cutoff[2] = cutoff[0];
     cutoff[3] = cutoff[1];
   }
 
   // allocate other needed arrays
 
   newton = new int[nlevels];
   step = new double[nlevels];
 }
 
 /* ---------------------------------------------------------------------- */
 
 Respa::~Respa()
 {
   delete [] loop;
   delete [] newton;
   delete [] step;
 }
 
 /* ----------------------------------------------------------------------
    initialization before run
 ------------------------------------------------------------------------- */
 
 void Respa::init()
 {
   Integrate::init();
 
   // warn if no fixes
 
   if (modify->nfix == 0 && comm->me == 0)
     error->warning(FLERR,"No fixes defined, atoms won't move");
 
   // warn about incorrect pressures when using rRESPA with fix SHAKE
 
   int shakeflag = 0;
   for (int i = 0; i < modify->nfix; i++)
     if (strcmp(modify->fix[i]->style,"shake") == 0) shakeflag = 1;
   if (shakeflag && comm->me == 0)
     error->warning(FLERR,"Fix shake with rRESPA computes invalid pressures");
 
   // create fix needed for storing atom-based respa level forces
   // will delete it at end of run
 
   char **fixarg = new char*[4];
   fixarg[0] = (char *) "RESPA";
   fixarg[1] = (char *) "all";
   fixarg[2] = (char *) "RESPA";
   fixarg[3] = new char[8];
   sprintf(fixarg[3],"%d",nlevels);
   modify->add_fix(4,fixarg);
   delete [] fixarg[3];
   delete [] fixarg;
   fix_respa = (FixRespa *) modify->fix[modify->nfix-1];
 
   // insure respa inner/middle/outer is using Pair class that supports it
 
   if (level_inner >= 0)
     if (force->pair && force->pair->respa_enable == 0)
       error->all(FLERR,"Pair style does not support rRESPA inner/middle/outer");
 
   // virial_style = 1 (explicit) since never computed implicitly like Verlet
 
   virial_style = 1;
 
   // setup lists of computes for global and per-atom PE and pressure
 
   ev_setup();
 
   // detect if fix omp is present and will clear force arrays for us
   int ifix = modify->find_fix("package_omp");
   if (ifix >= 0) external_force_clear = 1;
 
   // set flags for what arrays to clear in force_clear()
   // need to clear additionals arrays if they exist
 
   torqueflag = 0;
   if (atom->torque_flag) torqueflag = 1;
   erforceflag = 0;
   if (atom->erforce_flag) erforceflag = 1;
   e_flag = 0;
   if (atom->e_flag) e_flag = 1;
   rho_flag = 0;
   if (atom->rho_flag) rho_flag = 1;
 
   // step[] = timestep for each level
 
   step[nlevels-1] = update->dt;
   for (int ilevel = nlevels-2; ilevel >= 0; ilevel--)
     step[ilevel] = step[ilevel+1]/loop[ilevel];
 
   // set newton flag for each level
 
   for (int ilevel = 0; ilevel < nlevels; ilevel++) {
     newton[ilevel] = 0;
     if (force->newton_bond) {
       if (level_bond == ilevel || level_angle == ilevel ||
           level_dihedral == ilevel || level_improper == ilevel)
         newton[ilevel] = 1;
     }
     if (force->newton_pair) {
       if (level_pair == ilevel || level_inner == ilevel ||
           level_middle == ilevel || level_outer == ilevel)
         newton[ilevel] = 1;
     }
   }
 
   // orthogonal vs triclinic simulation box
 
   triclinic = domain->triclinic;
 }
 
 /* ----------------------------------------------------------------------
    setup before run
 ------------------------------------------------------------------------- */
 
 void Respa::setup()
 {
   if (comm->me == 0 && screen) fprintf(screen,"Setting up run ...\n");
 
   update->setupflag = 1;
 
   // setup domain, communication and neighboring
   // acquire ghosts
   // build neighbor lists
 
   atom->setup();
   modify->setup_pre_exchange();
   if (triclinic) domain->x2lamda(atom->nlocal);
   domain->pbc();
   domain->reset_box();
   comm->setup();
   if (neighbor->style) neighbor->setup_bins();
   comm->exchange();
   if (atom->sortfreq > 0) atom->sort();
   comm->borders();
   if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
   domain->image_check();
   domain->box_too_small_check();
   modify->setup_pre_neighbor();
   neighbor->build();
   neighbor->ncalls = 0;
 
   // compute all forces
 
   ev_set(update->ntimestep);
 
   for (int ilevel = 0; ilevel < nlevels; ilevel++) {
     force_clear(newton[ilevel]);
     modify->setup_pre_force_respa(vflag,ilevel);
     if (level_pair == ilevel && pair_compute_flag)
       force->pair->compute(eflag,vflag);
     if (level_inner == ilevel && pair_compute_flag)
       force->pair->compute_inner();
     if (level_middle == ilevel && pair_compute_flag)
       force->pair->compute_middle();
     if (level_outer == ilevel && pair_compute_flag)
       force->pair->compute_outer(eflag,vflag);
     if (level_bond == ilevel && force->bond)
       force->bond->compute(eflag,vflag);
     if (level_angle == ilevel && force->angle)
       force->angle->compute(eflag,vflag);
     if (level_dihedral == ilevel && force->dihedral)
       force->dihedral->compute(eflag,vflag);
     if (level_improper == ilevel && force->improper)
       force->improper->compute(eflag,vflag);
     if (level_kspace == ilevel && force->kspace) {
       force->kspace->setup();
       if (kspace_compute_flag) force->kspace->compute(eflag,vflag);
     }
     if (newton[ilevel]) comm->reverse_comm();
     copy_f_flevel(ilevel);
   }
 
   modify->setup(vflag);
   sum_flevel_f();
   output->setup();
   update->setupflag = 0;
 }
 
 /* ----------------------------------------------------------------------
    setup without output
    flag = 0 = just force calculation
    flag = 1 = reneighbor and force calculation
 ------------------------------------------------------------------------- */
 
 void Respa::setup_minimal(int flag)
 {
   update->setupflag = 1;
 
   // setup domain, communication and neighboring
   // acquire ghosts
   // build neighbor lists
 
   if (flag) {
     modify->setup_pre_exchange();
     if (triclinic) domain->x2lamda(atom->nlocal);
     domain->pbc();
     domain->reset_box();
     comm->setup();
     if (neighbor->style) neighbor->setup_bins();
     comm->exchange();
     comm->borders();
     if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
     domain->image_check();
     domain->box_too_small_check();
     modify->setup_pre_neighbor();
     neighbor->build();
     neighbor->ncalls = 0;
   }
 
   // compute all forces
 
   ev_set(update->ntimestep);
 
   for (int ilevel = 0; ilevel < nlevels; ilevel++) {
     force_clear(newton[ilevel]);
     modify->setup_pre_force_respa(vflag,ilevel);
     if (level_pair == ilevel && pair_compute_flag)
       force->pair->compute(eflag,vflag);
     if (level_inner == ilevel && pair_compute_flag)
       force->pair->compute_inner();
     if (level_middle == ilevel && pair_compute_flag)
       force->pair->compute_middle();
     if (level_outer == ilevel && pair_compute_flag)
       force->pair->compute_outer(eflag,vflag);
     if (level_bond == ilevel && force->bond)
       force->bond->compute(eflag,vflag);
     if (level_angle == ilevel && force->angle)
       force->angle->compute(eflag,vflag);
     if (level_dihedral == ilevel && force->dihedral)
       force->dihedral->compute(eflag,vflag);
     if (level_improper == ilevel && force->improper)
       force->improper->compute(eflag,vflag);
     if (level_kspace == ilevel && force->kspace) {
       force->kspace->setup();
       if (kspace_compute_flag) force->kspace->compute(eflag,vflag);
     }
     if (newton[ilevel]) comm->reverse_comm();
     copy_f_flevel(ilevel);
   }
 
   modify->setup(vflag);
   sum_flevel_f();
   update->setupflag = 0;
 }
 
 /* ----------------------------------------------------------------------
    run for N steps
 ------------------------------------------------------------------------- */
 
 void Respa::run(int n)
 {
   bigint ntimestep;
 
   for (int i = 0; i < n; i++) {
 
     ntimestep = ++update->ntimestep;
     ev_set(ntimestep);
 
     recurse(nlevels-1);
 
     if (modify->n_end_of_step) {
       timer->stamp();
       modify->end_of_step();
       timer->stamp(Timer::MODIFY);
     }
 
     if (ntimestep == output->next) {
       timer->stamp();
       sum_flevel_f();
       output->write(update->ntimestep);
       timer->stamp(Timer::OUTPUT);
     }
   }
 }
 
 /* ----------------------------------------------------------------------
    delete rRESPA fix at end of run, so its atom arrays won't persist
 ------------------------------------------------------------------------- */
 
 void Respa::cleanup()
 {
   modify->post_run();
   modify->delete_fix("RESPA");
   domain->box_too_small_check();
+  update->update_time();
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Respa::reset_dt()
 {
   step[nlevels-1] = update->dt;
   for (int ilevel = nlevels-2; ilevel >= 0; ilevel--)
     step[ilevel] = step[ilevel+1]/loop[ilevel];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Respa::recurse(int ilevel)
 {
   copy_flevel_f(ilevel);
 
   for (int iloop = 0; iloop < loop[ilevel]; iloop++) {
 
     timer->stamp();
     modify->initial_integrate_respa(vflag,ilevel,iloop);
     if (modify->n_post_integrate_respa)
       modify->post_integrate_respa(ilevel,iloop);
     timer->stamp(Timer::MODIFY);
 
     if (ilevel) recurse(ilevel-1);
 
     // at outermost level, check on rebuilding neighbor list
     // at innermost level, communicate
     // at middle levels, do nothing
 
     if (ilevel == nlevels-1) {
       int nflag = neighbor->decide();
       if (nflag) {
         if (modify->n_pre_exchange) {
           timer->stamp();
           modify->pre_exchange();
           timer->stamp(Timer::MODIFY);
         }
         if (triclinic) domain->x2lamda(atom->nlocal);
         domain->pbc();
         if (domain->box_change) {
           domain->reset_box();
           comm->setup();
           if (neighbor->style) neighbor->setup_bins();
         }
         timer->stamp();
         comm->exchange();
         if (atom->sortfreq > 0 && 
             update->ntimestep >= atom->nextsort) atom->sort();
         comm->borders();
         if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
         timer->stamp(Timer::COMM);
         if (modify->n_pre_neighbor) {
           modify->pre_neighbor();
           timer->stamp(Timer::MODIFY);
         }
         neighbor->build();
         timer->stamp(Timer::NEIGHBOR);
       } else if (ilevel == 0) {
         timer->stamp();
         comm->forward_comm();
         timer->stamp(Timer::COMM);
       }
 
     } else if (ilevel == 0) {
       timer->stamp();
       comm->forward_comm();
       timer->stamp(Timer::COMM);
     }
 
     // force computations
     // important that ordering is same as Verlet
     // so that any order dependencies are the same
     // when potentials are invoked at same level
 
     force_clear(newton[ilevel]);
     if (modify->n_pre_force_respa) {
       timer->stamp();
       modify->pre_force_respa(vflag,ilevel,iloop);
       timer->stamp(Timer::MODIFY);
     }
 
     timer->stamp();
     if (level_pair == ilevel && pair_compute_flag) {
       force->pair->compute(eflag,vflag);
       timer->stamp(Timer::PAIR);
     }
     if (level_inner == ilevel && pair_compute_flag) {
       force->pair->compute_inner();
       timer->stamp(Timer::PAIR);
     }
     if (level_middle == ilevel && pair_compute_flag) {
       force->pair->compute_middle();
       timer->stamp(Timer::PAIR);
     }
     if (level_outer == ilevel && pair_compute_flag) {
       force->pair->compute_outer(eflag,vflag);
       timer->stamp(Timer::PAIR);
     }
     if (level_bond == ilevel && force->bond) {
       force->bond->compute(eflag,vflag);
       timer->stamp(Timer::BOND);
     }
     if (level_angle == ilevel && force->angle) {
       force->angle->compute(eflag,vflag);
       timer->stamp(Timer::BOND);
     }
     if (level_dihedral == ilevel && force->dihedral) {
       force->dihedral->compute(eflag,vflag);
       timer->stamp(Timer::BOND);
     }
     if (level_improper == ilevel && force->improper) {
       force->improper->compute(eflag,vflag);
       timer->stamp(Timer::BOND);
     }
     if (level_kspace == ilevel && kspace_compute_flag) {
       force->kspace->compute(eflag,vflag);
       timer->stamp(Timer::KSPACE);
     }
 
     if (newton[ilevel]) {
       comm->reverse_comm();
       timer->stamp(Timer::COMM);
     }
     timer->stamp();
     if (modify->n_post_force_respa)
       modify->post_force_respa(vflag,ilevel,iloop);
     modify->final_integrate_respa(ilevel,iloop);
     timer->stamp(Timer::MODIFY);
   }
 
   copy_f_flevel(ilevel);
 }
 
 /* ----------------------------------------------------------------------
    clear force on own & ghost atoms
 ------------------------------------------------------------------------- */
 
 void Respa::force_clear(int newtonflag)
 {
   if (external_force_clear) return;
 
   // clear global force array
   // nall includes ghosts only if newton flag is set
 
   int nall;
   if (newtonflag) nall = atom->nlocal + atom->nghost;
   else nall = atom->nlocal;
 
   size_t nbytes = sizeof(double) * nall;
 
   if (nbytes > 0 ) {
     memset(&(atom->f[0][0]),0,3*nbytes);
     if (torqueflag)  memset(&(atom->torque[0][0]),0,3*nbytes);
     if (erforceflag) memset(&(atom->erforce[0]),  0,  nbytes);
     if (e_flag)      memset(&(atom->de[0]),       0,  nbytes);
     if (rho_flag)    memset(&(atom->drho[0]),     0,  nbytes);
   }
 }
 
 /* ----------------------------------------------------------------------
    copy force components from atom->f to FixRespa->f_level
 ------------------------------------------------------------------------- */
 
 void Respa::copy_f_flevel(int ilevel)
 {
   double ***f_level = fix_respa->f_level;
   double **f = atom->f;
   int n = atom->nlocal;
 
   for (int i = 0; i < n; i++) {
     f_level[i][ilevel][0] = f[i][0];
     f_level[i][ilevel][1] = f[i][1];
     f_level[i][ilevel][2] = f[i][2];
   }
 }
 
 /* ----------------------------------------------------------------------
    copy force components from FixRespa->f_level to atom->f
 ------------------------------------------------------------------------- */
 
 void Respa::copy_flevel_f(int ilevel)
 {
   double ***f_level = fix_respa->f_level;
   double **f = atom->f;
   int n = atom->nlocal;
 
   for (int i = 0; i < n; i++) {
     f[i][0] = f_level[i][ilevel][0];
     f[i][1] = f_level[i][ilevel][1];
     f[i][2] = f_level[i][ilevel][2];
   }
 }
 
 /* ----------------------------------------------------------------------
    sum all force components from FixRespa->f_level to create full atom->f
 ------------------------------------------------------------------------- */
 
 void Respa::sum_flevel_f()
 {
   copy_flevel_f(0);
 
   double ***f_level = fix_respa->f_level;
   double **f = atom->f;
   int n = atom->nlocal;
 
   for (int ilevel = 1; ilevel < nlevels; ilevel++) {
     for (int i = 0; i < n; i++) {
       f[i][0] += f_level[i][ilevel][0];
       f[i][1] += f_level[i][ilevel][1];
       f[i][2] += f_level[i][ilevel][2];
     }
   }
 }
diff --git a/src/thermo.cpp b/src/thermo.cpp
index 1b9ce64ba..634fc420f 100644
--- a/src/thermo.cpp
+++ b/src/thermo.cpp
@@ -1,1959 +1,1971 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #include "lmptype.h"
 #include "mpi.h"
 #include "math.h"
 #include "stdlib.h"
 #include "string.h"
 #include "thermo.h"
 #include "atom.h"
 #include "update.h"
 #include "comm.h"
 #include "domain.h"
 #include "lattice.h"
 #include "modify.h"
 #include "fix.h"
 #include "compute.h"
 #include "input.h"
 #include "variable.h"
 #include "force.h"
 #include "pair.h"
 #include "bond.h"
 #include "angle.h"
 #include "dihedral.h"
 #include "improper.h"
 #include "kspace.h"
 #include "output.h"
 #include "timer.h"
 #include "math_const.h"
 #include "memory.h"
 #include "error.h"
 
 #include "math_const.h"
 
 using namespace LAMMPS_NS;
 using namespace MathConst;
 
 // customize a new keyword by adding to this list:
 
-// step, elapsed, elaplong, dt, cpu, tpcpu, spcpu
+// step, elapsed, elaplong, dt, time, cpu, tpcpu, spcpu
 // atoms, temp, press, pe, ke, etotal, enthalpy
 // evdwl, ecoul, epair, ebond, eangle, edihed, eimp, emol, elong, etail
 // vol, lx, ly, lz, xlo, xhi, ylo, yhi, zlo, zhi, xy, xz, yz, xlat, ylat, zlat
 // pxx, pyy, pzz, pxy, pxz, pyz
 // fmax, fnorm
 // cella, cellb, cellc, cellalpha, cellbeta, cellgamma
 
 // customize a new thermo style by adding a DEFINE to this list
 // also insure allocation of line string is correct in constructor
 
 #define ONE "step temp epair emol etotal press"
 #define MULTI "etotal ke temp pe ebond eangle edihed eimp evdwl ecoul elong press"
 
 enum{IGNORE,WARN,ERROR};           // same as write_restart.cpp
 enum{ONELINE,MULTILINE};
 enum{INT,FLOAT,BIGINT};
 enum{SCALAR,VECTOR,ARRAY};
 
 #define INVOKED_SCALAR 1
 #define INVOKED_VECTOR 2
 #define INVOKED_ARRAY 4
 
 #define DELTA 8
 
 /* ---------------------------------------------------------------------- */
 
 Thermo::Thermo(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
 {
   MPI_Comm_rank(world,&me);
 
   int n = strlen(arg[0]) + 1;
   style = new char[n];
   strcpy(style,arg[0]);
 
   // set thermo_modify defaults
 
   modified = 0;
   normuserflag = 0;
   lineflag = ONELINE;
   lostflag = ERROR;
   lostbefore = 0;
   flushflag = 0;
 
   // set style and corresponding lineflag
   // custom style builds its own line of keywords
   // customize a new thermo style by adding to if statement
   // allocate line string used for 3 tasks
   //   concat of custom style args
   //   one-time thermo output of header line
   //   each line of numeric thermo output
   //   256 = extra for ONE or MULTI string or multi formatting
   //   64 = max per-arg chars in header or numeric output
 
   if (strcmp(style,"one") == 0) {
     line = new char[256+6*64];
     strcpy(line,ONE);
   } else if (strcmp(style,"multi") == 0) {
     line = new char[256+12*64];
     strcpy(line,MULTI);
     lineflag = MULTILINE;
 
   } else if (strcmp(style,"custom") == 0) {
     if (narg == 1) error->all(FLERR,"Illegal thermo style custom command");
     line = new char[256+narg*64];
     line[0] = '\0';
     for (int iarg = 1; iarg < narg; iarg++) {
       strcat(line,arg[iarg]);
       strcat(line," ");
     }
     line[strlen(line)-1] = '\0';
 
   } else error->all(FLERR,"Illegal thermo style command");
 
   // ptrs, flags, IDs for compute objects thermo may use or create
 
   temperature = NULL;
   pressure = NULL;
   pe = NULL;
 
   index_temp = index_press_scalar = index_press_vector = index_pe = -1;
 
   id_temp = (char *) "thermo_temp";
   id_press = (char *) "thermo_press";
   id_pe = (char *) "thermo_pe";
 
   // count fields in line
   // allocate per-field memory
   // process line of keywords
 
   nfield_initial = atom->count_words(line);
   allocate();
   parse_fields(line);
 
   // format strings
 
   char *bigint_format = (char *) BIGINT_FORMAT;
   char *fformat_multi = (char *) "---------------- Step %%8%s ----- "
     "CPU = %%11.4f (sec) ----------------";
 
   sprintf(format_multi,fformat_multi,&bigint_format[1]);
   format_float_one_def = (char *) "%12.8g";
   format_float_multi_def = (char *) "%14.4f";
   format_int_one_def = (char *) "%8d";
   format_int_multi_def = (char *) "%14d";
   sprintf(format_bigint_one_def,"%%8%s",&bigint_format[1]);
   sprintf(format_bigint_multi_def,"%%14%s",&bigint_format[1]);
 
   format_float_user = NULL;
   format_int_user = NULL;
   format_bigint_user = NULL;
 }
 
 /* ---------------------------------------------------------------------- */
 
 Thermo::~Thermo()
 {
   delete [] style;
   delete [] line;
 
   deallocate();
 
   // format strings
 
   delete [] format_float_user;
   delete [] format_int_user;
   delete [] format_bigint_user;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::init()
 {
   int i,n;
 
   // set normvalue to default setting unless user has specified it
 
   if (normuserflag) normvalue = normuser;
   else if (strcmp(update->unit_style,"lj") == 0) normvalue = 1;
   else normvalue = 0;
 
   // add Volume field if volume changes and not style = custom
   // this check must come after domain init, so box_change is set
 
   nfield = nfield_initial;
   if (domain->box_change && strcmp(style,"custom") != 0)
     addfield("Volume",&Thermo::compute_vol,FLOAT);
 
   // set format string for each field
   // include keyword if lineflag = MULTILINE
   // add '/n' every 3 values if lineflag = MULTILINE
   // add trailing '/n' to last value
 
   char *ptr;
   for (i = 0; i < nfield; i++) {
     format[i][0] = '\0';
     if (lineflag == MULTILINE && i % 3 == 0) strcat(format[i],"\n");
 
     if (format_user[i]) ptr = format_user[i];
     else if (vtype[i] == FLOAT) {
       if (format_float_user) ptr = format_float_user;
       else if (lineflag == ONELINE) ptr = format_float_one_def;
       else if (lineflag == MULTILINE) ptr = format_float_multi_def;
     } else if (vtype[i] == INT) {
       if (format_int_user) ptr = format_int_user;
       else if (lineflag == ONELINE) ptr = format_int_one_def;
       else if (lineflag == MULTILINE) ptr = format_int_multi_def;
     } else if (vtype[i] == BIGINT) {
       if (format_bigint_user) ptr = format_bigint_user;
       else if (lineflag == ONELINE) ptr = format_bigint_one_def;
       else if (lineflag == MULTILINE) ptr = format_bigint_multi_def;
     }
 
     n = strlen(format[i]);
     if (lineflag == ONELINE) sprintf(&format[i][n],"%s ",ptr);
     else sprintf(&format[i][n],"%-8s = %s ",keyword[i],ptr);
 
     if (i == nfield-1) strcat(format[i],"\n");
   }
 
   // find current ptr for each Compute ID
   // cudable = 0 if any compute used by Thermo is non-CUDA
 
   cudable = 1;
 
   int icompute;
   for (i = 0; i < ncompute; i++) {
     icompute = modify->find_compute(id_compute[i]);
     if (icompute < 0) error->all(FLERR,"Could not find thermo compute ID");
     computes[i] = modify->compute[icompute];
     cudable = cudable && computes[i]->cudable;
   }
 
   // find current ptr for each Fix ID
   // check that fix frequency is acceptable with thermo output frequency
 
   int ifix;
   for (i = 0; i < nfix; i++) {
     ifix = modify->find_fix(id_fix[i]);
     if (ifix < 0) error->all(FLERR,"Could not find thermo fix ID");
     fixes[i] = modify->fix[ifix];
     if (output->thermo_every % fixes[i]->global_freq)
       error->all(FLERR,"Thermo and fix not computed at compatible times");
   }
 
   // find current ptr for each Variable ID
 
   int ivariable;
   for (i = 0; i < nvariable; i++) {
     ivariable = input->variable->find(id_variable[i]);
     if (ivariable < 0)
       error->all(FLERR,"Could not find thermo variable name");
     variables[i] = ivariable;
   }
 
   // set ptrs to keyword-specific Compute objects
 
   if (index_temp >= 0) temperature = computes[index_temp];
   if (index_press_scalar >= 0) pressure = computes[index_press_scalar];
   if (index_press_vector >= 0) pressure = computes[index_press_vector];
   if (index_pe >= 0) pe = computes[index_pe];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::header()
 {
   if (lineflag == MULTILINE) return;
 
   int loc = 0;
   for (int i = 0; i < nfield; i++)
     loc += sprintf(&line[loc],"%s ",keyword[i]);
   sprintf(&line[loc],"\n");
 
   if (me == 0) {
     if (screen) fprintf(screen,"%s",line);
     if (logfile) fprintf(logfile,"%s",line);
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute(int flag)
 {
   int i;
 
   firststep = flag;
   bigint ntimestep = update->ntimestep;
 
   // check for lost atoms
   // turn off normflag if natoms = 0 to avoid divide by 0
 
   natoms = lost_check();
   if (natoms == 0) normflag = 0;
   else normflag = normvalue;
 
   // invoke Compute methods needed for thermo keywords
 
   for (i = 0; i < ncompute; i++)
     if (compute_which[i] == SCALAR) {
       if (!(computes[i]->invoked_flag & INVOKED_SCALAR)) {
         computes[i]->compute_scalar();
         computes[i]->invoked_flag |= INVOKED_SCALAR;
       }
     } else if (compute_which[i] == VECTOR) {
       if (!(computes[i]->invoked_flag & INVOKED_VECTOR)) {
         computes[i]->compute_vector();
         computes[i]->invoked_flag |= INVOKED_VECTOR;
       }
     } else if (compute_which[i] == ARRAY) {
       if (!(computes[i]->invoked_flag & INVOKED_ARRAY)) {
         computes[i]->compute_array();
         computes[i]->invoked_flag |= INVOKED_ARRAY;
       }
     }
 
   // if lineflag = MULTILINE, prepend step/cpu header line
 
   int loc = 0;
   if (lineflag == MULTILINE) {
     double cpu;
     if (flag) cpu = timer->elapsed(Timer::LOOP);
     else cpu = 0.0;
     loc = sprintf(&line[loc],format_multi,ntimestep,cpu);
   }
 
   // add each thermo value to line with its specific format
 
   for (ifield = 0; ifield < nfield; ifield++) {
     (this->*vfunc[ifield])();
     if (vtype[ifield] == FLOAT)
       loc += sprintf(&line[loc],format[ifield],dvalue);
     else if (vtype[ifield] == INT)
       loc += sprintf(&line[loc],format[ifield],ivalue);
     else if (vtype[ifield] == BIGINT) {
       loc += sprintf(&line[loc],format[ifield],bivalue);
     }
   }
 
   // print line to screen and logfile
 
   if (me == 0) {
     if (screen) fprintf(screen,"%s",line);
     if (logfile) {
       fprintf(logfile,"%s",line);
       if (flushflag) fflush(logfile);
     }
   }
 }
 
 /* ----------------------------------------------------------------------
    check for lost atoms, return current number of atoms
 ------------------------------------------------------------------------- */
 
 bigint Thermo::lost_check()
 {
   // ntotal = current # of atoms
 
   bigint ntotal;
   bigint nblocal = atom->nlocal;
   MPI_Allreduce(&nblocal,&ntotal,1,MPI_LMP_BIGINT,MPI_SUM,world);
   if (ntotal < 0 || ntotal > MAXBIGINT)
     error->all(FLERR,"Too many total atoms");
   if (ntotal == atom->natoms) return ntotal;
 
   // if not checking or already warned, just return
   // reset total atom count
 
   if (lostflag == IGNORE) return ntotal;
   if (lostflag == WARN && lostbefore == 1) {
     atom->natoms = ntotal;
     return ntotal;
   }
 
   // error message
 
   if (lostflag == ERROR) {
     char str[64];
     sprintf(str,
             "Lost atoms: original " BIGINT_FORMAT " current " BIGINT_FORMAT,
             atom->natoms,ntotal);
     error->all(FLERR,str);
   }
 
   // warning message
 
   char str[64];
   sprintf(str,
           "Lost atoms: original " BIGINT_FORMAT " current " BIGINT_FORMAT,
           atom->natoms,ntotal);
   if (me == 0) error->warning(FLERR,str,0);
 
   // reset total atom count
 
   atom->natoms = ntotal;
   lostbefore = 1;
   return ntotal;
 }
 
 /* ----------------------------------------------------------------------
    modify thermo parameters
 ------------------------------------------------------------------------- */
 
 void Thermo::modify_params(int narg, char **arg)
 {
   if (narg == 0) error->all(FLERR,"Illegal thermo_modify command");
 
   modified = 1;
 
   int iarg = 0;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"temp") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
       if (index_temp < 0) error->all(FLERR,"Thermo style does not use temp");
       delete [] id_compute[index_temp];
       int n = strlen(arg[iarg+1]) + 1;
       id_compute[index_temp] = new char[n];
       strcpy(id_compute[index_temp],arg[iarg+1]);
 
       int icompute = modify->find_compute(arg[iarg+1]);
       if (icompute < 0)
         error->all(FLERR,"Could not find thermo_modify temperature ID");
       temperature = modify->compute[icompute];
 
       if (temperature->tempflag == 0)
         error->all(FLERR,"Thermo_modify temperature ID does not "
                    "compute temperature");
       if (temperature->igroup != 0 && comm->me == 0)
         error->warning(FLERR,
                        "Temperature for thermo pressure is not for group all");
 
       // reset id_temp of pressure to new temperature ID
       // either pressure currently being used by thermo or "thermo_press"
 
       if (index_press_scalar >= 0) {
         icompute = modify->find_compute(id_compute[index_press_scalar]);
         if (icompute < 0) error->all(FLERR,
                                      "Pressure ID for thermo does not exist");
       } else if (index_press_vector >= 0) {
         icompute = modify->find_compute(id_compute[index_press_vector]);
         if (icompute < 0) error->all(FLERR,
                                      "Pressure ID for thermo does not exist");
       } else icompute = modify->find_compute((char *) "thermo_press");
 
       modify->compute[icompute]->reset_extra_compute_fix(arg[iarg+1]);
 
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"press") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
       if (index_press_scalar < 0 && index_press_vector < 0)
         error->all(FLERR,"Thermo style does not use press");
 
       if (index_press_scalar >= 0) {
         delete [] id_compute[index_press_scalar];
         int n = strlen(arg[iarg+1]) + 1;
         id_compute[index_press_scalar] = new char[n];
         strcpy(id_compute[index_press_scalar],arg[iarg+1]);
       }
       if (index_press_vector >= 0) {
         delete [] id_compute[index_press_vector];
         int n = strlen(arg[iarg+1]) + 1;
         id_compute[index_press_vector] = new char[n];
         strcpy(id_compute[index_press_vector],arg[iarg+1]);
       }
 
       int icompute = modify->find_compute(arg[iarg+1]);
       if (icompute < 0) error->all(FLERR,
                                    "Could not find thermo_modify pressure ID");
       pressure = modify->compute[icompute];
 
       if (pressure->pressflag == 0)
         error->all(FLERR,"Thermo_modify pressure ID does not compute pressure");
 
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"lost") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
       if (strcmp(arg[iarg+1],"ignore") == 0) lostflag = IGNORE;
       else if (strcmp(arg[iarg+1],"warn") == 0) lostflag = WARN;
       else if (strcmp(arg[iarg+1],"error") == 0) lostflag = ERROR;
       else error->all(FLERR,"Illegal thermo_modify command");
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"norm") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
       normuserflag = 1;
       if (strcmp(arg[iarg+1],"no") == 0) normuser = 0;
       else if (strcmp(arg[iarg+1],"yes") == 0) normuser = 1;
       else error->all(FLERR,"Illegal thermo_modify command");
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"flush") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
       if (strcmp(arg[iarg+1],"no") == 0) flushflag = 0;
       else if (strcmp(arg[iarg+1],"yes") == 0) flushflag = 1;
       else error->all(FLERR,"Illegal thermo_modify command");
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"line") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Illegal thermo_modify command");
       if (strcmp(arg[iarg+1],"one") == 0) lineflag = ONELINE;
       else if (strcmp(arg[iarg+1],"multi") == 0) lineflag = MULTILINE;
       else error->all(FLERR,"Illegal thermo_modify command");
       iarg += 2;
 
     } else if (strcmp(arg[iarg],"format") == 0) {
       if (iarg+3 > narg) error->all(FLERR,"Illegal thermo_modify command");
       if (strcmp(arg[iarg+1],"int") == 0) {
         if (format_int_user) delete [] format_int_user;
         int n = strlen(arg[iarg+2]) + 1;
         format_int_user = new char[n];
         strcpy(format_int_user,arg[iarg+2]);
         if (format_bigint_user) delete [] format_bigint_user;
         n = strlen(format_int_user) + 3;
         format_bigint_user = new char[n];
         char *ptr = strchr(format_int_user,'d');
         if (ptr == NULL)
           error->all(FLERR,
                      "Thermo_modify int format does not contain d character");
         *ptr = '\0';
         sprintf(format_bigint_user,"%s%s%s",format_int_user,
                 BIGINT_FORMAT,ptr+1);
         *ptr = 'd';
       } else if (strcmp(arg[iarg+1],"float") == 0) {
         if (format_float_user) delete [] format_float_user;
         int n = strlen(arg[iarg+2]) + 1;
         format_float_user = new char[n];
         strcpy(format_float_user,arg[iarg+2]);
       } else {
         int i = atoi(arg[iarg+1]) - 1;
         if (i < 0 || i >= nfield_initial)
           error->all(FLERR,"Illegal thermo_modify command");
         if (format_user[i]) delete [] format_user[i];
         int n = strlen(arg[iarg+2]) + 1;
         format_user[i] = new char[n];
         strcpy(format_user[i],arg[iarg+2]);
       }
       iarg += 3;
 
     } else error->all(FLERR,"Illegal thermo_modify command");
   }
 }
 
 /* ----------------------------------------------------------------------
    allocate all per-field memory
 ------------------------------------------------------------------------- */
 
 void Thermo::allocate()
 {
   // n = specified fields + Volume field (added at run time)
 
   int n = nfield_initial + 1;
 
   keyword = new char*[n];
   for (int i = 0; i < n; i++) keyword[i] = new char[32];
   vfunc = new FnPtr[n];
   vtype = new int[n];
 
   format = new char*[n];
   for (int i = 0; i < n; i++) format[i] = new char[32];
   format_user = new char*[n];
   for (int i = 0; i < n; i++) format_user[i] = NULL;
 
   field2index = new int[n];
   argindex1 = new int[n];
   argindex2 = new int[n];
 
   // factor of 3 is max number of computes a single field can add
 
   ncompute = 0;
   id_compute = new char*[3*n];
   compute_which = new int[3*n];
   computes = new Compute*[3*n];
 
   nfix = 0;
   id_fix = new char*[n];
   fixes = new Fix*[n];
 
   nvariable = 0;
   id_variable = new char*[n];
   variables = new int[n];
 }
 
 /* ----------------------------------------------------------------------
    deallocate all per-field memory
 ------------------------------------------------------------------------- */
 
 void Thermo::deallocate()
 {
   int n = nfield_initial + 1;
 
   for (int i = 0; i < n; i++) delete [] keyword[i];
   delete [] keyword;
   delete [] vfunc;
   delete [] vtype;
 
   for (int i = 0; i < n; i++) delete [] format[i];
   delete [] format;
   for (int i = 0; i < n; i++) delete [] format_user[i];
   delete [] format_user;
 
   delete [] field2index;
   delete [] argindex1;
   delete [] argindex2;
 
   for (int i = 0; i < ncompute; i++) delete [] id_compute[i];
   delete [] id_compute;
   delete [] compute_which;
   delete [] computes;
 
   for (int i = 0; i < nfix; i++) delete [] id_fix[i];
   delete [] id_fix;
   delete [] fixes;
 
   for (int i = 0; i < nvariable; i++) delete [] id_variable[i];
   delete [] id_variable;
   delete [] variables;
 }
 
 /* ----------------------------------------------------------------------
    parse list of thermo keywords from str
    set compute flags (temp, press, pe, etc)
 ------------------------------------------------------------------------- */
 
 void Thermo::parse_fields(char *str)
 {
   nfield = 0;
 
   // customize a new keyword by adding to if statement
 
   char *word = strtok(str," \0");
   while (word) {
 
     if (strcmp(word,"step") == 0) {
       addfield("Step",&Thermo::compute_step,BIGINT);
     } else if (strcmp(word,"elapsed") == 0) {
       addfield("Elapsed",&Thermo::compute_elapsed,BIGINT);
     } else if (strcmp(word,"elaplong") == 0) {
       addfield("Elaplong",&Thermo::compute_elapsed_long,BIGINT);
     } else if (strcmp(word,"dt") == 0) {
       addfield("Dt",&Thermo::compute_dt,FLOAT);
+    } else if (strcmp(word,"time") == 0) {
+      addfield("Time",&Thermo::compute_time,FLOAT);
     } else if (strcmp(word,"cpu") == 0) {
       addfield("CPU",&Thermo::compute_cpu,FLOAT);
     } else if (strcmp(word,"tpcpu") == 0) {
       addfield("T/CPU",&Thermo::compute_tpcpu,FLOAT);
     } else if (strcmp(word,"spcpu") == 0) {
       addfield("S/CPU",&Thermo::compute_spcpu,FLOAT);
 
     } else if (strcmp(word,"atoms") == 0) {
       addfield("Atoms",&Thermo::compute_atoms,BIGINT);
     } else if (strcmp(word,"temp") == 0) {
       addfield("Temp",&Thermo::compute_temp,FLOAT);
       index_temp = add_compute(id_temp,SCALAR);
     } else if (strcmp(word,"press") == 0) {
       addfield("Press",&Thermo::compute_press,FLOAT);
       index_press_scalar = add_compute(id_press,SCALAR);
     } else if (strcmp(word,"pe") == 0) {
       addfield("PotEng",&Thermo::compute_pe,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"ke") == 0) {
       addfield("KinEng",&Thermo::compute_ke,FLOAT);
       index_temp = add_compute(id_temp,SCALAR);
     } else if (strcmp(word,"etotal") == 0) {
       addfield("TotEng",&Thermo::compute_etotal,FLOAT);
       index_temp = add_compute(id_temp,SCALAR);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"enthalpy") == 0) {
       addfield("Enthalpy",&Thermo::compute_enthalpy,FLOAT);
       index_temp = add_compute(id_temp,SCALAR);
       index_press_scalar = add_compute(id_press,SCALAR);
       index_pe = add_compute(id_pe,SCALAR);
 
     } else if (strcmp(word,"evdwl") == 0) {
       addfield("E_vdwl",&Thermo::compute_evdwl,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"ecoul") == 0) {
       addfield("E_coul",&Thermo::compute_ecoul,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"epair") == 0) {
       addfield("E_pair",&Thermo::compute_epair,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"ebond") == 0) {
       addfield("E_bond",&Thermo::compute_ebond,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"eangle") == 0) {
       addfield("E_angle",&Thermo::compute_eangle,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"edihed") == 0) {
       addfield("E_dihed",&Thermo::compute_edihed,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"eimp") == 0) {
       addfield("E_impro",&Thermo::compute_eimp,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"emol") == 0) {
       addfield("E_mol",&Thermo::compute_emol,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"elong") == 0) {
       addfield("E_long",&Thermo::compute_elong,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
     } else if (strcmp(word,"etail") == 0) {
       addfield("E_tail",&Thermo::compute_etail,FLOAT);
       index_pe = add_compute(id_pe,SCALAR);
 
     } else if (strcmp(word,"vol") == 0) {
       addfield("Volume",&Thermo::compute_vol,FLOAT);
     } else if (strcmp(word,"lx") == 0) {
       addfield("Lx",&Thermo::compute_lx,FLOAT);
     } else if (strcmp(word,"ly") == 0) {
       addfield("Ly",&Thermo::compute_ly,FLOAT);
     } else if (strcmp(word,"lz") == 0) {
       addfield("Lz",&Thermo::compute_lz,FLOAT);
 
     } else if (strcmp(word,"xlo") == 0) {
       addfield("Xlo",&Thermo::compute_xlo,FLOAT);
     } else if (strcmp(word,"xhi") == 0) {
       addfield("Xhi",&Thermo::compute_xhi,FLOAT);
     } else if (strcmp(word,"ylo") == 0) {
       addfield("Ylo",&Thermo::compute_ylo,FLOAT);
     } else if (strcmp(word,"yhi") == 0) {
       addfield("Yhi",&Thermo::compute_yhi,FLOAT);
     } else if (strcmp(word,"zlo") == 0) {
       addfield("Zlo",&Thermo::compute_zlo,FLOAT);
     } else if (strcmp(word,"zhi") == 0) {
       addfield("Zhi",&Thermo::compute_zhi,FLOAT);
 
     } else if (strcmp(word,"xy") == 0) {
       addfield("Xy",&Thermo::compute_xy,FLOAT);
     } else if (strcmp(word,"xz") == 0) {
       addfield("Xz",&Thermo::compute_xz,FLOAT);
     } else if (strcmp(word,"yz") == 0) {
       addfield("Yz",&Thermo::compute_yz,FLOAT);
 
     } else if (strcmp(word,"xlat") == 0) {
       if (domain->lattice == NULL)
         error->all(FLERR,"Thermo keyword requires lattice be defined");
       addfield("Xlat",&Thermo::compute_xlat,FLOAT);
     } else if (strcmp(word,"ylat") == 0) {
       if (domain->lattice == NULL)
         error->all(FLERR,"Thermo keyword requires lattice be defined");
       addfield("Ylat",&Thermo::compute_ylat,FLOAT);
     } else if (strcmp(word,"zlat") == 0) {
       if (domain->lattice == NULL)
         error->all(FLERR,"Thermo keyword requires lattice be defined");
       addfield("Zlat",&Thermo::compute_zlat,FLOAT);
 
     } else if (strcmp(word,"pxx") == 0) {
       addfield("Pxx",&Thermo::compute_pxx,FLOAT);
       index_press_vector = add_compute(id_press,VECTOR);
     } else if (strcmp(word,"pyy") == 0) {
       addfield("Pyy",&Thermo::compute_pyy,FLOAT);
       index_press_vector = add_compute(id_press,VECTOR);
     } else if (strcmp(word,"pzz") == 0) {
       addfield("Pzz",&Thermo::compute_pzz,FLOAT);
       index_press_vector = add_compute(id_press,VECTOR);
     } else if (strcmp(word,"pxy") == 0) {
       addfield("Pxy",&Thermo::compute_pxy,FLOAT);
       index_press_vector = add_compute(id_press,VECTOR);
     } else if (strcmp(word,"pxz") == 0) {
       addfield("Pxz",&Thermo::compute_pxz,FLOAT);
       index_press_vector = add_compute(id_press,VECTOR);
     } else if (strcmp(word,"pyz") == 0) {
       addfield("Pyz",&Thermo::compute_pyz,FLOAT);
       index_press_vector = add_compute(id_press,VECTOR);
 
     } else if (strcmp(word,"fmax") == 0) {
       addfield("Fmax",&Thermo::compute_fmax,FLOAT);
     } else if (strcmp(word,"fnorm") == 0) {
       addfield("Fnorm",&Thermo::compute_fnorm,FLOAT);
 
     } else if (strcmp(word,"cella") == 0) {
       addfield("Cella",&Thermo::compute_cella,FLOAT);
     } else if (strcmp(word,"cellb") == 0) {
       addfield("Cellb",&Thermo::compute_cellb,FLOAT);
     } else if (strcmp(word,"cellc") == 0) {
       addfield("Cellc",&Thermo::compute_cellc,FLOAT);
     } else if (strcmp(word,"cellalpha") == 0) {
       addfield("CellAlpha",&Thermo::compute_cellalpha,FLOAT);
     } else if (strcmp(word,"cellbeta") == 0) {
       addfield("CellBeta",&Thermo::compute_cellbeta,FLOAT);
     } else if (strcmp(word,"cellgamma") == 0) {
       addfield("CellGamma",&Thermo::compute_cellgamma,FLOAT);
 
     // compute value = c_ID, fix value = f_ID, variable value = v_ID
     // count trailing [] and store int arguments
     // copy = at most 8 chars of ID to pass to addfield
 
     } else if ((strncmp(word,"c_",2) == 0) || (strncmp(word,"f_",2) == 0) ||
                (strncmp(word,"v_",2) == 0)) {
 
       int n = strlen(word);
       char *id = new char[n];
       strcpy(id,&word[2]);
       char copy[9];
       strncpy(copy,id,8);
       copy[8] = '\0';
 
       // parse zero or one or two trailing brackets from ID
       // argindex1,argindex2 = int inside each bracket pair, 0 if no bracket
 
       char *ptr = strchr(id,'[');
       if (ptr == NULL) argindex1[nfield] = 0;
       else {
         *ptr = '\0';
         argindex1[nfield] = input->variable->int_between_brackets(ptr);
         ptr++;
         if (*ptr == '[') {
           argindex2[nfield] = input->variable->int_between_brackets(ptr);
           ptr++;
         } else argindex2[nfield] = 0;
       }
 
       if (word[0] == 'c') {
         n = modify->find_compute(id);
         if (n < 0) error->all(FLERR,"Could not find thermo custom compute ID");
         if (argindex1[nfield] == 0 && modify->compute[n]->scalar_flag == 0)
           error->all(FLERR,"Thermo compute does not compute scalar");
         if (argindex1[nfield] > 0 && argindex2[nfield] == 0) {
           if (modify->compute[n]->vector_flag == 0)
             error->all(FLERR,"Thermo compute does not compute vector");
           if (argindex1[nfield] > modify->compute[n]->size_vector)
             error->all(FLERR,"Thermo compute vector is accessed out-of-range");
         }
         if (argindex1[nfield] > 0 && argindex2[nfield] > 0) {
           if (modify->compute[n]->array_flag == 0)
             error->all(FLERR,"Thermo compute does not compute array");
           if (argindex1[nfield] > modify->compute[n]->size_array_rows ||
               argindex2[nfield] > modify->compute[n]->size_array_cols)
             error->all(FLERR,"Thermo compute array is accessed out-of-range");
         }
 
         if (argindex1[nfield] == 0)
           field2index[nfield] = add_compute(id,SCALAR);
         else if (argindex2[nfield] == 0)
           field2index[nfield] = add_compute(id,VECTOR);
         else
           field2index[nfield] = add_compute(id,ARRAY);
         addfield(copy,&Thermo::compute_compute,FLOAT);
 
       } else if (word[0] == 'f') {
         n = modify->find_fix(id);
         if (n < 0) error->all(FLERR,"Could not find thermo custom fix ID");
         if (argindex1[nfield] == 0 && modify->fix[n]->scalar_flag == 0)
           error->all(FLERR,"Thermo fix does not compute scalar");
         if (argindex1[nfield] > 0 && argindex2[nfield] == 0) {
           if (modify->fix[n]->vector_flag == 0)
             error->all(FLERR,"Thermo fix does not compute vector");
           if (argindex1[nfield] > modify->fix[n]->size_vector)
             error->all(FLERR,"Thermo fix vector is accessed out-of-range");
         }
         if (argindex1[nfield] > 0 && argindex2[nfield] > 0) {
           if (modify->fix[n]->array_flag == 0)
             error->all(FLERR,"Thermo fix does not compute array");
           if (argindex1[nfield] > modify->fix[n]->size_array_rows ||
               argindex2[nfield] > modify->fix[n]->size_array_cols)
             error->all(FLERR,"Thermo fix array is accessed out-of-range");
         }
 
         field2index[nfield] = add_fix(id);
         addfield(copy,&Thermo::compute_fix,FLOAT);
 
       } else if (word[0] == 'v') {
         n = input->variable->find(id);
         if (n < 0) 
           error->all(FLERR,"Could not find thermo custom variable name");
         if (input->variable->equalstyle(n) == 0)
           error->all(FLERR,
                      "Thermo custom variable is not equal-style variable");
         if (argindex1[nfield])
           error->all(FLERR,"Thermo custom variable cannot be indexed");
 
         field2index[nfield] = add_variable(id);
         addfield(copy,&Thermo::compute_variable,FLOAT);
       }
 
       delete [] id;
 
     } else error->all(FLERR,"Invalid keyword in thermo_style custom command");
 
     word = strtok(NULL," \0");
   }
 }
 
 /* ----------------------------------------------------------------------
    add field to list of quantities to print
 ------------------------------------------------------------------------- */
 
 void Thermo::addfield(const char *key, FnPtr func, int typeflag)
 {
   strcpy(keyword[nfield],key);
   vfunc[nfield] = func;
   vtype[nfield] = typeflag;
   nfield++;
 }
 
 /* ----------------------------------------------------------------------
    add compute ID to list of Compute objects to call
    return location of where this Compute is in list
    if already in list with same which, do not add, just return index
 ------------------------------------------------------------------------- */
 
 int Thermo::add_compute(const char *id, int which)
 {
   int icompute;
   for (icompute = 0; icompute < ncompute; icompute++)
     if ((strcmp(id,id_compute[icompute]) == 0) &&
         which == compute_which[icompute]) break;
   if (icompute < ncompute) return icompute;
 
   int n = strlen(id) + 1;
   id_compute[ncompute] = new char[n];
   strcpy(id_compute[ncompute],id);
   compute_which[ncompute] = which;
   ncompute++;
   return ncompute-1;
 }
 
 /* ----------------------------------------------------------------------
    add fix ID to list of Fix objects to call
 ------------------------------------------------------------------------- */
 
 int Thermo::add_fix(const char *id)
 {
   int n = strlen(id) + 1;
   id_fix[nfix] = new char[n];
   strcpy(id_fix[nfix],id);
   nfix++;
   return nfix-1;
 }
 
 /* ----------------------------------------------------------------------
    add variable ID to list of Variables to evaluate
 ------------------------------------------------------------------------- */
 
 int Thermo::add_variable(const char *id)
 {
   int n = strlen(id) + 1;
   id_variable[nvariable] = new char[n];
   strcpy(id_variable[nvariable],id);
   nvariable++;
   return nvariable-1;
 }
 
 /* ----------------------------------------------------------------------
    compute a single thermodyanmic value, word is any keyword in custom list
    called when a variable is evaluated by Variable class
    return value as double in answer
    return 0 if str is recoginzed keyword, 1 if unrecognized
    customize a new keyword by adding to if statement
 ------------------------------------------------------------------------- */
 
 int Thermo::evaluate_keyword(char *word, double *answer)
 {
   // turn off normflag if natoms = 0 to avoid divide by 0
   // normflag must be set for lo-level thermo routines that may be invoked
 
   natoms = atom->natoms;
   if (natoms == 0) normflag = 0;
   else normflag = normvalue;
 
   // invoke a lo-level thermo routine to compute the variable value
   // if keyword requires a compute, error if thermo doesn't use the compute
   // if inbetween runs and needed compute is not current, error
   // if in middle of run and needed compute is not current, invoke it
   // for keywords that use pe indirectly (evdwl, ebond, etc):
   //   check if energy was tallied on this timestep and set pe->invoked_flag
   //   this will trigger next timestep for energy tallying via addstep()
 
   if (strcmp(word,"step") == 0) {
     compute_step();
     dvalue = bivalue;
 
   } else if (strcmp(word,"elapsed") == 0) {
     if (update->whichflag == 0)
       error->all(FLERR,
                  "This variable thermo keyword cannot be used between runs");
     compute_elapsed();
     dvalue = bivalue;
 
   } else if (strcmp(word,"elaplong") == 0) {
     if (update->whichflag == 0)
       error->all(FLERR,
                  "This variable thermo keyword cannot be used between runs");
     compute_elapsed_long();
     dvalue = bivalue;
 
   } else if (strcmp(word,"dt") == 0) {
     compute_dt();
 
+  } else if (strcmp(word,"time") == 0) {
+    compute_time();
+
   } else if (strcmp(word,"cpu") == 0) {
     if (update->whichflag == 0)
       error->all(FLERR,
                  "This variable thermo keyword cannot be used between runs");
     compute_cpu();
 
   } else if (strcmp(word,"tpcpu") == 0) {
     if (update->whichflag == 0)
       error->all(FLERR,
                  "This variable thermo keyword cannot be used between runs");
     compute_tpcpu();
 
   } else if (strcmp(word,"spcpu") == 0) {
     if (update->whichflag == 0)
       error->all(FLERR,
                  "This variable thermo keyword cannot be used between runs");
     compute_spcpu();
 
   } else if (strcmp(word,"atoms") == 0) {
     compute_atoms();
     dvalue = bivalue;
 
   } else if (strcmp(word,"temp") == 0) {
     if (!temperature)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init temp");
     if (update->whichflag == 0) {
       if (temperature->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
       temperature->compute_scalar();
       temperature->invoked_flag |= INVOKED_SCALAR;
     }
     compute_temp();
 
   } else if (strcmp(word,"press") == 0) {
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_SCALAR)) {
       pressure->compute_scalar();
       pressure->invoked_flag |= INVOKED_SCALAR;
     }
     compute_press();
 
   } else if (strcmp(word,"pe") == 0) {
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     if (update->whichflag == 0) {
       if (pe->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pe->invoked_flag & INVOKED_SCALAR)) {
       pe->compute_scalar();
       pe->invoked_flag |= INVOKED_SCALAR;
     }
     compute_pe();
 
   } else if (strcmp(word,"ke") == 0) {
     if (!temperature)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init temp");
     if (update->whichflag == 0) {
       if (temperature->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
       temperature->compute_scalar();
       temperature->invoked_flag |= INVOKED_SCALAR;
     }
     compute_ke();
 
   } else if (strcmp(word,"etotal") == 0) {
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     if (update->whichflag == 0) {
       if (pe->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pe->invoked_flag & INVOKED_SCALAR)) {
       pe->compute_scalar();
       pe->invoked_flag |= INVOKED_SCALAR;
     }
     if (!temperature)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init temp");
     if (update->whichflag == 0) {
       if (temperature->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
       temperature->compute_scalar();
       temperature->invoked_flag |= INVOKED_SCALAR;
     }
     compute_etotal();
 
   } else if (strcmp(word,"enthalpy") == 0) {
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     if (update->whichflag == 0) {
       if (pe->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pe->invoked_flag & INVOKED_SCALAR)) {
       pe->compute_scalar();
       pe->invoked_flag |= INVOKED_SCALAR;
     }
     if (!temperature)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init temp");
     if (update->whichflag == 0) {
       if (temperature->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(temperature->invoked_flag & INVOKED_SCALAR)) {
       temperature->compute_scalar();
       temperature->invoked_flag |= INVOKED_SCALAR;
     }
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_scalar != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_SCALAR)) {
       pressure->compute_scalar();
       pressure->invoked_flag |= INVOKED_SCALAR;
     }
     compute_enthalpy();
 
   } else if (strcmp(word,"evdwl") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_evdwl();
 
   } else if (strcmp(word,"ecoul") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_ecoul();
 
   } else if (strcmp(word,"epair") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_epair();
 
   } else if (strcmp(word,"ebond") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_ebond();
 
   } else if (strcmp(word,"eangle") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_eangle();
 
   } else if (strcmp(word,"edihed") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_edihed();
 
   } else if (strcmp(word,"eimp") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_eimp();
 
   } else if (strcmp(word,"emol") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_emol();
 
   } else if (strcmp(word,"elong") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_elong();
 
   } else if (strcmp(word,"etail") == 0) {
     if (update->eflag_global != update->ntimestep)
       error->all(FLERR,"Energy was not tallied on needed timestep");
     if (!pe)
       error->all(FLERR,
                  "Thermo keyword in variable requires thermo to use/init pe");
     pe->invoked_flag |= INVOKED_SCALAR;
     compute_etail();
 
   } else if (strcmp(word,"vol") == 0) compute_vol();
   else if (strcmp(word,"lx") == 0) compute_lx();
   else if (strcmp(word,"ly") == 0) compute_ly();
   else if (strcmp(word,"lz") == 0) compute_lz();
 
   else if (strcmp(word,"xlo") == 0) compute_xlo();
   else if (strcmp(word,"xhi") == 0) compute_xhi();
   else if (strcmp(word,"ylo") == 0) compute_ylo();
   else if (strcmp(word,"yhi") == 0) compute_yhi();
   else if (strcmp(word,"zlo") == 0) compute_zlo();
   else if (strcmp(word,"zhi") == 0) compute_zhi();
 
   else if (strcmp(word,"xy") == 0) compute_xy();
   else if (strcmp(word,"xz") == 0) compute_xz();
   else if (strcmp(word,"yz") == 0) compute_yz();
 
   else if (strcmp(word,"xlat") == 0) {
     if (domain->lattice == NULL)
       error->all(FLERR,"Thermo keyword in variable requires lattice be defined");
     compute_xlat();
   } else if (strcmp(word,"ylat") == 0) {
     if (domain->lattice == NULL)
       error->all(FLERR,"Thermo keyword in variable requires lattice be defined");
     compute_ylat();
   } else if (strcmp(word,"zlat") == 0) {
     if (domain->lattice == NULL)
       error->all(FLERR,"Thermo keyword in variable requires lattice be defined");
     compute_zlat();
 
   } else if (strcmp(word,"pxx") == 0) {
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_vector != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
       pressure->compute_vector();
       pressure->invoked_flag |= INVOKED_VECTOR;
     }
     compute_pxx();
 
   } else if (strcmp(word,"pyy") == 0) {
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_vector != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
       pressure->compute_vector();
       pressure->invoked_flag |= INVOKED_VECTOR;
     }
     compute_pyy();
 
   } else if (strcmp(word,"pzz") == 0) {
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_vector != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
       pressure->compute_vector();
       pressure->invoked_flag |= INVOKED_VECTOR;
     }
     compute_pzz();
 
   } else if (strcmp(word,"pxy") == 0) {
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_vector != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
       pressure->compute_vector();
       pressure->invoked_flag |= INVOKED_VECTOR;
     }
     compute_pxy();
 
   } else if (strcmp(word,"pxz") == 0) {
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_vector != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
       pressure->compute_vector();
       pressure->invoked_flag |= INVOKED_VECTOR;
     }
     compute_pxz();
 
   } else if (strcmp(word,"pyz") == 0) {
     if (!pressure)
       error->all(FLERR,"Thermo keyword in variable requires "
                  "thermo to use/init press");
     if (update->whichflag == 0) {
       if (pressure->invoked_vector != update->ntimestep)
         error->all(FLERR,"Compute used in variable thermo keyword between runs "
                    "is not current");
     } else if (!(pressure->invoked_flag & INVOKED_VECTOR)) {
       pressure->compute_vector();
       pressure->invoked_flag |= INVOKED_VECTOR;
     }
     compute_pyz();
 
   } else if (strcmp(word,"fmax") == 0) compute_fmax();
   else if (strcmp(word,"fnorm") == 0) compute_fnorm();
 
   else if (strcmp(word,"cella") == 0) compute_cella();
   else if (strcmp(word,"cellb") == 0) compute_cellb();
   else if (strcmp(word,"cellc") == 0) compute_cellc();
   else if (strcmp(word,"cellalpha") == 0) compute_cellalpha();
   else if (strcmp(word,"cellbeta") == 0) compute_cellbeta();
   else if (strcmp(word,"cellgamma") == 0) compute_cellgamma();
 
   else return 1;
 
   *answer = dvalue;
   return 0;
 }
 
 /* ----------------------------------------------------------------------
    extraction of Compute, Fix, Variable results
    compute/fix are normalized by atoms if returning extensive value
    variable value is not normalized (formula should normalize if desired)
 ------------------------------------------------------------------------- */
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_compute()
 {
   int m = field2index[ifield];
   Compute *compute = computes[m];
 
   if (compute_which[m] == SCALAR) {
     dvalue = compute->scalar;
     if (normflag && compute->extscalar) dvalue /= natoms;
   } else if (compute_which[m] == VECTOR) {
     dvalue = compute->vector[argindex1[ifield]-1];
     if (normflag) {
       if (compute->extvector == 0) return;
       else if (compute->extvector == 1) dvalue /= natoms;
       else if (compute->extlist[argindex1[ifield]-1]) dvalue /= natoms;
     }
   } else {
     dvalue = compute->array[argindex1[ifield]-1][argindex2[ifield]-1];
     if (normflag && compute->extarray) dvalue /= natoms;
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_fix()
 {
   int m = field2index[ifield];
   Fix *fix = fixes[m];
 
   if (argindex1[ifield] == 0) {
     dvalue = fix->compute_scalar();
     if (normflag && fix->extscalar) dvalue /= natoms;
   } else if (argindex2[ifield] == 0) {
     dvalue = fix->compute_vector(argindex1[ifield]-1);
     if (normflag) {
       if (fix->extvector == 0) return;
       else if (fix->extvector == 1) dvalue /= natoms;
       else if (fix->extlist[argindex1[ifield]-1]) dvalue /= natoms;
     }
   } else {
     dvalue = fix->compute_array(argindex1[ifield]-1,argindex2[ifield]-1);
     if (normflag && fix->extarray) dvalue /= natoms;
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_variable()
 {
   dvalue = input->variable->compute_equal(variables[field2index[ifield]]);
 }
 
 /* ----------------------------------------------------------------------
    one method for every keyword thermo can output
    called by compute() or evaluate_keyword()
    compute will have already been called
    set ivalue/dvalue/bivalue if value is int/double/bigint
    customize a new keyword by adding a method
 ------------------------------------------------------------------------- */
 
 void Thermo::compute_step()
 {
   bivalue = update->ntimestep;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_elapsed()
 {
   bivalue = update->ntimestep - update->firststep;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_elapsed_long()
 {
   bivalue = update->ntimestep - update->beginstep;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_dt()
 {
   dvalue = update->dt;
 }
 
 /* ---------------------------------------------------------------------- */
 
+void Thermo::compute_time()
+{
+  dvalue = update->atime + (update->ntimestep-update->atimestep)*update->dt;
+}
+
+/* ---------------------------------------------------------------------- */
+
 void Thermo::compute_cpu()
 {
   if (firststep == 0) dvalue = 0.0;
   else dvalue = timer->elapsed(Timer::LOOP);
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_tpcpu()
 {
   double new_cpu;
   double new_time = update->ntimestep * update->dt;
 
   if (firststep == 0) {
     new_cpu = 0.0;
     dvalue = 0.0;
   } else {
     new_cpu = timer->elapsed(Timer::LOOP);
     double cpu_diff = new_cpu - last_tpcpu;
     double time_diff = new_time - last_time;
     if (time_diff > 0.0 && cpu_diff > 0.0) dvalue = time_diff/cpu_diff;
     else dvalue = 0.0;
   }
 
   last_time = new_time;
   last_tpcpu = new_cpu;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_spcpu()
 {
   double new_cpu;
   int new_step = update->ntimestep;
 
   if (firststep == 0) {
     new_cpu = 0.0;
     dvalue = 0.0;
   } else {
     new_cpu = timer->elapsed(Timer::LOOP);
     double cpu_diff = new_cpu - last_spcpu;
     int step_diff = new_step - last_step;
     if (cpu_diff > 0.0) dvalue = step_diff/cpu_diff;
     else dvalue = 0.0;
   }
 
   last_step = new_step;
   last_spcpu = new_cpu;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_atoms()
 {
   bivalue = atom->natoms;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_temp()
 {
   dvalue = temperature->scalar;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_press()
 {
   dvalue = pressure->scalar;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_pe()
 {
   dvalue = pe->scalar;
   if (normflag) dvalue /= natoms;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_ke()
 {
   dvalue = temperature->scalar;
   dvalue *= 0.5 * temperature->dof * force->boltz;
   if (normflag) dvalue /= natoms;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_etotal()
 {
   compute_pe();
   double ke = temperature->scalar;
   ke *= 0.5 * temperature->dof * force->boltz;
   if (normflag) ke /= natoms;
   dvalue += ke;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_enthalpy()
 {
   compute_etotal();
   double etmp = dvalue;
 
   compute_vol();
   double vtmp = dvalue;
   if (normflag) vtmp /= natoms;
 
   compute_press();
   double ptmp = dvalue;
 
   dvalue = etmp + ptmp*vtmp/(force->nktv2p);
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_evdwl()
 {
   double tmp = 0.0;
   if (force->pair) tmp += force->pair->eng_vdwl;
   MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
 
   if (force->pair && force->pair->tail_flag) {
     double volume = domain->xprd * domain->yprd * domain->zprd;
     dvalue += force->pair->etail / volume;
   }
 
   if (normflag) dvalue /= natoms;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_ecoul()
 {
   double tmp = 0.0;
   if (force->pair) tmp += force->pair->eng_coul;
   MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
   if (normflag) dvalue /= natoms;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_epair()
 {
   double tmp = 0.0;
   if (force->pair) tmp += force->pair->eng_vdwl + force->pair->eng_coul;
   MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
 
   if (force->kspace) dvalue += force->kspace->energy;
   if (force->pair && force->pair->tail_flag) {
     double volume = domain->xprd * domain->yprd * domain->zprd;
     dvalue += force->pair->etail / volume;
   }
 
   if (normflag) dvalue /= natoms;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_ebond()
 {
   if (force->bond) {
     double tmp = force->bond->energy;
     MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
     if (normflag) dvalue /= natoms;
   } else dvalue = 0.0;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_eangle()
 {
   if (force->angle) {
     double tmp = force->angle->energy;
     MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
     if (normflag) dvalue /= natoms;
   } else dvalue = 0.0;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_edihed()
 {
   if (force->dihedral) {
     double tmp = force->dihedral->energy;
     MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
     if (normflag) dvalue /= natoms;
   } else dvalue = 0.0;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_eimp()
 {
   if (force->improper) {
     double tmp = force->improper->energy;
     MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
     if (normflag) dvalue /= natoms;
   } else dvalue = 0.0;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_emol()
 {
   double tmp = 0.0;
   if (atom->molecular) {
     if (force->bond) tmp += force->bond->energy;
     if (force->angle) tmp += force->angle->energy;
     if (force->dihedral) tmp += force->dihedral->energy;
     if (force->improper) tmp += force->improper->energy;
     MPI_Allreduce(&tmp,&dvalue,1,MPI_DOUBLE,MPI_SUM,world);
     if (normflag) dvalue /= natoms;
   } else dvalue = 0.0;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_elong()
 {
   if (force->kspace) {
     dvalue = force->kspace->energy;
     if (normflag) dvalue /= natoms;
   } else dvalue = 0.0;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_etail()
 {
   if (force->pair && force->pair->tail_flag) {
     double volume = domain->xprd * domain->yprd * domain->zprd;
     dvalue = force->pair->etail / volume;
     if (normflag) dvalue /= natoms;
   } else dvalue = 0.0;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_vol()
 {
   if (domain->dimension == 3)
     dvalue = domain->xprd * domain->yprd * domain->zprd;
   else
     dvalue = domain->xprd * domain->yprd;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_lx()
 {
   dvalue = domain->xprd;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_ly()
 {
   dvalue = domain->yprd;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_lz()
 {
   dvalue = domain->zprd;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_xlo()
 {
   dvalue = domain->boxlo[0];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_xhi()
 {
   dvalue = domain->boxhi[0];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_ylo()
 {
   dvalue = domain->boxlo[1];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_yhi()
 {
   dvalue = domain->boxhi[1];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_zlo()
 {
   dvalue = domain->boxlo[2];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_zhi()
 {
   dvalue = domain->boxhi[2];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_xy()
 {
   dvalue = domain->xy;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_xz()
 {
   dvalue = domain->xz;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_yz()
 {
   dvalue = domain->yz;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_xlat()
 {
   dvalue = domain->lattice->xlattice;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_ylat()
 {
   dvalue = domain->lattice->ylattice;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_zlat()
 {
   dvalue = domain->lattice->zlattice;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_pxx()
 {
   dvalue = pressure->vector[0];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_pyy()
 {
   dvalue = pressure->vector[1];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_pzz()
 {
   dvalue = pressure->vector[2];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_pxy()
 {
   dvalue = pressure->vector[3];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_pxz()
 {
   dvalue = pressure->vector[4];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_pyz()
 {
   dvalue = pressure->vector[5];
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_fmax()
 {
   double **f = atom->f;
   int nlocal = atom->nlocal;
 
   double max = 0.0;
   for (int i = 0; i < nlocal; i++) {
     max = MAX(max,fabs(f[i][0]));
     max = MAX(max,fabs(f[i][1]));
     max = MAX(max,fabs(f[i][2]));
   }
   double maxall;
   MPI_Allreduce(&max,&maxall,1,MPI_DOUBLE,MPI_MAX,world);
   dvalue = maxall;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_fnorm()
 {
   double **f = atom->f;
   int nlocal = atom->nlocal;
 
   double dot = 0.0;
   for (int i = 0; i < nlocal; i++)
     dot += f[i][0]*f[i][0] + f[i][1]*f[i][1] + f[i][2]*f[i][2];
   double dotall;
   MPI_Allreduce(&dot,&dotall,1,MPI_DOUBLE,MPI_SUM,world);
   dvalue = sqrt(dotall);
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_cella()
 {
   dvalue = domain->xprd;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_cellb()
 {
   if (!domain->triclinic)
     dvalue = domain->yprd;
   else {
     double* h = domain->h;
     dvalue = sqrt(h[1]*h[1]+h[5]*h[5]);
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_cellc()
 {
   if (!domain->triclinic)
     dvalue = domain->zprd;
   else {
     double* h = domain->h;
     dvalue = sqrt(h[2]*h[2]+h[3]*h[3]+h[4]*h[4]);
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_cellalpha()
 {
   if (!domain->triclinic)
     dvalue = 90.0;
   else {
 
     // Cos(alpha) = (xy.xz + ly.yz)/(b.c)
 
     double* h = domain->h;
     double cosalpha = (h[5]*h[4]+h[1]*h[3])/
       sqrt((h[1]*h[1]+h[5]*h[5])*(h[2]*h[2]+h[3]*h[3]+h[4]*h[4]));
     dvalue = acos(cosalpha)*180.0/MY_PI;
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_cellbeta()
 {
   if (!domain->triclinic)
     dvalue = 90.0;
   else {
 
     // Cos(beta) = xz/c
 
     double* h = domain->h;
     double cosbeta = h[4]/sqrt(h[2]*h[2]+h[3]*h[3]+h[4]*h[4]);
     dvalue = acos(cosbeta)*180.0/MY_PI;
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Thermo::compute_cellgamma()
 {
   if (!domain->triclinic)
     dvalue = 90.0;
   else {
 
     // Cos(gamma) = xy/b
 
     double* h = domain->h;
     double cosgamma = h[5]/sqrt(h[1]*h[1]+h[5]*h[5]);
     dvalue = acos(cosgamma)*180.0/MY_PI;
   }
 }
diff --git a/src/thermo.h b/src/thermo.h
index 173e7239d..e0a10ea0d 100644
--- a/src/thermo.h
+++ b/src/thermo.h
@@ -1,392 +1,393 @@
 /* -*- c++ -*- ----------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #ifndef LMP_THERMO_H
 #define LMP_THERMO_H
 
 #include "pointers.h"
 
 namespace LAMMPS_NS {
 
 class Thermo : protected Pointers {
   friend class WriteRestart;           // accesses lostflag
   friend class WriteData;              // accesses lostflag
   friend class MinCG;                  // accesses compute_pe
 
  public:
   char *style;
   int normflag;          // 0 if do not normalize by atoms, 1 if normalize
   int modified;          // 1 if thermo_modify has been used, else 0
   int cudable;           // 1 if all computes used are cudable
 
   Thermo(class LAMMPS *, int, char **);
   ~Thermo();
   void init();
   bigint lost_check();
   void modify_params(int, char **);
   void header();
   void compute(int);
   int evaluate_keyword(char *, double *);
 
  private:
   char *line;
   char **keyword;
   int *vtype;
 
   int nfield,nfield_initial;
   int me;
 
   char **format,**format_user;
   char *format_float_one_def,*format_float_multi_def;
   char *format_int_one_def,*format_int_multi_def;
   char *format_float_user,*format_int_user,*format_bigint_user;
   char format_multi[128];
   char format_bigint_one_def[8],format_bigint_multi_def[8];
 
   int normvalue;         // use this for normflag unless natoms = 0
   int normuserflag;      // 0 if user has not set, 1 if has
   int normuser;
 
   int firststep;
   int lostflag,lostbefore;
   int flushflag,lineflag;
 
   double last_tpcpu,last_spcpu;
   double last_time;
   bigint last_step;
 
   bigint natoms;
 
                          // data used by routines that compute single values
   int ivalue;            // integer value to print
   double dvalue;         // double value to print
   bigint bivalue;        // big integer value to print
   int ifield;            // which field in thermo output is being computed
   int *field2index;      // which compute,fix,variable calcs this field
   int *argindex1;        // indices into compute,fix scalar,vector
   int *argindex2;
 
                          // data for keyword-specific Compute objects
                          // index = where they are in computes list
                          // id = ID of Compute objects
                          // Compute * = ptrs to the Compute objects
   int index_temp,index_press_scalar,index_press_vector,index_pe;
   char *id_temp,*id_press,*id_pe;
   class Compute *temperature,*pressure,*pe;
 
   int ncompute;                // # of Compute objects called by thermo
   char **id_compute;           // their IDs
   int *compute_which;          // 0/1/2 if should call scalar,vector,array
   class Compute **computes;    // list of ptrs to the Compute objects
 
   int nfix;                    // # of Fix objects called by thermo
   char **id_fix;               // their IDs
   class Fix **fixes;           // list of ptrs to the Fix objects
 
   int nvariable;               // # of variables evaulated by thermo
   char **id_variable;          // list of variable names
   int *variables;              // list of Variable indices
 
   // private methods
 
   void allocate();
   void deallocate();
 
   void parse_fields(char *);
   int add_compute(const char *, int);
   int add_fix(const char *);
   int add_variable(const char *);
 
   typedef void (Thermo::*FnPtr)();
   void addfield(const char *, FnPtr, int);
   FnPtr *vfunc;                // list of ptrs to functions
 
   void compute_compute();      // functions that compute a single value
   void compute_fix();          // via calls to  Compute,Fix,Variable classes
   void compute_variable();
 
   // functions that compute a single value
   // customize a new keyword by adding a method prototype
 
   void compute_step();
   void compute_elapsed();
   void compute_elapsed_long();
   void compute_dt();
+  void compute_time();
   void compute_cpu();
   void compute_tpcpu();
   void compute_spcpu();
 
   void compute_atoms();
   void compute_temp();
   void compute_press();
   void compute_pe();
   void compute_ke();
   void compute_etotal();
   void compute_enthalpy();
 
   void compute_evdwl();
   void compute_ecoul();
   void compute_epair();
   void compute_ebond();
   void compute_eangle();
   void compute_edihed();
   void compute_eimp();
   void compute_emol();
   void compute_elong();
   void compute_etail();
 
   void compute_vol();
   void compute_lx();
   void compute_ly();
   void compute_lz();
 
   void compute_xlo();
   void compute_xhi();
   void compute_ylo();
   void compute_yhi();
   void compute_zlo();
   void compute_zhi();
 
   void compute_xy();
   void compute_xz();
   void compute_yz();
 
   void compute_xlat();
   void compute_ylat();
   void compute_zlat();
 
   void compute_pxx();
   void compute_pyy();
   void compute_pzz();
   void compute_pxy();
   void compute_pyz();
   void compute_pxz();
 
   void compute_fmax();
   void compute_fnorm();
 
   void compute_cella();
   void compute_cellb();
   void compute_cellc();
   void compute_cellalpha();
   void compute_cellbeta();
   void compute_cellgamma();
 };
 
 }
 
 #endif
 
 /* ERROR/WARNING messages:
 
 E: Illegal ... command
 
 Self-explanatory.  Check the input script syntax and compare to the
 documentation for the command.  You can use -echo screen as a
 command-line option when running LAMMPS to see the offending line.
 
 E: Could not find thermo compute ID
 
 Compute ID specified in thermo_style command does not exist.
 
 E: Could not find thermo fix ID
 
 Fix ID specified in thermo_style command does not exist.
 
 E: Thermo and fix not computed at compatible times
 
 Fixes generate values on specific timesteps.  The thermo output
 does not match these timesteps.
 
 E: Could not find thermo variable name
 
 Self-explanatory.
 
 E: Too many total atoms
 
 See the setting for bigint in the src/lmptype.h file.
 
 E: Lost atoms: original %ld current %ld
 
 Lost atoms are checked for each time thermo output is done.  See the
 thermo_modify lost command for options.  Lost atoms usually indicate
 bad dynamics, e.g. atoms have been blown far out of the simulation
 box, or moved futher than one processor's sub-domain away before
 reneighboring.
 
 W: Lost atoms: original %ld current %ld
 
 Lost atoms are checked for each time thermo output is done.  See the
 thermo_modify lost command for options.  Lost atoms usually indicate
 bad dynamics, e.g. atoms have been blown far out of the simulation
 box, or moved futher than one processor's sub-domain away before
 reneighboring.
 
 E: Thermo style does not use temp
 
 Cannot use thermo_modify to set this parameter since the thermo_style
 is not computing this quantity.
 
 E: Could not find thermo_modify temperature ID
 
 The compute ID needed by thermo style custom to compute temperature does
 not exist.
 
 E: Thermo_modify temperature ID does not compute temperature
 
 The specified compute ID does not compute temperature.
 
 W: Temperature for thermo pressure is not for group all
 
 User-assigned temperature to thermo via the thermo_modify command does
 not compute temperature for all atoms.  Since thermo computes a global
 pressure, the kinetic energy contribution from the temperature is
 assumed to also be for all atoms.  Thus the pressure printed by thermo
 could be inaccurate.
 
 E: Pressure ID for thermo does not exist
 
 The compute ID needed to compute pressure for thermodynamics does not
 exist.
 
 E: Thermo style does not use press
 
 Cannot use thermo_modify to set this parameter since the thermo_style
 is not computing this quantity.
 
 E: Could not find thermo_modify pressure ID
 
 The compute ID needed by thermo style custom to compute pressure does
 not exist.
 
 E: Thermo_modify pressure ID does not compute pressure
 
 The specified compute ID does not compute pressure.
 
 E: Thermo_modify int format does not contain d character
 
 Self-explanatory.
 
 E: Thermo keyword requires lattice be defined
 
 The xlat, ylat, zlat keywords refer to lattice properties.
 
 E: Could not find thermo custom compute ID
 
 The compute ID needed by thermo style custom to compute a requested
 quantity does not exist.
 
 E: Thermo compute does not compute scalar
 
 Self-explanatory.
 
 E: Thermo compute does not compute vector
 
 Self-explanatory.
 
 E: Thermo compute vector is accessed out-of-range
 
 Self-explanatory.
 
 E: Thermo compute does not compute array
 
 Self-explanatory.
 
 E: Thermo compute array is accessed out-of-range
 
 Self-explanatory.
 
 E: Could not find thermo custom fix ID
 
 The fix ID needed by thermo style custom to compute a requested
 quantity does not exist.
 
 E: Thermo fix does not compute scalar
 
 Self-explanatory.
 
 E: Thermo fix does not compute vector
 
 Self-explanatory.
 
 E: Thermo fix vector is accessed out-of-range
 
 Self-explanatory.
 
 E: Thermo fix does not compute array
 
 Self-explanatory.
 
 E: Thermo fix array is accessed out-of-range
 
 Self-explanatory.
 
 E: Could not find thermo custom variable name
 
 Self-explanatory.
 
 E: Thermo custom variable is not equal-style variable
 
 Only equal-style variables can be output with thermodynamics, not
 atom-style variables.
 
 E: Thermo custom variable cannot be indexed
 
 Self-explanatory.
 
 E: Invalid keyword in thermo_style custom command
 
 One or more specified keywords are not recognized.
 
 E: This variable thermo keyword cannot be used between runs
 
 Keywords that refer to time (such as cpu, elapsed) do not
 make sense in between runs.
 
 E: Thermo keyword in variable requires thermo to use/init temp
 
 You are using a thermo keyword in a variable that requires temperature
 to be calculated, but your thermo output does not use it.  Add it to
 your thermo output.
 
 E: Compute used in variable thermo keyword between runs is not current
 
 Some thermo keywords rely on a compute to calculate their value(s).
 Computes cannot be invoked by a variable in between runs.  Thus they
 must have been evaluated on the last timestep of the previous run in
 order for their value(s) to be accessed.  See the doc page for the
 variable command for more info.
 
 E: Thermo keyword in variable requires thermo to use/init press
 
 You are using a thermo keyword in a variable that requires pressure to
 be calculated, but your thermo output does not use it.  Add it to your
 thermo output.
 
 E: Thermo keyword in variable requires thermo to use/init pe
 
 You are using a thermo keyword in a variable that requires
 potential energy to be calculated, but your thermo output
 does not use it.  Add it to your thermo output.
 
 E: Energy was not tallied on needed timestep
 
 You are using a thermo keyword that requires potentials to
 have tallied energy, but they didn't on this timestep.  See the
 variable doc page for ideas on how to make this work.
 
 E: Thermo keyword in variable requires lattice be defined
 
 The xlat, ylat, zlat keywords refer to lattice properties.
 
 */
diff --git a/src/update.cpp b/src/update.cpp
index b502822c8..ad5884293 100644
--- a/src/update.cpp
+++ b/src/update.cpp
@@ -1,413 +1,429 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #include "string.h"
 #include "stdlib.h"
 #include "update.h"
 #include "integrate.h"
 #include "min.h"
 #include "style_integrate.h"
 #include "style_minimize.h"
 #include "neighbor.h"
 #include "force.h"
 #include "modify.h"
 #include "fix.h"
 #include "domain.h"
 #include "region.h"
 #include "compute.h"
 #include "output.h"
 #include "memory.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
 
 /* ---------------------------------------------------------------------- */
 
 Update::Update(LAMMPS *lmp) : Pointers(lmp)
 {
   char *str;
 
   ntimestep = 0;
+  atime = 0.0;
+  atimestep = 0;
   first_update = 0;
 
   whichflag = 0;
   firststep = laststep = 0;
   beginstep = endstep = 0;
   setupflag = 0;
   multireplica = 0;
 
   restrict_output = 0;
 
   eflag_global = vflag_global = -1;
 
   unit_style = NULL;
   set_units("lj");
 
   integrate_style = NULL;
   integrate = NULL;
   minimize_style = NULL;
   minimize = NULL;
 
   if (lmp->cuda) {
     str = (char *) "verlet/cuda";
     create_integrate(1,&str,NULL);
   } else {
     str = (char *) "verlet";
     create_integrate(1,&str,NULL);
   }
 
   str = (char *) "cg";
   create_minimize(1,&str);
 }
 
 /* ---------------------------------------------------------------------- */
 
 Update::~Update()
 {
   delete [] unit_style;
 
   delete [] integrate_style;
   delete integrate;
 
   delete [] minimize_style;
   delete minimize;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Update::init()
 {
   // if USER-CUDA mode is enabled:
   // integrate/minimize style must be CUDA variant
 
   if (whichflag == 1 && lmp->cuda)
     if (strstr(integrate_style,"cuda") == NULL)
       error->all(FLERR,"USER-CUDA mode requires CUDA variant of run style");
   if (whichflag == 2 && lmp->cuda)
     if (strstr(minimize_style,"cuda") == NULL)
       error->all(FLERR,"USER-CUDA mode requires CUDA variant of min style");
 
   // init the appropriate integrate and/or minimize class
   // if neither (e.g. from write_restart) then just return
 
   if (whichflag == 0) return;
   if (whichflag == 1) integrate->init();
   else if (whichflag == 2) minimize->init();
 
   // only set first_update if a run or minimize is being performed
 
   first_update = 1;
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Update::set_units(const char *style)
 {
   // physical constants from:
   // http://physics.nist.gov/cuu/Constants/Table/allascii.txt
   // using thermochemical calorie = 4.184 J
 
   if (strcmp(style,"lj") == 0) {
     force->boltz = 1.0;
     force->hplanck = 0.18292026;  // using LJ parameters for argon
     force->mvv2e = 1.0;
     force->ftm2v = 1.0;
     force->mv2d = 1.0;
     force->nktv2p = 1.0;
     force->qqr2e = 1.0;
     force->qe2f = 1.0;
     force->vxmu2f = 1.0;
     force->xxt2kmu = 1.0;
     force->e_mass = 0.0;    // not yet set
     force->hhmrr2e = 0.0;
     force->mvh2r = 0.0;
     force->angstrom = 1.0;
     force->femtosecond = 1.0;
     force->qelectron = 1.0;
 
     dt = 0.005;
     neighbor->skin = 0.3;
 
   } else if (strcmp(style,"real") == 0) {
     force->boltz = 0.0019872067;
     force->hplanck = 95.306976368;
     force->mvv2e = 48.88821291 * 48.88821291;
     force->ftm2v = 1.0 / 48.88821291 / 48.88821291;
     force->mv2d = 1.0 / 0.602214179;
     force->nktv2p = 68568.415;
     force->qqr2e = 332.06371;
     force->qe2f = 23.060549;
     force->vxmu2f = 1.4393264316e4;
     force->xxt2kmu = 0.1;
     force->e_mass = 1.0/1836.1527556560675;
     force->hhmrr2e = 0.0957018663603261;
     force->mvh2r = 1.5339009481951;
     force->angstrom = 1.0;
     force->femtosecond = 1.0;
     force->qelectron = 1.0;
 
     dt = 1.0;
     neighbor->skin = 2.0;
 
   } else if (strcmp(style,"metal") == 0) {
     force->boltz = 8.617343e-5;
     force->hplanck = 4.135667403e-3;
     force->mvv2e = 1.0364269e-4;
     force->ftm2v = 1.0 / 1.0364269e-4;
     force->mv2d = 1.0 / 0.602214179;
     force->nktv2p = 1.6021765e6;
     force->qqr2e = 14.399645;
     force->qe2f = 1.0;
     force->vxmu2f = 0.6241509647;
     force->xxt2kmu = 1.0e-4;
     force->e_mass = 0.0;    // not yet set
     force->hhmrr2e = 0.0;
     force->mvh2r = 0.0;
     force->angstrom = 1.0;
     force->femtosecond = 1.0e-3;
     force->qelectron = 1.0;
 
     dt = 0.001;
     neighbor->skin = 2.0;
 
   } else if (strcmp(style,"si") == 0) {
     force->boltz = 1.3806504e-23;
     force->hplanck = 6.62606896e-34;
     force->mvv2e = 1.0;
     force->ftm2v = 1.0;
     force->mv2d = 1.0;
     force->nktv2p = 1.0;
     force->qqr2e = 8.9876e9;
     force->qe2f = 1.0;
     force->vxmu2f = 1.0;
     force->xxt2kmu = 1.0;
     force->e_mass = 0.0;    // not yet set
     force->hhmrr2e = 0.0;
     force->mvh2r = 0.0;
     force->angstrom = 1.0e-10;
     force->femtosecond = 1.0e-15;
     force->qelectron = 1.6021765e-19;
 
     dt = 1.0e-8;
     neighbor->skin = 0.001;
 
   } else if (strcmp(style,"cgs") == 0) {
     force->boltz = 1.3806504e-16;
     force->hplanck = 6.62606896e-27;
     force->mvv2e = 1.0;
     force->ftm2v = 1.0;
     force->mv2d = 1.0;
     force->nktv2p = 1.0;
     force->qqr2e = 1.0;
     force->qe2f = 1.0;
     force->vxmu2f = 1.0;
     force->xxt2kmu = 1.0;
     force->e_mass = 0.0;    // not yet set
     force->hhmrr2e = 0.0;
     force->mvh2r = 0.0;
     force->angstrom = 1.0e-8;
     force->femtosecond = 1.0e-15;
     force->qelectron = 4.8032044e-10;
 
     dt = 1.0e-8;
     neighbor->skin = 0.1;
 
   } else if (strcmp(style,"electron") == 0) {
     force->boltz = 3.16681534e-6;
     force->hplanck = 0.1519829846;
     force->mvv2e = 1.06657236;
     force->ftm2v = 0.937582899;
     force->mv2d = 1.0;
     force->nktv2p = 2.94210108e13;
     force->qqr2e = 1.0;
     force->qe2f = 1.94469051e-10;
     force->vxmu2f = 3.39893149e1;
     force->xxt2kmu = 3.13796367e-2;
     force->e_mass = 0.0;    // not yet set
     force->hhmrr2e = 0.0;
     force->mvh2r = 0.0;
     force->angstrom = 1.88972612;
     force->femtosecond = 0.0241888428;
     force->qelectron = 1.0;
 
     dt = 0.001;
     neighbor->skin = 2.0;
 
   } else error->all(FLERR,"Illegal units command");
 
   delete [] unit_style;
   int n = strlen(style) + 1;
   unit_style = new char[n];
   strcpy(unit_style,style);
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Update::create_integrate(int narg, char **arg, char *suffix)
 {
   if (narg < 1) error->all(FLERR,"Illegal run_style command");
 
   delete [] integrate_style;
   delete integrate;
 
   int sflag;
   new_integrate(arg[0],narg-1,&arg[1],suffix,sflag);
 
   if (sflag) {
     char estyle[256];
     sprintf(estyle,"%s/%s",arg[0],suffix);
     int n = strlen(estyle) + 1;
     integrate_style = new char[n];
     strcpy(integrate_style,estyle);
   } else {
     int n = strlen(arg[0]) + 1;
     integrate_style = new char[n];
     strcpy(integrate_style,arg[0]);
   }
 }
 
 /* ----------------------------------------------------------------------
    create the Integrate style, first with suffix appended
 ------------------------------------------------------------------------- */
 
 void Update::new_integrate(char *style, int narg, char **arg,
                            char *suffix, int &sflag)
 {
   int success = 0;
 
   if (suffix && lmp->suffix_enable) {
     sflag = 1;
     char estyle[256];
     sprintf(estyle,"%s/%s",style,suffix);
     success = 1;
 
     if (0) return;
 
 #define INTEGRATE_CLASS
 #define IntegrateStyle(key,Class) \
     else if (strcmp(estyle,#key) == 0) integrate = new Class(lmp,narg,arg);
 #include "style_integrate.h"
 #undef IntegrateStyle
 #undef INTEGRATE_CLASS
 
     else success = 0;
   }
 
   if (!success) {
     sflag = 0;
 
     if (0) return;
 
 #define INTEGRATE_CLASS
 #define IntegrateStyle(key,Class) \
     else if (strcmp(style,#key) == 0) integrate = new Class(lmp,narg,arg);
 #include "style_integrate.h"
 #undef IntegrateStyle
 #undef INTEGRATE_CLASS
 
     else error->all(FLERR,"Illegal integrate style");
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Update::create_minimize(int narg, char **arg)
 {
   if (narg != 1) error->all(FLERR,"Illegal min_style command");
 
   delete [] minimize_style;
   delete minimize;
 
   if (0) return;      // dummy line to enable else-if macro expansion
 
 #define MINIMIZE_CLASS
 #define MinimizeStyle(key,Class) \
   else if (strcmp(arg[0],#key) == 0) minimize = new Class(lmp);
 #include "style_minimize.h"
 #undef MINIMIZE_CLASS
 
   else error->all(FLERR,"Illegal min_style command");
 
   int n = strlen(arg[0]) + 1;
   minimize_style = new char[n];
   strcpy(minimize_style,arg[0]);
 }
 
 /* ----------------------------------------------------------------------
    reset timestep as called from input script
 ------------------------------------------------------------------------- */
 
 void Update::reset_timestep(int narg, char **arg)
 {
   if (narg != 1) error->all(FLERR,"Illegal reset_timestep command");
   bigint newstep = ATOBIGINT(arg[0]);
   reset_timestep(newstep);
 }
 
 /* ----------------------------------------------------------------------
    reset timestep
+   set atimestep to new timestep, so future update_time() calls will be correct
    trigger reset of timestep for output and for fixes that require it
    do not allow any timestep-dependent fixes to be defined
    reset eflag/vflag global so nothing will think eng/virial are current
    reset invoked flags of computes,
      so nothing will think they are current between runs
    clear timestep list of computes that store future invocation times
    called from rerun command and input script (indirectly)
 ------------------------------------------------------------------------- */
 
 void Update::reset_timestep(bigint newstep)
 {
   ntimestep = newstep;
   if (ntimestep < 0) error->all(FLERR,"Timestep must be >= 0");
   if (ntimestep > MAXBIGINT) error->all(FLERR,"Too big a timestep");
 
+  atimestep = ntimestep;
+
   output->reset_timestep(ntimestep);
 
   for (int i = 0; i < modify->nfix; i++) {
     if (modify->fix[i]->time_depend)
       error->all(FLERR,
                  "Cannot reset timestep with a time-dependent fix defined");
     modify->fix[i]->reset_timestep(ntimestep);
   }
 
   eflag_global = vflag_global = -1;
 
   for (int i = 0; i < modify->ncompute; i++) {
     modify->compute[i]->invoked_scalar = -1;
     modify->compute[i]->invoked_vector = -1;
     modify->compute[i]->invoked_array = -1;
     modify->compute[i]->invoked_peratom = -1;
     modify->compute[i]->invoked_local = -1;
   }
 
   for (int i = 0; i < modify->ncompute; i++)
     if (modify->compute[i]->timeflag) modify->compute[i]->clearstep();
 
   // NOTE: 7Jun12, adding rerun command, don't think this is required
 
   //for (int i = 0; i < domain->nregion; i++)
   //  if (domain->regions[i]->dynamic_check())
   //    error->all(FLERR,"Cannot reset timestep with a dynamic region defined");
 }
 
+/* ----------------------------------------------------------------------
+   update elapsed simulation time
+   called at end of runs or when timestep size changes
+------------------------------------------------------------------------- */
+
+void Update::update_time()
+{
+  atime += (ntimestep-atimestep) * dt;
+  atimestep = ntimestep;
+}
+
 /* ----------------------------------------------------------------------
    memory usage of update and integrate/minimize
 ------------------------------------------------------------------------- */
 
 bigint Update::memory_usage()
 {
   bigint bytes = 0;
   if (whichflag == 1) bytes += integrate->memory_usage();
   else if (whichflag == 2) bytes += minimize->memory_usage();
   return bytes;
 }
diff --git a/src/update.h b/src/update.h
index f94ac92d9..1f347d7d0 100644
--- a/src/update.h
+++ b/src/update.h
@@ -1,105 +1,108 @@
 /* -*- c++ -*- ----------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #ifndef LMP_UPDATE_H
 #define LMP_UPDATE_H
 
 #include "pointers.h"
 
 namespace LAMMPS_NS {
 
 class Update : protected Pointers {
  public:
   double dt;                      // timestep
   double etol,ftol;               // minimizer tolerances on energy/force
   bigint ntimestep;               // current step (dynamics or min iterations)
   int nsteps;                     // # of steps to run (dynamics or min iter)
   int whichflag;                  // 0 for unset, 1 for dynamics, 2 for min
+  double atime;                   // simulation time at atime_step
+  bigint atimestep;               // last timestep atime was updated
   bigint firststep,laststep;      // 1st & last step of this run
   bigint beginstep,endstep;       // 1st and last step of multiple runs
   int first_update;               // 0 before initial update, 1 after
   int max_eval;                   // max force evaluations for minimizer
   int restrict_output;            // 1 if output should not write dump/restart
   int setupflag;                  // set when setup() is computing forces
   int multireplica;               // 1 if min across replicas, else 0
 
   bigint eflag_global,eflag_atom;  // timestep global/peratom eng is tallied on
   bigint vflag_global,vflag_atom;  // ditto for virial
 
   char *unit_style;
 
   class Integrate *integrate;
   char *integrate_style;
 
   class Min *minimize;
   char *minimize_style;
 
   Update(class LAMMPS *);
   ~Update();
   void init();
   void set_units(const char *);
   void create_integrate(int, char **, char *);
   void create_minimize(int, char **);
   void reset_timestep(int, char **);
   void reset_timestep(bigint);
+  void update_time();
   bigint memory_usage();
 
  private:
   void new_integrate(char *, int, char **, char *, int &);
 
 };
 
 }
 
 #endif
 
 /* ERROR/WARNING messages:
 
 E: USER-CUDA mode requires CUDA variant of run style
 
 CUDA mode is enabled, so the run style must include a cuda suffix.
 
 E: USER-CUDA mode requires CUDA variant of min style
 
 CUDA mode is enabled, so the min style must include a cuda suffix.
 
 E: Illegal ... command
 
 Self-explanatory.  Check the input script syntax and compare to the
 documentation for the command.  You can use -echo screen as a
 command-line option when running LAMMPS to see the offending line.
 
 E: Illegal integrate style
 
 Self-explanatory.
 
 E: Timestep must be >= 0
 
 Specified timestep is invalid.
 
 E: Too big a timestep
 
 Specified timestep is too large.
 
 E: Cannot reset timestep with a time-dependent fix defined
 
 You cannot reset the timestep when a fix that keeps track of elapsed
 time is in place.
 
 E: Cannot reset timestep with a dynamic region defined
 
 Dynamic regions (see the region command) have a time dependence.
 Thus you cannot change the timestep when one or more of these
 are defined.
 
 */
diff --git a/src/verlet.cpp b/src/verlet.cpp
index 9020c9399..966d14dba 100644
--- a/src/verlet.cpp
+++ b/src/verlet.cpp
@@ -1,441 +1,442 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #include "string.h"
 #include "verlet.h"
 #include "neighbor.h"
 #include "domain.h"
 #include "comm.h"
 #include "atom.h"
 #include "force.h"
 #include "pair.h"
 #include "bond.h"
 #include "angle.h"
 #include "dihedral.h"
 #include "improper.h"
 #include "kspace.h"
 #include "output.h"
 #include "update.h"
 #include "modify.h"
 #include "compute.h"
 #include "fix.h"
 #include "timer.h"
 #include "memory.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
 
 /* ---------------------------------------------------------------------- */
 
 Verlet::Verlet(LAMMPS *lmp, int narg, char **arg) :
   Integrate(lmp, narg, arg) {}
 
 /* ----------------------------------------------------------------------
    initialization before run
 ------------------------------------------------------------------------- */
 
 void Verlet::init()
 {
   Integrate::init();
 
   // warn if no fixes
 
   if (modify->nfix == 0 && comm->me == 0)
     error->warning(FLERR,"No fixes defined, atoms won't move");
 
   // virial_style:
   // 1 if computed explicitly by pair->compute via sum over pair interactions
   // 2 if computed implicitly by pair->virial_fdotr_compute via sum over ghosts
 
   if (force->newton_pair) virial_style = 2;
   else virial_style = 1;
 
   // setup lists of computes for global and per-atom PE and pressure
 
   ev_setup();
 
   // detect if fix omp is present for clearing force arrays
 
   int ifix = modify->find_fix("package_omp");
   if (ifix >= 0) external_force_clear = 1;
 
   // set flags for what arrays to clear in force_clear()
   // need to clear additionals arrays if they exist
 
   torqueflag = 0;
   if (atom->torque_flag) torqueflag = 1;
   erforceflag = 0;
   if (atom->erforce_flag) erforceflag = 1;
   e_flag = 0;
   if (atom->e_flag) e_flag = 1;
   rho_flag = 0;
   if (atom->rho_flag) rho_flag = 1;
 
   // orthogonal vs triclinic simulation box
 
   triclinic = domain->triclinic;
 }
 
 /* ----------------------------------------------------------------------
    setup before run
 ------------------------------------------------------------------------- */
 
 void Verlet::setup()
 {
   if (comm->me == 0 && screen) fprintf(screen,"Setting up run ...\n");
 
   update->setupflag = 1;
 
   // setup domain, communication and neighboring
   // acquire ghosts
   // build neighbor lists
 
   atom->setup();
   modify->setup_pre_exchange();
   if (triclinic) domain->x2lamda(atom->nlocal);
   domain->pbc();
   domain->reset_box();
   comm->setup();
   if (neighbor->style) neighbor->setup_bins();
   comm->exchange();
   if (atom->sortfreq > 0) atom->sort();
   comm->borders();
   if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
   domain->image_check();
   domain->box_too_small_check();
   modify->setup_pre_neighbor();
   neighbor->build();
   neighbor->ncalls = 0;
 
   // compute all forces
 
   ev_set(update->ntimestep);
   force_clear();
   modify->setup_pre_force(vflag);
 
   if (pair_compute_flag) force->pair->compute(eflag,vflag);
   else if (force->pair) force->pair->compute_dummy(eflag,vflag);
 
   if (atom->molecular) {
     if (force->bond) force->bond->compute(eflag,vflag);
     if (force->angle) force->angle->compute(eflag,vflag);
     if (force->dihedral) force->dihedral->compute(eflag,vflag);
     if (force->improper) force->improper->compute(eflag,vflag);
   }
 
   if (force->kspace) {
     force->kspace->setup();
     if (kspace_compute_flag) force->kspace->compute(eflag,vflag);
     else force->kspace->compute_dummy(eflag,vflag);
   }
 
   if (force->newton) comm->reverse_comm();
 
   modify->setup(vflag);
   output->setup();
   update->setupflag = 0;
 }
 
 /* ----------------------------------------------------------------------
    setup without output
    flag = 0 = just force calculation
    flag = 1 = reneighbor and force calculation
 ------------------------------------------------------------------------- */
 
 void Verlet::setup_minimal(int flag)
 {
   update->setupflag = 1;
 
   // setup domain, communication and neighboring
   // acquire ghosts
   // build neighbor lists
 
   if (flag) {
     modify->setup_pre_exchange();
     if (triclinic) domain->x2lamda(atom->nlocal);
     domain->pbc();
     domain->reset_box();
     comm->setup();
     if (neighbor->style) neighbor->setup_bins();
     comm->exchange();
     comm->borders();
     if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
     domain->image_check();
     domain->box_too_small_check();
     modify->setup_pre_neighbor();
     neighbor->build();
     neighbor->ncalls = 0;
   }
 
   // compute all forces
 
   ev_set(update->ntimestep);
   force_clear();
   modify->setup_pre_force(vflag);
 
   if (pair_compute_flag) force->pair->compute(eflag,vflag);
   else if (force->pair) force->pair->compute_dummy(eflag,vflag);
 
   if (atom->molecular) {
     if (force->bond) force->bond->compute(eflag,vflag);
     if (force->angle) force->angle->compute(eflag,vflag);
     if (force->dihedral) force->dihedral->compute(eflag,vflag);
     if (force->improper) force->improper->compute(eflag,vflag);
   }
 
   if (force->kspace) {
     force->kspace->setup();
     if (kspace_compute_flag) force->kspace->compute(eflag,vflag);
     else force->kspace->compute_dummy(eflag,vflag);
   }
 
   if (force->newton) comm->reverse_comm();
 
   modify->setup(vflag);
   update->setupflag = 0;
 }
 
 /* ----------------------------------------------------------------------
    run for N steps
 ------------------------------------------------------------------------- */
 
 void Verlet::run(int n)
 {
   bigint ntimestep;
   int nflag,sortflag;
 
   int n_post_integrate = modify->n_post_integrate;
   int n_pre_exchange = modify->n_pre_exchange;
   int n_pre_neighbor = modify->n_pre_neighbor;
   int n_pre_force = modify->n_pre_force;
   int n_post_force = modify->n_post_force;
   int n_end_of_step = modify->n_end_of_step;
 
   if (atom->sortfreq > 0) sortflag = 1;
   else sortflag = 0;
 
   for (int i = 0; i < n; i++) {
 
     ntimestep = ++update->ntimestep;
     ev_set(ntimestep);
 
     // initial time integration
 
     timer->stamp();
     modify->initial_integrate(vflag);
     if (n_post_integrate) modify->post_integrate();
     timer->stamp(Timer::MODIFY);
 
     // regular communication vs neighbor list rebuild
 
     nflag = neighbor->decide();
 
     if (nflag == 0) {
       timer->stamp();
       comm->forward_comm();
       timer->stamp(Timer::COMM);
     } else {
       if (n_pre_exchange) {
         timer->stamp();
         modify->pre_exchange();
         timer->stamp(Timer::MODIFY);
       }
       if (triclinic) domain->x2lamda(atom->nlocal);
       domain->pbc();
       if (domain->box_change) {
         domain->reset_box();
         comm->setup();
         if (neighbor->style) neighbor->setup_bins();
       }
       timer->stamp();
       comm->exchange();
       if (sortflag && ntimestep >= atom->nextsort) atom->sort();
       comm->borders();
       if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
       timer->stamp(Timer::COMM);
       if (n_pre_neighbor) {
         modify->pre_neighbor();
         timer->stamp(Timer::MODIFY);
       }
       neighbor->build();
       timer->stamp(Timer::NEIGHBOR);
     }
 
     // force computations
     // important for pair to come before bonded contributions
     // since some bonded potentials tally pairwise energy/virial
     // and Pair:ev_tally() needs to be called before any tallying
 
     force_clear();
 
     timer->stamp();
 
     if (n_pre_force) {
       modify->pre_force(vflag);
       timer->stamp(Timer::MODIFY);
     }
 
 
     if (pair_compute_flag) {
       force->pair->compute(eflag,vflag);
       timer->stamp(Timer::PAIR);
     }
 
     if (atom->molecular) {
       if (force->bond) force->bond->compute(eflag,vflag);
       if (force->angle) force->angle->compute(eflag,vflag);
       if (force->dihedral) force->dihedral->compute(eflag,vflag);
       if (force->improper) force->improper->compute(eflag,vflag);
       timer->stamp(Timer::BOND);
     }
 
     if (kspace_compute_flag) {
       force->kspace->compute(eflag,vflag);
       timer->stamp(Timer::KSPACE);
     }
 
     // reverse communication of forces
 
     if (force->newton) {
       comm->reverse_comm();
       timer->stamp(Timer::COMM);
     }
 
     // force modifications, final time integration, diagnostics
 
     if (n_post_force) modify->post_force(vflag);
     modify->final_integrate();
     if (n_end_of_step) modify->end_of_step();
     timer->stamp(Timer::MODIFY);
 
     // all output
 
     if (ntimestep == output->next) {
       timer->stamp();
       output->write(ntimestep);
       timer->stamp(Timer::OUTPUT);
     }
   }
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Verlet::cleanup()
 {
   modify->post_run();
   domain->box_too_small_check();
+  update->update_time();
 }
 
 /* ----------------------------------------------------------------------
    clear force on own & ghost atoms
    clear other arrays as needed
 ------------------------------------------------------------------------- */
 
 void Verlet::force_clear()
 {
   int i;
 
   if (external_force_clear) return;
 
   // clear force on all particles
   // if either newton flag is set, also include ghosts
   // when using threads always clear all forces.
 
   if (neighbor->includegroup == 0) {
     int nall;
     if (force->newton) nall = atom->nlocal + atom->nghost;
     else nall = atom->nlocal;
 
     size_t nbytes = sizeof(double) * nall;
 
     if (nbytes > 0) {
       memset(&(atom->f[0][0]),0,3*nbytes);
       if (torqueflag)  memset(&(atom->torque[0][0]),0,3*nbytes);
       if (erforceflag) memset(&(atom->erforce[0]),  0,  nbytes);
       if (e_flag)      memset(&(atom->de[0]),       0,  nbytes);
       if (rho_flag)    memset(&(atom->drho[0]),     0,  nbytes);
     }
 
   // neighbor includegroup flag is set
   // clear force only on initial nfirst particles
   // if either newton flag is set, also include ghosts
 
   } else {
     int nall = atom->nfirst;
 
     double **f = atom->f;
     for (i = 0; i < nall; i++) {
       f[i][0] = 0.0;
       f[i][1] = 0.0;
       f[i][2] = 0.0;
     }
 
     if (torqueflag) {
       double **torque = atom->torque;
       for (i = 0; i < nall; i++) {
         torque[i][0] = 0.0;
         torque[i][1] = 0.0;
         torque[i][2] = 0.0;
       }
     }
 
     if (erforceflag) {
       double *erforce = atom->erforce;
       for (i = 0; i < nall; i++) erforce[i] = 0.0;
     }
 
     if (e_flag) {
       double *de = atom->de;
       for (i = 0; i < nall; i++) de[i] = 0.0;
     }
 
     if (rho_flag) {
       double *drho = atom->drho;
       for (i = 0; i < nall; i++) drho[i] = 0.0;
     }
 
     if (force->newton) {
       nall = atom->nlocal + atom->nghost;
 
       for (i = atom->nlocal; i < nall; i++) {
         f[i][0] = 0.0;
         f[i][1] = 0.0;
         f[i][2] = 0.0;
       }
 
       if (torqueflag) {
         double **torque = atom->torque;
         for (i = atom->nlocal; i < nall; i++) {
           torque[i][0] = 0.0;
           torque[i][1] = 0.0;
           torque[i][2] = 0.0;
         }
       }
 
       if (erforceflag) {
         double *erforce = atom->erforce;
         for (i = atom->nlocal; i < nall; i++) erforce[i] = 0.0;
       }
 
       if (e_flag) {
         double *de = atom->de;
         for (i = 0; i < nall; i++) de[i] = 0.0;
       }
 
       if (rho_flag) {
         double *drho = atom->drho;
         for (i = 0; i < nall; i++) drho[i] = 0.0;
       }
     }
   }
 }
diff --git a/src/version.h b/src/version.h
index 81efb3170..5d67f892b 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define LAMMPS_VERSION "14 May 2013"
+#define LAMMPS_VERSION "24 May 2013"